# 关于表格
- 键值对形式的数据,符合程序员的阅读习惯。但普通人,更习惯阅读表格形式的数据。
# 表格分类
在计算机中编辑表格时,普通人通常会使用 Microsoft 公司的 Excel 软件。这种软件保存的表格文件,扩展名通常为 .xlsx 。
- 优点:
- Excel 不止提供了编辑表格这一基础功能,还提供了绘制图表、公式运算等功能,满足用户的各种使用需求。
- 缺点:
- .xlsx 文件通常只能被 Excel 软件打开、编辑,而 Excel 是一款付费软件。因此,如果人们普遍使用 .xlsx 文件,就意味着每个人都要购买 Excel 软件的使用权。
- Python 安装 openpyxl 等专业的第三方库,才能解读 .xlsx 文件的内容。否则,直接用 open() 打开 .xlsx 文件,只能看到 bytes 格式的数据,不能解读。
- 优点:
除了 .xlsx 文件之外,还有一种常见的表格文件,扩展名为 .csv 。它采用 CSV(Comma Separated Values)格式。
- 优点:
- 格式简单。只需要在相邻字段之间,插入一个英文逗号,作为分隔符。
- 通用性强,可以被大部分软件打开、编辑。
- 例如 Python 可以直接用 open() 打开、编辑 .csv 文件。不过推荐使用 csv 标准库,更方便。
- 缺点:
- 只能实现编辑表格这一基础功能。
- 优点:
用 Excel 软件也可以打开 .csv 文件,还可以将 .xlsx 文件保存为 .csv 文件。
- 当 .csv 文件符合以下格式时,它在 Excel 软件中显示的内容,才会与 .xlsx 文件一致。
- 每行的相邻字段之间,插入一个英文逗号,作为分隔符。
- 每行文本的换行符为 '\r\n' 。
- 单个字段中,如果包含英文逗号、英文双引号,则要在每个双引号之前添加一个双引号进行转义,还要用一对双引号将这个字段包住,从而避免被识别为多个字段。
- 例:用 Excel 编辑 .xlsx 文件,写入如下三个单元格:用 Excel 将它保存为 .csv 文件,然后用 Python 读取该 .csv 文件,可见它内容如下:
AB A,B A"B
>>> with open('test.csv', newline='') as f: # 这里设置 newline='' 是为了避免自动替换换行符,从而保留原始的换行符 ... f.read() ... 'AB,"A,B","A""B"\r\n'
- 当 .csv 文件符合以下格式时,它在 Excel 软件中显示的内容,才会与 .xlsx 文件一致。
# import csv
:Python 的标准库,用于读写 csv 文件。
例:写入 .csv 表格
>>> import csv >>> with open('test.csv', 'w', newline='') as f: ... writer = csv.writer(f) # 针对文件对象 f ,创建一个 csv 写入器 ... writer.writerow('hello') # 写入表格的一行内容。该方法要求输入一个可迭代对象,将其中每个元素写作一个字段 ... writer.writerows('world') # 写入表格的多行内容。该方法要求输入一个可迭代对象,对其中每个元素执行一次 writerow() ... 11
- 检查写入 .csv 文件的内容:
>>> with open('test.csv') as f: ... f.read() ... 'h,e,l,l,o\nw\no\nr\nl\nd\n'
- 检查写入 .csv 文件的内容:
例:读取 .csv 表格:
>>> with open('test.csv', 'r') as f: ... reader = csv.reader(f) # 针对文件对象 f ,创建一个 csv 阅读器 ... headers = next(reader) # 读取表格的第一行内容 ... print(headers) ... for line in reader: # 每次迭代,获取表格的一行内容 ... print(line) ... ['h', 'e', 'l', 'l', 'o'] ['w'] ['o'] ['r'] ['l'] ['d']
- 除了文件对象,针对其它可迭代对象,也可以创建 csv 阅读器。
>>> data = ['a,b,c\n', '1,2,3'] >>> [i for i in csv.reader(data)] [['a', 'b', 'c'], ['1', '2', '3']]
- 除了文件对象,针对其它可迭代对象,也可以创建 csv 阅读器。
CSV 文本格式没有严格的标准,存在多种方言(或者说风格)。
- 常见的几种方言如下:
>>> csv.list_dialects() ['excel', 'excel-tab', 'unix']
- csv.reader() 和 csv.writer() 默认采用
dialect='excel'
,其定义如下:class excel(Dialect): delimiter = ',' # 相邻字段之间的分隔符 quotechar = '"' # 单个字段的定界符,避免单个字段被识别为多个字段 doublequote = True # 添加 quotechar 时,是否在当前字段的前后都加上 quotechar ,还是只在前面加上 quotechar skipinitialspace = False # 是否忽略 delimiter 之后的空格 lineterminator = '\r\n' # 换行符 quoting = QUOTE_MINIMAL # 何时添加 quotechar 。QUOTE_ALL 表示总是添加。QUOTE_MINIMAL 表示尽量不添加,除非字段包含特殊字符
- 改成
delimiter = '\t'
,就变成了dialect='excel-tab'
方言。 - 改成
lineterminator = '\n'
和quoting = QUOTE_ALL
,就变成了dialect='unix'
方言。
- 改成
- 例:自定义一种方言
>>> class myDialect(csv.excel): ... delimiter = '|' ... >>> csv.register_dialect('myDialect', myDialect) # 注册 dialect >>> with open('test.csv', 'w', newline='') as f: ... writer = csv.writer(f, dialect='myDialect') # 采用 dialect ... writer.writerow('hello') ...
- 常见的几种方言如下:
# import openpyxl
:Python 的第三方库,用于读写 Excel 2010 软件生成的表格文件,扩展名通常为 .xlsx 或 .xlsm 。
- 官方文档 (opens new window)
- 安装:
pip install openpyxl
# Workbook
在 Excel 软件中,一个 .xlsx 文件,负责存储一个工作簿(Workbook)。
- 一个 Workbook 包含任意个工作表(Worksheet)。
- 每个 Worksheet 包含任意个单元格(cell)。这些单元格呈矩形排列,分为多行(row)、多列(column)。
例:创建表格
>>> from openpyxl import Workbook >>> wb = Workbook() # 创建一个 Workbook 对象 >>> wb.sheetnames # 列出所有 Worksheet 的名称。新创建的 Workbook 只包含一个 Worksheet ['Sheet'] >>> ws = wb.create_sheet('Sheet1', 0) # 插入一个新的 Worksheet ,放在位置 0 处。如果不指定位置,则默认放在最后 >>> ws.title = 'Sheet1' # 修改 Worksheet 的名称 >>> wb.save('1.xlsx') # 将 Workbook 保存为一个 .xlsx 文件
例:打开表格
>>> from openpyxl import load_workbook >>> wb = load_workbook('1.xlsx') >>> wb.sheetnames ['Sheet1', 'Sheet'] >>> ws = wb['Sheet1'] # 选择一个 Worksheet >>> ws <Worksheet "Sheet1">
- 如果以只读模式打开 .xlsx 文件,则可以大幅减少内存开销:
>>> wb = load_workbook('1.xlsx', read_only=True) >>> wb.close() # 只读模式下,需要手动关闭对文件描述符的占用
- 或者通过 open() 打开文件,载入内存:
import io with open('1.xlsx', 'rb') as f: in_mem_file = io.BytesIO(f.read()) wb = load_workbook(in_mem_file, read_only=True)
- 如果以只读模式打开 .xlsx 文件,则可以大幅减少内存开销:
例:修改表格
>>> ws.max_row # 查询 Worksheet 的最大行数 1 >>> ws.max_column # 查询 Worksheet 的最大列数 1 >>> ws.column_dimensions['A'].width = 20.0 # 设置列宽 >>> ws.row_dimensions[1].height = 20.0 # 设置行高
# Cell
例:插入一行单元格
>>> ws.append([1, 2, 3]) # 在 Worksheet 末尾追加一行。要求输入一个可迭代对象,将其中每个元素保存为该行的一个单元格 >>> ws.append([4, 5, 6]) >>> ws.append([7, 8, 9])
例:遍历单元格
>>> for row in ws: # 遍历 Worksheet 的每行,每行由多个 cell 组成 ... print(row) ... (<Cell 'Sheet1'.A1>, <Cell 'Sheet1'.B1>, <Cell 'Sheet1'.C1>) (<Cell 'Sheet1'.A2>, <Cell 'Sheet1'.B2>, <Cell 'Sheet1'.C2>) (<Cell 'Sheet1'.A3>, <Cell 'Sheet1'.B3>, <Cell 'Sheet1'.C3>)
例:获取指定位置的单元格
>>> ws.cell(row=1, column=1) # 通过行号、列号,获取一个 cell 。两种编号都是从 1 开始递增 <Cell 'Sheet1'.A1> >>> ws['A1'] # 通过索引,获取第 A 列、第 1 行的那个 cell <Cell 'Sheet1'.A1> >>> ws['A'] # 获取第 A 列,所有不为空的 cell (<Cell 'Sheet1'.A1>, <Cell 'Sheet1'.A2>, <Cell 'Sheet1'.A3>) >>> ws['1'] # 获取第 1 行,所有不为空的 cell (<Cell 'Sheet1'.A1>, <Cell 'Sheet1'.B1>, <Cell 'Sheet1'.C1>) >>> ws['A1':'B2'] # 通过切片,获取矩形范围内的一组 cell ((<Cell 'Sheet1'.A1>, <Cell 'Sheet1'.B1>), (<Cell 'Sheet1'.A2>, <Cell 'Sheet1'.B2>))
例:对单元格进行赋值
>>> ws['A1'] = 'hello' # 对 cell 赋值 >>> ws['A1'].value # 读取 cell 的值 'hello' >>> ws['A10'].value # 可以读取任意 cell 的值,如果取值为空,则返回 None >>> ws['C4'] = '=SUM(A1:C3)' # 给 cell 赋值时,可以输入 Excel 的公式
关于坐标:
>>> ws['A1'].coordinate # 完整坐标 'A1' >>> ws['A1'].row # 行坐标 1 >>> ws['A1'].column # 列坐标,用数字表示 1 >>> ws['A1'].column_letter # 列坐标,用字母表示 'A'
>>> from openpyxl.utils import get_column_letter, column_index_from_string >>> get_column_letter(2) # 将列坐标,从数字转换成字母 'B' >>> column_index_from_string('AA') # 将列坐标,从字母转换成数字 27
关于字体:
>>> cell.font.name # 查看当前字体 'Calibri' >>> cell.font.sz 2.0
from openpyxl.styles import Font font1 = Font(name='Calibri', # 字体 size=2.0, # 字号 bold=False, # 加粗 italic=False, # 斜体 underline='None', # 下划线 color='FF000000' # 字体颜色 ...) cell.Font = font1 # 设置字体