1. 程式人生 > >poi操作表格table

poi操作表格table

表格對於頁面的佈局具有重大的意義,正因為其靈活性,所以用模板引擎處理word中的Table時,顯得並不是那麼簡單,本文將討論如何利用poi-tl(1.2.0版本)提供的工具來簡化表格處理。關於如何使用poi-tl,參見中文Wiki

表格模板

poi-tl預設實現了N行N列的樣式(如下圖),同時提供了當資料為空時,展示一行空資料的文案(如下圖中的No Data Descs)。
image

在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)

自定義表格之新建表格

我們完全可以從無到有去建立一個新的表格。

  1. 無需事先建立表格,在docx中,直接輸入{{table}}
  2. 預設{{table}}是文字模板,我們需要通過registerPolicy設定此模板為自定義模板。
XWPFTemplate template = XWPFTemplate.compile("src/test/resources/complex.docx");
template.registerPolicy("table", new MyTableRenderPolicy());
  1. 新建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物件,可以插入表格,合併單元格等操作。

自定義表格之動態處理已有表格

對於事先已知道部分表格樣式,我們只需要處理剩餘部分的表格可以採用此方式。

比如下圖,我們在模板中設計好表格頭和表格未的樣式,表格中間的資料則可以動態處理。
image

  1. 定義如圖的模板,在表格內輸入模板元素{{table}}
  2. 通過registerPolicy設定此模板為自定義模板
  3. 新建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物件對錶格進行刪除行列、增加行列、設定文字等操作。