讓我頭疼一下午的Excel合併單元格
Excel匯出常見問題
excel匯出其實不算什麼難事
在網上copy下模板程式碼,填充自己的業務資料,提供一個http介面基本就可以得到你要匯出的資料了。
但是,凡事都有例外,截止今天,excel匯出我遇到的主要是兩大類問題
1、大資料量的excel資料,比如幾十萬條甚至更多的資料匯出
2、因為excel中內容的問題,導致匯出後的excel不能直接開啟,報錯“由於一些內容不可取,Excel無法開啟xxx.xlsx。是否要開啟並修復此工作簿?”
針對第一種大資料量問題,我遇到的主要問題是excel儲存的記錄上限和匯出超時等問題
解決方法是將匯出格式為xls升級為xlsx,xls每個sheet最多支援65536條記錄,xlsx最多支援1048576條記錄;超時則可以採用前端直接返回,後端非同步取資料並匯出的方式避免超時。
這種情況不是今天要介紹的重點,今天要介紹的第二種情況的解決思路。
需求描述
1、層級關係最多為四級
2、對於相同層級,如果內容相同需要縱向合併單元格,空白行不需要合併
3、樣例資料如下所示
一級目錄1,二級目錄1,三級目錄1,四級目錄2, 一級目錄1,二級目錄1,三級目錄3, 一級目錄1,二級目錄1,三級目錄5, 一級目錄1,二級目錄3, 一級目錄1,二級目錄5,三級目錄5, 一級目錄2,二級目錄2,三級目錄2, 一級目錄2,二級目錄2,三級目錄3, 一級目錄2,二級目錄4,三級目錄4, 一級目錄2,二級目錄7, 一級目錄3,二級目錄6,三級目錄4, 一級目錄3,二級目錄6,三級目錄10, 一級目錄4, 一級目錄5,二級目錄8,三級目錄6,
解決思路
將上面樣例資料存入一個集合中,遍歷每條記錄並存放到相應的單元格。
如果不需要合併單元格,到這裡,就可以提供匯出的Excel了。
但是重點是合併單元格。
遇到的問題
初步排查
自認為程式碼已經就位,呼叫介面,Excel檔案也成功下載了,結果開啟的那一刻一個對話方塊讓我頭疼了一下午。
報錯資訊如下
第一反應是肯定資料錯亂了,估計是單元格之間相互擠佔,資料肯定也是不堪入目。
但是我按照智慧的Excel提示,點選“開啟並修復”後發現,資料沒有我想的那麼糟,甚至仔細看看,發現居然沒有問題。
有點小激動的同時,心裡還是有點不爽,總不能讓別人每次匯出的時候都使用這個智慧的“開啟並修復”功能才能看匯出的資料吧。
但是光從這個報錯資訊來看確實沒有什麼線索,於是網上找了一通與“由於一些內容不可取,Excel無法開啟xxx.xlsx。是否要開啟並修復此工作簿?”有關的解決方法。雖然有不少人遇到過這樣的問題,但是引起問題的原因不太一樣,有些是因為sheet的命名包含特殊字元,有些是匯出的Excel內容中有非法字元,還有說要在response的header中加入Content-length欄位的。
進一步排查
搜了一通,沒有什麼進展,這時候想起來在剛剛點選“開啟並修復”後,還彈出了一個對話方塊,於是點選對話方塊中的檢視
得到線索如下
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><logFileName>修復結果到 xxx.xml</logFileName><summary>在檔案“/Users/jackie/Downloads/xxx.xlsx”中檢測到錯誤</summary><removedRecords summary="以下是已刪除記錄的列表:"><removedRecord>已刪除的記錄: /xl/worksheets/sheet1.xml 的 合併單元格</removedRecord></removedRecords></recoveryLog>
排除了前面提到的種種非法字元的原因,看到線索裡的“合併單元格”,基本可以斷定這是因為在合併單元格的過程中出了問題。
尋找問題根本原因
結合合併單元格導致Excel表格無法開啟的症狀在網上搜索一通
我將下載的Excel表格的字尾從xlsx改為zip並開啟
開啟sheet1.xml檔案,找到mergeCells標籤,將其內容拷貝到XML線上格式化工具中檢視
經過人眼搜尋,終於發現了問題所在
...
<mergeCell ref="B175:B189"/>
<mergeCell ref="B176:B190"/>
...
這裡顯然出現了覆蓋合併的情況,進而導致開啟Excel報錯的情況(後面經過測試發現,重複合併單元格也會出現同樣的報錯資訊)
順著這個思路,排查程式碼,不斷除錯測試,考慮各種情況下的合併單元格場景,最終搞定了這個稍稍複雜的合併單元格的Excel匯出功能。
一點思考
雖然知道是合併單元格導致的問題,但是在實際調整程式碼時花費了幾乎一個下午,曾經一度頭大到不想思考。
回頭想想,在這個問題上有兩大收穫。
1、排查問題的思路很重要
問題的現象已經擺在眼前,排查了不是非法字元的原因,就應該尋找其他原因
利用一切可以利用的手頭資訊比如上面簡短而關鍵的報錯日誌資訊。
活用搜索引擎,這種問題肯定已經有前人踩過雷,去看下他們是怎麼排雷的就好,不用自己再去研究排雷的具體方法了。
2、寫程式碼之前先想好
現在想想這段合併單元格的程式碼是不是可以寫的更加漂亮,我想應該是可以的,但是能不能從30行精簡為10行甚至5行,我想這不太可能。
因為這個匯出合併時會遇到各種情況,比如連續相同的單元格何時合併,空白行如何保證不合並,某空白行區域前和後又如何實現合併等問題。
所以,寫這段程式碼前應該先梳理所有可能的場景包括一些特殊情況,盡其所能羅列所有的情況,這樣才能保證在應對各種情形的資料時正常匯出。
程式碼稍後我會放到專案rome裡
對了,匯出效果圖呈上
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。