代码返回包含 OLE 错误 0x800a01a8 的 pywintypes 错误

问题描述 投票:0回答:1

我有一个从 Excel 文件获取数据的程序。我正在使用 Python 3.11.4 和 xlWings。 数据由一些标准数据和一些用户输入定义的数据组成。该 Excel 包含的列的技术数据属于列顶部的产品 ID。数据保存在提取开始之前创建的数据库中。有关需要提取的数据的信息存储在字典中,数据库的标头充当键。对于标准数据,字典的值是一个数组,其中包含从 Excel 中找到的值,以及用作在数据库中创建列的数据类型的字符串。对于用户定义的数据,该数组有两个附加元素:搜索字符串(在 Excel 中查找的内容)和查找该字符串的地址。将针对循环遍历的每一列更新将保存在数据库中的字典中的值。该代码循环遍历用户提供的文档。

问题:当一次从多个文件中提取数据时,代码在特定的 Excel 文件中返回错误:

pywintypes.com_error:(-2146827864,'OLE错误0x800a01a8',无,无) 在第 1395 行(下一个块的最后一行):

                #Retrieve properties
                for header in headers:
                    if header_basis[header][3] is None:
                        header_basis[header][0] = "not found!"
                    else:
                        header_basis[header][0] = header_basis[header][3].offset(0,i).value

headers 是一个数组,其中包含定义用户定义数据名称的字符串。这些字符串是数据库的列标题和字典的键。

代码本身相当长,有很多内容与这个问题关系不大(我假设)但是重要的部分在这里(用(...)分隔):

def search_productcard_excel(path, families, headers, search_strings, master):
(...)
    #Create dictionary with value and database data type. 
    header_basis = {
        "product_ID": [None, "BIGINT(20)"],
        "doc_name": [None, "VARCHAR(50)"],
        "family": [None, "VARCHAR(50)"],
        "num_of_conductors": [None, "VARCHAR(50)"],
        "type": [None, "VARCHAR(50)"],
        "CSA": [None, "VARCHAR(50)"],
        #"current": [None, "FLOAT(5)"],
        "note_1": [None, "VARCHAR(50)"],
        "note_2": [None, "VARCHAR(50)"],
    }
    for i, header in enumerate(headers):
        #Add the search string and address for manual data too
        header_basis[header] = [None, "VARCHAR(50)", search_strings[i], None]
(...)
    #Create new table
    sql_string = f"CREATE TABLE {temp_table} ("
    for i, key in enumerate(header_basis.keys()):
        if i > 0:
            sql_string += ", "
        sql_string += f"{key} {header_basis[key][1]}"
    sql_string = sql_string + ")"
    cursor.execute(sql_string)
    connection.commit()
(...)
    #Do for all document names
    create_log_text("Start searching documents...\n")
    for doc_name in doc_name_arr:
        xml_files = []
        for extension in ALLOWED_FILES:
            xml_files.extend(glob.glob(os.path.join(path, f"{doc_name}.{extension}")))

        #do for all found documents
        for xml_file in xml_files:
(...)
            #Find the start position of the given properties
            for i, header in enumerate(headers):
                search_string = header_basis[header][2]
                #Search for both columns if "&&" is found
                if search_string.find("&&") != -1:
                    char_pos = search_string.find("&&")
                    search_string_1 = search_string[0:char_pos-1]
                    search_string_2 = search_string[char_pos+3:]
                    temp_range = fun_search_string(search_string_1,
                                                   worksheet[PROPERTY_RANGE_BACKUP],
                                                   0)
                    if temp_range is not None:
                        for search_cell in temp_range:
                            if search_cell is None:
                                header_basis[header][3] = None
                            else:
                                temp_result = fun_search_string(
                                    search_string_2,
                                    worksheet[search_cell.offset(0,2).address],
                                    0
                                    )[0]
                                if temp_result is not None:
                                    header_basis[header][3] = search_cell.offset(0,2)
                                    break
                else:
                    header_basis[header][3] = (
                        fun_search_string(
                            search_string,
                            worksheet[PROPERTY_RANGE],0
                            )[0]
                        )

            #Get family name
            header_basis["family"][0] = worksheet["B2"].value

            #for every column (CSA)
            create_log_text("Search given values...\n")
            for i in range(1, MAX_SIZES):
(...)
                #Retrieve properties
                for header in headers:
                    if header_basis[header][3] is None:
                        header_basis[header][0] = "not found!"
                    else:
                        header_basis[header][0] = header_basis[header][3].offset(0,i).value
(...)
                #Do for every product
                for cell in id_cells:
(...)
                    #Add row table
                    #Create sql command
                    sql_string = f"INSERT INTO {temp_table} ("
                    for j, key in enumerate(header_basis.keys()):
                        if j > 0:
                            sql_string += ", "
                        sql_string += key
                    sql_string = sql_string + ") VALUES ("
                    for j, key in enumerate(header_basis.keys()):
                        val = header_basis[key][0]
                        if j > 0:
                            sql_string += ", "
                        try:
                            float(val)
                            sql_string = sql_string + str(val)
                        except ValueError:
                            sql_string = sql_string + f"'{str(val)}'"
                        except TypeError:
                            sql_string = sql_string + "''"
                    sql_string = sql_string + ")"
                    #print(sql_string)
                    cursor.execute(sql_string)
(...)
            #close workbook
            create_log_text("Closing file...\n")
            workbook.close()
(...)
    #close excel app
    app.quit()

当仅从返回错误的一个特定文件中提取数据时,而不是一次提取多个文档,它不会返回错误。 另外,在稍微简化代码之前,我将这些值存储在与其他数据(地址、数据类型和搜索字符串)分开的数组中:

val_arr[i] = fun_search_string(search_string, worksheet[PROPERTY_RANGE],0)[0]
代替
header_basis[header][3] = (fun_search_string(search_string, worksheet[PROPERTY_RANGE],0)[0])
这没有返回任何错误。 我不知道 pywintypes.com_error 到底是什么,也不知道其中的“OLE 错误 0x800a01a8”意味着什么,因此我很难弄清楚从哪里开始。我在网上也没有找到答案。

编辑:我自己找到了解决方案。我怀疑这与记忆有关。所以我只是在每次循环更新

header_basis[header][3] is None
之前设置
header_basis[header][3]
。这似乎有效。我

python-3.x mysql-connector xlwings
1个回答
0
投票

我怀疑该错误与内存问题有关。也许字典在不知不觉中填充了数据,因为值没有被删除而是更新了。在循环中更新之前,我将字典值重置为 None 。这似乎有效。我不确定到底为什么,因为我认为更新字典值(例如 header_basis[header][3] = blabla)会删除以前的值并且不会留下任何剩余数据。也许这也与存储范围有关。

以下代码:

        #Find the start position of the given properties
        for i, header in enumerate(headers):
            search_string = header_basis[header][2]
            #Search for both columns if "&&" is found

成为:

        #Find the start position of the given properties
        for i, header in enumerate(headers):
            search_string = header_basis[header][2]
            header_basis[header][3] = None #Empty the dictionary value
            #Search for both columns if "&&" is found
© www.soinside.com 2019 - 2024. All rights reserved.