【Python】xlsxwriter的使用

第一章:xlsxwriter 入门与核心概念
1.1 xlsxwriter 概述

xlsxwriter 是一个 Python 模块,用于将文本、数字、公式以及格式化信息写入 Microsoft Excel 2007+ .xlsx 格式的文件。

主要特点:

  • 仅创建新文件:这是最重要的特性。它不能读取或修改现有的 Excel 文件。
  • 高性能:对于写入大量数据,xlsxwriter 通常比其他库有更好的性能,部分原因在于其流式写入和内存优化选项。
  • 丰富的功能集
    • 支持几乎所有的 Excel 单元格格式化选项。
    • 可以创建多种类型的图表。
    • 支持单元格合并、数据验证、条件格式、表格、筛选器等。
    • 可以写入超链接、注释、图片。
    • 支持 VBA 宏(通过嵌入现有包含宏的 vbaProject.bin 文件)。
    • 提供内存优化模式 (constant_memory),用于处理非常大的数据集。
  • 跨平台:与 Python 本身一样,可以在 Windows, macOS, Linux 等多种操作系统上运行。
  • 不依赖 Excel: 生成的 .xlsx 文件完全符合 Office Open XML (OOXML) 规范,不需要在服务器或运行环境中安装 Microsoft Excel。
  • 与 Pandas 集成: 可以作为 Pandas ExcelWriter 的引擎,方便地将 DataFrame 导出到 Excel。

openpyxl 的关键区别:

特性 xlsxwriter openpyxl
文件操作 仅创建新文件 (.xlsx) 创建、读取、修改现有文件 (.xlsx, .xlsm)
依赖性 无外部依赖 (除了Python标准库) 无外部依赖 (除了Python标准库)
性能 通常在写入新大文件时性能更优 读取和修改操作灵活,写入性能尚可
图表API 较底层,但功能全面 提供了较好的图表对象模型
VBA宏 可以嵌入 vbaProject.bin 可以读取和保存包含宏的文件 (.xlsm)
内存优化 提供 constant_memory 模式 也有只读/只写优化模式

选择哪个库取决于具体需求。如果你的任务是从头生成 Excel 文件,特别是需要高性能或特定高级格式化功能时,xlsxwriter 是一个绝佳的选择。如果需要读取或修改现有文件,则应选择 openpyxl

1.2 安装 xlsxwriter

安装 xlsxwriter 非常简单,使用 pip 即可:

pip install XlsxWriter

这条命令会从 Python Package Index (PyPI) 下载并安装最新版本的 xlsxwriter

1.3 基本工作流程

使用 xlsxwriter 创建 Excel 文件的基本步骤如下:

  1. 导入 xlsxwriter 模块。
  2. 创建一个新的 Workbook 对象:这是 Excel 文件在内存中的表示。在创建 Workbook 对象时,需要指定要输出的文件名。
  3. Workbook 中添加一个或多个 Worksheet 对象:每个工作表对应 Excel 文件中的一个 sheet。
  4. Worksheet 的单元格中写入数据:可以使用 worksheet.write() 方法或其特定类型的变体(如 write_string(), write_number(), write_formula() 等)。
  5. (可选)应用格式化:创建 Format 对象并将其应用于单元格或行/列。
  6. (可选)执行其他操作:如插入图表、图片、设置列宽、合并单元格等。
  7. 关闭 Workbook 对象:调用 workbook.close() 方法。这个步骤至关重要,它会将所有数据和格式写入到磁盘上的 .xlsx 文件中。如果不调用 close(),文件可能不会被正确创建或内容不完整。 推荐使用 with 语句来自动管理 Workbook 的关闭。
1.4 第一个 xlsxwriter 程序:Hello Excel

让我们创建一个简单的 Excel 文件,包含一些基本数据。

import xlsxwriter # 导入 xlsxwriter 模块

# 1. 创建一个新的 Excel 文件并添加一个工作表。
# 构造函数 Workbook() 接受文件名作为参数。
workbook = xlsxwriter.Workbook('hello_excel.xlsx') # 创建一个名为 'hello_excel.xlsx' 的 Workbook 对象

# add_worksheet() 方法添加一个新的工作表。
# 如果不指定名称,工作表将按默认名称命名,如 Sheet1, Sheet2 等。
worksheet = workbook.add_worksheet('问候') # 向工作簿中添加一个名为 '问候' 的工作表

