官方文档:https://openpyxl.readthedocs.io/en/stable/ 拓展资料:https://mp.weixin.qq.com/s/Q9EmcBB-r-2b2AW0Qx1Hcw

xlrd和xlwt两者的主要区别在于写入操作,其中xlwt针对Ecxec2007之前的版本,即.xls文件,其要求单个sheet不超过65535行,而openpyxl则主要针对Excel2007之后的版本(.xlsx),它对文件大小没有限制。另外还有区别就是二者在读写速度上的差异,xlrd/xlwt在读写方面的速度都要优于openpyxl,但因为xlwt无法生成xlsx是个硬伤,所以想要尽量提高效率又不影响结果时,可以考虑用xlrd读取,用openpyxl写入。

Excel文件三个对象: workbook: 工作簿,一个excel文件包含多个sheet。 sheet:工作表,一个workbook有多个,表名识别,如“sheet1”,“sheet2”等。 cell: 单元格,存储数据对象 row:行 column:列

openpyxl

简化版

  1. import datetime
  2. from openpyxl import Workbook
  3. wb = Workbook() # 实例化之后后面才可以调用wb
  4. # 抓取活跃工作表!
  5. ws = wb.active
  6. # 修改工作表!
  7. ws.title = '2022' # 修改活跃工作表sheet名
  8. ws['A1'] = 42
  9. ws.append([1, 2, 3])
  10. ws['B5'] = datetime.datetime.now()
  11. # 保存工作表!
  12. wb.save('sample.xlsx') # 这个操作将覆盖已存在的文件,没有任何提示!

完整版

  1. import datetime
  2. from openpyxl import Workbook, load_workbook, worksheet
  3. wb = Workbook() # 实例化
  4. # 1.新建工作表(二选一) ——————————————————————
  5. wb.create_sheet('2023') # 在后面插入一个新的工作表
  6. wb.create_sheet('2021', 0) # 在前面插入一个新的工作表
  7. ws = wb.active
  8. # 1.打开本地已存在的工作表(二选一) ——————————————————————
  9. # wb = load_workbook('openpyxl_note.xlsx') # py和Excel在一个文件夹下给文件名即可
  10. # wb = load_workbook('D:\\OneDrive\\Python\\Tomato\\openpyxl_note.xlsx') # 地址是双斜线\\
  11. # 2.打印工作表名称(可选) —————————————————————
  12. print(wb.sheetnames) # 打印出表单名结果是字典,结果是 ['2021', 'Sheet', '2023']
  13. for sheet in wb:
  14. print(sheet.title) # 遍历后打印出表单名,结果是列表形式展现(竖向)
  15. # 3.根据打印的列表定位(选择要操作的)工作表 ——————————————————————
  16. # 如果不定位工作表,会以激活(打开后显示的)的工作表写入
  17. ws = wb.active # 激活活跃工作表,打开文档后显示的
  18. ws['A5'] = 2099 # 赋值
  19. # 修改列表名
  20. ws0 = wb["Sheet"] # 找到Sheet列表
  21. ws0.title = '2022' # 修改Sheet列表名称
  22. # 插入当前时间
  23. ws1 = wb["2021"] # 通过列表名来定位
  24. ws1['A1'] = datetime.datetime.now() # 写入当前时间
  25. ws1.append([1, 2, 3, 4, 5, 6, 7, 8, 9])
  26. # 这种方式不能用了
  27. # ws2 = wb.get_sheet_by_name('2021') # 这种调用方式已过时,不能用了
  28. # ws2['A1'] = '1024'
  29. # 赋值
  30. ws3 = wb.worksheets[1] # 通过序号来定位
  31. ws3['B1'] = '我是第二个工作表' # 赋值
  32. # 在下方空白区域添加一行,数据从左到右依次填入
  33. ws4 = wb.worksheets[1] # 通过序号来定位
  34. ws4.append([1, 3, 5, 7])
  35. ws4.append([2, 4, 6, 8])
  36. ws4.append([0.2, 0.8, 0.3, 0.7])
  37. # 4.定位(选择要操作的)单元格 ——————————————————————
  38. print('【遍历,A列】')
  39. for cell in ws4["A"]:
  40. print(cell.value)
  41. print('【遍历,第一行】')
  42. for cell in ws4["1"]:
  43. print(cell.value)
  44. print('【遍历,多列】')
  45. for cell in ws4["A1:A3"]: # 使用切片获取,得到一个列表
  46. print(cell[0].value) # 打印单元格的值,这里打印的是元组,所以要先获取元组再取值(竖向)
  47. print('【遍历,多行】')
  48. for row in ws4['1:3']:
  49. for cell in row:
  50. print(cell.value) # 结果一行一行,一个一个展示
  51. # ______________________________________________
  52. print('【遍历,所有行】')
  53. for row in ws4.rows: # 循环获取ws4表下的行数据
  54. for cell in row: # 循环获取单元格数据
  55. print(cell.value, end=',') # 取值到空为止(横向),如果数据少于10行,默认取10行,按照表格里的位置打印出来
  56. print()
  57. print('【遍历,所有列】') # A1 A2 A3这样的顺序(返回的列都是元组,所以需要取两次)
  58. for column in ws4.columns: # 循环获取ws4表下的列数据
  59. for cell in column: # 循环获取单元格数据
  60. print(cell.value, end=',') # 取值到空为止(纵向),如果数据少于10行,默认取10行
  61. print()
  62. # ______________________________________________
  63. print('【指定行,从第3行到第5行】') # 返回的列都是元组,所以需要取两次
  64. for row in ws4.iter_rows(min_row=3, max_row=5):
  65. for cell in row:
  66. print(cell.value, end=',') # 按照表格里的位置打印出来
  67. print()
  68. print('【指定列,从第3列到第4列】')
  69. for column in ws4.iter_cols(min_col=3, max_col=4):
  70. for i in column:
  71. print(i.value, end=',') # 如果数据少于10行,默认取10行
  72. print()
  73. print('【指定列与列,从第3行到第5行,从第2列到第4列】')
  74. for row in ws4.iter_rows(min_row=3, max_row=5, min_col=2, max_col=4):
  75. for cell in row:
  76. print(cell.value, end=',') # 按照表格里的位置打印出来
  77. print()
  78. # 5.保存 ——————————————————————
  79. wb.save('openpyxl_note.xlsx') # 注意!!!这个操作将覆盖已存在的文件,没有任何提示!

