You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python将MySQL数据导入Excel ListObject时报错:must be real number, not Table

Python将MySQL数据导入Excel ListObject时报错:must be real number, not Table

看起来你遇到的问题是参数类型不匹配导致的,咱们一步步来梳理和解决:

错误原因分析

你在调用mysql_to_excel_listobject函数时,把source_lo(一个xlwings的Table对象)传给了参数listobject_name,但这个参数的设计是要接收字符串类型的ListObject名称,而不是Table对象本身。当函数内部执行sheet.range(listobject_name).listobject时,把Table对象传给了range方法——这个方法只接受地址字符串、名称字符串或者数字型的行列号,自然就会抛出must be real number, not Table的错误。

另外,你函数里的逻辑还有两个小问题:

  1. 同时用xw.Book和pandas.to_excel操作同一个Excel文件,容易导致文件锁定或数据不一致
  2. 没有把MySQL的列名同步到DataFrame,写入Excel后可能没有表头对应

修复方案和优化代码

1. 修正函数调用的参数

把调用时的source_lo替换成它的名称字符串source_lo.name:

# 原错误调用
# mysql_to_excel_listobject(QUERY,
#     test_file_path, "22-Jan", source_lo,
#     5, 2
# )

# 修正后的调用
mysql_to_excel_listobject(QUERY,
    test_file_path, "22-Jan", source_lo.name,
    5, 2
)

2. 优化函数内部逻辑(核心修复)

重新编写函数,用xlwings原生方式操作ListObject,避免文件多次打开的问题,同时完善错误排查:

import mysql.connector
import pandas as pd
import xlwings as xw
from datetime import datetime
import traceback

today = datetime.now()
test_file_path = rf"E:\ReconTest\Reconcilation Reports\QF\2025\Jan\QF - January Internal Reconciliation Summary.xlsx"

# 改用参数化查询,避免SQL注入和日期格式问题
QUERY = """
        SELECT *
        FROM dailyfiledto
        WHERE Cust = %s AND fdate = %s
      """

def mysql_to_excel_listobject(query,
                              excel_file, sheet_name, listobject_name,
                              query_params=None):
    """
    Fetches data from MySQL, loads it into a Pandas DataFrame,
    and writes it to a specified Excel ListObject.

    Args:
        query: SQL query to execute (use %s for parameters).
        excel_file: Path to the Excel file.
        sheet_name: Name of the sheet containing the ListObject.
        listobject_name: Name of the ListObject (string).
        query_params: Tuple of parameters for the SQL query (optional).
    """

    try:
        # Connect to MySQL database
        conn = mysql.connector.connect(
            host="localhost",
            user="root",
            password="",
            database="azm"
        )
        cursor = conn.cursor()

        # Execute the SQL query with parameters (if provided)
        if query_params:
            cursor.execute(query, query_params)
        else:
            cursor.execute(query)

        # Get column names from MySQL result
        column_names = [desc[0] for desc in cursor.description]
        # Fetch all rows
        data = cursor.fetchall()

        # Create DataFrame with column names
        df = pd.DataFrame(data, columns=column_names)
        print(f"Fetched {len(df)} records from MySQL")

        # Use xlwings to write to ListObject
        with xw.App(visible=False) as app:
            wb = xw.Book(excel_file)
            sheet = wb.sheets[sheet_name]

            # Get the target ListObject
            listobject = sheet.tables[listobject_name]

            # Clear existing data (preserve headers)
            if listobject.data_body_range:
                listobject.data_body_range.delete()

            # Write data to ListObject if DataFrame is not empty
            if not df.empty:
                listobject.data_body_range = df.values.tolist()

            wb.save()
        print("Data successfully written to ListObject")

    except Exception as e:
        print(f"Error: {e}")
        traceback.print_exc()  # Print full error stack for easier debugging

    finally:
        # Clean up database connections
        if 'conn' in locals() and conn.is_connected():
            cursor.close()
            conn.close()

# --- 调用修正后的函数 ---
workbook = xw.Book(test_file_path)
new_sheet_name = today.strftime("%d-%b")
new_sheet = workbook.sheets[new_sheet_name]
source_lo = new_sheet.tables[0]

# Pass query parameters to avoid SQL injection
mysql_to_excel_listobject(
    query=QUERY,
    excel_file=test_file_path,
    sheet_name=new_sheet_name,
    listobject_name=source_lo.name,
    query_params=('QF', today.strftime('%Y-%m-%d'))
)

3. 关键改动说明

  • 参数化SQL查询:把原来的字符串拼接换成%s占位符,避免SQL注入风险,同时解决日期格式兼容问题
  • xlwings原生操作ListObject:直接通过listobject.data_body_range读写数据,不需要手动指定起始行列,逻辑更简洁
  • 后台Excel进程:用with xw.App(visible=False)启动无界面Excel,避免弹窗干扰,操作完成自动关闭
  • 详细错误日志:新增traceback.print_exc(),可以打印错误发生的具体行号和调用栈,方便快速定位问题
  • 完善的资源清理:确保数据库连接、游标和Excel进程都被正确关闭

额外注意事项

  1. 确保运行代码时,目标Excel文件没有被手动打开,否则xlwings可能无法获取写入权限
  2. 确认Excel工作表中的ListObject名称和你传入的listobject_name一致,可以在Excel的表格设计选项卡中查看表格名称
  3. 如果你的ListObject有固定的表头,确保MySQL查询返回的列顺序和Excel表头顺序一致,避免数据错位

备注:内容来源于stack exchange,提问作者Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 14:40:29