# 2. 向单元格写入数据。
# write() 方法用于向单元格写入数据。
# 参数可以是:(row, col, item, cell_format=None) 或 (cell_name, item, cell_format=None)
# row 和 col 是从0开始的索引。

# 使用 A1 单元格引用方式写入字符串
worksheet.write('A1', '你好,世界!') # 在 A1 单元格写入字符串 '你好,世界!'

# 使用行号和列号 (row, col) 方式写入数字
worksheet.write(1, 0, 123.45) # 在第2行第1列 (即 A2 单元格,索引为 1,0) 写入数字 123.45

# 写入公式
worksheet.write(2, 0, '=SUM(A2, 10)') # 在 A3 单元格写入公式 '=SUM(A2, 10)'

# 写入日期 (需要使用 workbook.add_format() 来格式化日期)
import datetime # 导入 datetime 模块
date_format = workbook.add_format({
   'num_format': 'yyyy-mm-dd hh:mm:ss'}) # 创建一个日期格式对象
a_date = datetime.datetime(2023, 11, 15, 10, 30, 0) # 创建一个 datetime 对象
worksheet.write_datetime('A4', a_date, date_format) # 在 A4 单元格写入日期,并应用日期格式

# 3. 关闭 Workbook 对象。
# 这会将数据写入 Excel 文件并关闭它。
workbook.close() # 关闭工作簿,将内存中的数据写入到磁盘文件

print("文件 'hello_excel.xlsx' 已成功创建。") # 打印成功创建文件的消息

打开生成的 hello_excel.xlsx 文件,你会看到:

  • 一个名为 “问候” 的工作表。
  • A1 单元格包含文本 “你好,世界!”。
  • A2 单元格包含数字 123.45。
  • A3 单元格包含公式 =SUM(A2,10),并且其显示值为 133.45。
  • A4 单元格包含日期 “2023-11-15 10:30:00”。

使用 with 语句管理 Workbook (推荐)

为了确保 workbook.close() 总是被调用,即使在发生异常时也是如此,推荐使用 with 语句:

import xlsxwriter # 导入 xlsxwriter 模块
import datetime # 导入 datetime 模块

file_name_with_with = 'hello_with_statement.xlsx' # 定义文件名

with xlsxwriter.Workbook(file_name_with_with) as workbook: # 使用 with 语句创建 Workbook 对象,确保自动关闭
    worksheet = workbook.add_worksheet("示例Sheet") # 添加一个名为 "示例Sheet" 的工作表

    worksheet.write_string(0, 0, "使用with语句") # 在 A1 单元格写入字符串
    worksheet.write_number(1, 0, 999) # 在 A2 单元格写入数字
    worksheet.write_formula(2, 0, '=B2*2') # 在 A3 单元格写入公式
    
    date_fmt = workbook.add_format({
   'num_format': 'yyyy/mm/dd'}) # 创建日期格式
    worksheet.write_datetime(3, 0, datetime.date(2024, 1, 1), date_fmt) # 在 A4 单元格写入日期

print(f"文件 '{
     file_name_with_with}' 已通过 with 语句成功创建。") # 打印成功消息

with 语句块结束时,workbook 对象的 __exit__ 方法会被调用,该方法内部会执行 self.close()

第二章:写入不同数据类型到单元格

xlsxwriter 提供了多种 write_*() 方法来显式地处理不同类型的数据,这有助于确保数据在 Excel 中被正确解释和存储。虽然通用的 write() 方法通常能根据 Python 数据类型自动选择合适的 Excel 类型,但使用特定类型的方法可以提供更精细的控制。

2.1 write_string(row, col, string, cell_format=None)

用于写入字符串。

# ... (假设 workbook 和 worksheet 已创建) ...
# worksheet = workbook.add_worksheet()

worksheet.write_string(0, 0, "这是一个字符串") # 在 A1 写入字符串
worksheet.write_string('B1', "另一个字符串") # 在 B1 写入字符串

Excel 对单元格中的字符串长度有限制(通常是32767个字符)。如果字符串超过此限制,xlsxwriter 会截断它或引发异常,具体行为取决于版本和配置。

2.2 write_number(row, col, number, cell_format=None)

用于写入整数或浮点数。

# ... (worksheet 已创建) ...
worksheet.write_number(1, 0, 123) # 在 A2 写入整数 123
worksheet.write_number('B2', 3.14159) # 在 B2 写入浮点数 3.14159
worksheet.write_number(1, 2, -50.5) # 在 C2 写入负数 -50.5
2.3 write_blank(row, col, blank, cell_format=None)

