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的错误。
另外,你函数里的逻辑还有两个小问题:
- 同时用
xw.Book和pandas.to_excel操作同一个Excel文件,容易导致文件锁定或数据不一致 - 没有把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进程都被正确关闭
额外注意事项
- 确保运行代码时,目标Excel文件没有被手动打开,否则xlwings可能无法获取写入权限
- 确认Excel工作表中的ListObject名称和你传入的
listobject_name一致,可以在Excel的表格设计选项卡中查看表格名称 - 如果你的ListObject有固定的表头,确保MySQL查询返回的列顺序和Excel表头顺序一致,避免数据错位
备注:内容来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

