poi生成word固定表格列宽
一、需求
根据数据库生成文档,文档包含大量表格,表格数量不确定,每个表格行数也不确定。
二、实现方案
引入依赖
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.4</version>
</dependency>
代码实现
- 静态常量
public static final int FONT_SIZE = 9; public static final TitleStyle[] titleStyles = {new TitleStyle("一级标题", 44, true),new TitleStyle("二级标题", 36, true),new TitleStyle("三级标题", 32, true),new TitleStyle("四级标题", 30, false)};public record TitleStyle(String name, int fontSize, boolean bold) {}
- 创建文档
/*** A3 Portrait 16840 23814 720* A3 Landscape 23814 16940 720* A4 Portrait 11907 16840 720* A4 Landscape 16840 11907 720*/ public void createDocument(int width, int height, int top, int right, int bottom, int left) {XWPFDocument document = new XWPFDocument();CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();CTPageSz pageSz = sectPr.addNewPgSz();pageSz.setW(BigInteger.valueOf(width));pageSz.setH(BigInteger.valueOf(height));pageSz.setOrient(width > height ? STPageOrientation.LANDSCAPE : STPageOrientation.PORTRAIT);CTPageMar pageMar = sectPr.addNewPgMar();pageMar.setTop(BigInteger.valueOf(top));pageMar.setRight(BigInteger.valueOf(right));pageMar.setBottom(BigInteger.valueOf(bottom));pageMar.setLeft(BigInteger.valueOf(left));for (int i = 0; i < titleStyles.length; i++) {addCustomHeadingStyle(document, titleStyles[i], i + 1);} }private static void addCustomHeadingStyle(XWPFDocument document, TitleStyle titleStyle, int headingLevel) {CTStyle ctStyle = CTStyle.Factory.newInstance();ctStyle.setStyleId(titleStyle.name());CTString styleName = CTString.Factory.newInstance();styleName.setVal(titleStyle.name());ctStyle.setName(styleName);CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();indentNumber.setVal(BigInteger.valueOf(headingLevel));// lower number > style is more prominent in the formats barctStyle.setUiPriority(indentNumber);CTOnOff onOffNull = CTOnOff.Factory.newInstance();ctStyle.setUnhideWhenUsed(onOffNull);// style shows up in the formats barctStyle.setQFormat(onOffNull);// style defines a heading of the given levelCTPPr ppr = CTPPr.Factory.newInstance();ppr.setOutlineLvl(indentNumber);ctStyle.setPPr(ppr);CTRPr rpr = CTRPr.Factory.newInstance();// font sizeCTHpsMeasure ctHpsMeasure = CTHpsMeasure.Factory.newInstance();ctHpsMeasure.setVal(BigInteger.valueOf(titleStyle.fontSize()));rpr.setSz(ctHpsMeasure);rpr.setSzCs(ctHpsMeasure);// fond boldif (titleStyle.bold()) {CTOnOff b = rpr.addNewB();b.setVal(STOnOff.TRUE);}ctStyle.setRPr(rpr);XWPFStyle style = new XWPFStyle(ctStyle);style.setType(STStyleType.PARAGRAPH);XWPFStyles styles = document.createStyles();styles.addStyle(style); }
- 创建标题
public void createTitle(int level, int id, String title) {XWPFParagraph paragraph = document.createParagraph();paragraph.setStyle(titleStyles[level - 1].name());XWPFRun run = paragraph.createRun();run.setText(title);CTBookmark bookmark = paragraph.getCTP().addNewBookmarkStart();bookmark.setName("bm_" + id);bookmark.setId(BigInteger.valueOf(id));paragraph.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(id)); }
- 创建表格
public XWPFTable createTable(int width, TableTitle... titles) {XWPFTable table = document.createTable(1, titles.length);CTTblPr TblPr = table.getCTTbl().addNewTblPr();TblPr.addNewTblLayout().setType(STTblLayoutType.FIXED); // 布局固定,不随内容改变宽度CTTblWidth tblW = TblPr.isSetTblW() ? TblPr.getTblW() : TblPr.addNewTblW();tblW.setType(STTblWidth.DXA);tblW.setW(BigInteger.valueOf(width));// 表格边颜色CTTblBorders borders = TblPr.addNewTblBorders();tableBorderStyle(borders.addNewInsideH());tableBorderStyle(borders.addNewInsideV());tableBorderStyle(borders.addNewLeft());tableBorderStyle(borders.addNewRight());tableBorderStyle(borders.addNewTop());tableBorderStyle(borders.addNewBottom());XWPFTableRow row = table.getRow(0);for (int i = 0; i < titles.length; i++) {TableTitle title = titles[i];XWPFTableCell cell = row.getCell(i);cell.setColor("3a60a0");if (title.width() > 0) {CTTcPr ctTcPr = cell.getCTTc().addNewTcPr();CTTblWidth tblWidth = ctTcPr.isSetTcW() ? ctTcPr.getTcW() : ctTcPr.addNewTcW();tblWidth.setW(BigInteger.valueOf(title.width()));tblWidth.setType(STTblWidth.DXA);}XWPFParagraph paragraphArray = cell.getParagraphArray(0);XWPFRun run = paragraphArray.createRun();run.setText(title.name());run.setBold(true);run.setColor("f5f5f5a");run.setFontSize(FONT_SIZE);paragraphArray.setAlignment(ParagraphAlignment.CENTER); // 水平居中}return table; }public record TableTitle(String name, int width) {}
- 创建空行
public void createBlankLine() {document.createParagraph(); }
- 创建表格行
XWPFTableRow row = table.createRow();
- 获取单元格
XWPFTableCell cell = row.getCell(0);
- 创建超链接
public static void createHyperlinkRunToAnchor(XWPFParagraph paragraph, String text, int id) {paragraph.setVerticalAlignment(TextAlignment.CENTER);CTHyperlink ctHyperlink = paragraph.getCTP().addNewHyperlink();ctHyperlink.setAnchor("bm_" + id);ctHyperlink.addNewR();XWPFHyperlinkRun hyperlinkRun = new XWPFHyperlinkRun(ctHyperlink, ctHyperlink.getRArray(0), paragraph);hyperlinkRun.setText(text);hyperlinkRun.setColor("0000FF");hyperlinkRun.setUnderline(UnderlinePatterns.SINGLE);hyperlinkRun.setFontSize(FONT_SIZE); }public static void createHyperlinkRunToFile(XWPFParagraph paragraph, String text, String fileName, Integer id) {paragraph.setVerticalAlignment(TextAlignment.CENTER);String uri = fileName;if (id != null) {uri += "#bm_" + id;}String rId = paragraph.getDocument().getPackagePart().addExternalRelationship(uri, XWPFRelation.HYPERLINK.getRelation()).getId();CTHyperlink ctHyperlink = paragraph.getCTP().addNewHyperlink();ctHyperlink.setId(rId);ctHyperlink.addNewR();XWPFHyperlinkRun hyperlinkRun = new XWPFHyperlinkRun(ctHyperlink, ctHyperlink.getRArray(0), paragraph);hyperlinkRun.setText(text);hyperlinkRun.setColor("0000FF");hyperlinkRun.setUnderline(UnderlinePatterns.SINGLE);hyperlinkRun.setFontSize(FONT_SIZE); }