用于写入一个空单元格。这与单元格中有一个空字符串 "" 不同。一个真正的空单元格通常用于格式化或作为公式的占位符。
参数 blank 通常是 None

# ... (worksheet 已创建) ...
# 创建一个带边框的格式,用于空单元格
blank_format = workbook.add_format({
   'border': 1}) # 创建一个带单线边框的格式
worksheet.write_blank(2, 0, None, blank_format) # 在 A3 写入一个空单元格,并应用边框格式
worksheet.write_string(2, 1, "", blank_format)  # 在 B3 写入一个空字符串,并应用边框格式 (注意区别)

在Excel中,A3单元格将是真正的空(但有边框),而B3单元格包含一个零长度的字符串。

2.4 write_formula(row, col, formula, cell_format=None, value=None)

用于写入 Excel 公式。

  • formula: 字符串形式的 Excel 公式,必须以 = 开头。
  • cell_format: 可选的单元格格式。
  • value: 可选参数,用于设置公式计算的初始结果。如果 Excel 文件被不支持公式计算的应用程序(如某些查看器)打开,这个值会被显示。如果省略,xlsxwriter 通常会将值设置为0。
# ... (worksheet 已创建) ...
worksheet.write_number('A5', 10) # 在 A5 写入数字 10
worksheet.write_number('B5', 20) # 在 B5 写入数字 20

# 写入简单公式
worksheet.write_formula('C5', '=A5+B5') # 在 C5 写入公式 '=A5+B5'

# 写入带结果的公式
worksheet.write_formula('D5', '=SUM(A5:B5)', None, 30) # 在 D5 写入公式 '=SUM(A5:B5)',并指定结果为30

# 写入引用其他工作表的公式
worksheet2 = workbook.add_worksheet('Sheet2') # 添加另一个工作表 Sheet2
worksheet2.write_number('A1', 100) # 在 Sheet2 的 A1 写入数字 100
# 假设当前 worksheet 是 'Sheet1'
worksheet.write_formula('E5', "=Sheet2!A1 * 2") # 在 Sheet1 的 E5 写入引用 Sheet2!A1 的公式

# 动态公式 (字符串函数等)
worksheet.write_formula('F5', '=LEFT(A1, 2)') # 在 F5 写入公式 '=LEFT(A1, 2)' (假设A1是 "这是一个字符串")

# 数组公式 (见后续高级部分)
# worksheet.write_array_formula('A6:A8', '{=TREND(C1:C3,B1:B3)}')

公式的语法和函数名必须是英文的,即使在非英文版的 Excel 中也是如此。Excel 会在打开文件时自动将它们本地化。

2.5 write_datetime(row, col, datetime_obj, cell_format=None)

用于写入 Python datetime.datetime, datetime.date, 或 datetime.time 对象。Excel 将日期和时间存储为序列号。xlsxwriter 会自动进行转换。为了正确显示日期/时间,通常需要提供一个包含数字格式的 cell_format

import datetime # 导入 datetime 模块
# ... (workbook 和 worksheet 已创建) ...

# 创建日期时间格式
date_fmt_full = workbook.add_format({
   'num_format': 'yyyy-mm-dd hh:mm:ss', 'align': 'left'}) # 创建完整日期时间格式
date_fmt_ymd = workbook.add_format({
   'num_format': 'yyyy"年"mm"月"dd"日"'}) # 创建年月日格式
time_fmt = workbook.add_format({
   'num_format': 'hh:mm AM/PM'}) # 创建时间格式

# 写入 datetime.datetime 对象
dt_obj = datetime.datetime(2023, 12, 25, 14, 30, 55) # 创建一个 datetime 对象
worksheet.write_datetime('A7', dt_obj, date_fmt_full) # 在 A7 写入完整的日期时间

# 写入 datetime.date 对象
d_obj = datetime.date(2024, 7, 1) # 创建一个 date 对象
worksheet.write_datetime('B7', d_obj, date_fmt_ymd) # 在 B7 写入日期 (年月日)

# 写入 datetime.time 对象 (Excel 中时间是日期的一部分,通常是序列号的小数部分)
# 单独的时间对象会被视为从1899-12-30 (或1904-01-01,取决于日期系统) 开始的小数
t_obj = datetime.time(18, 45, 0) # 创建一个 time 对象
worksheet.write_datetime('C7', t_obj, time_fmt) # 在 C7 写入时间
# 注意:如果单元格没有日期部分,Excel可能会显示一个奇怪的日期(如1900-01-00)。
# 如果只想显示时间,通常会将日期时间对象(如 datetime.datetime.now())写入,并仅用时间格式化。
# 或者,如果只关注时间部分,可以写一个包含时间的完整日期,然后只显示时间。
full_dt_for_time = datetime.datetime(2000, 1, 1, 18, 45, 0) # 创建一个包含日期的 datetime 对象
worksheet.write_datetime('D7', full_dt_for_time, time_fmt) # 在 D7 写入,仅显示时间部分

