python:openpyxl基础操作(一):创建.xlsx文件

目录

前言:

安装openpyxl:

创建.xlsx文件:

添加单元格内容

单个添加:

多个添加:

增删单元格:

 遍历表格中的值:

合并拆分单元格:


前言:

本文仅供个人学习记录+复习所用,探索过程中难免出现差错和纰漏,如文中有错误,以及可以改进的地方,还请各位不吝赐教。

安装openpyxl:

安装openpyxl的时候,我遇到了各种各样的错误,首先在pycharm内部解释器中进行安装,显示安装失败。

搜索后发现,是由于自己的pip没有达到最新版本,在cmd中更新了pip,并直接pip install openpyxl

结果依然出了错,无法安装。

(由于目前已经安装完毕,没有保存当时出错的流程图,但我自己总结了下原因,如果有相同情况的小伙伴可以尝试下)

1. 更新pip:我在pycharm中遇到过“有新版本,但无法刷新出新版本,无法更新的情况”

曾使用cmd对pip进行更新,但由于我的pycharm和其项目均在D盘,而我更新的操作是在C:/user里进行的,可能导致“更新”没有发生在d盘中。

(这一点的确是我没想到的,不过也暴露了我非科班、对计算机了解太浅显的短板。)

解决这一问题,是我在pycharm里再次尝试安装openpyxl的时候,根据pycharm给的提示,在cmd中D盘的某一地址下进行操作。

这次更新成功了。

2. 更新完pip就可以直接在解释器内安装openpyxl了。

大部分情况下,pycharm里会在打开解释器的时候显示可以更新的包,直接更新即可。

创建.xlsx文件:

首先引入包:

from openpyxl import Workbook
from openpyxl import load_workbook

使用Workbook创建excel表格。注意首字母需要大写。如果忽略,会报错。

创建表格后需要进行保存,接下来的内容会介绍具体操作,但要注意,创建、修改后都不要忘记保存,否则修改后的内容只会出现在pycharm里,而不是表格中。

使用load_workbook加载已经创建好的表格。

wb = Workbook()  # pay attention to the first letter
'''创建一个表格,注意,wb并非是保存文件的名字,而是变量。
此时wb是一个文件,里面什么都没有,没有sheet表单'''
sheet = wb.active
'''此时我们在文件wb中创建了一个sheet'''

 创建单个表单的时候可以直接使用wb.active,这种情况适用于在空文件中创建第一个sheet。

提问:是否可以多次调用active?

答:可以多次调用,但只能生成第一个调用active的表单,其余调用结果不予显示。

提问:那么如何创建多个表单?

答:

sheet_1 = wb.create_sheet('sheet_1')
sheet_2 = wb.create_sheet('sheet_2')

括号内传入的参数是表单的名称,生成的表单是空表单。

保存:

wb.save('theFstSample.xlsx')

这一步骤可以放在所有语句结尾。传入的参数是excel文件的文件名,注意不要忘记其扩展名。

保存的位置和所编写的py文件的位置一样。

添加单元格内容

单个添加:

sheet_2['A1'] = 56
sheet_2['A2'] = 78
sheet_2['A3'] = 90

注意添加的表单,是sheet_2:

 当打开表格查看输出结果的时候,一定要关闭文档,否则再次修改时会出现:

Traceback (most recent call last):
   File "D:\pythonProject\ExcelImport.py", line 31, in <module>
     wb.save('theFstSample.xlsx')
   File "D:\pythonProject\venv\lib\site-packages\openpyxl\workbook\workbook.py", line 386, in save
     save_workbook(self, filename)
   File "D:\pythonProject\venv\lib\site-packages\openpyxl\writer\excel.py", line 291, in save_workbook
     archive = ZipFile(filename, 'w', ZIP_DEFLATED, allowZip64=True)
   File "C:\Users\Suen\AppData\Local\Programs\Python\Python310\lib\zipfile.py", line 1240, in __init__
     self.fp = io.open(file, filemode)
PermissionError: [Errno 13] Permission denied: 'theFstSample.xlsx'

遇到这样的情况,只需要关闭excel文档,重新运行程序即可。

多个添加:

问题:单个添加挺慢啊,有快一些的方法吗?

答:有的。

rows = (
    (998, 997, 996),
    (787, 988, 876),
    (233, 445, 786)
)

for row in rows:
    sheet.append(row)

使用append()可以完成填充表格。(万金油append)

增删单元格:

两个函数的调用:

sheet.insert_rows(idx=2, amount=4)  # we insert blank cells.
print(sheet.max_row, sheet.max_column)
# 7 3  测试是否插入,如果不想测试,可以直接打开文件
sheet.insert_cols(idx=2, amount=4)
print(sheet.max_row, sheet.max_column)
# 7 7
sheet.delete_rows(idx=2)  

 

 注意:如果是在空白格的地方添加单元格,比如在A7下面或G1右面添加,表格不会发生改变。

 遍历表格中的值:

在遍历之前,有一个问题需要解决:

如何输出某一个单元格(cell)的值呢?

答:直接打印输出的是cell对象,需要在后面调用下value

print(sheet['A1'])
# <Cell 'Sheet'.A1>  单元格对象
sheet_1['A3'] = 10
print(sheet_1['A3'].value, sheet_1['A2'].value)
# 10 None

如果单元格内没有值,则会返回None。(这个和pandas里面不一样,pandas如果没有值会返回NaN)

迭代:

for col_ in sheet.columns:
    print(col_, ", ")
# u cannot output the value of per cell based on method above.
'''
(<Cell 'Sheet'.A1>, <Cell 'Sheet'.A2>, <Cell 'Sheet'.A3>, <Cell 'Sheet'.A4>, <Cell 'Sheet'.A5>, <Cell 'Sheet'.A6>) , 
(<Cell 'Sheet'.B1>, <Cell 'Sheet'.B2>, <Cell 'Sheet'.B3>, <Cell 'Sheet'.B4>, <Cell 'Sheet'.B5>, <Cell 'Sheet'.B6>) , 
(<Cell 'Sheet'.C1>, <Cell 'Sheet'.C2>, <Cell 'Sheet'.C3>, <Cell 'Sheet'.C4>, <Cell 'Sheet'.C5>, <Cell 'Sheet'.C6>) , 
(<Cell 'Sheet'.D1>, <Cell 'Sheet'.D2>, <Cell 'Sheet'.D3>, <Cell 'Sheet'.D4>, <Cell 'Sheet'.D5>, <Cell 'Sheet'.D6>) , 
(<Cell 'Sheet'.E1>, <Cell 'Sheet'.E2>, <Cell 'Sheet'.E3>, <Cell 'Sheet'.E4>, <Cell 'Sheet'.E5>, <Cell 'Sheet'.E6>) , 
(<Cell 'Sheet'.F1>, <Cell 'Sheet'.F2>, <Cell 'Sheet'.F3>, <Cell 'Sheet'.F4>, <Cell 'Sheet'.F5>, <Cell 'Sheet'.F6>) , 
'''

iter_col = sheet.iter_cols(min_col=1, min_row=1, max_col=6, max_row=6, values_only=True)
for col_ in iter_col:
    print(col_, ', ')
'''
(998, None, None, None, 787, 233) , 
(None, None, None, None, None, None) , 
(None, None, None, None, None, None) , 
(None, None, None, None, None, None) , 
(997, None, None, None, 988, 445) , 
(996, None, None, None, 876, 786) , 
'''

for i in sheet.values:
    print(i, ', ')
'''
(998, None, None, None, 787, 233) , 
(None, None, None, None, None, None) , 
(None, None, None, None, None, None) , 
(None, None, None, None, None, None) , 
(997, None, None, None, 988, 445) , 
(996, None, None, None, 876, 786) , 
'''

以上是三种不同的迭代方式。但注意他们的区别。为什么第一个迭代出来的是对象,而不是单元格内的值。

于是我又产生了一个问题,在迭代的过程中,我可以设置迭代的范围(注意函数内部的参数)。是否可以将参数的范围设定在一个单元格内部,并输出值?

i = sheet.iter_cols(min_col=1, min_row=1, max_col=1, max_row=1, values_only=True)
print(i)
'''
<generator object Worksheet._cells_by_col at 0x000001DDFEC9AF80>
'''
print(type(i))
'''<class 'generator'>'''

然而并不行。 

合并拆分单元格:

sheet.merge_cells('A1:B2')

sheet.merge_cells(start_row=3, start_column=1, end_column=2, end_row=4)

sheet.unmerge_cells("A1:B2")

sheet.unmerge_cells(start_row=3, start_column=1, end_column=2, end_row=4)

在这段处理中,我直接合并后又拆分了,在尝试的过程中,可以通过打开文件来确认单元格是否被合并/拆分。

检查完之后不要忘记关闭文件窗口哦。

另外,合并的函数时:merge_cells();pycharm里会有提示,需要选择后面带有参数项的merge而不是merged,否则会报错。