poi操作表格table
表格對於頁面的佈局具有重大的意義,正因為其靈活性,所以用模板引擎處理word中的Table時,顯得並不是那麼簡單,本文將討論如何利用poi-tl(1.2.0版本)提供的工具來簡化表格處理。關於如何使用poi-tl,參見中文Wiki
表格模板
poi-tl預設實現了N行N列的樣式(如下圖),同時提供了當資料為空時,展示一行空資料的文案(如下圖中的No Data Descs)。
在poi-tl的1.2.0版本中,表格模板語法是#,資料結構是com.deepoove.poi.data.TableRenderData。
1. 表格頭使用headers[]定義,支援設定背景色
2. 表格資料使用datas[]定義,不同列的資料在datas中使用分號隔開
3. 寬度使用width定義
4. 無資料文案使用noDatadesc定義
{
"datas": [
"beijing;beijing",
"zhejiang;hangzhou"
],
"headers": [
{
"style": {
"color": "1E915D",
"fontSize": 0
},
"text": "province"
},
{
"style": {
"color": "1E915D",
"fontSize": 0
},
"text": "city"
}
],
"noDatadesc": "no datas",
"width": 0
}
具體Java程式碼參考:
@Test
public void testTable() throws Exception {
Map<String, Object> datas = new HashMap<String, Object>() {
{
// 有表格頭 有資料
put("table", new TableRenderData(new ArrayList<RenderData>() {
{
add(new TextRenderData("1E915D", "province"));
add(new TextRenderData("1E915D", "city"));
}
}, new ArrayList<Object>() {
{
add("beijing;beijing");
add("zhejiang;hangzhou");
}
}, "no datas", 0));
}
};
XWPFTemplate template = XWPFTemplate.compile("src/test/resources/table.docx").render(datas);
FileOutputStream out = new FileOutputStream("out_table.docx");
template.write(out);
out.flush();
out.close();
template.close();
}
表格的寬度怎麼定義的
是一個點的二十分之一,或者是1440分之一英寸。官方解釋如下:
dxa - Specifies that the value is in twentieths of a point (1/1440 of an inch).
首先1英寸=2.54釐米,A4紙大小為21cm*29.7cm。
如果這個width設定成5670,則表示這個表格的寬度是10cm。
拋開對這個單位理解的難度,我們最常見的應該是寬度自適應和寬度最大。
如果在poi-tl中設定了width=0,則表格是寬度自適應的。
以A4紙為例,頁面寬度為21cm,左右頁邊距各位3.17cm,則表格的width=(21-3.17*2)/2.54*1440,大約為8310。
合併單元格
但是,很多業務場景並不僅限於如此簡單的表格佈局,產品需求總是豐富多彩的。poi-tl對XWPFDocument進行了封裝,增強實現了一些基本功能。在com.deepoove.poi.NiceXWPFDocument
中提供了合併的功能。
/**
* 合併行單元格
* @param table
* @param row
* @param fromCol
* @param toCol
*/
public void mergeCellsHorizonal(XWPFTable table, int row, int fromCol,
int toCol)
/**
* 合併列單元格
* @param table
* @param col
* @param fromRow
* @param toRow
*/
public void mergeCellsVertically(XWPFTable table, int col, int fromRow,
int toRow)
自定義表格之新建表格
我們完全可以從無到有去建立一個新的表格。
- 無需事先建立表格,在docx中,直接輸入{{table}}
- 預設{{table}}是文字模板,我們需要通過registerPolicy設定此模板為自定義模板。
XWPFTemplate template = XWPFTemplate.compile("src/test/resources/complex.docx");
template.registerPolicy("table", new MyTableRenderPolicy());
- 新建MyTableRenderPolicy.java,實現
RenderPolicy
介面
@Override
public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
NiceXWPFDocument doc = template.getXWPFDocument();
RunTemplate runTemplate = (RunTemplate) eleTemplate;
XWPFRun run = runTemplate.getRun();
if (null == data) return;
//doc.insertNewTable(run, row, col);
//doc.mergeCellsHorizonal(table, 1, 0, 1);
//...
runTemplate.getRun().setText("", 0);
}
至此,我們持有了NiceXWPFDocument和XWPFRun物件,可以插入表格,合併單元格等操作。
自定義表格之動態處理已有表格
對於事先已知道部分表格樣式,我們只需要處理剩餘部分的表格可以採用此方式。
比如下圖,我們在模板中設計好表格頭和表格未的樣式,表格中間的資料則可以動態處理。
- 定義如圖的模板,在表格內輸入模板元素{{table}}
- 通過registerPolicy設定此模板為自定義模板
- 新建MyTableRenderPolicy.java,繼承
DynamicTableRenderPolicy
。
public class MyTableRenderPolicy extends DynamicTableRenderPolicy {
@Override
public void render(XWPFTable table, Object data) {
//table.getRow(1).getCell(0)
//XWPFTableRow row = table.insertNewTableRow(1);
//table.removeRow(1);
}
}
至此,我們可以通過XWPFTable物件對錶格進行刪除行列、增加行列、設定文字等操作。