# 写入当前日期和时间
worksheet.write_datetime('E7', datetime.datetime.now(), date_fmt_full) # 在 E7 写入当前日期时间
2.6 write_boolean(row, col, boolean, cell_format=None)

用于写入布尔值 TrueFalse。Excel 会将它们显示为 TRUE 和 FALSE。

# ... (worksheet 已创建) ...
worksheet.write_boolean(7, 0, True)  # 在 A8 写入布尔值 TRUE
worksheet.write_boolean('B8', False) # 在 B8 写入布尔值 FALSE
2.7 write_url(row, col, url, cell_format=None, string=None, tip=None)

用于写入超链接。

  • url: 链接的目标地址 (例如 'http://www.python.org/''internal:Sheet2!A1''file:///path/to/file.txt')。
  • cell_format: 可选,应用到链接文本的格式。xlsxwriter 默认会应用标准的蓝色下划线超链接样式。你可以通过 workbook.get_default_url_format() 获取并修改这个默认格式,或者提供一个全新的格式。
  • string: 可选,链接显示的文本。如果省略,将显示 url 本身。
  • tip: 可选,鼠标悬停在链接上时显示的工具提示文本 (屏幕提示)。
# ... (worksheet 已创建) ...

# 获取并修改默认的URL格式 (例如,去掉下划线)
url_format = workbook.get_default_url_format() # 获取默认URL格式对象
url_format.set_underline(False) # 设置URL格式为无下划线
url_format.set_font_color('navy') # 设置URL字体颜色为海军蓝

# 写入外部URL,显示自定义文本和提示
worksheet.write_url('A9', 'https://www.djangoproject.com/', string='Django官网', tip='访问Django项目主页') # 在 A9 写入外部URL

# 写入内部工作表链接
worksheet.write_url('B9', "internal:Sheet2!B5", string="跳转到Sheet2的B5", cell_format=url_format) # 在 B9 写入内部链接,并应用自定义格式

# 写入文件链接
worksheet.write_url('C9', r'file:///C:\Users\Public\Documents\example.txt', string='打开示例文档') # 在 C9 写入文件链接 (注意路径格式)
                                                                                              # 对于本地文件,路径需要是绝对路径,并且格式正确

# 写入邮件链接
worksheet.write_url('D9', 'mailto:[email protected]?subject=Hello from XlsxWriter', string='发送邮件') # 在 D9 写入邮件链接

# 如果只想显示URL本身作为链接文本
worksheet.write_url('E9', 'https://xlsxwriter.readthedocs.io/') # 在 E9 写入URL,链接文本也是URL本身
2.8 通用 write(row, col, data, cell_format=None) 方法

write() 方法会尝试根据传入的 data 的 Python 类型来调用相应的 write_*() 方法。

  • str -> write_string()
  • int, float -> write_number()
  • bool -> write_boolean()
  • datetime.datetime, datetime.date, datetime.time -> write_datetime()
  • 如果 data 是以 = 开头的字符串,则调用 write_formula()
  • 如果 dataNone,则调用 write_blank() (除非有格式,否则可能不写入任何内容)。
# ... (worksheet 已创建) ...
worksheet.write(9, 0, "自动类型推断") # 在 A10 写入,自动识别为字符串
worksheet.write(9, 1, 789.01)         # 在 B10 写入,自动识别为数字
worksheet.write(9, 2, True)           # 在 C10 写入,自动识别为布尔值
worksheet.write(9, 3, datetime.date.today(), date_fmt_ymd) # 在 D10 写入,自动识别为日期,并应用格式
worksheet.write(9, 4, '=B10*2')       # 在 E10 写入,自动识别为公式
worksheet.write(9, 5, None)           # 在 F10 写入,识别为blank (如果没格式,单元格会是空的)

虽然 write() 很方便,但在某些情况下,显式使用 write_*() 方法可以提供更好的可读性和控制,特别是当数据类型可能不明确或需要特定处理时。

2.9 行和列的限制

