创建简单的电子表格和条形图#

在本例中,将从头创建,并添加一些数据,然后绘制它。还将探讨一些有限的单元格样式和格式。

from openpyxl import Workbook

wb = Workbook()
ws = wb.active

treeData = [["Type", "Leaf Color", "Height"], ["Maple", "Red", 549], ["Oak", "Green", 783], ["Pine", "Green", 1204]]

接下来,使用 Worksheet.append 函数把这些数据输入工作表。

for row in treeData:
    ws.append(row)

应该将标题设置为粗体,使其更加突出,为此需要创建 styles.Font,并将其应用到标题行的所有单元格。

from openpyxl.styles import Font

ft = Font(bold=True)

for row in ws["A1:C1"]:
    for cell in row:
        cell.font = ft

是时候做一些图表了:

from openpyxl.chart import BarChart, Series, Reference

chart = BarChart()
chart.type = "col"
chart.title = "Tree Height"
chart.y_axis.title = 'Height (cm)'
chart.x_axis.title = 'Tree Type'
chart.legend = None

这就创建了柱状图的框架。现在需要添加对数据所在位置的引用,并将其传递给图表对象

data = Reference(ws, min_col=3, min_row=2, max_row=4, max_col=3)
categories = Reference(ws, min_col=1, min_row=2, max_row=4, max_col=1)
chart.add_data(data)
chart.set_categories(categories)

最后可以把它添加到表格中。

ws.add_chart(chart, "E1")
wb.save("../build/TreeData.xlsx")
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[7], line 2
      1 ws.add_chart(chart, "E1")
----> 2 wb.save("../build/TreeData.xlsx")

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/openpyxl/workbook/workbook.py:386, in Workbook.save(self, filename)
    384 if self.write_only and not self.worksheets:
    385     self.create_sheet()
--> 386 save_workbook(self, filename)

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/openpyxl/writer/excel.py:291, in save_workbook(workbook, filename)
    279 def save_workbook(workbook, filename):
    280     """Save the given workbook on the filesystem under the name filename.
    281 
    282     :param workbook: the workbook to save
   (...)
    289 
    290     """
--> 291     archive = ZipFile(filename, 'w', ZIP_DEFLATED, allowZip64=True)
    292     workbook.properties.modified = datetime.datetime.now(tz=datetime.timezone.utc).replace(tzinfo=None)
    293     writer = ExcelWriter(workbook, archive)

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/zipfile/__init__.py:1331, in ZipFile.__init__(self, file, mode, compression, allowZip64, compresslevel, strict_timestamps, metadata_encoding)
   1329 while True:
   1330     try:
-> 1331         self.fp = io.open(file, filemode)
   1332     except OSError:
   1333         if filemode in modeDict:

FileNotFoundError: [Errno 2] No such file or directory: '../build/TreeData.xlsx'

添加图片#

from openpyxl import Workbook

from openpyxl.drawing.image import Image
wb = Workbook()
ws = wb.active

ws['A1'] = 'You should see three logos below'
# create an image
img = Image('../../../logo.jpg')
# add to worksheet and anchor next to cells
ws.add_image(img, 'A1')
wb.save('../build/logo.xlsx')
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[11], line 3
      1 # add to worksheet and anchor next to cells
      2 ws.add_image(img, 'A1')
----> 3 wb.save('../build/logo.xlsx')

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/openpyxl/workbook/workbook.py:386, in Workbook.save(self, filename)
    384 if self.write_only and not self.worksheets:
    385     self.create_sheet()
--> 386 save_workbook(self, filename)

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/openpyxl/writer/excel.py:291, in save_workbook(workbook, filename)
    279 def save_workbook(workbook, filename):
    280     """Save the given workbook on the filesystem under the name filename.
    281 
    282     :param workbook: the workbook to save
   (...)
    289 
    290     """
--> 291     archive = ZipFile(filename, 'w', ZIP_DEFLATED, allowZip64=True)
    292     workbook.properties.modified = datetime.datetime.now(tz=datetime.timezone.utc).replace(tzinfo=None)
    293     writer = ExcelWriter(workbook, archive)

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/zipfile/__init__.py:1331, in ZipFile.__init__(self, file, mode, compression, allowZip64, compresslevel, strict_timestamps, metadata_encoding)
   1329 while True:
   1330     try:
