阿里開源的這個庫,讓 Excel 導出不再複雜(既要能寫,還要寫的好看)

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你好,我是看山。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.howardliu.cn/effective-java-easyexcel-action-write/","title":"","type":null},"content":[{"type":"text","text":"前文","attrs":{}}]},{"type":"text","text":" 聊了 EasyExcel 的內容導出,本文主要說一下導出文件的格式化,格式化包括工作表/單元格樣式和內容格式化。畢竟,有時候還是要看臉。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"內容比較多,文內只會列出關鍵代碼,想要完整源碼,可以關注公號「看山的小屋」回覆“easyexcel”獲取。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"註解格式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過註解定義格式是 EasyExcel 封裝的高級功能,可以讓我們很方便的定義格式。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"格式化內容","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先定義一個使用註解格式化內容的實體類:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\npublic class FormatContentItem {\n @ExcelProperty(value = \"字符串標題\", converter = TitleFormatConverter.class)\n private String string;\n @DateTimeFormat(\"yyyy 年 MM 月 dd 日 HH 時 mm 分 ss 秒\")\n @ExcelProperty(value = \"日期標題\")\n private Date date;\n @NumberFormat(\"0.000%\")\n @ExcelProperty(\"數字標題\")\n private Double doubleData;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"DateTimeFormat","attrs":{}}],"attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"NumberFormat","attrs":{}}],"attrs":{}},{"type":"text","text":"兩個註解都是自帶的註解,用於格式化時間和數字。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"DateTimeFormat","attrs":{}}],"attrs":{}},{"type":"text","text":"註解有兩個屬性,一個屬性是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"value","attrs":{}}],"attrs":{}},{"type":"text","text":",用來定義時間格式,可以參考","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.text.SimpleDateFormat","attrs":{}}],"attrs":{}},{"type":"text","text":";另一個屬性是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"use1904windowing","attrs":{}}],"attrs":{}},{"type":"text","text":",表示使用時間使用 1904 時間系統還是 1900 時間系統,默認是否。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"NumberFormat","attrs":{}}],"attrs":{}},{"type":"text","text":"註解有兩個屬性,一個屬性是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"value","attrs":{}}],"attrs":{}},{"type":"text","text":",用來定義數字格式,可以參考","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.text.DecimalFormat","attrs":{}}],"attrs":{}},{"type":"text","text":";另一個屬性是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"roundingMode","attrs":{}}],"attrs":{}},{"type":"text","text":",用來定義保留小數的方式,使用的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"java.math.RoundingMode","attrs":{}}],"attrs":{}},{"type":"text","text":"枚舉。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"想要格式化字符串,可以藉助","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelProperty","attrs":{}}],"attrs":{}},{"type":"text","text":"的 converter 屬性,這個屬性傳入實現","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Converter","attrs":{}}],"attrs":{}},{"type":"text","text":"的類。比如示例中的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"TitleFormatConverter","attrs":{}}],"attrs":{}},{"type":"text","text":",代碼如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class TitleFormatConverter implements Converter {\n @Override\n public Class> supportJavaTypeKey() {\n return String.class;\n }\n\n @Override\n public CellDataTypeEnum supportExcelTypeKey() {\n return CellDataTypeEnum.STRING;\n }\n\n @Override\n public WriteCellData> convertToExcelData(String value, ExcelContentProperty contentProperty,\n GlobalConfiguration globalConfiguration) {\n return new WriteCellData<>(String.format(\"標題:%s(自定義)\", value));\n }\n\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d7/d7459fb97f8e41dd4528c950ead74d91.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"定義行高、列寬","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用註解定義行高的話,可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HeadRowHeight","attrs":{}}],"attrs":{}},{"type":"text","text":"定義表頭高度,使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ContentRowHeight","attrs":{}}],"attrs":{}},{"type":"text","text":"定義表體高度,這個註解定義之後,所有表體高度都是相同的。列寬可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ColumnWidth","attrs":{}}],"attrs":{}},{"type":"text","text":"註解定義,這個註解可以定義在類上,表示整個表格的列都一樣寬,也可以定義的屬性上,表示指定列的寬度。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\n@HeadRowHeight(20)\n@ContentRowHeight(10)\n@ColumnWidth(25)\npublic class FormatCellItem {\n @ExcelProperty(\"字符串標題\")\n private String string;\n @ExcelProperty(\"日期標題\")\n private Date date;\n @ColumnWidth(50)\n @ExcelProperty(\"數字標題\")\n private Double doubleData;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c4/c4f64985e540d3bfc240a91e927dfa05.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"單元格定義樣式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"控制單元格樣式有四個註解:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HeadStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HeadFontStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ContentStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ContentFontStyle","attrs":{}}],"attrs":{}},{"type":"text","text":",這四個註解可以定義在類上作爲全局表格的樣式,也可以定義在字段上,作爲當前列的樣式。下面分別說一下這幾個註解中比較常用的配置。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"*Style:分爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HeadStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ContentStyle","attrs":{}}],"attrs":{}},{"type":"text","text":",分別定義表頭和表體樣式","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"dataFormat:表頭格式化,short 格式,是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"org.apache.poi.ss.usermodel.BuiltinFormats","attrs":{}}],"attrs":{}},{"type":"text","text":"類中已定義格式的小標","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"border*:分別是 borderLeft、borderRight、borderTop、borderBottom 四個屬性,類型是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.enums.poi.BorderStyleEnum","attrs":{}}],"attrs":{}},{"type":"text","text":"枚舉,用來定義表頭單元格邊框樣式。邊框的顏色也可以定義,使用、*BorderColor 定義即可。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"fillPatternType:填充類型,類型是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.enums.poi.FillPatternTypeEnum","attrs":{}}],"attrs":{}},{"type":"text","text":"枚舉,如果想要填充背景色,這個屬性需要設置爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SOLID_FOREGROUND","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"fillForegroundColor:前景色,類型是 short,值卻是使用的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"org.apache.poi.ss.usermodel.IndexedColors","attrs":{}}],"attrs":{}},{"type":"text","text":"枚舉的 idx 值,只不過,兩個類型不一致,一個是 short,一個是 int,沒有辦法直接引用。可見 java 中的依賴之間,還是有很多坑的。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"fillBackgroundColor:背景色,同","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fillForegroundColor","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"rotation:內容旋轉角度","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"*FontStyle:有","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HeadFontStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ContentFontStyle","attrs":{}}],"attrs":{}},{"type":"text","text":",分別定義表頭和表體的字體樣式。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"fontName:定義字體名稱,類型字符串","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"fontHeightInPoints:字號大小,類型是 short","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"italic:是否斜體,類型是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.enums.BooleanEnum","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"bold:是否加粗,類型是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.enums.BooleanEnum","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"strikeout:是否使用刪除線(這個詞本意是三振出局的意思,應該是與棒球有關)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"color:文本顏色,值使用的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"org.apache.poi.ss.usermodel.IndexedColors","attrs":{}}],"attrs":{}},{"type":"text","text":",依然有類型不一致的情況","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"underline:下劃線,類型是 byte,可以直接使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Font.U_NONE","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Font.U_SINGLE","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Font.U_DOUBLE","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Font.U_SINGLE_ACCOUNTING","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Font.U_DOUBLE_ACCOUNTING","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以這麼定義:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\n// 頭背景設置成紅色 IndexedColors.RED.getIndex()\n@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 10)\n// 頭字體設置成 20\n@HeadFontStyle(fontHeightInPoints = 20)\n// 內容的背景設置成綠色 IndexedColors.GREEN.getIndex()\n@ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 17)\n// 內容字體設置成 20\n@ContentFontStyle(fontHeightInPoints = 20)\npublic class FormatStyleCellItem {\n // 字符串的頭背景設置成粉紅 IndexedColors.PINK.getIndex()\n @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 14)\n // 字符串的頭字體設置成 20\n @HeadFontStyle(fontHeightInPoints = 30)\n // 字符串的內容的背景設置成天藍 IndexedColors.SKY_BLUE.getIndex()\n @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)\n // 字符串的內容字體設置成 20\n @ContentFontStyle(fontHeightInPoints = 30)\n @ExcelProperty(\"字符串標題\")\n private String string;\n @ExcelProperty(\"日期標題\")\n private Date date;\n @ExcelProperty(\"數字標題\")\n private Double doubleData;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/38/384248552b672c8498126acd2308f57e.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"類對象定義格式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種方式可以說是純手工組裝數據了,使用的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.data.WriteCellData","attrs":{}}],"attrs":{}},{"type":"text","text":"類,這個類相當於是單元格的定義,通過設置","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.enums.CellDataTypeEnum","attrs":{}}],"attrs":{}},{"type":"text","text":"枚舉類型的 type 屬性,可以指明當前單元格格式。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"守恆定律一直存在。這種方式靈活度很高,可以精細到具體的單元格格式,但是繁瑣程度也增加了。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"超鏈接","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"超鏈接使用的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.data.HyperlinkData","attrs":{}}],"attrs":{}},{"type":"text","text":"類,需要設置地址、超鏈類型(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.data.HyperlinkData.HyperlinkType","attrs":{}}],"attrs":{}},{"type":"text","text":"枚舉),然後將值寫入到","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteCellData","attrs":{}}],"attrs":{}},{"type":"text","text":"對象的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"hyperlinkData","attrs":{}}],"attrs":{}},{"type":"text","text":"屬性即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 設置超鏈接\nHyperlinkData hyperlinkData = new HyperlinkData();\nhyperlinkData.setAddress(\"https://www.howardliu.cn\");\nhyperlinkData.setHyperlinkType(HyperlinkType.URL);\nWriteCellData hyperlink = new WriteCellData<>(\"網站\");\nhyperlink.setHyperlinkData(hyperlinkData);\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"備註","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"備註使用的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.data.CommentData","attrs":{}}],"attrs":{}},{"type":"text","text":"類,需要設置作者、備註內容(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.data.RichTextStringData","attrs":{}}],"attrs":{}},{"type":"text","text":"類型),因爲備註的默認大小是單元格大小,如果感覺太小,還可以設置相對高度和寬度。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 設置備註\nCommentData commentData = new CommentData();\ncommentData.setAuthor(\"Howard Liu\");\ncommentData.setRichTextStringData(new RichTextStringData(\"這是一個備註\"));\n// 備註的默認大小是按照單元格的大小 這裏想調整到 4 個單元格那麼大 所以向後 向下 各額外佔用了一個單元格\ncommentData.setRelativeLastColumnIndex(1);\ncommentData.setRelativeLastRowIndex(1);\nWriteCellData comment = new WriteCellData<>(\"備註的單元格信息\");\ncomment.setCommentData(commentData);\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"公式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"公式使用的是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.data.FormulaData","attrs":{}}],"attrs":{}},{"type":"text","text":"類,可以直接設置","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"formulaValue","attrs":{}}],"attrs":{}},{"type":"text","text":"公式,不過官方不太推薦使用公式。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 設置公式\nFormulaData formulaData = new FormulaData();\n// 將 123456789 中的第一個數字替換成 2\n// 這裏只是例子 如果真的涉及到公式 能內存算好儘量內存算好 公式能不用盡量不用\nformulaData.setFormulaValue(\"REPLACE(123456789,1,1,2)\");\nWriteCellData formula = new WriteCellData<>();\nformula.setFormulaData(formulaData);\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"單元格格式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過類定義單元格格式,與通過註解定義本質是一樣的。所以與註解","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HeadStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HeadFontStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ContentStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ContentFontStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"對應,設置單元格格式的類是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteCellStyle","attrs":{}}],"attrs":{}},{"type":"text","text":",設置字體的類是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteFont","attrs":{}}],"attrs":{}},{"type":"text","text":"。其中這些類的屬性與註解的也是類似,不再贅述太多,直接上例子。(其實我覺得使用類定義格式的場景不多,真的碰到了,看看類定義就明白了)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 設置單個單元格的樣式 當然樣式 很多的話 也可以用註解等方式。\nWriteCellStyle writeCellStyleData = new WriteCellStyle();\n// 這裏需要指定 FillPatternType 爲 FillPatternType.SOLID_FOREGROUND 不然無法顯示背景顏色。\nwriteCellStyleData.setFillPatternType(FillPatternType.SOLID_FOREGROUND);\n// 背景綠色\nwriteCellStyleData.setFillForegroundColor(IndexedColors.GREEN.getIndex());\nWriteCellData writeCellStyle = new WriteCellData<>(\"單元格樣式\");\nwriteCellStyle.setWriteCellStyle(writeCellStyleData);\nwriteCellStyle.setType(CellDataTypeEnum.STRING);\n\n// 設置單個單元格多種樣式\nRichTextStringData richTextStringData = new RichTextStringData();\nrichTextStringData.setTextString(\"紅色綠色默認\");\n// 前 2 個字紅色\nWriteFont writeFont = new WriteFont();\nwriteFont.setColor(IndexedColors.RED.getIndex());\nrichTextStringData.applyFont(0, 2, writeFont);\n// 接下來 2 個字綠色\nwriteFont = new WriteFont();\nwriteFont.setColor(IndexedColors.GREEN.getIndex());\nrichTextStringData.applyFont(2, 4, writeFont);\nWriteCellData richTest = new WriteCellData<>();\nrichTest.setType(CellDataTypeEnum.RICH_TEXT_STRING);\nrichTest.setRichTextStringDataValue(richTextStringData);\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/20/205805c11774b72c29638d24cc5b4a8b.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"攔截器定義格式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了直接使用類定義格式,我們還可以藉助攔截器實現。(這裏在名稱上會有一些歧義,所用的類對象命名都是 xxxStrategy,翻譯過來就是 xxx 策略,但是官方對其命名爲攔截器)","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"已有攔截器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前面示例中使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteCellStyle","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteFont","attrs":{}}],"attrs":{}},{"type":"text","text":"可以實現單元格的樣式,如果想要實現整行數據都是相同的格式,可以藉助","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.style.HorizontalCellStyleStrategy","attrs":{}}],"attrs":{}},{"type":"text","text":"攔截器。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"/**\n * 使用已有策略實現自定義樣式\n *\n *
    \n *
  • HorizontalCellStyleStrategy 每一行的樣式都一樣 或者隔行一樣
  • \n *
  • AbstractVerticalCellStyleStrategy 每一列的樣式都一樣 需要自己回調每一頁
  • \n *
\n */\nprivate static void writeByCellStyleStrategy() {\n String fileName = defaultFileName(\"writeByCellStyleStrategy\");\n\n // 表頭策略\n WriteCellStyle headWriteCellStyle = new WriteCellStyle();\n // 背景設置爲紅色\n headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());\n WriteFont headWriteFont = new WriteFont();\n headWriteFont.setFontHeightInPoints((short) 40);\n headWriteCellStyle.setWriteFont(headWriteFont);\n\n // 表體策略\n WriteCellStyle contentWriteCellStyle = new WriteCellStyle();\n // 這裏需要指定 FillPatternType 爲 FillPatternType.SOLID_FOREGROUND 不然無法顯示背景顏色。表頭默認了 FillPatternType 所以可以不指定\n contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);\n // 背景綠色\n contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());\n WriteFont contentWriteFont = new WriteFont();\n // 字體大小\n contentWriteFont.setFontHeightInPoints((short) 20);\n contentWriteCellStyle.setWriteFont(contentWriteFont);\n\n // 這個策略是 頭是頭的樣式 內容是內容的樣式 其他的策略可以自己實現\n HorizontalCellStyleStrategy horizontalCellStyleStrategy =\n new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);\n\n // 這裏 需要指定寫用哪個 class 去寫,然後寫到第一個 sheet,名字爲模板 然後文件流會自動關閉\n EasyExcelFactory.write(fileName)\n .head(Item.class)\n .registerWriteHandler(horizontalCellStyleStrategy)\n .sheet()\n .doWrite(sampleItems());\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/de/debdbc6ad0d91200425e564dd73b219d.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正如上面的結果,如果我們某個單元格數據比較長,可能會有遮擋,這個時候我們可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy","attrs":{}}],"attrs":{}},{"type":"text","text":"實現自動列寬調整。不過這個不太精確,但聊勝於無。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeUseLongestMatchColumnWidthStyleStrategy() {\n String fileName = defaultFileName(\"writeUseLongestMatchColumnWidthStyleStrategy\");\n EasyExcelFactory.write(fileName)\n .head(Item.class)\n .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())\n .sheet()\n .doWrite(sampleItems());\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0b/0bd316ebf834435d3d2ef979f5bc9e45.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到,確實不夠精確。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"自定義攔截器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面展示的攔截器,都是實現了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.handler.WriteHandler","attrs":{}}],"attrs":{}},{"type":"text","text":"接口,然後使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.builder.AbstractExcelWriterParameterBuilder.registerWriteHandler","attrs":{}}],"attrs":{}},{"type":"text","text":"方法註冊到寫函數中。所以,我們也可能根據需要,自己定義需要的攔截器。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種自定義攔截器屬於低級功能,需要了解很多底層設計和 API,鑑於篇幅,本文沒有辦法覆蓋,這裏只給出例子。如果有需要,可以留言溝通。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如,我們需要某些單元格設置數據驗證,展現形式就是下拉菜單,我們可以這樣寫:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class ColumnValidationWriteHandler implements SheetWriteHandler {\n @Override\n public void afterSheetCreate(SheetWriteHandlerContext context) {\n // 區間設置 第一列第一行和第二行的數據。由於第一行是頭,所以第一、二行的數據實際上是第二三行\n CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);\n DataValidationHelper helper = context.getWriteSheetHolder().getSheet().getDataValidationHelper();\n DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {\"測試 1\", \"測試 2\"});\n DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);\n context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們需要將某個單元格的格式設置爲超鏈,也可以使用攔截器:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class CellStyleWriteHandler implements CellWriteHandler {\n @Override\n public void afterCellDispose(CellWriteHandlerContext context) {\n Cell cell = context.getCell();\n // 這裏可以對 cell 進行任何操作\n if (BooleanUtils.isTrue(context.getHead()) && cell.getColumnIndex() == 0) {\n CreationHelper createHelper = context.getWriteSheetHolder().getSheet().getWorkbook().getCreationHelper();\n Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);\n hyperlink.setAddress(\"https://www.howardliu.cn\");\n cell.setHyperlink(hyperlink);\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/82/82faa10d9a3d3e0a04befe45ddff1e19.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"合併單元格","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"EasyExcel 提供的合併單元格功能比較簡單,有兩種方式:基於註解的合併、基於攔截器的合併。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"註解","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基於註解的合併單元格提供了兩個註解:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"OnceAbsoluteMerge","attrs":{}}],"attrs":{}},{"type":"text","text":"註解實現指定位置的合併","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ContentLoopMerge","attrs":{}}],"attrs":{}},{"type":"text","text":"這個是內容的循環合併,指定某一列每幾行合併。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 將第 6-7 行的 2-3 列合併成一個單元格\n@OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)\n@Data\npublic class MergeCellItem {\n @ContentLoopMerge(eachRow = 2)\n @ExcelProperty(\"字符串標題\")\n private String string;\n @ExcelProperty(\"日期標題\")\n private Date date;\n @ExcelProperty(\"數字標題\")\n private Double doubleData;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0f/0fb0bdb63c4bd40cc328d2a233f99c19.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"攔截器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"攔截器合併也是有兩種,對應着註解:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"OnceAbsoluteMergeStrategy","attrs":{}}],"attrs":{}},{"type":"text","text":",相對位置合併","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"LoopMergeStrategy","attrs":{}}],"attrs":{}},{"type":"text","text":"循環合併","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeMergeCellCustom() {\n String fileName = defaultFileName(\"writeMergeCellCustom\");\n // 每隔 2 行會合並\n // 把 eachColumn 設置成 3 也就是我們數據的長度,所以就第一列會合並。當然其他合併策略也可以自己寫\n LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);\n EasyExcelFactory.write(fileName)\n .head(Item.class)\n .registerWriteHandler(loopMergeStrategy)\n .sheet()\n .doWrite(sampleItems());\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fb/fbe852e0dfc768800872416a12717482.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"文末總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文從實戰角度說了一下 EasyExcel 如果實現寫出好看的表格,EasyExcel中提供了很多用於格式化的註解、攔截器,可以實現通用的格式化輸出,如果還有更加個性化的格式要求,也可以自定義攔截器實現。接下來聊一下如何填充模板。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"推薦閱讀","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.howardliu.cn/effective-java-easyexcel-action-write/","title":"","type":null},"content":[{"type":"text","text":"阿里開源的這個庫,讓 Excel 導出不再複雜(簡簡單單的寫)","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.howardliu.cn/effective-java-easyexcel-action-write-pretty/","title":"","type":null},"content":[{"type":"text","text":"阿里開源的這個庫,讓 Excel 導出不再複雜(既要能寫,還要寫的好看)","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.howardliu.cn/effective-java-easyexcel-action-fill/","title":"","type":null},"content":[{"type":"text","text":"阿里開源的這個庫,讓Excel導出不再複雜(填充模板的使用指南)","attrs":{}}]}]}]}],"attrs":{}},{"type":"horizontalrule","attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你好,我是看山。遊於碼界,戲享人生。如果文章對您有幫助,請點贊、收藏、關注。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#d4d4d4","name":"user"}}],"text":"👇🏻歡迎關注我的公衆號「看山的小屋」,領取精選資料👇🏻","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9e/9e305acd1cca75053c144cb28adc6061.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章