本文将介绍如何使用Java和Apache POI库将试卷导出为Word文件,并提供打印、装订等功能。同时,将展示实现代码以及效果图。
Apache POI是一个开源的Java库,用于操作各种Microsoft Office格式的文档,包括Word、Excel和PowerPoint。在本文中,我们将介绍如何使用Apache POI来导出Word文件,并实现打印和装订功能。
功能说明
我们的目标是将试卷数据导出为Word文档,以便用户可以方便地打印和装订。下面是我们要实现的功能:
将试卷数据通过Apache POI库导出为Word文件。
Word文档应该具有良好的格式和布局,以确保打印效果良好。
文档的页眉和页脚应该包含相关信息,例如试卷标题和页码。
用户应该能够选择打印选项,并进行必要的页面设置。
用户还可以选择将导出的Word文档进行装订,以便更方便携带和存储。
实现步骤
以下是实现以上功能的基本步骤:
导入依赖:在项目的构建文件中添加Apache POI库的依赖项,以便能够使用其提供的API。
创建试卷模板:使用Word处理软件(如Microsoft Word)创建一个试卷模板,包括适当的格式、样式和布局。这个模板将用作导出的Word文档的基础。
编写Java代码:使用Apache POI的API来读取试卷数据,并将其填充到试卷模板中。这涉及到创建文档对象、段落、表格、样式等,以确保最终生成的Word文档符合要求。
添加页眉和页脚:使用Apache POI的API,在文档中添加适当的页眉和页脚信息,例如试卷标题和页码。
实现打印功能:在导出的Word文档中添加打印选项,使用户可以选择打印设置,如纸张大小、边距等。这可以通过添加相应的表单字段或设置文档属性来完成。
实现装订功能:为了方便用户携带和存储试卷,我们可以添加一个装订选项。这可以是一个简单的复选框,让用户选择是否需要装订导出的Word文档。
测试和调试:在导出功能实现后,进行全面的测试,并根据需要进行调试和优化。
简单示例代码
import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; import java.io.FileOutputStream; import java.math.BigInteger; public class WordExporter { public static void main(String[] args) { try { // 创建文档对象 XWPFDocument document = new XWPFDocument(); // 添加页眉 CTSectPr sectPr = document.getDocument().getBody().addNewSectPr(); XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(document, sectPr); XWPFHeader header = headerFooterPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT); // 设置页眉内容 XWPFParagraph headerParagraph = header.createParagraph(); XWPFRun headerRun = headerParagraph.createRun(); headerRun.setText("试卷标题"); // 创建段落对象 XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); // 设置段落内容 run.setText("这是一份试卷的内容"); // 添加页脚 XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT); // 设置页脚内容 XWPFParagraph footerParagraph = footer.createParagraph(); XWPFRun footerRun = footerParagraph.createRun(); footerRun.setText("页码:"); // 实现打印功能 CTPageMar pageMar = sectPr.addNewPgMar(); pageMar.setLeft(BigInteger.valueOf(720L)); pageMar.setRight(BigInteger.valueOf(720L)); pageMar.setTop(BigInteger.valueOf(720L)); pageMar.setBottom(BigInteger.valueOf(720L)); // 实现装订功能 boolean needBinding = true; if (needBinding) { CTDocProtect protection = document.getDocument().addNewDocumentProtection(); protection.setEnforcement(true); protection.setEdit(STDocProtect.READ_ONLY); protection.setFormatting(STDocProtect.READ_ONLY); protection.setEnforceComments(STDocProtect.COMMENTS_READ_ONLY); protection.setEnforceTrackedChanges(STDocProtect.READ_ONLY); } // 保存文档 FileOutputStream out = new FileOutputStream("试卷.docx"); document.write(out); out.close(); System.out.println("Word文件导出成功!"); } catch (Exception e) { System.out.println("导出Word文件时发生错误:" + e.getMessage()); } } }
扩展示例
当然我们往往都需要比较复杂的功能。
例如:将试卷导出word,并可以打印,装订。
效果图
文章来源:https://www.toymoban.com/diary/java/481.html
完整示例代码
package com.xxxxx.business.course.utils; import com.alibaba.fastjson.JSONObject; import com.deepoove.poi.xwpf.NiceXWPFDocument; import com.xxxxx.business.course.domain.*; import com.xxxxx.business.utils.UtilTools; import com.xxxxx.business.utils.domain.JudgeRule; import com.xxxxx.business.utils.impl.BaseImpl; import com.xxxxx.common.core.domain.R; import com.xxxxx.common.core.utils.DateUtils; import com.xxxxx.common.core.utils.StringUtils; import com.xxxxx.common.core.utils.file.FileTypeUtils; import com.xxxxx.common.core.utils.file.ImageUtils; import com.xxxxx.common.core.utils.reflect.ReflectUtils; import com.xxxxx.common.core.utils.sign.Base64; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.util.IOUtils; import org.apache.poi.util.Units; import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; import org.apache.poi.xwpf.usermodel.*; import org.apache.xmlbeans.impl.xb.xmlschema.SpaceAttribute; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.List; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; /** * 试卷归档帮助类 */ public class VerifyPaperFileUtils extends BaseImpl { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); public static VerifyPaperFileUtils getInstance() { return new VerifyPaperFileUtils(); } private VerifyPaperFileUtils() { } private Integer pageNum = 0; private XWPFDocument docx; private CTSectPr ctSectPr; private QuestionImportRule importRule = QuestionImportRule.getDefaultRule(""); private VerifyPaper verifyPaper; private PaperTemplate paperTemplate; private boolean includeAnswer = false; private String imgRegex = "img"; private String[] quSortNoArr = new String[]{"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十"}; private String rgb_black = "000000"; /** * 外部调用方法,导出word * * @param response * @param verifyPaper * @throws IOException */ public R<?> exportWord(HttpServletResponse response, VerifyPaper verifyPaper, PaperTemplate paperTemplate) throws Exception { this.verifyPaper = verifyPaper; if (paperTemplate == null) paperTemplate = VerifyPaperFileUtils.getDefaultPaperTemplate(); this.paperTemplate = paperTemplate; R<?> r = this.init(); if (!r.isSuccess()) throw new Exception(r.getMsg()); response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); response.setCharacterEncoding("utf-8"); return this.exportWord(response); } /** * 验证相关数据 * * @return */ private R<?> init() { if (this.verifyPaper == null) { return R.fail("未选择试卷"); } if (this.verifyPaper.getVerifyPaperQtList() == null || verifyPaper.getVerifyPaperQtList().size() == 0) { return R.fail("未设置课程题型"); } if (this.verifyPaper.getVerifyPaperQtList().stream().filter(s -> s.getVerifyPaperQuList() == null || s.getVerifyPaperQuList().size() == 0).count() > 0) return R.fail("有题型未设置试题"); return validTemplate(); } private R<?> validTemplate() { if (this.paperTemplate == null) { return R.fail("未设置模板"); } return R.ok(); } /** * 导出word,私有方法 * * @param response * @throws IOException */ private R<?> exportWord(HttpServletResponse response) throws IOException, InvalidFormatException { try { R<?> r = writeWord(); if (!r.isSuccess()) return r; docx.write(response.getOutputStream()); return R.ok(); } catch (Exception e) { logger.error("导出Word异常,{}", e.getMessage()); throw e; } finally { IOUtils.closeQuietly(docx); } } /** * 试题数据写入文档 */ private R<?> writeWord() throws IOException, InvalidFormatException { R<XWPFDocument> r = createDocxTemplate(); if (!r.isSuccess()) return R.fail(r.getMsg()); docx = r.getData(); writePaperInfo(); writeWordQts(); return R.ok(); } /** * 制作模板 * 模板各种设置 * * @return */ private R<XWPFDocument> createDocxTemplate() { XWPFDocument document = new NiceXWPFDocument(); R<?> r = writeWordPageSetting(document); if (!r.isSuccess()) return R.fail(r.getMsg()); //整体设置 writeWordPageSetting(document); //页眉 writeWordHeader(document); //页脚 writeWordFooter(document); return R.ok(document); } /** * 页面设置 * * @return */ private R<?> writeWordPageSetting(XWPFDocument docx) { if (StringUtils.isEmpty(paperTemplate.getPtPageSize())) return R.fail("未设置模板尺寸"); ctSectPr = docx.getDocument().getBody().getSectPr(); if (ctSectPr == null) ctSectPr = docx.getDocument().getBody().addNewSectPr(); CTPageSz ctPageSz = ctSectPr.isSetPgSz() ? ctSectPr.getPgSz() : ctSectPr.addNewPgSz(); switch (paperTemplate.getPtPageSize().toUpperCase()) { case "A3": ctPageSz.setW(getTwipFromCM(29.7)); //设置宽度(这里是一个ulong类型,单位:缇 , 1厘米=567缇) ctPageSz.setH(getTwipFromCM(42)); //设置高度(这里是一个ulong类型) break; case "A4": ctPageSz.setW(getTwipFromCM(21)); ctPageSz.setH(getTwipFromCM(29.7)); break; case "A5": ctPageSz.setW(getTwipFromCM(14.8)); ctPageSz.setH(getTwipFromCM(21)); break; case "B4": ctPageSz.setW(getTwipFromCM(25.7)); ctPageSz.setH(getTwipFromCM(36)); break; case "B5": ctPageSz.setW(getTwipFromCM(18.2)); ctPageSz.setH(getTwipFromCM(25.7)); break; case "16开": ctPageSz.setW(getTwipFromCM(18.4)); ctPageSz.setH(getTwipFromCM(26)); break; case "32开": ctPageSz.setW(getTwipFromCM(13)); ctPageSz.setH(getTwipFromCM(18.4)); break; case "大32开": ctPageSz.setW(getTwipFromCM(14)); ctPageSz.setH(getTwipFromCM(20.3)); break; default: return R.fail(StringUtils.format("不支持的尺寸:{}", paperTemplate.getPtPageSize())); } if (paperTemplate.getPtDirection().intValue() == 1) // 横向 { BigInteger tempW = ctPageSz.getW(); ctPageSz.setW(ctPageSz.getH()); ctPageSz.setH(tempW); ctPageSz.setOrient(STPageOrientation.LANDSCAPE); } //设置边距 CTPageMar pageMar = ctSectPr.getPgMar(); if (pageMar == null) pageMar = ctSectPr.addNewPgMar(); pageMar.setBottom(getTwipFromCM(paperTemplate.getPtMarginBottom().doubleValue())); pageMar.setTop(getTwipFromCM(paperTemplate.getPtMarginTop().doubleValue())); pageMar.setRight(getTwipFromCM(paperTemplate.getPtMarginRight().doubleValue())); pageMar.setLeft(getTwipFromCM(paperTemplate.getPtMarginLeft().doubleValue())); pageMar.setHeader(getTwipFromCM(paperTemplate.getPtHeaderMargin().doubleValue()));//页眉到顶端的距离 pageMar.setFooter(getTwipFromCM(paperTemplate.getPtFooterMargin().doubleValue()));//页脚到低端的距离 if (paperTemplate.getPtMarginBottom().doubleValue() > 2) { pageMar.setFooter(getTwipFromCM(1)); } else { double leftH = paperTemplate.getPtMarginBottom().doubleValue() - 1; if (leftH > 0) { pageMar.setFooter(getTwipFromCM(leftH)); } } //处理分栏 if (paperTemplate.getPtColumNum().intValue() > 1) { if (!ctSectPr.isSetCols()) ctSectPr.addNewCols(); if (!UtilTools.compareBigIntegerValue(BigInteger.valueOf(paperTemplate.getPtColumNum()), ctSectPr.getCols().getNum())) { CTColumns ctColumns = ctSectPr.getCols(); ctColumns.setNum(BigInteger.valueOf(paperTemplate.getPtColumNum().longValue())); ctSectPr.setCols(ctColumns); } } return R.ok(); } /** * 设置头部 */ private void writeWordHeader(XWPFDocument docx) { if (StringUtils.isEmpty(paperTemplate.getPtSealLineType())) { paperTemplate.setPtSealLineType("once"); } XWPFHeader header = null; //STHdrFtr.Enum headerType = StringUtils.equalsIgnoreCase(paperTemplate.getPtSealLineType(), "once") ? STHdrFtr.DEFAULT : STHdrFtr.Enum.forString(paperTemplate.getPtSealLineType()); if (!StringUtils.equalsIgnoreCase(paperTemplate.getPtSealLineType(), "once")) { XWPFHeaderFooterPolicy headerFooterPolicy = docx.getHeaderFooterPolicy(); if (headerFooterPolicy == null) headerFooterPolicy = docx.createHeaderFooterPolicy(); String sealType = ""; sealType = paperTemplate.getPtSealLineType().toLowerCase(); switch (sealType) { case "default": //每页 header = headerFooterPolicy.createHeader(STHdrFtr.DEFAULT); break; case "odd": //奇数页 header = headerFooterPolicy.createHeader(STHdrFtr.DEFAULT); docx.setEvenAndOddHeadings(true); break; case "even": //偶数页 header = headerFooterPolicy.createHeader(STHdrFtr.EVEN); docx.setEvenAndOddHeadings(true); break; } } if (paperTemplate.getPtPageHeadShow() && StringUtils.isNotEmpty(paperTemplate.getPtPageHeadText())) { if (header == null) { XWPFHeaderFooterPolicy headerFooterPolicy = docx.getHeaderFooterPolicy(); if (headerFooterPolicy == null) headerFooterPolicy = docx.createHeaderFooterPolicy(); header = headerFooterPolicy.createHeader(STHdrFtr.DEFAULT); } XWPFParagraph p = header.createParagraph(); if (StringUtils.isNotEmpty(paperTemplate.getPtPageHeadAlign())) p.setAlignment(Enum.valueOf(ParagraphAlignment.class, paperTemplate.getPtPageHeadAlign())); XWPFRun run = p.createRun(); run.setText(paperTemplate.getPtPageHeadText()); run.setFontSize(paperTemplate.getPtPageHeadSize()); } //在页眉里面添加装订线 //制作左边装订线 writeWordBroadside(docx, header); } /** * 设置侧边栏 * 换新页面设置一个 */ private void writeWordBroadside(XWPFDocument docx, XWPFHeader header) { if (paperTemplate.getPtSealLineShow() == null || !paperTemplate.getPtSealLineShow()) return; ctSectPr = docx.getDocument().getBody().getSectPr(); if (ctSectPr == null) ctSectPr = docx.getDocument().getBody().addNewSectPr(); //创建一个 CTPageMar pageMar = ctSectPr.isSetPgMar() ? ctSectPr.getPgMar() : ctSectPr.addNewPgMar(); //装订线宽度 BigInteger slideBarWidth = pageMar.getLeft(); if (pageMar.getGutter() != null) slideBarWidth.add(pageMar.getGutter()); if (paperTemplate.getPtSealLineWidth().doubleValue() > 2.5) { slideBarWidth = slideBarWidth.subtract(getTwipFromCM(0.5)); } BigInteger cellWidth = slideBarWidth.divide(BigInteger.valueOf(2)); //BigInteger top = BigInteger.valueOf(1); BigInteger slideBarHeight = ctSectPr.getPgSz().getH().subtract(BigInteger.valueOf(2)); // 创建一个侧边栏 XWPFTable sidebarTable = StringUtils.equalsIgnoreCase(paperTemplate.getPtSealLineType(), "once") ? docx.createTable(1, 2) : header.createTable(1, 2); CTTblPr ctTblPr = sidebarTable.getCTTbl().getTblPr(); if (ctTblPr == null) ctTblPr = sidebarTable.getCTTbl().addNewTblPr(); //设置宽度 ctTblPr.getTblW().setType(STTblWidth.DXA); ctTblPr.getTblW().setW(slideBarWidth); // BigInteger x = BigInteger.ZERO.subtract(slideBarWidth); //居左 CTJc jcTable = ctTblPr.isSetJc() ? ctTblPr.getJc() : ctTblPr.addNewJc(); jcTable.setVal(STJc.LEFT); sidebarTable.setTableAlignment(TableRowAlign.LEFT); //定位 CTTblPPr ctTblPPr = ctTblPr.isSetTblpPr() ? ctTblPr.getTblpPr() : ctTblPr.addNewTblpPr(); ctTblPPr.setVertAnchor(STVAnchor.PAGE); ctTblPPr.setHorzAnchor(STHAnchor.PAGE); ctTblPPr.setTblpXSpec(STXAlign.LEFT); ctTblPPr.setTblpYSpec(STYAlign.TOP); ctTblPPr.setTblpX(BigInteger.ZERO); ctTblPPr.setTblpY(BigInteger.ZERO); //去除边框 setTableBorder(sidebarTable, false); for (XWPFTableRow row : sidebarTable.getRows()) { row.setHeight(slideBarHeight.intValue()); for (XWPFTableCell cell : row.getTableCells()) { cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); CTTcPr ctTcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr(); if (!ctTcPr.isSetTcW()) ctTcPr.addNewTcW(); ctTcPr.getTcW().setW(cellWidth); //文字方向 CTTextDirection cellDirection = ctTcPr.isSetTextDirection() ? ctTcPr.getTextDirection() : ctTcPr.addNewTextDirection(); cellDirection.setVal(STTextDirection.BT_LR); //垂直居中 CTVerticalJc ctVerticalJc = ctTcPr.isSetVAlign() ? ctTcPr.getVAlign() : ctTcPr.addNewVAlign(); ctVerticalJc.setVal(STVerticalJc.Enum.forString("center")); //左对齐 CTOnOff noWap = ctTcPr.isSetNoWrap() ? ctTcPr.getNoWrap() : ctTcPr.addNewNoWrap(); noWap.setVal(STOnOff.Enum.forString("on")); } } //学生信息 XWPFTableCell cellInfo = sidebarTable.getRow(0).getCell(0); //String blankStr = " "; String blankStr = "_____________"; XWPFParagraph paragraph = cellInfo.getParagraphs().get(0); paragraph.setVerticalAlignment(TextAlignment.CENTER); paragraph.setAlignment(ParagraphAlignment.CENTER); //paragraph.setFontAlignment(2); if (paperTemplate.getPtSealLineStudentCode()) { addTextToSidebar(paragraph, " 学号:", false); addTextToSidebar(paragraph, blankStr, false); } if (paperTemplate.getPtSealLineStudentName()) { addTextToSidebar(paragraph, " 姓名:", false); addTextToSidebar(paragraph, blankStr, false); } if (paperTemplate.getPtSealLineStudentCollege()) { addTextToSidebar(paragraph, " 学院:", false); addTextToSidebar(paragraph, blankStr, false); } if (paperTemplate.getPtSealLineStudentGrade()) { addTextToSidebar(paragraph, " 年级:", false); addTextToSidebar(paragraph, blankStr, false); } if (paperTemplate.getPtSealLineStudentDepartment()) { addTextToSidebar(paragraph, " 系:", false); addTextToSidebar(paragraph, blankStr, false); } if (paperTemplate.getPtSealLineStudentSpecialty()) { addTextToSidebar(paragraph, " 专业:", false); addTextToSidebar(paragraph, blankStr, false); } if (paperTemplate.getPtSealLineStudentClass()) { addTextToSidebar(paragraph, " 班级:", false); addTextToSidebar(paragraph, blankStr, false); } //装订线 XWPFTableCell cellLine = sidebarTable.getRow(0).getCell(1); paragraph = cellLine.getParagraphs().get(0); paragraph.setVerticalAlignment(TextAlignment.CENTER); paragraph.setAlignment(ParagraphAlignment.CENTER); // paragraph.setAlignment(ParagraphAlignment.CENTER); // paragraph.setFontAlignment(2); //String lineStr = "-----------------------------------------------"; String lineStr = "-------------------------------------------"; addTextToSidebar(paragraph, lineStr, false); addTextToSidebar(paragraph, " 密 - 封 - 线 ", false); addTextToSidebar(paragraph, lineStr, false); } private void addTextToSidebar(XWPFParagraph paragraph, String text, boolean isUnderline) { XWPFRun studentRun = paragraph.createRun(); studentRun.setText(text); studentRun.setFontSize(paperTemplate.getPtSealLineSize()); studentRun.setFontFamily(paperTemplate.getPtSealLineFamily()); if (isUnderline) { studentRun.setUnderline(UnderlinePatterns.SINGLE); } } private void addTextToSidebar(XWPFParagraph paragraph, String text, boolean isUnderline, boolean isBold) { XWPFRun studentRun = paragraph.createRun(); studentRun.setText(text); studentRun.setFontSize(paperTemplate.getPtSealLineSize()); studentRun.setFontFamily(paperTemplate.getPtSealLineFamily()); if (isBold) studentRun.setBold(true); if (isUnderline) { studentRun.setUnderline(UnderlinePatterns.SINGLE); } } /** * 设置页脚 */ private void writeWordFooter(XWPFDocument docx) { boolean hasFoot = paperTemplate.getPtPageFootShow() && StringUtils.isNotEmpty(paperTemplate.getPtPageFootText()); boolean hasPageNum = paperTemplate.getPtPageNumShow(); if (hasFoot || hasPageNum) { XWPFHeaderFooterPolicy headerFooterPolicy = docx.getHeaderFooterPolicy(); if (headerFooterPolicy == null) headerFooterPolicy = docx.createHeaderFooterPolicy(); XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT); XWPFParagraph p = footer.getParagraphs() != null && footer.getParagraphs().size() > 0 ? footer.getParagraphs().get(0) : footer.createParagraph(); if (hasFoot) { if (StringUtils.isNotEmpty(paperTemplate.getPtPageFootAlign())) p.setAlignment(Enum.valueOf(ParagraphAlignment.class, paperTemplate.getPtPageFootAlign())); XWPFRun run = p.createRun(); run.setText(paperTemplate.getPtPageFootText()); run.setFontSize(paperTemplate.getPtPageFootSize()); if (hasPageNum) { p.setAlignment(ParagraphAlignment.LEFT); } } else { p.setAlignment(ParagraphAlignment.CENTER); } if (hasPageNum) { //设置分页 if (hasFoot) { CTTabStop tabStop = p.getCTP().getPPr().addNewTabs().addNewTab(); tabStop.setVal(STTabJc.RIGHT); //设置位置? int twipsPerInch = 1440; tabStop.setPos(BigInteger.valueOf(6 * twipsPerInch)); } XWPFRun run = p.createRun(); run.setFontSize(paperTemplate.getPtPageNumSize()); run.setText("第"); if (hasFoot) run.addTab(); //当前页 begin //p.getCTP().addNewFldSimple().setInstr("PAGE \\* MERGEFORMAT"); run = p.createRun(); run.setShadow(false); run.setFontSize(paperTemplate.getPtPageNumSize()); CTFldChar fldChar = run.getCTR().addNewFldChar(); fldChar.setFldCharType(STFldCharType.Enum.forString("begin")); run.setFontSize(paperTemplate.getPtPageNumSize()); CTText ctText = run.getCTR().addNewInstrText(); ctText.setStringValue("PAGE \\* MERGEFORMAT"); ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve")); fldChar = run.getCTR().addNewFldChar(); fldChar.setFldCharType(STFldCharType.Enum.forString("end")); //当前页 end run = p.createRun(); run.setFontSize(paperTemplate.getPtPageNumSize()); run.setText("页 (共"); //总页数 begin run = p.createRun(); run.setFontSize(paperTemplate.getPtPageNumSize()); fldChar = run.getCTR().addNewFldChar(); fldChar.setFldCharType(STFldCharType.Enum.forString("begin")); run = p.createRun(); run.setFontSize(paperTemplate.getPtPageNumSize()); ctText = run.getCTR().addNewInstrText(); ctText.setStringValue("NUMPAGES \\* MERGEFORMAT"); ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve")); //run = p.createRun(); //run.setFontSize(paperTemplate.getPtPageNumSize()); fldChar = run.getCTR().addNewFldChar(); fldChar.setFldCharType(STFldCharType.Enum.forString("end")); //总页数 end run = p.createRun(); run.setFontSize(paperTemplate.getPtPageNumSize()); run.setText("页)"); } } } /** * 写入试卷信息 */ private void writePaperInfo() throws IOException, InvalidFormatException { //顶部标题 if (paperTemplate.getPtTitle() && StringUtils.isNotEmpty(verifyPaper.getVerifyPaperTopName())) { XWPFParagraph topTitle = createParagraph(paperTemplate.getPtTitleFontSize()); topTitle.setAlignment(ParagraphAlignment.CENTER); XWPFRun run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtTitleFontFamily()); run.setFontSize(paperTemplate.getPtTitleFontSize()); run.setText(verifyPaper.getVerifyPaperTopName()); run.setBold(paperTemplate.getPtTitleBold()); } //试卷标题 if (StringUtils.isNotEmpty(verifyPaper.getVerifyPaperName())) { XWPFParagraph topTitle = createParagraph(paperTemplate.getPtTitleSubFontSize()); topTitle.setAlignment(ParagraphAlignment.CENTER); XWPFRun run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtTitleSubFontFamily()); run.setFontSize(paperTemplate.getPtTitleSubFontSize()); run.setText(verifyPaper.getVerifyPaperName()); run.setBold(paperTemplate.getPtTitleSubBold()); } // 答案及标准字样 if (includeAnswer) { XWPFParagraph topTitle = createParagraph(paperTemplate.getPtTitleSubFontSize()); topTitle.setAlignment(ParagraphAlignment.CENTER); XWPFRun run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtTitleSubFontFamily()); run.setFontSize(paperTemplate.getPtTitleSubFontSize()); run.setText("参考答案及评分标准"); } //考试信息 if (paperTemplate.getPtPaperInfoShow()) { XWPFParagraph topTitle = createParagraph(paperTemplate.getPtPaperInfoSize()); topTitle.setAlignment(ParagraphAlignment.CENTER); boolean haPre = false; if (paperTemplate.getPtShowAnswerMode()) { XWPFRun run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText("考试形式:"); run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText(StringUtils.format(" {} ", verifyPaper.getVpAnswerMode() == 0 ? "闭卷" : "开卷")); run.setUnderline(UnderlinePatterns.SINGLE); haPre = true; } if (paperTemplate.getPtShowAnswerTime()) { XWPFRun run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText((haPre ? " " : "") + "考试时间:"); run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText(StringUtils.format(" {} ", verifyPaper.getVpTotalTimeMinute())); run.setUnderline(UnderlinePatterns.SINGLE); run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText("分钟"); haPre = true; } if (paperTemplate.getPtShowAnswerTime()) { XWPFRun run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText((haPre ? " " : "") + "满分:"); run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText(StringUtils.format(" {} ", verifyPaper.getVpTotalMark().stripTrailingZeros().toPlainString())); run.setUnderline(UnderlinePatterns.SINGLE); run = topTitle.createRun(); run.setFontFamily(paperTemplate.getPtPaperInfoFamily()); run.setFontSize(paperTemplate.getPtPaperInfoSize()); run.setText("分。"); haPre = true; } addNewBlankLine(docx); } //得分栏 if (paperTemplate.getPtScoreColumn()) { int colNum = 2 + verifyPaper.getVerifyPaperQtList().size(); double colWidth = 2; XWPFTable scoreTable = docx.createTable(3, colNum); scoreTable.setTableAlignment(TableRowAlign.CENTER); scoreTable.setWidth(getTwipFromCM(colWidth * colNum).intValue()); setTableBorder(scoreTable, true); for (XWPFTableRow row : scoreTable.getRows()) { row.setHeight(getTwipFromCM(1).intValue()); for (XWPFTableCell cell : row.getTableCells()) { cell.setWidth(getTwipFromCM(colWidth).toString()); } } setCellText(scoreTable.getRows().get(0).getTableCells().get(0), "题 号", paperTemplate.getPtScoreColumnFamily(), paperTemplate.getPtScoreColumnSize(), paperTemplate.getPtScoreColumnBold(), false, ParagraphAlignment.CENTER, XWPFTableCell.XWPFVertAlign.CENTER); for (int i = 0; i < verifyPaper.getVerifyPaperQtList().size(); i++) { setCellText(scoreTable.getRow(0).getCell(i + 1), this.quSortNoArr[i], paperTemplate.getPtScoreColumnFamily(), paperTemplate.getPtScoreColumnSize(), paperTemplate.getPtScoreColumnBold(), false, ParagraphAlignment.CENTER, XWPFTableCell.XWPFVertAlign.CENTER); } setCellText(scoreTable.getRow(0).getCell(colNum - 1), "总 分", paperTemplate.getPtScoreColumnFamily(), paperTemplate.getPtScoreColumnSize(), paperTemplate.getPtScoreColumnBold(), false, ParagraphAlignment.CENTER, XWPFTableCell.XWPFVertAlign.CENTER); setCellText(scoreTable.getRow(1).getCell(0), "得 分", paperTemplate.getPtScoreColumnFamily(), paperTemplate.getPtScoreColumnSize(), paperTemplate.getPtScoreColumnBold(), false, ParagraphAlignment.CENTER, XWPFTableCell.XWPFVertAlign.CENTER); setCellText(scoreTable.getRow(2).getCell(0), "评阅人", paperTemplate.getPtScoreColumnFamily(), paperTemplate.getPtScoreColumnSize(), paperTemplate.getPtScoreColumnBold(), false, ParagraphAlignment.CENTER, XWPFTableCell.XWPFVertAlign.CENTER); addNewBlankLine(docx); } if (StringUtils.isNotEmpty(paperTemplate.getPtReadme())) { XWPFTable readmeTable = docx.createTable(1, 2); readmeTable.setTableAlignment(TableRowAlign.CENTER); readmeTable.setWidth(getTwipFromCM(15).intValue()); setTableBorder(readmeTable, false); XWPFTableCell cell1 = readmeTable.getRow(0).getCell(0); cell1.setWidth(getTwipFromCM(2).toString()); XWPFParagraph paragraph = cell1.getParagraphs().get(0); paragraph.setVerticalAlignment(TextAlignment.TOP); paragraph.setAlignment(ParagraphAlignment.RIGHT); XWPFRun run = paragraph.createRun(); run.setFontSize(paperTemplate.getPtReadmeFontSize()); run.setFontFamily(paperTemplate.getPtReadmeFontFamily()); if (paperTemplate.getPtReadmeBold()) run.setBold(true); run.setText("注意:"); //右侧注意事项 XWPFTableCell cell2 = readmeTable.getRow(0).getCell(1); paragraph = cell2.getParagraphs().get(0); paragraph.setSpacingLineRule(LineSpacingRule.AT_LEAST); paragraph.setVerticalAlignment(TextAlignment.TOP); paragraph.setAlignment(ParagraphAlignment.LEFT); run = paragraph.createRun(); run.setFontSize(paperTemplate.getPtReadmeFontSize()); run.setFontFamily(paperTemplate.getPtReadmeFontFamily()); if (paperTemplate.getPtReadmeBold()) run.setBold(true); run.setText(paperTemplate.getPtReadme()); addNewBlankLine(docx); } } private XWPFParagraph createParagraph(Integer fontSize) { XWPFParagraph paragraph = docx.createParagraph(); paragraph.setAlignment(ParagraphAlignment.LEFT); paragraph.setVerticalAlignment(TextAlignment.CENTER); if (fontSize != null) { setParagraphTopPadding(paragraph, fontSize); } return paragraph; } /** * 设置段落第一行头部间隔 * 间隔为字体的一半 * * @param paragraph * @param fontSize */ private void setParagraphTopPadding(XWPFParagraph paragraph, Integer fontSize) { BigInteger space = getTwipFromPound(fontSize.doubleValue()).divide(BigInteger.valueOf(2)); paragraph.setSpacingBefore(space.intValue()); } /** * 表格设置文字 * * @param cell * @param text * @param fontFamily * @param fontSize * @param isBold * @param isUnderLine * @param align * @param vAlign */ private void setCellText(XWPFTableCell cell, String text, String fontFamily, Integer fontSize, Boolean isBold, Boolean isUnderLine, ParagraphAlignment align, XWPFTableCell.XWPFVertAlign vAlign ) { XWPFParagraph paragraph = cell.getParagraphs().get(0); if (align != null) paragraph.setAlignment(align); if (vAlign != null) cell.setVerticalAlignment(vAlign); XWPFRun run = paragraph.createRun(); run.setText(text); if (StringUtils.isNotEmpty(fontFamily)) run.setFontFamily(fontFamily); if (fontSize != null) run.setFontSize(fontSize); if (isBold != null) run.setBold(isBold); if (isUnderLine != null && isUnderLine) run.setUnderline(UnderlinePatterns.SINGLE); } /** * 添加空行 * * @param document */ private void addNewBlankLine(XWPFDocument document) { XWPFParagraph paragraph = document.createParagraph(); paragraph.createRun().setText(""); } /** * 设置题型 */ private void writeWordQts() throws IOException, InvalidFormatException { for (int i = 0; i < verifyPaper.getVerifyPaperQtList().size(); i++) { VerifyPaperQt qt = verifyPaper.getVerifyPaperQtList().get(i); //处理标题 writeWordQtTitle(qt, i); //处理试题 writeQuestionForQt(qt); } } /** * 写入题型试题 * * @return */ private void writeWordQtTitle(VerifyPaperQt qt, Integer qtIndex) { String ext = qt.getVpQtDescription(); if (StringUtils.isEmpty(ext)) ext = StringUtils.format("(本大题{}小题,每小题{}分,共{}分)", qt.getVpQtQuNum(), qt.getVpQtQuMark().stripTrailingZeros().toPlainString(), qt.getVpQtMark().stripTrailingZeros().toPlainString()); String title = StringUtils.format("{}、{} {}", quSortNoArr[qtIndex], qt.getVerifyPaperQtName(), ext); //表格 if (paperTemplate.getPtQtScoreColumn() != null && paperTemplate.getPtQtScoreColumn()) { if (qtIndex > 1) addNewBlankLine(docx); setQtTitleScoreColumn(title); } else { XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQtTitleSize()); paragraph.setAlignment(ParagraphAlignment.LEFT); //字体左对齐 XWPFRun runText = paragraph.createRun(); runText.setBold(paperTemplate.getPtQtTitleBold()); runText.setText(title); runText.setFontSize(paperTemplate.getPtQtTitleSize().intValue()); runText.setFontFamily(paperTemplate.getPtQtTitleFamily(), XWPFRun.FontCharRange.ascii); } } /** * 添加得分栏+标题 * 创建表格合并行 * * @param title */ private void setQtTitleScoreColumn(String title) { BigInteger w = this.ctSectPr.getPgSz().getW(); XWPFTable pTable = docx.createTable(2, 2); pTable.setTableAlignment(TableRowAlign.LEFT); CTTblPr ctTblPr = pTable.getCTTbl().getTblPr(); ctTblPr.getTblW().setType(STTblWidth.DXA); //设置宽度 ctTblPr.getTblW().setW(w); mergeCell(pTable, 0, 1, 1); pTable.getRow(0).setHeight(getTwipFromCM(1).intValue()); pTable.getRow(1).setHeight(getTwipFromCM(1).intValue()); //得分栏 2 厘米 XWPFTableCell cellScore = pTable.getRow(0).getCell(0); cellScore.setWidth(getTwipFromCM(2).toString()); setCellText(cellScore, "得分", paperTemplate.getPtQtScoreColumnFamily(), paperTemplate.getPtQtScoreColumnSize(), true, false, ParagraphAlignment.CENTER, XWPFTableCell.XWPFVertAlign.CENTER); //标题栏 XWPFTableCell cellTitle = pTable.getRow(0).getCell(1); cellTitle.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); XWPFParagraph paragraph = cellTitle.getParagraphs().get(0); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQtTitleSize()).divide(BigInteger.valueOf(2)).intValue()); paragraph.setAlignment(ParagraphAlignment.LEFT); paragraph.setVerticalAlignment(TextAlignment.CENTER); XWPFRun runText = paragraph.createRun(); if (paperTemplate.getPtQtTitleBold() != null) runText.setBold(paperTemplate.getPtQtTitleBold()); runText.setText(title); runText.setFontSize(paperTemplate.getPtQtTitleSize().intValue()); runText.setFontFamily(paperTemplate.getPtQtTitleFamily(), XWPFRun.FontCharRange.ascii); setTableBorder(pTable, false); //设置边框 CTTcBorders borders = CTTcBorders.Factory.newInstance(); CTBorder border = CTBorder.Factory.newInstance(); border.setVal(STBorder.SINGLE); border.setColor(rgb_black); border.setSz(BigInteger.ONE); border.setSpace(BigInteger.ZERO); borders.setLeft(border); borders.setBottom(border); borders.setRight(border); borders.setTop(border); CTTcPr ctTcPr1 = pTable.getRow(0).getCell(0).getCTTc().getTcPr(); if (ctTcPr1 == null) ctTcPr1 = pTable.getRow(0).getCell(0).getCTTc().addNewTcPr(); ctTcPr1.setTcBorders(borders); CTTcPr ctTcPr2 = pTable.getRow(1).getCell(0).getCTTc().getTcPr(); if (ctTcPr2 == null) ctTcPr2 = pTable.getRow(1).getCell(0).getCTTc().addNewTcPr(); ctTcPr2.setTcBorders(borders); } // // private void setQtTitleScoreColumn(String title) { // BigInteger w = this.ctSectPr.getPgSz().getW(); // XWPFTable pTable = docx.createTable(1, 2); // setTableBorder(pTable, false); // pTable.setTableAlignment(TableRowAlign.LEFT); // CTTblPr ctTblPr = pTable.getCTTbl().getTblPr(); // ctTblPr.getTblW().setType(STTblWidth.DXA); // //设置宽度 // ctTblPr.getTblW().setW(w); // // pTable.getRow(0).setHeight(getTwipFromCM(2).intValue()); // //得分栏 2 厘米 // XWPFTableCell cellScore = pTable.getRow(0).getCell(0); // cellScore.setWidth(getTwipFromCM(2).toString()); // setQtScoreColumnTable(cellScore); // // //标题栏 // XWPFTableCell cellTitle = pTable.getRow(0).getCell(1); // cellTitle.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); // // XWPFParagraph paragraph = cellTitle.getParagraphs().get(0); // paragraph.setAlignment(ParagraphAlignment.LEFT); // paragraph.setVerticalAlignment(TextAlignment.CENTER); // XWPFRun runText = paragraph.createRun(); // if (paperTemplate.getPtQtTitleBold() != null) runText.setBold(paperTemplate.getPtQtTitleBold()); // runText.setText(title); // runText.setFontSize(paperTemplate.getPtQtTitleSize().intValue()); // runText.setFontFamily(paperTemplate.getPtQtTitleFamily(), XWPFRun.FontCharRange.ascii); // } /** * 合并单元格 * * @param table 表格对象 * @param beginRowIndex 开始行索引 * @param endRowIndex 结束行索引 * @param colIndex 合并列索引 */ private void mergeCell(XWPFTable table, int beginRowIndex, int endRowIndex, int colIndex) { if (beginRowIndex == endRowIndex || beginRowIndex > endRowIndex) { return; } //合并行单元格的第一个单元格 CTVMerge startMerge = CTVMerge.Factory.newInstance(); startMerge.setVal(STMerge.RESTART); //合并行单元格的第一个单元格之后的单元格 CTVMerge endMerge = CTVMerge.Factory.newInstance(); endMerge.setVal(STMerge.CONTINUE); CTTc ctTc = table.getRow(beginRowIndex).getCell(colIndex).getCTTc(); (ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr()).setVMerge(startMerge); for (int i = beginRowIndex + 1; i <= endRowIndex; i++) { ctTc = table.getRow(i).getCell(colIndex).getCTTc(); (ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr()).setVMerge(endMerge); } } /** * 获取得分栏 * * @return */ private void setQtScoreColumnTable(XWPFTableCell cell) { XWPFTable xwpfTable = docx.createTable(2, 1);// new XWPFTable(CTTbl.Factory.newInstance(), cell, 2, 1);// cell.insertTable(0, xwpfTable); logger.info("表格:{}", cell.getTables().size()); xwpfTable = cell.getTables().get(0); xwpfTable.setTableAlignment(TableRowAlign.CENTER); xwpfTable.setWidth(getTwipFromCM(2).toString()); //设置边框 setTableBorder(xwpfTable, true); XWPFTableRow row1 = xwpfTable.getRow(0); row1.setHeight(getTwipFromCM(1).intValue()); XWPFTableCell cell1 = row1.getCell(0); cell1.setWidth(getTwipFromCM(2).toString()); cell1.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); XWPFParagraph p = cell1.getParagraphs().get(0); p.setAlignment(ParagraphAlignment.CENTER); //字体左对齐 p.setVerticalAlignment(TextAlignment.CENTER); XWPFRun rt = p.createRun(); rt.setBold(paperTemplate.getPtQtScoreColumnBold()); rt.setFontSize(paperTemplate.getPtScoreColumnSize()); rt.setFontFamily(paperTemplate.getPtScoreColumnFamily(), XWPFRun.FontCharRange.ascii); rt.setText("得分"); XWPFTableRow row2 = xwpfTable.getRow(1); row2.setHeight(getTwipFromCM(1).intValue()); } /** * 写入题型试题 * * @return */ private void writeQuestionForQt(VerifyPaperQt qt) throws IOException, InvalidFormatException { for (VerifyPaperQu qu : qt.getVerifyPaperQuList()) { getQuLines(qu, qu.getVpQuIndexQt()); } } /** * 将文字写入段落 * * @param paragraph * @param line * @throws IOException * @throws InvalidFormatException */ private void writeWordQuLine(XWPFParagraph paragraph, String line) throws IOException, InvalidFormatException { for (LineIncludeImg lineImg : getContainImgArr(line)) { if (StringUtils.isEmpty(lineImg.text) && lineImg.image == null) continue; String imgLine = lineImg.text; String picExtension = ""; if (imgLine == null) imgLine = ""; byte[] imgBytes = null; if (lineImg.image != null) { imgLine = ""; imgBytes = lineImg.image; } else if (imgLine.startsWith("data:image/")) { String base64Str = imgLine.substring(imgLine.indexOf(',') + 1); picExtension = imgLine.substring(imgLine.indexOf('/') + 1, imgLine.indexOf(';')); imgBytes = Base64.decode(base64Str); for (int i = 0; i < imgBytes.length; ++i) { if (imgBytes[i] < 0) { imgBytes[i] += 256; } } imgLine = ""; } if (imgBytes != null) { InputStream inputStream = new ByteArrayInputStream(imgBytes); BufferedImage image = ImageIO.read(inputStream); int width = image.getWidth(); int height = image.getHeight(); inputStream.close(); XWPFRun picRun = paragraph.createRun(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String picName = simpleDateFormat.format(DateUtils.getNowDate()) + "." + picExtension; InputStream picStream = new ByteArrayInputStream(imgBytes); //picRun.addPicture(picStream, getPictureType(picExtension), picName, width, height); double scaling = 1.0; //2)2023-06-13 优化 若图片宽度超过word的最大宽值,图片将会变形、所以通过等比缩小来处理 word文档中:宽大最大650px(17厘米) BigDecimal maxWidthWord = new BigDecimal(650); BigDecimal widthDecimal = new BigDecimal(width); if (widthDecimal.compareTo(maxWidthWord) > 0) { BigDecimal divide = maxWidthWord.divide(widthDecimal, 2, RoundingMode.HALF_UP); scaling = divide.doubleValue(); picRun.addPicture(picStream, getPictureType(picExtension), picName, Units.toEMU(width - width * scaling), Units.toEMU(height - height * scaling)); } else { picRun.addPicture(picStream, getPictureType(picExtension), picName, Units.toEMU(width), Units.toEMU(height)); } CTInline inline = picRun.getCTR().getDrawingList().get(0).getInlineArray(0); inline.getDocPr().setId(1L); //id必须从1开始 解决打开文档时 报错(NPOI v2.4 已修复) //此处是否可关闭 picStream.close(); } else if (StringUtils.isNotEmpty(imgLine)) { //创建 run对象 XWPFRun runText = paragraph.createRun(); runText.setText(imgLine); runText.setBold(paperTemplate.getPtQuStemBold()); runText.setFontSize(paperTemplate.getPtQuStemSize()); runText.setFontFamily(paperTemplate.getPtQuStemFamily(), XWPFRun.FontCharRange.ascii); } } } /** * 获取一道试题段落 * * @param qe * @param qIndex * @return */ private void getQuLines(VerifyPaperQu qe, Integer qIndex) throws IOException, InvalidFormatException { if (qe.getQuestionIsMultipleStem() == null || !qe.getQuestionIsMultipleStem()) { //无子试题 //list.addAll(); getSingleLines(qe, qIndex); } else { //有子试题 getMultipleLines(qe, qIndex); } } /** * 获取单题面行 * * @param qe * @return */ private void getSingleLines(VerifyPaperQu qe, Integer qIndex) throws IOException, InvalidFormatException { VerifyPaperQuStem quStem = qe.getVerifyPaperQuStem(); //题面 String stem = StringUtils.getTextFromHTML(quStem.getQuStem(), imgRegex); String line = StringUtils.format("{}. ", qIndex); XWPFParagraph stemParagraph = createParagraph(paperTemplate.getPtQuStemSize()); //试题题号加粗 XWPFRun run = stemParagraph.createRun(); run.setText(line); run.setFontSize(paperTemplate.getPtQuStemSize()); run.setBold(true); writeWordQuLine(stemParagraph, stem); //选项 for (int i = 0; i < 10; i++) { char c = ((char) (65 + i)); String optionTag = String.valueOf(c).toUpperCase(); String pName = StringUtils.format("quOption{}{}", optionTag, i + 1); String option = ReflectUtils.invokeGetter(quStem, pName); if (StringUtils.isEmpty(option)) break; option = StringUtils.getTextFromHTML(option, imgRegex); XWPFParagraph optionParagraph = createParagraph(paperTemplate.getPtQuStemSize()); optionParagraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(optionParagraph, StringUtils.format("{}、{}", optionTag, option)); } //答案 if (includeAnswer && StringUtils.isNotEmpty(quStem.getQuAnswer())) { String answer = StringUtils.getTextFromHTML(quStem.getQuAnswer(), imgRegex); XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.AnswerStartWord, answer)); } //评分点,填空题不显示评分点 if (includeAnswer && StringUtils.isNotEmpty(quStem.getQuJudgePoint()) && !qe.getQuestionIsFillBlank()) { JudgeRule judgeRule = JSONObject.parseObject(quStem.getQuJudgePoint(), JudgeRule.class); if (judgeRule.getItems() != null && judgeRule.getItems().size() > 0) { String points = StringUtils.joinWith(importRule.PointSeparateWord, judgeRule.getItems().get(0).getPoints().stream().map(p -> p.getAnswer()).toArray(String[]::new)); XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.PointStartWord, points)); } } //评析 if (includeAnswer && StringUtils.isNotEmpty(quStem.getQuAnalyse())) { String answer = StringUtils.getTextFromHTML(quStem.getQuAnalyse(), imgRegex); XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.AnalyseStartWord, answer)); } if (includeAnswer) { //难度 XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.DifficultyStartWord, qe.getDifficulty())); } //知识点 if (includeAnswer && StringUtils.isNotEmpty(qe.getKnowledgeList())) { //须处理关系 ????????? //list.add(StringUtils.format("{}{}", importRule.KnowledgeStartWord,qe.getKnowledgeList().)); } //年份 if (includeAnswer) { XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.YearStartWord, qe.getQuestionYear())); } //来源 if (includeAnswer && StringUtils.isNotEmpty(qe.getQuestionOrigin())) { XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.OriginStartWord, qe.getQuestionOrigin())); } docx.createParagraph().createRun().setText("\n"); //添加一个空行 //list.add("\n"); if (!includeAnswer && qe.getQuestionIsSubjective()) { //自适应高度计算,根据答案文字数量 } } /** * 获取多题面试题行 * * @param qe * @return */ private void getMultipleLines(VerifyPaperQu qe, Integer qIndex) throws IOException, InvalidFormatException { VerifyPaperQuStem quStem = qe.getVerifyPaperQuStem(); //题面 String stem = StringUtils.getTextFromHTML(quStem.getQuStem(), imgRegex); String line = (StringUtils.format("{}.", qIndex.toString())); XWPFParagraph stemParagraph = createParagraph(paperTemplate.getPtQuStemSize()); //试题题号加粗 XWPFRun run = stemParagraph.createRun(); run.setText(line); run.setFontSize(paperTemplate.getPtQuStemSize()); run.setBold(true); writeWordQuLine(stemParagraph, stem); //子试题 for (int i = 0; i < qe.getSubQuestionList().size(); i++) { getSubQuLines(qe.getSubQuestionList().get(i), i + 1); } //评析 if (includeAnswer && StringUtils.isNotEmpty(quStem.getQuAnalyse())) { String answer = StringUtils.getTextFromHTML(quStem.getQuAnalyse(), imgRegex); XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.AnalyseStartWord, answer)); } //难度 if (includeAnswer) { XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.DifficultyStartWord, qe.getDifficulty())); //知识点 if (includeAnswer && StringUtils.isNotEmpty(qe.getKnowledgeList())) { //list.add(StringUtils.format("{}{}", importRule.KnowledgeStartWord, qe.getKnowledgeName())); } //年份 paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.YearStartWord, qe.getQuestionYear())); //来源 if (includeAnswer && StringUtils.isNotEmpty(qe.getQuestionOrigin())) { paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize() * 2).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.OriginStartWord, qe.getQuestionOrigin())); } } //添加一个空行 this.addNewBlankLine(docx); } /** * 获取子题面行 * * @param subQe * @return */ private void getSubQuLines(VerifyPaperQu subQe, Integer qSubIndex) throws IOException, InvalidFormatException { //题面 VerifyPaperQuStem quStem = subQe.getVerifyPaperQuStem(); String stem = StringUtils.getTextFromHTML(quStem.getQuStem(), imgRegex); String line = (StringUtils.format("{}). ", qSubIndex)); XWPFParagraph stemParagraph = createParagraph(paperTemplate.getPtQuStemSize()); stemParagraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize()).intValue()); //试题题号加粗 XWPFRun run = stemParagraph.createRun(); run.setText(line); run.setFontSize(paperTemplate.getPtQuStemSize()); run.setBold(true); writeWordQuLine(stemParagraph, stem); //选项 for (int i = 0; i < 10; i++) { char c = ((char) (65 + i)); String optionTag = String.valueOf(c).toUpperCase(); String pName = StringUtils.format("quOption{}{}", optionTag, i + 1); String option = ReflectUtils.invokeGetter(quStem, pName); if (StringUtils.isEmpty(option)) break; option = StringUtils.getTextFromHTML(option, imgRegex); XWPFParagraph optionParagraph = createParagraph(paperTemplate.getPtQuStemSize()); optionParagraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize()).intValue()); writeWordQuLine(optionParagraph, StringUtils.format("{}、{}", optionTag, option)); } //答案 if (includeAnswer && StringUtils.isNotEmpty(quStem.getQuAnswer())) { String answer = StringUtils.getTextFromHTML(quStem.getQuAnswer(), imgRegex); XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize()).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.AnswerStartWord, answer)); } //评分点 if (includeAnswer && StringUtils.isNotEmpty(quStem.getQuJudgePoint()) && !subQe.getQuestionIsFillBlank()) { JudgeRule judgeRule = JSONObject.parseObject(quStem.getQuJudgePoint(), JudgeRule.class); if (judgeRule.getItems() != null && judgeRule.getItems().size() > 0) { String points = StringUtils.joinWith(importRule.PointSeparateWord, judgeRule.getItems().get(0).getPoints().stream().map(p -> p.getAnswer()).toArray(String[]::new)); XWPFParagraph paragraph = createParagraph(paperTemplate.getPtQuStemSize()); paragraph.setIndentationLeft(getTwipFromPound(paperTemplate.getPtQuStemSize()).intValue()); writeWordQuLine(paragraph, StringUtils.format("{}{}", importRule.PointStartWord, points)); } } //添加一个空行 this.addNewBlankLine(docx); if (!includeAnswer && subQe.getQuestionIsSubjective()) { //自适应高度计算,根据答案文字数量 } } private boolean isMatchWithRegex(String regex, String input) { if (StringUtils.isEmpty(regex)) return false; return Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matcher(input).find(); } /** * 通过图片分割 * * @param str * @return */ public List<LineIncludeImg> getContainImgArr(String str) { String imgReg = "<img\\s*/?[^>]*>"; List<LineIncludeImg> list = new ArrayList<>(); if (!isMatchWithRegex(imgReg, str)) { list.add(new LineIncludeImg(str)); return list; } String getSrcReg = "\\bsrc\\b\\s*=\\s*['\"]?([^'\"]*)['\"]?";// "<img.*src=('|\")(.+?)('|\").*/?[^>]*>"; String removeSrcReg = "(^\\bsrc\\b\\s*=\\s*['\"]?)|(['\"]?$)"; //读取base64 Matcher matcher = Pattern.compile(imgReg, Pattern.CASE_INSENSITIVE).matcher(str); int _index = 0; //2023-06-13 支持多个图片 while (matcher.find()) { if (matcher.start() > _index) { list.add(new LineIncludeImg(str.substring(_index, matcher.start()))); } _index = matcher.end(); String group = str.substring(matcher.start(), matcher.end()); Matcher mSrc = Pattern.compile(getSrcReg, Pattern.CASE_INSENSITIVE).matcher(group); if (mSrc.find()) { String srcText = mSrc.group(); String src = srcText.replaceAll(removeSrcReg, ""); if (src.startsWith("data:image/")) { list.add(new LineIncludeImg(src)); } else if (StringUtils.ishttp(src)) { String extend = FileTypeUtils.getFileType(src); byte[] srcBase64 = ImageUtils.getImage(src);// UtilTools.getImageDataFromServer(src); if (StringUtils.isEmpty(extend)) extend = FileTypeUtils.getFileExtendName(srcBase64); //下载图片获取base64HttpUtils list.add(new LineIncludeImg(srcBase64, extend)); } } } if (_index < str.length()) { list.add(new LineIncludeImg(str.substring(_index))); } return list; } /** * 获取图片类型 * * @param picExtension * @return */ public int getPictureType(String picExtension) { switch (picExtension.toUpperCase()) { case "EMF": return 2; case "WMF": return 3; case "PICT": return 4; case "JPEG": return 5; case "PNG": return 6; case "DIB": return 7; case "GIF": return 8; case "TIFF": return 9; case "EPS": return 10; case "BMP": return 11; case "WPG": return 12; default: return 5; } } public class LineIncludeImg { public LineIncludeImg(byte[] image, String extend) { this.image = image; this.extend = extend; } public LineIncludeImg(String text) { this.text = text; } /** * 文本内容 */ public String text; //图片二进制数据 public byte[] image; //扩展名,不带 . public String extend; } /** * 每厘米567缇 */ private double teePerCM = 567; /** * 每厘米28.35磅 */ private double poundPerCm = 28.35; /** * 根据磅,获取缇 * * @return */ private BigInteger getTwipFromPound(double pound) { Double d = pound * teePerCM / poundPerCm; return BigInteger.valueOf(d.longValue()); } /** * 根据厘米,获取缇 * * @param cm * @return */ private BigInteger getTwipFromCM(double cm) { Double d = cm * teePerCM; return BigInteger.valueOf(d.longValue()); } private void setTableBorder(XWPFTable table, boolean hasBorder) { if (hasBorder) { table.setTopBorder(XWPFTable.XWPFBorderType.SINGLE, 1, 0, rgb_black); table.setRightBorder(XWPFTable.XWPFBorderType.SINGLE, 1, 0, rgb_black); table.setLeftBorder(XWPFTable.XWPFBorderType.SINGLE, 1, 0, rgb_black); table.setBottomBorder(XWPFTable.XWPFBorderType.SINGLE, 1, 0, rgb_black); table.setInsideVBorder(XWPFTable.XWPFBorderType.SINGLE, 1, 0, rgb_black); table.setInsideHBorder(XWPFTable.XWPFBorderType.SINGLE, 1, 0, rgb_black); } else { table.setLeftBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, ""); table.setRightBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, ""); table.setTopBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, ""); table.setBottomBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, ""); table.setInsideHBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, ""); table.setInsideVBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, ""); } } /** * 获取默认模板 * * @return */ public static PaperTemplate getDefaultPaperTemplate() { PaperTemplate paperTemplate = new PaperTemplate(); paperTemplate.setPtFooterMargin(BigDecimal.ZERO); paperTemplate.setPaperTemplateName("默认模板配置"); paperTemplate.setPaperTemplateCode("default-template"); paperTemplate.setPtPageSize("A4"); paperTemplate.setPtDirection(0); paperTemplate.setPtColumNum(1); paperTemplate.setPtEnFontFamily("");//Helvetica paperTemplate.setPtTitle(true); paperTemplate.setPtTitleBold(true); paperTemplate.setPtTitleFontFamily("黑体"); paperTemplate.setPtTitleFontSize(18); paperTemplate.setPtTitleSub(""); paperTemplate.setPtTitleSubBold(true); paperTemplate.setPtTitleSubFontFamily("黑体"); paperTemplate.setPtTitleSubFontSize(18); paperTemplate.setPtPaperInfoShow(true); paperTemplate.setPtPaperInfoFamily("黑体"); paperTemplate.setPtPaperInfoSize(12); paperTemplate.setPtPaperInfoBold(false); paperTemplate.setPtShowAnswerMode(true); paperTemplate.setPtShowAnswerTime(true); paperTemplate.setPtShowPaperMark(true); paperTemplate.setPtScoreColumn(true); paperTemplate.setPtScoreColumnFamily("宋体"); paperTemplate.setPtScoreColumnSize(12); paperTemplate.setPtScoreColumnBold(false); paperTemplate.setPtReadme(""); paperTemplate.setPtReadmeBold(false); paperTemplate.setPtReadmeFontFamily("宋体"); paperTemplate.setPtReadmeBold(false); paperTemplate.setPtReadmeFontSize(12); paperTemplate.setPtScoreColumn(true); paperTemplate.setPtScoreColumnBold(false); paperTemplate.setPtScoreColumnFamily("宋体"); paperTemplate.setPtScoreColumnSize(12); paperTemplate.setPtQtScoreColumn(true); paperTemplate.setPtQtScoreColumnBold(true); paperTemplate.setPtQtScoreColumnFamily("宋体"); paperTemplate.setPtQtScoreColumnSize(12); paperTemplate.setPtQtTitleBold(true); paperTemplate.setPtQtTitleFamily("宋体"); paperTemplate.setPtQtTitleSize(12); paperTemplate.setPtQuStemBold(false); paperTemplate.setPtQuStemFamily("宋体"); paperTemplate.setPtQuStemSize(11); paperTemplate.setPtMarginTop(BigDecimal.valueOf(2.54)); paperTemplate.setPtMarginBottom(BigDecimal.valueOf(2.54)); paperTemplate.setPtMarginLeft(BigDecimal.valueOf(3.18)); paperTemplate.setPtMarginRight(BigDecimal.valueOf(3.18)); paperTemplate.setPtPageHeadShow(false); paperTemplate.setPtHeaderMargin(BigDecimal.ZERO); paperTemplate.setPtPageHeadFontFamily("宋体"); paperTemplate.setPtPageHeadSize(11); paperTemplate.setPtPageHeadText(""); paperTemplate.setPtPageHeadAlign("center"); paperTemplate.setPtPageFootShow(false); paperTemplate.setPtFooterMargin(BigDecimal.ZERO); paperTemplate.setPtPageFootFontFamily("宋体"); paperTemplate.setPtPageFootSize(11); paperTemplate.setPtPageFootText(""); paperTemplate.setPtPageFootAlign("left"); paperTemplate.setPtPageNumShow(true); paperTemplate.setPtPageNumAlign("center"); paperTemplate.setPtPageNumFontFamily("宋体"); paperTemplate.setPtPageNumSize(9); paperTemplate.setPtSealLineShow(true); paperTemplate.setPtSealLineType("once"); paperTemplate.setPtSealLineFamily("宋体"); paperTemplate.setPtSealLineSize(12); paperTemplate.setPtSealLineStudentName(true); paperTemplate.setPtSealLineStudentCode(true); paperTemplate.setPtSealLineStudentCollege(true); paperTemplate.setPtSealLineStudentGrade(true); paperTemplate.setPtSealLineStudentSpecialty(true); paperTemplate.setPtSealLineStudentDepartment(false); paperTemplate.setPtSealLineStudentClass(false); return paperTemplate; } }
感谢分享
作者:javacoffeenet
扩展示例来源:https://www.cnblogs.com/javacoffeenet/p/17560899.html文章来源地址https://www.toymoban.com/diary/java/481.html
到此这篇关于使用Apache POI导出Word文件的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!