package com.rongyichuang.review; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.junit.jupiter.api.Test; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; import java.io.File; import java.io.FileOutputStream; import java.math.BigInteger; /** * 快速验证DOCX表格宽度与签字区域布局 */ public class DocxLayoutTest { private void applyTableLayout(XWPFTable table, int[] colWidthsTwips) { CTTbl ctTbl = table.getCTTbl(); CTTblPr tblPr = ctTbl.getTblPr() == null ? ctTbl.addNewTblPr() : ctTbl.getTblPr(); CTTblWidth tblW = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); tblW.setType(STTblWidth.DXA); int total = 0; for (int w : colWidthsTwips) total += w; tblW.setW(BigInteger.valueOf(total)); CTTblGrid grid = ctTbl.getTblGrid() == null ? ctTbl.addNewTblGrid() : ctTbl.getTblGrid(); while (grid.sizeOfGridColArray() > 0) { grid.removeGridCol(0); } for (int w : colWidthsTwips) { CTTblGridCol col = grid.addNewGridCol(); col.setW(BigInteger.valueOf(w)); } } private void ensureCells(XWPFTableRow row, int cellCount) { int existing = row.getTableCells().size(); for (int i = existing; i < cellCount; i++) { row.addNewTableCell(); } } private void setCellText(XWPFTableCell cell, String text) { while (cell.getParagraphs().size() > 0) { cell.removeParagraph(0); } XWPFParagraph p = cell.addParagraph(); p.setAlignment(ParagraphAlignment.LEFT); XWPFRun run = p.createRun(); run.setFontSize(12); run.setText(text); CTTcPr tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr(); CTTblWidth w = tcPr.isSetTcW() ? tcPr.getTcW() : tcPr.addNewTcW(); w.setType(STTblWidth.DXA); } @Test public void generateSampleDoc() throws Exception { XWPFDocument doc = new XWPFDocument(); XWPFParagraph title = doc.createParagraph(); title.setAlignment(ParagraphAlignment.CENTER); XWPFRun tr = title.createRun(); tr.setText("评审评分表(布局验证)"); tr.setBold(true); tr.setFontSize(18); XWPFTable table = doc.createTable(); applyTableLayout(table, new int[]{6072, 1500, 1500}); XWPFTableRow header = table.getRow(0); ensureCells(header, 3); setCellText(header.getCell(0), "评分项"); setCellText(header.getCell(1), "得分"); setCellText(header.getCell(2), "满分"); for (int i = 1; i <= 5; i++) { XWPFTableRow row = table.createRow(); ensureCells(row, 3); setCellText(row.getCell(0), "示例项目" + i); setCellText(row.getCell(1), String.valueOf(10 * i)); setCellText(row.getCell(2), "100"); } // 签字区 XWPFParagraph spacer = doc.createParagraph(); spacer.setSpacingBefore(200); XWPFTable signTable = doc.createTable(1, 2); applyTableLayout(signTable, new int[]{6500, 2572}); XWPFTableRow row = signTable.getRow(0); ensureCells(row, 2); setCellText(row.getCell(0), "专家评审签字:_______________"); setCellText(row.getCell(1), "签字日期:__________"); File out = new File("d:/code/new-ryc/tmp/docx-layout-sample.docx"); out.getParentFile().mkdirs(); try (FileOutputStream fos = new FileOutputStream(out)) { doc.write(fos); } doc.close(); } }