在工作中,经常遇到需要将Excel中的数据批量导入到数据库的情况,尤其是当Excel表格中包含合并单元格时,处理起来更为复杂。为了确保数据准确无误地导入,我们需要确保Excel中的数据列与数据库中的字段一一对应。下面将介绍如何使用Python实现这一功能。
- 安装必要库:确保已安装
pandas
、openpyxl
(用于读取Excel文件)和mysql.connector
(用于连接数据库)。 - 读取Excel文件:使用
load_workbook读取excel。
- 处理合并单元格:如果Excel中存在合并单元格,
pandas
会将其填充为NaN。我们需要遍历这些NaN值,并用合并单元格的左上角值进行填充。 - 连接数据库:使用
mysql.connector.connect()
创建与数据库的连接。 - 导入数据:使用insert语句逐行导入数据,该方法支持批量插入。
- 验证数据:在导入完成后,通过查询数据库验证数据的准确性和完整性。
import pandas as pd
import numpy as np
from openpyxl import load_workbook # 确保正确导入 load_workbook
import mysql.connector
import re
excel_file = 'XXX.xlsx' # 替换为你的 Excel 文件路径
sheet_name = 'SheetXXXX' # 替换为你的工作表名称
# 加载工作簿
wb = load_workbook(filename=excel_file)
sheet = wb[sheet_name]
# 获取合并单元格的范围
merged_ranges = list(sheet.merged_cells.ranges)
# 构建数据字典
data = {}
for row in sheet.iter_rows(values_only=True):
for col_idx, cell_value in enumerate(row):
if col_idx not in data:
data[col_idx] = []
data[col_idx].append(cell_value)
# 处理合并单元格
for merged_range in merged_ranges:
min_col, min_row, max_col, max_row = merged_range.min_col, merged_range.min_row, merged_range.max_col, merged_range.max_row
merged_value = sheet.cell(row=min_row, column=min_col).value
for row in range(min_row, max_row + 1):
for col in range(min_col, max_col + 1):
data[col - 1][row - 1] = merged_value
# 将数据字典转换为 DataFrame
df = pd.DataFrame(data)
#只保留从第三行开始的数据
df = df.iloc[1:]
# 打印 DataFrame
print(df)
# 保存到文件
output_file = 'output.txt' # 替换为你想要保存的文件名
df.to_csv(output_file, sep='\t', index=False)
# 设置 MySQL 数据库连接
# 请替换为你的数据库连接信息
db_config = {
'user': 'user',
'password': 'password',
'host': 'host',
'database': 'database'
}
# 获取数据库表的字段名
table_name = 'table_name' # 替换为你的数据库表名
# 连接到 MySQL 数据库
connection = mysql.connector.connect(**db_config)
cursor = connection.cursor()
# 获取数据库表的字段名
column_query = f"""
SELECT column_name
FROM information_schema.columns
WHERE table_name = '{table_name}'
ORDER BY ordinal_position
"""
cursor.execute(column_query)
table_columns = [row[0] for row in cursor.fetchall()]
print(table_columns)
# 逐行写入数据
insert_query = f"INSERT INTO {table_name} ({', '.join(table_columns[1:])}) VALUES ({', '.join(['%s'] * len(table_columns[1:]))})"
for index, row in df.iterrows():
# row_data = tuple(row.fillna('').values) # 将 NaN 替换为空字符串
row_data = tuple([None if pd.isna(val) or val == '' else val for val in row.values]) # 将 NaN 或空字符串替换为 None
cursor.execute(insert_query, row_data)
# 提交事务
connection.commit()
print(f"数据已成功写入数据库表 {table_name} 中。")
# 关闭数据库连接
cursor.close()
connection.close()