-> 1331         self.fp = io.open(file, filemode)
   1332     except OSError:
   1333         if filemode in modeDict:

FileNotFoundError: [Errno 2] No such file or directory: '../build/logo.xlsx'

修改图片尺寸:

_from = AnchorMarker(0, 50000, 1, 50000)
to = AnchorMarker(15, -50000, 40, -50000)
anchor = TwoCellAnchor('twoCell', _from, to)
ws.add_image(img, anchor)

样式#

样式用于更改显示在屏幕上的数据的外观。它们还用于确定数字的格式。

样式可以应用于以下方面:

  • 设置字体大小、颜色、下划线等

  • 填充以设置图案或颜色渐变

  • 在单元格上设置边框

  • 单元格对齐

  • 保护

以下为默认值:

from openpyxl.styles import PatternFill, Border, Side, Alignment, Protection, Font
font = Font(name='Calibri',
            size=11,
            bold=False,
            italic=False,
            vertAlign=None,
            underline='none',
            strike=False,
            color='FF000000')
fill = PatternFill(fill_type=None,
                   start_color='FFFFFFFF',
                   end_color='FF000000')
border = Border(left=Side(border_style=None, color='FF000000'),
                right=Side(border_style=None, color='FF000000'),
                top=Side(border_style=None, color='FF000000'),
                bottom=Side(border_style=None, color='FF000000'),
                diagonal=Side(border_style=None, color='FF000000'),
                diagonal_direction=0, 
                outline=Side(border_style=None, color='FF000000'),
                vertical=Side(border_style=None, color='FF000000'),
                horizontal=Side(border_style=None, color='FF000000'))
alignment=Alignment(horizontal='general',
                    vertical='bottom',
                    text_rotation=0,
                    wrap_text=False,
                    shrink_to_fit=False,
                    indent=0)
number_format = 'General'
protection = Protection(locked=True, hidden=False)

单元格样式和命名样式#

有两种类型的样式:单元格样式和命名样式,也称为样式模板。

单元格样式#

单元格样式在对象之间共享,一旦它们被分配,就不能更改。这可以避免不必要的副作用,比如当只有一个单元格发生变化时,许多单元格的样式都会发生变化。

from openpyxl.styles import colors
from openpyxl.styles import Font, Color
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
a1 = ws['A1']
d4 = ws['D4']
ft = Font(color="FF0000")
a1.font = ft
d4.font = ft
# a1.font.italic = True # is not allowed # doctest: +SKIP
# If you want to change the color of a Font, you need to reassign it::
a1.font = Font(color="FF0000", italic=True) # the change only affects A1

样式副本#

样式可以有副本:

from openpyxl.styles import Font
from copy import copy
ft1 = Font(name='Arial', size=14)
ft2 = copy(ft1)
ft2.name = "Tahoma"
ft1.name
'Arial'
ft2.name
'Tahoma'
ft2.size # copied from the
14.0

颜色#

字体、背景、边框等的颜色可以通过三种方式设置:索引、aRGB或主题。索引颜色是遗留实现,颜色本身取决于工作簿或应用程序默认提供的索引。主题颜色对于颜色的互补阴影是有用的,但也取决于工作簿中出现的主题。因此,建议使用 aRGB 颜色。

aRGB 颜色#

RGB 颜色是用红、绿、蓝的十六进制值设置的。

from openpyxl.styles import Font
font = Font(color="FF0000")

alpha 值在理论上是指颜色的透明度,但这与单元格样式无关。默认值 00 将前置任何简单的 RGB 值:

from openpyxl.styles import Font
font = Font(color="00FF00")
font.color.rgb
'0000FF00'

它还支持遗留的索引颜色以及主题和色调。

from openpyxl.styles.colors import Color

c = Color(indexed=32)
c = Color(theme=6, tint=0.5)
c
<openpyxl.styles.colors.Color object>
Parameters:
rgb=None, indexed=None, auto=None, theme=6, tint=0.5, type='theme'

应用样式#

样式直接应用于单元格

from openpyxl.workbook import Workbook

from openpyxl.styles import Font, Fill
wb = Workbook()
ws = wb.active
c = ws['A1']
c.font = Font(size=12)

