python 读数据库accdb中表导出到xlsx

本文介绍了如何使用Python的pyodbc和pandas库将数据从MicrosoftAccess数据库执行SQL查询后导出到Excel电子表格。首先,需要建立数据库连接,然后执行查询获取数据,最后将数据帧写入Excel文件。

您可以使用 Python 中的以下步骤将数据从 Microsoft Access 数据库导出到 Excel 电子表格:

导入必要的库:

连接到 Access 数据库:

执行 SQL 查询以检索数据:

将数据写入 Excel 电子表格:
注意:此代码假定您已安装 pyodbc 和 pandas 库。 如果没有,您可以使用 pip 安装它们:

import pyodbc
import pandas as pd

# Connect to the database
conn = pyodbc.connect(r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=D:\riocomponents\Advanced Data Import 3.11\demos\data\country.mdb;")


# Execute a SQL query to retrieve data from the database
query = 'SELECT * FROM country'
df = pd.read_sql(query, conn)


# Create a new Excel workbook and add a worksheet
df.to_excel('output.xlsx', index=False)

 

2016驱动程序下载链接:https://www.microsoft.com/en-us/download/details.aspx?id=54920

2010驱动程序下载链接:https://www.microsoft.com/en-us/download/details.aspx?id=13255

感谢补充信息! 你说: > ✅ 其他表(inbound、outbound、stock)都能导出成功 > ❌ 只有 `material_master` 表导出失败 这说明: - 数据库连接 ✔️ - 邮件发送逻辑 ✔️ - 日期字段不是问题 ❌ - 唯独 `material_master` 出错 → 很可能是 **表名拼写错误** 或 **字段中有保留字** --- # 🔍 错误原因分析(主数据表导出失败) Access 是一个“敏感”的数据库系统,常见导致 `material_master` 查询失败的原因如下: | 原因 | 说明 | |------|------| | 1. 📝 **表名不叫 `material_master`** | 实际可能是 `MaterialMaster`、`物料主数据` 等 | | 2. ⚠️ **字段名使用了 Access 保留关键字** | 如 `Name`、`Date`、`Level` 等是保留字 | | 3. 💥 **字段名包含空格或特殊字符** | 如 `Customer Ref`、`创建时间` | | 4. 🧩 **表不存在或被重命名** | 用户可能改过名字 | --- ## ✅ 解决方案:精准定位 + 安全查询 我们来做一个 **增强版的 `execute_query_all` 函数**,带自动探测和容错。 --- ### ✅ 替换原来的 `execute_query_all` 和相关调用部分 请将整个 `export_and_send_data()` 中与 `material_master` 相关的部分替换为以下代码: ```python # ======================================== # 导出并发送数据(修复仅 material_master 报错) # ======================================== def export_and_send_data(): if not cursor: messagebox.showwarning("警告", "数据库未连接,无法导出数据") return if not messagebox.askyesno("确认发送", "是否确认将本月、上月的出入库、库存及物料主数据发送到后台管理?"): return try: today = datetime.today() first_day_this_month = today.replace(day=1) last_day_last_month = first_day_this_month - timedelta(days=1) first_day_last_month = last_day_last_month.replace(day=1) INBOUND_DATE_FIELD = "date_in" # ← 根据你实际情况修改 OUTBOUND_DATE_FIELD = "date_out" # ← 同上 def execute_query_for_month(table, date_field, month_start, month_end): query = f"SELECT * FROM [{table}] WHERE [{date_field}] >= ? AND [{date_field}] <= ?" try: cursor.execute(query, (month_start, month_end)) rows = cursor.fetchall() columns = [col[0] for col in cursor.description] return pd.DataFrame.from_records(rows, columns=columns) except Exception as e: print(f"❌ 查询 {table} 失败: {e}") raise e def safe_fetch_table(table_name): """安全获取整张表数据,兼容保留字和特殊字段名""" try: # 方法1:尝试直接查 * cursor.execute(f"SELECT * FROM [{table_name}]") except pyodbc.ProgrammingError as e: if "Too few parameters" in str(e): # 可能是因为字段是保留字(如 Name) # 方法2:手动列出字段(避免保留字冲突) try: print(f"⚠️ 尝试通过列名逐个查询 {table_name}") columns = [] for col in cursor.columns(table=table_name): columns.append(col.COLUMN_NAME) if not columns: raise ValueError(f"无法取表 {table_name} 的结构") # 构造安全 SELECT:所有字段加 [] 括起来 select_fields = ", ".join([f"[{col}]" for col in columns]) query = f"SELECT {select_fields} FROM [{table_name}]" cursor.execute(query) except Exception as inner_e: messagebox.showerror("结构错误", f"无法查询表 {table_name} 的字段结构:\n{inner_e}") raise inner_e else: raise e rows = cursor.fetchall() columns = [col[0] for col in cursor.description] return pd.DataFrame.from_records(rows, columns=columns) files = [] # 1. 本月 & 上月 入库 for label, start, end in [ ("this_month", first_day_this_month, today), ("last_month", first_day_last_month, last_day_last_month) ]: inbound_df = execute_query_for_month("inbound", INBOUND_DATE_FIELD, start, end) inbound_file = f"{label}_inbound.xlsx" inbound_df.to_excel(inbound_file, index=False) files.append(inbound_file) # 2. 本月 & 上月 出库 for label, start, end in [ ("this_month", first_day_this_month, today), ("last_month", first_day_last_month, last_day_last_month) ]: outbound_df = execute_query_for_month("outbound", OUTBOUND_DATE_FIELD, start, end) outbound_file = f"{label}_outbound.xlsx" outbound_df.to_excel(outbound_file, index=False) files.append(outbound_file) # 3. 当前库存 stock_df = safe_fetch_table("stock") stock_file = "current_stock.xlsx" stock_df.to_excel(stock_file, index=False) files.append(stock_file) # 4. ✅ 物料主数据(使用安全方式) try: master_df = safe_fetch_table("material_master") # ← 改成你的真实表名! master_file = "material_master.xlsx" master_df.to_excel(master_file, index=False) files.append(master_file) except Exception as e: messagebox.showerror("导出失败", f"无法导出物料主数据表:\n" f"可能原因:\n" f"1. 表名不是 'material_master'(检查是否叫 MaterialMaster / 主数据 / etc)\n" f"2. 字段包含保留字(如 Name)且未加 []\n" f"3. 数据库损坏\n\n" f"错误详情:\n{e}") return # 失败则停止发送 # 创建 ZIP 包 zip_filename = "inventory_data.zip" with zipfile.ZipFile(zip_filename, 'w') as zipf: for file in files: zipf.write(file) os.remove(file) # 构建邮件 msg = EmailMessage() msg['Subject'] = f'出入库、库存及物料主数据 - {today.strftime("%Y-%m-%d")}' msg['From'] = 'notifier3@wikachina.com' msg['To'] = 'liang.chen@wika.com' msg.set_content( '附件为本月和上月的出入库记录、当前库存以及物料主数据,请查收。\n\n' '包含文件:\n' ' - this_month_inbound.xlsx\n' ' - last_month_inbound.xlsx\n' ' - this_month_outbound.xlsx\n' ' - last_month_outbound.xlsx\n' ' - current_stock.xlsx\n' ' - material_master.xlsx' ) with open(zip_filename, 'rb') as f: msg.add_attachment(f.read(), maintype='application', subtype='zip', filename=zip_filename) with smtplib.SMTP('smtp.wikachina.com', 25) as smtp: smtp.starttls() smtp.login('notifier3@wikachina.com', 'Wik@202003') smtp.send_message(msg) os.remove(zip_filename) messagebox.showinfo("成功", "📦 数据已成功发送,包含物料主数据!") except Exception as e: print(f"❌ 导出失败:{e}") ``` --- ## ✅ 关键改进点 | 改进 | 作用 | |------|------| | `safe_fetch_table()` | 自动处理保留字字段(如 `Name`) | | 使用 `[字段名]` 括号 | 防止 Access 把 `Name` 当函数 | | 先探测结构再查询 | 即使字段是保留字也能取 | | 更友好的报错提示 | 明确告诉你是不是表名错了 | --- ## ✅ 最关键一步:确认你的主数据表真实名称! 运行这个脚本查看所有表名: ```python import pyodbc conn_str = ( r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};' r'DBQ=./Data/DB.accdb;' r'PWD=zaq1XSW@;' ) conn = pyodbc.connect(conn_str) cursor = conn.cursor() print("📋 数据库中所有用户表:") for table_info in cursor.tables(tableType='TABLE'): print(f" → {table_info.tableName}") conn.close() ``` 输出示例: ``` 📋 数据库中所有用户表: → MSysNavPaneGroupCategories → MSysNavPaneGroups → MSysNavPaneObjectIDs → MSysNavPaneSortOrder → inbound → outbound → stock → MaterialMaster ← 注意大小写和命名! ``` 👉 所以你应该把: ```python master_df = safe_fetch_table("material_master") ``` 改成: ```python master_df = safe_fetch_table("MaterialMaster") ``` --- ## ✅ 常见真实表名对照 | 你以为的名字 | 实际可能叫 | |-------------|-----------| | `material_master` | `MaterialMaster` | | `material_master` | `主数据` | | `material_master` | `物料清单` | | `material_master` | `tblMaterial` | --- ## ✅ 总结:解决步骤 1. ✅ 运行上面的“打印所有表名”脚本 2. ✅ 找到真实的主数据表名(比如叫 `MaterialMaster`) 3. ✅ 修改这一行: ```python master_df = safe_fetch_table("MaterialMaster") # ← 改成你的真实表名 ``` 4. ✅ 再次点击「发送数据」→ 应该成功! --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值