天天看點

使用Python Xlsxwriter建立Excel電子表格(第3部分:格式,迷你圖與圖表)

标簽:Python與Excel,Xlsxwriter

在上次的基礎上,我們将使用Python xlsxwriter庫通過添加格式、迷你圖和圖表來美化我們枯燥的Excel電子表格。如果你需要從頭開始,請參閱:

>>>使用PythonXlsxwriter建立Excel電子表格

>>>使用PythonXlsxwriter建立Excel電子表格(第2部分:公式,連結與命名區域)

Excel之是以成為最受歡迎的商業軟體,其中一個原因可能是其豐富的示範功能。它有許多内置功能,可以将普通檔案轉換為講故事的工具。如果你還沒有“美化”你的Excel工作表,現在就應該考慮去做。甚至更好的是,可以編寫一個Python程式來自動使Excel更漂亮。

格式化Excel工作表

要建立格式化的單元格,涉及兩個步驟:建立一個Format對象,然後将格式寫入單元格。

建立Format對象

要将格式添加到Excel工作表,第一步是建立一個format對象,這是使用workbook.add_format方法完成的。

format = workbook.add_format()           

複制

現在,這是一個“空”格式,我們需要用想要的特定格式填充它。有兩種方法可以做到。

1.使用對象方法/接口添加格式

例如,我們想要加粗一個文本單元格,使文本顔色為綠色,同時将字型更改為”微軟雅黑”。

title_format = workbook.add_format()
title_format.set_bold()
title_format.set_font_color('green')
title_format.set_font_name('微軟雅黑')           

複制

2.使用格式構造函數添加格式

下面是如何使用格式構造函數實作相同的結果,我們隻需傳遞一個包含所有格式屬性的字典:

title_format = workbook.add_format({
   'bold': True,
   'font_color':'green',
   'font_name':'微軟雅黑'
})           

複制

看起來,第二種方法更簡潔。

将格式寫入單元格

我們剛剛建立了文本格式,但還沒有在工作表上使用它。要在工作表上顯示,我們需要将其寫入單元格。

worksheet.write()方法接受另一個參數cell_format。

寫入“财富累積”作為計算表的标題。繼續前面的示例,我們将“計算”工作表命名為ws_2。

ws_2.write(0,1,"累積财富",title_format)

在電子表格中添加邊框線

在使用xlsxwriter時,可能不想在大多數情況下為邊框線而煩惱。這是可以做到的,但卻是一個乏味的過程,除非所有邊的邊框線都是相同的樣式。原因如下:

要向單元格添加任何格式,需要将格式連同資料一起寫入單元格。這意味着“更改”為不同的格式需要在将新格式傳遞到worksheet.write()方法時重新寫入資料。

明白了嗎?如果要在Excel中手動添加格式,則隻需選擇資料單元格/區域,然後按格式按鈕。相比之下,對于xlsxwriter,我們必須同時向單元格寫入資料和格式。

編寫如下表格式的代碼需要大量工作。對于某些單元格,我們需要為單元格的每一側使用不同的邊框格式。是以,其要點是,不用麻煩在xlsxwriter中繪制邊框線,因為它的80%的工作隻得到2%的結果。

格式化屬性和設定方法

下面是用于設定格式的格式屬性及其相應對象方法的清單。xlsxwriter官方文檔如下:

https://xlsxwriter.readthedocs.io/format.html#format-methods-and-format-properties

使用Python Xlsxwriter建立Excel電子表格(第3部分:格式,迷你圖與圖表)

圖1

數字格式

在Excel中設定數字格式很簡單:

1.在Excel中,右鍵單擊任意單元格,選擇“設定單元格格式”。

2.在“數字”頁籤下,單擊清單中的“自定義”。

3.在右側視窗中找到不同的數字格式,粘貼到Python代碼中。

讓我們建立一些數字格式的對象,使我們的電子表格看起來更專業。

f_bold =wb.add_format({'bold':True}) #加粗
f_money = wb.add_format()
f_money.set_num_format('#,##0') #貨币格式 ->
f_thousand =wb.add_format({'num_format':'#,##0'}) #千位分隔符 -> 1,000
f_pct = wb.add_format({'num_format':'0%',
                       'font_color':'green',
                       'bg_color':'black'}) #綠色字型,黑色背景的百分比格式
f_top_border =wb.add_format({'top':3})
f_left_board =wb.add_format({'left':2})           

複制

合并單元格

合并單元格很簡單,隻需使用worksheet.merge_range()。我們可以使用(開始行、開始列、結束行、結束列)表示法或A1表示法,合并一些單元格,同時格式化它們。

f_merge = wb.add_format({'border':6,
                         'bold':True,
                         'font_size':20,
                         'font_color':'green',
                         'font_name':'微軟雅黑',
                         'align':'center'})
ws_2.merge_range(0,1,0,17, "财富積累",f_merge)
#ws_2.merge_range("B1:R1","财富積累",f_merge)           

複制

自動篩選

如果經常使用自動篩選功能,還可以在工作表中添加自動篩選功能。同樣,(行、列)和A1樣式的符号是可互換的。