Excel 工作表有最大行数和列数限制:

  • 最大行数: 1,048,576 (即 220)
  • 最大列数: 16,384 (即 214),对应列名 “XFD”

xlsxwriter 会遵守这些限制。尝试写入超出范围的单元格会导致错误。

第三章:单元格格式化 (Formatting)

格式化是 xlsxwriter 的核心强项之一。它允许你对单元格应用丰富的格式,包括字体、数字格式、对齐方式、颜色、边框等。

3.1 Format 对象

xlsxwriter 中,所有的单元格格式化都是通过 Format 对象来定义的。Format 对象由 Workbookadd_format() 方法创建。

# ... (workbook 已创建) ...

# 创建一个 Format 对象
bold_format = workbook.add_format() # 创建一个空的 Format 对象
bold_format.set_bold() # 调用 Format 对象的方法来设置属性,例如设置为粗体

# 或者在创建时通过字典传递属性
red_italic_format = workbook.add_format({
   'bold': False, 'italic': True, 'font_color': 'red'}) # 创建Format对象并初始化属性

# 将 Format 对象应用于单元格
# worksheet = workbook.add_worksheet()
worksheet.write('A1', '粗体文本', bold_format) # 在 A1 单元格写入文本 "粗体文本",并应用 bold_format 格式
worksheet.write('B1', '红色斜体', red_italic_format) # 在 B1 单元格写入文本 "红色斜体",并应用 red_italic_format 格式

add_format() 方法返回一个 Format 对象。你可以多次调用 Format 对象的方法来设置不同的格式属性。Format 对象在工作簿中是共享的,如果多个单元格使用完全相同的格式,它们会引用同一个 Format 对象,这有助于减小文件大小。

3.2 常见的格式属性

Format 对象支持大量的属性设置方法。以下是一些最常用的:

3.2.1 字体 (Font) 属性
  • set_font_name(font_name): 设置字体名称,如 ‘Arial’, ‘微软雅黑’, ‘Times New Roman’。
    font_name_format = workbook.add_format() # 创建格式对象
    font_name_format.set_font_name('微软雅黑') # 设置字体为微软雅黑
    worksheet.write('A2', '微软雅黑字体', font_name_format) # 应用格式
    
  • set_font_size(size): 设置字体大小 (磅)。
    font_size_format = workbook.add_format({
         'font_size': 16}) # 创建格式对象并设置字体大小为16
    worksheet.write('B2', '16号字', font_size_format) # 应用格式
    
  • set_font_color(color_string): 设置字体颜色。颜色可以是HTML样式的 '#RRGGBB' 字符串(如 '#FF0000' 代表红色),或者预定义的颜色名称(如 'red', 'green', 'blue', 'yellow', 'magenta', 'cyan', 'black', 'white', 'gray' 等)。
    font_color_format = workbook.add_format() # 创建格式对象
    font_color_format.set_font_color('blue') # 设置字体颜色为蓝色
    worksheet.write('C2', '蓝色字体', font_color_format) # 应用格式
    font_color_hex_format = workbook.add_format({
         'font_color': '#E066FF'}) # 紫色
    worksheet.write('D2', '自定义紫色字体', font_color_hex_format) # 应用格式
    
  • set_bold(): 设置为粗体。
  • set_italic(): 设置为斜体。
  • set_underline(style): 设置下划线。style 可以是:
    • 1True: 单下划线 (默认)
    • 2: 双下划线
    • 33: 单会计式下划线
    • 34: 双会计式下划线
    bold_italic_format = workbook.add_format({
         'bold': True, 'italic': True}) # 创建粗斜体格式
    worksheet.write('A3', '粗斜体', bold_italic_format) # 应用格式
    underline_format = workbook.add_format() # 创建格式对象
    underline_format.set_underline(2) # 设置双下划线
    worksheet.write('B3', '双下划线', underline_format) # 应用格式
    
  • set_font_strikeout(): 设置删除线。
  • set_font_script(style): 设置上标或下标。style 可以是:
    • 1: 上标
    • 2: 下标
    strike_format = workbook.add_format({
         'font_strikeout': True}) # 创建删除线格式
    worksheet.write('C3', '删除线', strike_format) # 应用格式
    
    superscript_format = workbook.add_format() # 创建格式对象
    superscript_format.set_font_script(1) # 设置为上标
    worksheet.write_rich_string('D3', 'E=mc', superscript_format, '2') # 写入 "E=mc²" (见富文本部分)
    
    su

你可能感兴趣的:(python,开发语言)