内容去重

从Excel表中可以看到有两条重复记录
openpyxl 表格读写 - 图1

  1. import pandas as pd
  2. from openpyxl import Workbook, load_workbook, worksheet # 表格处理
  3. wb = Workbook() # 实例化
  4. # 读取Excel中Sheet1中的数据
  5. data = pd.DataFrame(pd.read_excel(
  6. 'D:\\OneDrive\\Python\\Tomato\\delete_cols.xlsx', 'Sheet1'))
  7. # 查看读取数据内容
  8. # print(data) # 可以不打印出来,打印出来是写代码时候要看数据准确性,下面同理
  9. # 查看是否有重复行,Ture表示有重复(删除的数据),False为没有(也是最终保留的数据)
  10. re_row = data.duplicated()
  11. # print(re_row)
  12. # 查看去除重复行的数据,存储要去除的数据(上面为Ture的数据)
  13. no_re_row = data.drop_duplicates()
  14. # print(no_re_row)
  15. # 查看基于[物品]列去除重复行的数据
  16. wp = data.drop_duplicates(['物品'])
  17. print(wp) # 打印去重后表格的内容
  18. # 将去除重复行后的数据输出到excel表中
  19. no_re_row.to_excel(
  20. 'D:\\OneDrive\\Python\\Tomato\\delete_cols.xlsx', 'Sheet1')
  21. # 因为去重时候多加了一列序号,我们把它删除并保存 _______________
  22. wb = load_workbook('D:\\OneDrive\\Python\\Tomato\\Tomato.xlsx') # 打开表格
  23. worksheet = wb.worksheets[0] # 找到第一个工作表
  24. worksheet.delete_cols(1) # 删除表格的第一列,这里的值是从1开始而不是0,行是rows,列是cols
  25. wb.save('D:\\OneDrive\\Python\\Tomato\\Tomato.xlsx') # 保存后样式会重置

输出结果
openpyxl 表格读写 - 图2

表格 - 样式修改

官方文档:https://openpyxl.readthedocs.io/en/stable/styles.html

一共有六种属性:

  • font(字体类):字号、字体颜色、下划线等
  • fill(填充类):颜色等
  • border(边框类):设置单元格边框
  • alignment(位置类):对齐方式
  • number_format(格式类):数据格式
  • protection(保护类):写保护

font(字体类)

  1. # 单格 字体 修改 ______________________________________
  2. from openpyxl.styles import Font # 导入包
  3. font = Font(u'宋体',size = 11,bold=True,italic=True,strike=True,color='000000') #定义样式
  4. ws['A1'].font = font # 应用样式
  5. # 指定列 修改 ______________________________________
  6. font = Font(color="b74022", bold=True)
  7. for x in ws['A':'B']: # 遍历A列到B列所有数据,注意列是字母(字符串),所以带引号
  8. # 也可以是 ['A1':'D5'],这样遍历的就是区间范围,而不是单独的行和列
  9. for cell in x:
  10. cell.font = font
  11. # 指定行 修改 ______________________________________
  12. font = Font(color="217346", bold=True)
  13. for y in ws[1:2]: # 遍历第1行到第2行的所有数据
  14. for cell in y:
  15. cell.font = font

size=11, 字体 color=’FF0000’ 色值不需要带# color=colors.WHITE, 字体颜色必须大写 bold=True, 加粗 italic=True, 斜体 strike=True,删除线 vertAlign=None, 垂直对齐 underline=’none’, #下划线

fill(填充类)

  1. # 单格 背景 修改 ______________________________________
  2. from openpyxl.styles import PatternFill # 导入包
  3. fill = PatternFill("solid", "b7472a")
  4. ws['B1'].fill = fill # 应用样式
  5. #多行多列的用法和font一样,只是把font改为fill