ws_2.autofilter('B10:F10')
#ws_2.autofilter(9,1,9,5)           

複制

建立圖表

與建立格式的方式類似,對于圖表,也需要建立一個“空”圖表對象,然後向其添加元素。

xlsxwriter目前支援以下圖表類型:

  • 面積圖
  • 條形圖或柱狀圖(即直方圖)
  • 折線圖
  • 餅圖或圓環圖
  • 散點圖
  • 股價圖
  • 雷達圖

為了示範,我們将建立一個折線圖和一個柱狀圖。

折線圖

可以自定義圖表元素,例如顔色、資料标簽、圖例等。這是通過将屬性字典傳遞chart.add_series()來完成的。

下列屬性是我們在示範中要使用的,有關完整的功能清單,請參閱xlsxwriter文檔。

  • “categories”:這是x軸标簽
  • “values”:圖形的實際值
  • “name”:資料系列的名稱,也用于圖例
  • “data_labels”:我們可以使用此參數标記資料點
  • “y2_axis”:次坐标軸y軸
line_chart =wb.add_chart({'type':'line'})
## 收入
line_chart.add_series({'categories':"=計算!B20",
                      'values':"=計算!C20",
                      'line':{'color':'blue'},
                      'name':'收入',
                      'y2_axis':True})
## 累積财富
line_chart.add_series({'categories':"=計算!
                      'values':"=計算!F20",
                      'line':{'color':'green'},
                      'name':'财富',
                     'data_labels':{'value':True,'position':'above','num_format':'$#,##0'},
                      'y2_axis':True})           

複制

接着,必須選擇放置圖表的位置。以下代碼将圖表放置在單元格H3中,或者更準确地說,它将使圖表的左上角位于單元格H3中。

ws_2.insert_chart('H3', line_chart)           

複制

柱狀圖

建立一個柱狀/條形圖。“柱狀”圖将顯示垂直直方圖,“條形”圖将顯示水準直方圖。這個約定與Excel描述這些圖表類型的方式完全比對。

我們還可以使用{'subtype':'stacked'}來指定堆積柱狀圖。

column_chart =wb.add_chart({'type':'column'})
# 收入
column_chart.add_series({'categories':"=計算!B20",
                         'values':"=計算!C20",
                        'fill':{'color':'blue'},
                         'name':'收入'})
# 支出
column_chart.add_series({'categories':"=計算!B20",
                         'values':"=計算!D20",
                        'fill':{'color':'yellow'},
                         'name':'支出'})
# 可投資收入
column_chart.add_series({'categories':"=計算!B20",
                         'values':"=計算!E20",
                        'fill':{'color':'green'},
                         'name':'可投資收入'})
ws_2.insert_chart('H21',column_chart)           

複制

使用Python組合兩個Excel圖表

一個很酷的特性是,我們可以使用Python xlsxwriter建立雙軸圖表。基本上,我們将兩個圖表組合在一起,形成一個新的圖表。當然,這兩個圖表需要有一些共同點,例如在示例中的x軸。否則,将完全不同的圖表組合在一起可能沒有多大意義。

通過組合柱形圖和折線圖,基本上建立了一個帕累托圖。下面的代碼塊很簡單:将柱形與折線圖結合起來,然後在帕累托圖上調整各個元素,例如标題、軸名稱、圖例位置等。

column_chart.combine(line_chart)
column_chart.set_title({'name':'财富積累'})
column_chart.set_x_axis({'name':'年數'})
column_chart.set_legend({'position':'bottom'})
column_chart.set_y_axis({'name':'收入标準'})
column_chart.set_y2_axis({'name':'财富标準'})
#設定圖表寬度和高度
column_chart.set_size({'width':700,'height':400})
ws_2.insert_chart('H33',column_chart)           

複制

迷你圖

下面介紹如何将迷你圖(Sparkine)添加到電子表格中。現在你可能已經注意到了這個結構,無論想在工作表上添加什麼元素,通常都是通過worksheet.add_something()方法完成的。

### 添加迷你圖
ws_2.add_sparkline('E3',
                   {'range':'C11:C20',
                    'type':'column',
                    'style':3})
ws_2.add_sparkline('E4',
                   {'range':'D11:D20',
                    'type':'column',
                    'style':2})           

複制

小結

綜上,下面是生成的功能齊全的Excel電子表格的Python代碼。

import xlsxwriter
from xlsxwriter.utility importxl_rowcol_to_cell
import pathlib
wb =xlsxwriter.Workbook(r'D:\excel-formula.xlsx')
ws_1 = wb.add_worksheet('輸入')
ws_2 = wb.add_worksheet('計算')
proj_start_row = 9
proj_start_col = 1
row = 1
col = 1
variables = {
   '年數': 10,
   '收入': 50000,
   '支出': 30000,
   '收入增長率': 0.05,
   '投資回報率': 0.06,
   '通脹率': 0.03,
   }
for i in variables.keys():
   ws_1.write(row,col,i)
   ws_1.write(row,col+1,variables[i])
   row += 1
