十天前知乎上有人提問 python:openpyxl模塊怎麼給表格添加分頁符?實現分頁打印功能?,看到問題以後,我很快的給他了一個如何添加垂直分頁符或水平分頁符的示例,你覺得問題就結束了?我是這麼覺得的,可是事實證實,我太天真了,就在我給出示例的幾分鐘後,他在個人回答下評論了,說是同時添加垂直分頁符和水平分頁符失敗了.
我當時的第一反應:
內心想着,確定是他的寫法有問題,堅決果斷的回覆到," 沒有試過同時添加兩種分頁符的操做,默認是水平分頁符,若是你先添加了垂直分頁符的話,應該後面須要從新聲明:openpyxl.worksheet.pagebreak.PageBreak.tagname = "rowBreaks",聽着本身飛快擊打鍵盤的聲音,本身不經有點飄飄然.就在沉浸在本身的YY當中,又過去了幾分鐘,他用正確的代碼錯誤的結果狠狠的摔在了個人臉上:python
col_break = openpyxl.worksheet.pagebreak.Break(5) #建立分頁符,參數5:在第5/6中間分頁 sheet1.page_breaks.tagname = 'rowBreaks' #分頁符屬性設置爲行分頁符 sheet1.page_breaks.append(col_break) #把分頁符對象添加到sheet對象裏 row_break = openpyxl.worksheet.pagebreak.Break(3) #建立分頁符 sheet1.page_breaks.tagname = 'colBreaks' #分頁符屬性設置爲列分頁符 sheet1.page_breaks.append(row_break) #把分頁符對象添加到sheet對象裏
"結果是在第3和5列添加了兩個垂直分頁符,是哪裏有問題?大師",他問道. 我看了一眼代碼好像沒有錯,個人心有點慌了,雙手開始微微顫抖起來,一遍又一遍地仔細地巡視着代碼,視圖找出錯誤反駁他,可是並無,抱着最後的但願,我把他的代碼複製到本身的文件中,而後敲下回車符, excel 文件靜靜的生成在目錄下,這多是我最後的但願了.拿鼠標的手不自覺的顫抖起來,那麼小的屏幕,那麼大的文件,鼠標怎麼半天都沒辦法移動上去,我深吸一口氣,控制住本身手,終於把鼠標一上去了,雙擊excel,閉上眼睛,再睜開,我知道,我錯了.可是就這麼放棄了嗎?毫不!我要把這個問題打到!app
"是時候展現真正的技術了"測試
俗話說"解鈴還須繫鈴人",咱們還得本身看一下問題代碼:spa
# example.py from openpyxl import Workbook from openpyxl.compat import range from openpyxl.utils import get_column_letter from openpyxl.worksheet.pagebreak import Break, PageBreak wb = Workbook() ws = wb.active for row in range(1, 20): for col in range(1,30): _ = ws.cell(column=col, row=row, value="{0}".format(get_column_letter(col))) col_break = Break(5) #建立分頁符,參數5:在第5/6中間分頁 ws.page_breaks.tagname = 'rowBreaks' #分頁符屬性設置爲行分頁符 ws.page_breaks.append(col_break) #把分頁符對象添加到sheet對象裏 row_break = Break(3) #建立分頁符 ws.page_breaks.tagname = 'colBreaks' #分頁符屬性設置爲列分頁符 ws.page_breaks.append(row_break) #把分頁符對象添加到sheet對象裏 wb.save(filename = dest_filename)
從代碼上應該是後面的 page_breaks 把前面的覆蓋了, 那讓咱們看看 page_breaks 到底是什麼東西.excel
class Worksheet(_WorkbookChild): # 省略部分代碼 def _setup(self): self.page_breaks = PageBreak() # 再看 PageBreak class PageBreak(Serialisable): tagname = "rowBreaks" # 省略部分代碼 def append(self, brk=None): """ Add a page break """ vals = list(self.brk) if not isinstance(brk, Break): brk = Break(id=self.count+1) vals.append(brk) self.brk = vals
從 example 中咱們不難發現,咱們是經過修改 page_breaks 的 tag_name 去決定插入的分頁符是垂直分頁符仍是水平分頁符的.可是 page_breaks 如今只有一個 PageBreak 這就難怪後聲明的會把前面的覆蓋了,那麼若是咱們把 page_breaks 變成 PageBreak 的列表呢?code
說改咱就改啊,首先嚐試修改 WorkSheet 類orm
class Worksheet(_WorkbookChild): # 省略部分代碼 def _setup(self): self.page_breaks = [PageBreak()]
而後再修改一下 example.pyxml
from openpyxl import Workbook from openpyxl.compat import range from openpyxl.utils import get_column_letter from openpyxl.worksheet.pagebreak import Break, PageBreak wb = Workbook() dest_filename = 'empty_book.xlsx' ws = wb.active for row in range(1, 20): for col in range(1,30): _ = ws.cell(column=col, row=row, value="{0}".format(get_column_letter(col))) rowPageBreak = PageBreak() rowPageBreak.tagname = 'rowBreaks' colPageBreak = PageBreak() colPageBreak.tagname = 'colBreaks' ws.page_breaks = [rowPageBreak, colPageBreak] ws.page_breaks[0].append(Break(id=5)) ws.page_breaks[1].append(Break(id=3)) wb.save(filename = dest_filename)
敲下回車,內心那個美滋滋,還沒高興幾秒鐘,就出問題了,果真作人仍是得低調一點對象
Traceback (most recent call last): File "test.py", line 24, in <module> wb.save(filename = dest_filename) File "F:\workspace\python\test_openpyxl\test_openpyxl\lib\site-packages\openpyxl\workbook\workbook.py", line 391, in save save_workbook(self, filename) File "F:\workspace\python\test_openpyxl\test_openpyxl\lib\site-packages\openpyxl\writer\excel.py", line 284, in save_workbook writer.save(filename) File "F:\workspace\python\test_openpyxl\test_openpyxl\lib\site-packages\openpyxl\writer\excel.py", line 266, in save self.write_data() File "F:\workspace\python\test_openpyxl\test_openpyxl\lib\site-packages\openpyxl\writer\excel.py", line 83, in write_data self._write_worksheets() File "F:\workspace\python\test_openpyxl\test_openpyxl\lib\site-packages\openpyxl\writer\excel.py", line 203, in _write_worksheets xml = ws._write() File "F:\workspace\python\test_openpyxl\test_openpyxl\lib\site-packages\openpyxl\worksheet\worksheet.py", line 893, in _write return write_worksheet(self) File "F:\workspace\python\test_openpyxl\test_openpyxl\lib\site-packages\openpyxl\writer\worksheet.py", line 151, in write_worksheet xf.write(ws.page_breaks.to_tree()) AttributeError: 'list' object has no attribute 'to_tree'
看了一眼錯誤信息,發現了從中做祟的傢伙再 worksheet.py 的 151 行, 讓咱們悄悄地看一眼,打槍的不要.blog
# worksheet.py # 省略部分代碼 if ws.page_breaks: xf.write(ws.page_breaks.to_tree())
原來是咱們修改了 page_breaks 以後, page_breaks 有時候再也不是孤家寡人了,咱們須要考慮它有另外的 PageBreak 的狀況了.
# worksheet.py # 省略部分代碼 if ws.page_breaks: if isinstance(ws.page_breaks,list): for page_break_item in ws.page_breaks: xf.write(page_break_item.to_tree()) else: xf.write(ws.page_breaks.to_tree())
回車,毫無問題,人生啊就是這麼寂寞如雪~~~
已經在 openpyxl 提了相應的issue,目前再寫測試用例,過段時間就提交 PR 了