注意,官方文档中写明,fill_type若没有特别指定类型,则后续的参数都无效

border(边框类)

  1. from openpyxl.styles import Border,Side # 注意隔离是导入两个包
  2. border = Border(left=Side(border_style='thin',color='000000'), #定义四个方向的边框样式
  3. right=Side(border_style='thin',color='000000'),
  4. top=Side(border_style='thin',color='000000'),
  5. bottom=Side(border_style='thin',color='000000'))
  6. ws['C1'].border = border #应用样式

alignment(位置类)

  1. from openpyxl.styles import Alignment # 导入包
  2. align = Alignment(horizontal='left',vertical='center',wrap_text=True) # 定义样式
  3. ws['D1'].alignment = align # 应用样式

horizontal 水平对齐可以左对齐left,还有居中center和右对齐right,分散对齐distributed,跨列居中centerContinuous,两端对齐justify,填充fill,常规general

vertical 垂直对齐可以居中center,还可以靠上top,靠下bottom,两端对齐justify,分散对齐distributed

wrap_text 自动换行,这是个布尔类型的参数,这个参数还可以写作wrapText

indent=0 缩进。

number_format(格式类)

数据格式属性number_format的值是字符串类型,不为对象,直接赋值即可。
openpyxl内置了一些数据格式查看 openpyxl.styles.numbers,也支持excel自定义格式,以下两种方式效果相同:

  1. # 使用openpyxl内置的格式
  2. from openpyxl.styles import numbers
  3. ws.cell['D2'].number_format = numbers.FORMAT_GENERAL
  4. ws.cell(row=2, column=4).number_format = numbers.FORMAT_DATE_XLSX15
  5. # 直接使用字符串修改D2
  6. ws.cell['D2'].number_format = 'General'
  7. ws.cell(row=2, column=4).number_format = 'd-mmm-yy'

protection(保护类)

  1. from openpyxl.styles import Protection # 导入包
  2. protection = Protection(locked=True,hidden = True)

上面的代码,相当于开启了下图的选项。

openpyxl 表格读写 - 图3

拆分合并

merge_cells()工作表方法,可以将一个矩形区域中的单元格合并为一个单 元格。在交互式环境中输入以下代码:

  1. import openpyxl
  2. wb = openpyxl.Workbook()
  3. sheet = wb.active
  4. sheet.merge_cells('A1:D3')
  5. sheet['A1'] = '12个单元格合并在一起'
  6. sheet.merge_cells('C5:D5')
  7. sheet['C5'] = '两个单元格合并在一起'
  8. wb.save('merged.xlsx')

image.png
要拆分单元格,就调用 unmerge_cells()工作表方法。在交互式环境中输入以下 代码:

  1. import openpyxl
  2. wb = openpyxl.load_workbook('merged.xlsx')
  3. sheet = wb.get_active_sheet()
  4. sheet.unmerge_cells('A1:D3') #拆分为独立单元格
  5. sheet.unmerge_cells('C5:D5') #拆分为独立单元格
  6. wb.save('merged.xlsx')

冻结窗口

对于太大而不能一屏显示的电子表格,“冻结”顶部的几行或最左边的几列,是 很有帮助的。例如,冻结的列或行表头,就算用户滚动电子表格,也是始终可见的。 这称为“冻结窗格”。

openpyxl 表格读写 - 图5
注意看:冻结的都是设置的单元格向上和向左移动一格的区域。

A2左边没有列,上面有一行,所以冻结第一行; C2左边有列A和列B,上面有一行,所以冻结列A、列B和行1

  1. >>> import openpyxl
  2. >>> wb = openpyxl.load_workbook('produceSales.xlsx')
  3. >>> sheet = wb.active
  4. >>> sheet.freeze_panes = 'A2'
  5. >>> wb.save('freezeExample.xlsx')

表格 - 设置宽高;

设置单行和一列的长和宽:

  1. from openpyxl import load_workbook
  2. wb = load_workbook('test.xlsx') #加载文档
  3. ws = wb[wb.sheetnames[0]] #选择第一个工作表并定义为ws,后面就直接引用ws,就说明是这个工作表
  4. # 调整A列的宽
  5. ws.column_dimensions['A'].width = 20.0
  6. # 调整第1行的高
  7. ws.row_dimensions[1].height = 40
  8. wb.save('test.xlsx')

设置所有行和全部列的长和宽

  1. from openpyxl import load_workbook
  2. from openpyxl.utils import get_column_letter
  3. wb = load_workbook('test.xlsx')
  4. print(wb.sheetnames)
  5. ws = wb[wb.sheetnames[0]]
  6. width = 2.0
  7. height = width * (2.2862 / 0.3612)
  8. print("row:", ws.max_row, "column:", ws.max_column)
  9. for i in range(1, ws.max_row+1):
  10. ws.row_dimensions[i].height = height
  11. for i in range(1, ws.max_column+1):
  12. ws.column_dimensions[get_column_letter(i)].width = width
  13. wb.save('test.xlsx')

修改某一列的时间格式