row = 1
f_bold =wb.add_format({'bold':True})
f_money = wb.add_format()
f_money.set_num_format('$#,##0')
f_thousand =wb.add_format({'num_format':'#,##0' })
f_pct =wb.add_format({'num_format':'0%',
                       'font_color': 'green',
                       'bg_color': 'black'})
f_merge = wb.add_format({'border':6,
                         'bold': True,
                         'font_size':20,
                         'font_color': 'green',
                         'font_name': '微軟雅黑',
                         'align': 'center'})
f_top_border =wb.add_format({'top':3})
f_left_board =wb.add_format({'left':2})
ws_2.merge_range("B1:R1",'财富積累', f_merge)
for i in variables.keys():
   ws_2.write(row, col, i)
   if i in ['收入', '支出']:
        ws_2.write(row, col+1, f'=輸入!{xl_rowcol_to_cell(row,col+1)}', f_money)
   elif i in ['收入增長率','投資回報率','通脹率']:
        ws_2.write(row, col+1, f'=輸入!{xl_rowcol_to_cell(row,col+1)}', f_pct)
   else:
        ws_2.write(row, col+1, f'=輸入!{xl_rowcol_to_cell(row,col+1)}')
   row += 1
calc_cols = ['年份','收入','支出','可投資收入','累積财富']
ws_2.write_row(proj_start_row,1,calc_cols)
ws_2.write_column(proj_start_row+1,proj_start_col,range(variables['年數']))
def annual_increase(ws, start_row,start_col, n, initial_value, name_range):
   ws.write(start_row, start_col, initial_value,f_thousand)
   for i in range(n-1):
        ws.write(start_row+1+i, start_col,f'={xl_rowcol_to_cell(start_row+i,start_col)}*(1+{name_range})',f_thousand)
   ws.write(start_row+n, start_col, f'=SUM({xl_rowcol_to_cell(start_row,start_col)}:{xl_rowcol_to_cell(start_row+n-1, start_col)})',f_thousand)
wb.define_name('income_increase',"='輸入'!
wb.define_name('investment_return',"='輸入'!
wb.define_name('inflation',"='輸入'!
annual_increase(ws_2, proj_start_row+1,proj_start_col+1, variables['年數'],variables['收入'], 'income_increase')
annual_increase(ws_2,proj_start_row+1, proj_start_col+2, variables['年數'],variables['支出'], 'inflation')
for i in range(variables['年數']):
   ws_2.write(proj_start_row+1+i,
               proj_start_col+3,
              f'={xl_rowcol_to_cell(proj_start_row+1+i,proj_start_col+1)}-{xl_rowcol_to_cell(proj_start_row+1+i, proj_start_col+2)}',f_thousand)
ws_2.write(proj_start_row+1,proj_start_col+4, f'={xl_rowcol_to_cell(proj_start_row+1,proj_start_col+3)}',f_thousand)
for i in range(variables['年數']-1):
   ws_2.write(proj_start_row+2+i, proj_start_col+4,
              f"={xl_rowcol_to_cell(proj_start_row+1+i,proj_start_col+4)}*(1+investment_return)+{xl_rowcol_to_cell(proj_start_row+2+i,proj_start_col+3)}",f_thousand)
line_chart =wb.add_chart({'type':'line'})
line_chart.add_series({'categories':"=計算!B20",
                      'values':"=計算!C20",
                      'line':{'color':'blue'},
                      'name':'收入',
                      'y2_axis':True})
line_chart.add_series({'categories':"=計算!
                      'values':"=計算!F20",
                      'line':{'color':'green'},
                      'name':'财富',
                     'data_labels':{'value':True,'position':'above','num_format':'$#,##0'},
                      'y2_axis':True})
column_chart =wb.add_chart({'type':'column'})
column_chart.add_series({'categories':"=計算!B20",
                         'values':"=計算!C20",
                        'line':{'color':'blue'},
                         'name':'收入'})
column_chart.add_series({'categories':"=計算!B20",
                         'values':"=計算!D20",
                         'line':{'color':'yellow'},
                         'name':'支出'})
column_chart.add_series({'categories':"=計算!B20",
                         'values':"=計算!E20",
                        'line':{'color':'green'},
                         'name':'可投資收入'})
column_chart.combine(line_chart)
column_chart.set_title({'name':'财富積累'})
column_chart.set_x_axis({'name':'年數'})
column_chart.set_legend({'position':'bottom'})
column_chart.set_y_axis({'name':'收入标準'})
column_chart.set_y2_axis({'name':'财富标準'})
column_chart.set_size({'width':700,'height':400})
ws_2.insert_chart('H3',column_chart)
### 添加迷你圖
ws_2.add_sparkline('E3',
                   {'range':'C11:C20',
                    'type':'column',
                    'style':3})
ws_2.add_sparkline('E4',
                   {'range':'D11:D20',
                    'type':'column',
                    'style':2})
ws_2.autofilter('B10:F10')
wb.close()           

複制

代碼運作結果如下圖2所示。

使用Python Xlsxwriter建立Excel電子表格(第3部分:格式,迷你圖與圖表)

圖2