样式也可以应用于列和行,但请注意,这只适用于文件关闭后创建的单元格(在 Excel 中)。如果你想对整个行和列应用样式,那么你必须自己对每个单元格应用样式。这是文件格式的限制:

col = ws.column_dimensions['A']
col.font = Font(bold=True)
row = ws.row_dimensions[1]
row.font = Font(underline="single")

样式化合并单元格#

合并的单元格的行为与其他单元格对象类似。它的值和格式在其左上角的单元格中定义。要更改整个合并单元格的边界,请更改其左上角单元格的边界。格式是为了写作而生成的。

from openpyxl.styles import Border, Side, PatternFill, Font, GradientFill, Alignment
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.merge_cells('B2:F4')
top_left_cell = ws['B2']
top_left_cell.value = "My Cell"
thin = Side(border_style="thin", color="000000")
double = Side(border_style="double", color="ff0000")
top_left_cell.border = Border(top=double, left=thin, right=thin, bottom=double)
top_left_cell.fill = PatternFill("solid", fgColor="DDDDDD")
top_left_cell.fill = fill = GradientFill(stop=("000000", "FFFFFF"))
top_left_cell.font  = Font(b=True, color="FF0000")
top_left_cell.alignment = Alignment(horizontal="center", vertical="center")
wb.save("../build/styled.xlsx")
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[23], line 15
     13 top_left_cell.font  = Font(b=True, color="FF0000")
     14 top_left_cell.alignment = Alignment(horizontal="center", vertical="center")
---> 15 wb.save("../build/styled.xlsx")

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/openpyxl/workbook/workbook.py:386, in Workbook.save(self, filename)
    384 if self.write_only and not self.worksheets:
    385     self.create_sheet()
--> 386 save_workbook(self, filename)

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/openpyxl/writer/excel.py:291, in save_workbook(workbook, filename)
    279 def save_workbook(workbook, filename):
    280     """Save the given workbook on the filesystem under the name filename.
    281 
    282     :param workbook: the workbook to save
   (...)
    289 
    290     """
--> 291     archive = ZipFile(filename, 'w', ZIP_DEFLATED, allowZip64=True)
    292     workbook.properties.modified = datetime.datetime.now(tz=datetime.timezone.utc).replace(tzinfo=None)
    293     writer = ExcelWriter(workbook, archive)

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/zipfile/__init__.py:1331, in ZipFile.__init__(self, file, mode, compression, allowZip64, compresslevel, strict_timestamps, metadata_encoding)
   1329 while True:
   1330     try:
-> 1331         self.fp = io.open(file, filemode)
   1332     except OSError:
   1333         if filemode in modeDict:

FileNotFoundError: [Errno 2] No such file or directory: '../build/styled.xlsx'

使用数字格式#

您可以为单元格指定数字格式,或者对于某些实例(如 datetime),它将自动格式化。

import datetime
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
# set date using a Python datetime
ws['A1'] = datetime.datetime(2010, 7, 21)
ws['A1'].number_format
'yyyy-mm-dd h:mm:ss'
ws["A2"] = 0.123456
ws["A2"].number_format = "0.00" # Display to 2dp

编辑页面设置#

from openpyxl.workbook import Workbook
wb = Workbook()
ws = wb.active
ws.page_setup.orientation = ws.ORIENTATION_LANDSCAPE
ws.page_setup.paperSize = ws.PAPERSIZE_TABLOID
ws.page_setup.fitToHeight = 0
ws.page_setup.fitToWidth = 1

命名样式#

与单元格样式相反,命名样式是可变的。当您想要同时对许多不同的单元格应用格式时,它们是有意义的。NB。将命名样式分配给单元格后,对样式的其他更改将不会影响单元格。

一旦已命名的样式被注册到工作簿中,就可以简单地通过名称引用它。

from openpyxl.styles import NamedStyle, Font, Border, Side
highlight = NamedStyle(name="highlight")
highlight.font = Font(bold=True, size=20)
bd = Side(style='thick', color="000000")
highlight.border = Border(left=bd, top=bd, right=bd, bottom=bd)

一旦创建了命名样式,就可以将它注册到工作簿中:

wb.add_named_style(highlight)

但是命名样式也会在第一次分配给单元格时自动注册:

ws['A1'].style = highlight

注册后,仅需使用名称分配样式:

ws['D5'].style = 'highlight'