>>> from env_helper import info; info()
页面更新时间: 2023-04-15 21:51:22
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-7-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

1.3. Python写入电子表格

我们可以使用openpyxl模块的 Workbook 函数来写入电子表格。

1.3.1. 创建工作簿与工作表

先来看一下如何实例化一个电子表格对象。

>>> from openpyxl import Workbook
>>> wb = Workbook()

这样就新建了一个新的工作表,这个工作薄可以保存以便其他程序使用。

若要指定只写模式,可以指定参数 write_only=True 。 在“只写”的情况下,可以访问工作簿与工作表, 但是没法访问单元格的信息。

一般打开电子表格时使用默认的可写可读模式就可以了。 在 OpenpyXL 可写可读模式下新建一个工作簿,会默认创建名为 Sheet 的表。 Excel 2016软件下新建的表默认名称为 Sheet1

sheetnames 属性可以查看电子表格中工作表名称的列表。旧版本中通过 get_sheet_names() 方法访问。

>>> wb.sheetnames
['Sheet']

工作表的名称可以修改,直接赋值就可以改工作表的名称:

>>> sheet = wb.active
>>> sheet.title = 'Sheet1'

新建一个工作表,可以指定索引,适当安排其在工作簿中的位置。 被安排到第二个工作表,index=0 就是第一个位置

>>> wb.create_sheet('Data', index=0)
>>> wb.create_sheet('Data2', index=1)
<Worksheet "Data2">

除了使用索引,也可以获取表格的名字。

或使用属性 sheetnames

>>> wb.sheetnames
['Data', 'Data2', 'Sheet1']

1.3.2. 删除工作表的方法

删除某个工作表,使用工作簿的方法 remove() ,或者直接使用 del 指令 del sheet

>>> wb.remove(sheet)

为了避免程序运行时出错,可以在删除工作表之前判断一下工作簿中是否有这个工作表:

>>> if sheet.title in wb.sheetnames:
>>>     wb.remove(sheet)

1.3.3. 写入单元格

要在电子表格中写入值,直接针对单元格进行写入操作即可。 对行或列的写入,都可以通过循环完成。

要写入单元格,直接给单元格赋值就行:

>>> sheet['A1'] = 'good'

还可以使用公式。B9 处写入平均值:

>>> sheet['B2'] = '=AVERAGE(B2:B8)'

但是如果是读取的时候需要加上 data_only=True 这样读到 B9 返回的就是数字,如果不加这个参数,返回的将是公式本身’=AVERAGE(B2:B8)

通过对单元格的操作,可以实现新增数据,也可以实现更改数据。

1.3.4. 使用 append() 函数写入数据

要批量写入数据,可以使用遍历功能逐单元格写入。 另外, OpenpyXL 还提供了 append() 函数将列表写入到一行中。 根据函数名称,这个函数只能用来写入新的数据,不能实现更新数据的功能; 写入的数据,会自动判断空白行,然后在空白行中添加数据。

灵活使用逐入写入的功能,也可以实现按列写入的功能。

按行写入数据

可以一次添加多行数据,从现有表格最下面第一行空白行开始(下面都是空白行)写入。

>>> sheet['B2'] = None

添加一行

>>> row = [1 ,2, 3, 4, 5]
>>> sheet.append(row)

现在将表格中数据打开出来查看:

>>> for row in sheet.rows:
>>>     for cell in row:
>>>         if cell.value:
>>>             pass
>>>         else:
>>>             cell.value = ''
>>>         print( f'{cell.coordinate:3}:({cell.value:<4})', end=', ')
>>>     print()
A1 :(good), B1 :(    ), C1 :(    ), D1 :(    ), E1 :(    ),
A2 :(    ), B2 :(    ), C2 :(    ), D2 :(    ), E2 :(    ),
A3 :(1   ), B3 :(2   ), C3 :(3   ), D3 :(4   ), E3 :(5   ),

可以看到在最下面添加了一行数据。

要添加二维列表与之类似,通过遍历的功能实现:

>>> rows = [
>>>  ['Num', 'd1', 'd2'],
>>>  [2, 40, 30],
>>>  [3, 40, 25],
>>> ]
>>> for row in rows:
>>>     sheet.append(row)
>>> for row in sheet.rows:
>>>     for cell in row:
>>>         if cell.value:
>>>             pass
>>>         else:
>>>             cell.value = ''
>>>         print( f'{cell.coordinate:3}:({cell.value:<4})' , end=', ')
>>>     print()
A1 :(good), B1 :(    ), C1 :(    ), D1 :(    ), E1 :(    ),
A2 :(    ), B2 :(    ), C2 :(    ), D2 :(    ), E2 :(    ),
A3 :(1   ), B3 :(2   ), C3 :(3   ), D3 :(4   ), E3 :(5   ),
A4 :(Num ), B4 :(d1  ), C4 :(d2  ), D4 :(    ), E4 :(    ),
A5 :(2   ), B5 :(40  ), C5 :(30  ), D5 :(    ), E5 :(    ),
A6 :(3   ), B6 :(40  ), C6 :(25  ), D6 :(    ), E6 :(    ),

按列写入数据

由于 append 函数只能按行写入。如果我们想按列写入呢。append 能实现需求么? 如果把上面的列表嵌套看作矩阵。 只要将矩阵转置就可以了。 使用 zip() 函数可以实现,不过内部的列表变成了元组就是了。都是可迭代对象,不影响结果。

>>> list(zip(*rows))
[('Num', 2, 3), ('d1', 40, 40), ('d2', 30, 25)]

解释下上面的list(zip(*rows))首先*rows将列表打散, 相当于填入了若干个参数,zip从某个列表中提取第1个值组合成一个tuple, 再从每个列表中提取第2个值组合成一个tuple,一直到最短列表的最后一个值提取完毕后结束, 更长列表的之后的值被舍弃,换句话,最后的元组个数是由原来每个参数(可迭代对象)的最短长度决定的。 比如现在随便删掉一个值,最短列表长度为2,data2那一列(竖着看)的值全部被舍弃。

>>> rows = [
>>>  ['Number', 'data1', 'data2'],
>>>  [2, 40, 33],
>>>  [3, 40, 25],
>>> ]
>>> wb.create_sheet('Data3', index=0)
<Worksheet "Data3">
>>> sheet = wb['Data3']
>>> for row in zip(*rows):
>>>     sheet.append(row)
>>> for row in sheet.rows:
>>>     for cell in row:
>>>         if cell.value:
>>>             pass
>>>         else:
>>>             cell.value = ''
>>>         print( f'{cell.coordinate:3}:({cell.value:<6})' , end=', ')
>>>     print()
A1 :(Number), B1 :(2     ), C1 :(3     ),
A2 :(data1 ), B2 :(40    ), C2 :(40    ),
A3 :(data2 ), B3 :(33    ), C3 :(25    ),

最后zip 返回的是 zip 对象,看不到数据的。使用list转换下就好了。使用 zip 可以方便实现将数据按列写入。

1.3.5. 保存文件

所有的操作结束后,通过 save() 方法保存文件。这个函数的参数为要保存的文件路径或 PosixPath 对象 ,后缀名为 xlsx

>>> wb.save('xx_example.xlsx')