日常数据处理中,经常遇到需要把一批 CSV 文件汇总到一个 Excel 工作簿的场景------每个 CSV 对应一个工作表,方便统一查看和分发。Python 原生 csv 模块可以读取数据,但要逐个写入 Excel 的不同工作表,还需要额外的写入逻辑。使用 Free Spire.XLS for Python 免费库可以直接将 CSV 加载为工作簿对象,再将其工作表复制到目标工作簿中,代码量很少。
环境准备
通过 pip 安装免费版本即可,支持 Python 3.6+ 以及 Windows、macOS、Linux:
bash
pip install Spire.Xls.Free
Free Spire.XLS for Python 无需安装 Microsoft Excel,在服务器或无桌面环境中也能运行。需要注意,免费版对 .xls 格式的读写有工作表数量限制(每个工作簿最多 5 个,每个工作表最多 200 行);如果输出为 .xlsx 格式,则不触发这一限制。对于工作表数量较多或行数较大的场景,建议输出 .xlsx。
核心思路
单个 CSV 文件用 Workbook.LoadFromFile() 加载后,数据会出现在工作簿的第一个工作表(索引 0)中。要合并多个 CSV,可以:
- 创建一个目标
Workbook; - 遍历 CSV 文件列表,每个文件单独加载;
- 用
Worksheets.AddCopy()将其工作表复制到目标工作簿; - 重命名复制过来的工作表,便于区分;
- 保存目标工作簿为
.xlsx。
AddCopy 方法会连同数据、格式一并复制,第二个参数 WorksheetCopyType.CopyAll 可确保完整性。
完整代码
以下脚本将指定目录下所有 CSV 文件合并到一个 Excel 文件中,每个 CSV 对应一个工作表:
python
import os
import glob
from spire.xls import *
from spire.xls.common import *
def merge_csv_to_excel(csv_dir, output_path, delimiter=","):
"""
将目录下的所有 CSV 文件合并到一个 Excel 文件中。
每个 CSV 对应一个工作表,工作表名取自文件名(不含扩展名)。
参数:
csv_dir: CSV 文件所在目录
output_path: 输出 Excel 文件路径(建议 .xlsx)
delimiter: CSV 分隔符,默认逗号
"""
csv_files = glob.glob(os.path.join(csv_dir, "*.csv"))
if not csv_files:
print("未找到 CSV 文件")
return
# 创建目标工作簿
target_book = Workbook()
# 删除默认生成的空白工作表(保留一个作为占位,后续按需删除)
# 这里先不删,处理完第一个文件后再统一处理
for idx, file_path in enumerate(csv_files):
file_name = os.path.splitext(os.path.basename(file_path))[0]
# 加载单个 CSV 文件
source_book = Workbook()
source_book.LoadFromFile(file_path, delimiter, 1, 1)
# 获取 CSV 解析后的工作表
source_sheet = source_book.Worksheets[0]
# 复制到目标工作簿
target_book.Worksheets.AddCopy(source_sheet, WorksheetCopyType.CopyAll)
# 重命名新复制的工作表
new_sheet = target_book.Worksheets[target_book.Worksheets.Count - 1]
new_sheet.Name = file_name[:31] # Excel 工作表名最长 31 个字符
source_book.Dispose()
print(f"已导入: {file_name}")
# 删除目标工作簿中最初的空白工作表
# 默认 Workbook() 会创建 3 个工作表,删除未使用的
for i in range(target_book.Worksheets.Count - 1, -1, -1):
sheet = target_book.Worksheets[i]
# 如果工作表名仍是默认的 Sheet1/Sheet2/Sheet3,且不在已导入的列表中
if sheet.Name in ["Sheet1", "Sheet2", "Sheet3"]:
target_book.Worksheets.RemoveAt(i)
# 保存为 xlsx
target_book.SaveToFile(output_path, FileFormat.Version2016)
target_book.Dispose()
print(f"\n合并完成: {output_path}")
if` `name` == `"main"`:`
`
merge_csv_to_excel(`
`
csv_dir=`"./csv_files"`,`
`
output_path=`"./merged_output.xlsx"`,`
`
delimiter=`","
`
)`
`
`
几个关键点
-
LoadFromFile 的参数 。
LoadFromFile(fileName, separator, startRow, startColumn)中,separator指定分隔符,不限于逗号。如果处理的是制表符分隔的 TSV,传入"\t"即可;分号分隔的欧洲数据文件传入";"。 -
工作表命名 。 Excel 工作表名最长 31 个字符,且不能包含
\ / ? * [ ] :等字符。上面的代码用file_name[:31]做了截断,如果实际文件名中包含特殊字符,建议再做一次替换处理。 -
删除默认工作表 。
Workbook()初始化时会自动创建 3 个空白工作表。上面的代码在导入完成后遍历删除名称为Sheet1/Sheet2/Sheet3的工作表,但要注意如果 CSV 文件名恰好也叫Sheet1.csv,会产生误删。更稳妥的做法是在创建目标工作簿后立即清空默认工作表:
python
target_book = Workbook()
while target_book.Worksheets.Count > 0:
target_book.Worksheets.RemoveAt(0)
这样 AddCopy 添加的工作表从第一个开始,逻辑更干净。但需要注意,如果删除所有工作表后直接 AddCopy,部分版本可能报错,此时可以先保留一个再替换。根据实际库版本调整即可。
- 非 UTF-8 编码的 CSV 。 如果 CSV 文件使用 GBK 等编码,
LoadFromFile可能无法正确解析中文。这种情况下可以先用 Python 的csv模块读取并转码为临时文件,再交给 Spire.XLS 加载,或者确认该库当前版本是否支持通过参数指定编码。
这个脚本适合轻量自动化场景,把零散 CSV 归集到一个 Excel 工作簿,每个文件单独一个 sheet。Free Spire.XLS for Python 的优势在于脱离 Office 环境运行,CSV 导入 API 封装简洁,不需要手动逐行读写单元格。