专业的编程技术博客社区

网站首页 > 博客文章 正文

Apache POI在指定位置插入表格(在apache配置文件中加载模块)

baijin 2024-08-31 16:09:32 博客文章 3 ℃ 0 评论

接到的需求是在模板表格的指定位置再插入表格。比如在模板的${proTable}处插入表格。

依赖的包

<dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi</artifactId>
 <version>3.15</version>
</dependency>
<dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi-ooxml</artifactId>
 <version>3.15</version>
</dependency>

插入表格

由于是在表格里的指定地方插入表格,所以要遍历表格的每个单元格,查找到要插入点的占位符。

// 处理表
 public CustomXWPFDocument generateCoopApplyWord(Map<String, Object> param, String template) {
 CustomXWPFDocument doc = null;
 try {
 OPCPackage pack = POIXMLDocument.openPackage(template);
 doc = new CustomXWPFDocument(pack);
 if (param != null && param.size() > 0) { 
 //处理表格
 Iterator<XWPFTable> it = doc.getTablesIterator();
 while (it.hasNext()) {
 XWPFTable table = it.next();
 List<XWPFTableRow> rows = table.getRows();
 for (XWPFTableRow row : rows) {
 List<XWPFTableCell> cells = row.getTableCells();
 for (XWPFTableCell cell : cells) {
 List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
 insertTable("${proTable}",param, cell); // 在"${proTable}"处插入表格 
 }
 } 
 }
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 return doc;
 }


// 在key处插入表格
 private void insertTable(String key, Map<String, Object> param, XWPFTableCell cell) {
 List<XWPFParagraph> paragraphList = cell.getParagraphs();
 if (paragraphList != null && paragraphList.size() > 0) {
 for (XWPFParagraph paragraph : paragraphList) {
 List<XWPFRun> runs = paragraph.getRuns();
 for (XWPFRun run : runs) {
 String text = run.getText(0);
 if (text != null) {
 if (text.indexOf(key) >= 0) {
 insertWhereKindTable(paragraph, param, cell);
 }
 }
 }
 }
 }
 }


// 插入并设置表格的值
 private void insertWhereKindTable(XWPFParagraph paragraph, Map<String, Object> param, XWPFTableCell cell) {
 // 得到这个指定位置的游标
 XmlCursor cursor = paragraph.getCTP().newCursor();
		// 在cursor插入表格
 XWPFTable tableOne = cell.insertNewTbl(cursor);// ---这个是关键
		// 如果自动生成了一行,可以删掉
 boolean a = tableOne.removeRow(0);
		// 添加属性
 CTTblGrid grid = tableOne.getCTTbl().addNewTblGrid();
 grid.addNewGridCol().setW(BigInteger.valueOf(2000));
 grid.addNewGridCol().setW(BigInteger.valueOf(2000));
 grid.addNewGridCol().setW(BigInteger.valueOf(2000));
		// 设置边框样式
 tableBorderStyle(tableOne);
		// 这里是根据前端传过来的数据来填充表格
 List<Map<String, Object>> tableValueList = (List<Map<String, Object>>) param.get("fore_com_list");
 XWPFTableRow tableOneRowOne = tableOne.createRow();
 tableOneRowOne.setHeight(380);
 tableOneRowOne.addNewTableCell().setText("专业");
 tableOneRowOne.addNewTableCell().setText("工作量");
 tableOneRowOne.addNewTableCell().setText("协作比例");
 tableOneRowOne.addNewTableCell().setText("协作费用");
 for (int i = 0; i < tableValueList.size(); i++) {
 Map<String, Object> map = tableValueList.get(i);
 XWPFTableRow tableRow = tableOne.createRow();
 tableRow.setHeight(380);
 tableRow.getCell(0).setText((String) map.get("CoopProfessionName"));
 tableRow.getCell(1).setText(String.valueOf(map.get("CoopWorkProportion")));
 tableRow.getCell(2).setText(String.valueOf(map.get("CoopProportion")));
 tableRow.getCell(3).setText(String.valueOf(map.get("CoopPrice")));
 }
		
		// 设置单元格样式
 tableCellStyle(tableOne, 1500);
 }


由于创建的新表格没有属性,比如设置边框样式,行高列宽等。POI给出了方法去设置这些属性。POI处理文档都是解析成xml格式。这里是截取部分,比如:

<w:tbl>
 <w:tblPr>
 <w:tblStyle w:val="12"/>
 <w:tblW w:w="9418" w:type="dxa"/>
 <w:jc w:val="center"/>
 <w:tblInd w:w="0" w:type="dxa"/>
 <w:tblLayout w:type="fixed"/>
 <w:tblCellMar>
 <w:top w:w="0" w:type="dxa"/>
 <w:left w:w="108" w:type="dxa"/>
 <w:bottom w:w="0" w:type="dxa"/>
 <w:right w:w="108" w:type="dxa"/>
 </w:tblCellMar>
 </w:tblPr>
 <w:tblGrid>
 <w:gridCol w:w="2058"/>
 <w:gridCol w:w="2236"/>
 <w:gridCol w:w="1455"/>
 <w:gridCol w:w="3669"/>
 </w:tblGrid>
 <w:tr>
 <w:tblPrEx>
 <w:tblLayout w:type="fixed"/>
 <w:tblCellMar>
 <w:top w:w="0" w:type="dxa"/>
 <w:left w:w="108" w:type="dxa"/>
 <w:bottom w:w="0" w:type="dxa"/>
 <w:right w:w="108" w:type="dxa"/>
 </w:tblCellMar>
 </w:tblPrEx>
 <w:trPr>
 <w:trHeight w:val="494" w:hRule="atLeast"/>
 <w:jc w:val="center"/>
 </w:trPr>
 <w:tc>
 <w:tcPr>
 <w:tcW w:w="2058" w:type="dxa"/>
 <w:tcBorders>
 <w:top w:val="single" w:color="auto" w:sz="8" w:space="0"/>
 <w:left w:val="single" w:color="auto" w:sz="8" w:space="0"/>
 <w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0"/>
 <w:right w:val="single" w:color="auto" w:sz="4" w:space="0"/>
 </w:tcBorders>
 <w:vAlign w:val="center"/>
 </w:tcPr>
 <w:p>
 <w:pPr>
 <w:widowControl/>
 <w:jc w:val="center"/>
 <w:rPr>
 <w:rFonts w:ascii="宋体" w:hAnsi="宋体" w:cs="宋体"/>
 <w:szCs w:val="21"/>
 </w:rPr>
 </w:pPr>
 <w:r>
 <w:rPr>
 <w:rFonts w:hint="eastAsia" w:ascii="宋体" w:hAnsi="宋体" w:cs="宋体"/>
 <w:szCs w:val="21"/>
 </w:rPr>
 <w:t>项目名称</w:t>
 </w:r>
 </w:p>
 </w:tc>

所以,如果要为新的表格设置属性,就要去操作这些节点,得到这个节点后就可以对其添加设置自己所需属性。其中:

  • CTTbl 就对应上面的 <w:tbl></w:tbl> ,得到表格属性
  • CTRow 就对应上面的 <w:tr></w:tr> ,得到行属性
  • CTTc 就对应上面的 <w:tc></w:tc> ,得到列属性
  • CTP 就对应上面的 <w:p></w:p> ,得到段落属性
  • CTR 就对应上面的 <w:r></w:r> ,得到run属性,操作文本
// 设置表格边框
 private void tableBorderStyle(XWPFTable table){
 //表格属性
 CTTblPr tablePr = table.getCTTbl().addNewTblPr();
 //表格宽度
 //CTTblWidth width = tablePr.addNewTblW();
 CTJc ctJc = tablePr.addNewJc();
 ctJc.setVal(STJc.Enum.forString("center"));
 //width.setW(BigInteger.valueOf(7000));
 //width.setType(STTblWidth.DXA);
 //表格颜色
 CTTblBorders borders=table.getCTTbl().getTblPr().addNewTblBorders();
 //表格内部横向表格颜色
 CTBorder hBorder=borders.addNewInsideH();
 hBorder.setVal(STBorder.Enum.forString("single"));
 hBorder.setSz(new BigInteger("1"));
 hBorder.setColor("000000");
 //表格内部纵向表格颜色
 CTBorder vBorder=borders.addNewInsideV();
 vBorder.setVal(STBorder.Enum.forString("single"));
 vBorder.setSz(new BigInteger("1"));
 vBorder.setColor("000000");
 //表格最左边一条线的样式
 CTBorder lBorder=borders.addNewLeft();
 lBorder.setVal(STBorder.Enum.forString("single"));
 lBorder.setSz(new BigInteger("1"));
 lBorder.setColor("000000");
 //表格最左边一条线的样式
 CTBorder rBorder=borders.addNewRight();
 rBorder.setVal(STBorder.Enum.forString("single"));
 rBorder.setSz(new BigInteger("1"));
 rBorder.setColor("000000");
 //表格最上边一条线(顶部)的样式
 CTBorder tBorder=borders.addNewTop();
 tBorder.setVal(STBorder.Enum.forString("single"));
 tBorder.setSz(new BigInteger("1"));
 tBorder.setColor("000000");
 //表格最下边一条线(底部)的样式
 CTBorder bBorder=borders.addNewBottom();
 bBorder.setVal(STBorder.Enum.forString("single"));
 bBorder.setSz(new BigInteger("1"));
 bBorder.setColor("000000");
 }


// 添加单元格属性
 private void tableCellStyle(XWPFTable table, int cellWidth) {
 List<XWPFTableRow> tableRows = table.getRows();
 for (int i = 0; i < tableRows.size(); i++) {
 XWPFTableRow xwpfTableRow = tableRows.get(i);
 List<XWPFTableCell> cellList = xwpfTableRow.getTableCells();
 for (XWPFTableCell tableCell : cellList) {
 CTTc ctTc = tableCell.getCTTc();
 CTTcPr ctTcPr = ctTc.addNewTcPr();
 ctTcPr.addNewTcW().setW(BigInteger.valueOf(cellWidth));
 ctTcPr.addNewVAlign().setVal(STVerticalJc.CENTER);
 ctTcPr.addNewGridSpan().setVal(BigInteger.valueOf(1));
 // 添加单元格里的run属性
 CTP ctp = ctTc.getPList().get(0);
 CTPPr ctpPr = ctp.addNewPPr();
 ctpPr.addNewWidowControl();
 ctpPr.addNewJc().setVal(STJc.CENTER);
 CTParaRPr ctParaRPr = ctpPr.addNewRPr();
 CTFonts ctFontsp = ctParaRPr.addNewRFonts();
 ctFontsp.setAscii("宋体");
 ctFontsp.setHAnsi("宋体");
 ctFontsp.setCs("宋体");
 ctParaRPr.addNewSzCs().setVal(BigInteger.valueOf(21));
 CTR ctr = ctp.getRList().get(0);
 //CTR ctr = ctp.addNewR();
 CTRPr ctrPr = ctr.addNewRPr();
 CTFonts ctFonts = ctrPr.addNewRFonts();
 ctFonts.setHint(STHint.Enum.forString("eastAsia"));
 ctFonts.setEastAsia("宋体");
 ctFonts.setAscii("宋体");
 ctFonts.setHAnsi("宋体");
 ctFonts.setCs("宋体");
 ctrPr.addNewSzCs().setVal(BigInteger.valueOf(21)); 
 }
 }
 }

把返回的XWPFDocument写入到对应的流中。

FileOutputStream fopts = new FileOutputStream("E://andy.docx");
doc.write(fopts);

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表