共计 43975 个字符,预计需要花费 110 分钟才能阅读完成。
本文将介绍如何使用 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 r = createDocxTemplate();
if (!r.isSuccess()) return R.fail(r.getMsg());
docx = r.getData();
writePaperInfo();
writeWordQts();
return R.ok();}
/**
* 制作模板
* 模板各种设置
*
* @return
*/
private R 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 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 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 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 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 getContainImgArr(String str) {String imgReg = "]*>";
List list = new ArrayList();
if (!isMatchWithRegex(imgReg, str)) {list.add(new LineIncludeImg(str));
return list;
}
String getSrcReg = "\bsrc\b\s*=\s*['"]?([^'"]*)['"]?";//"]*>";
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 感谢分享
作者:javacoffeenet
扩展示例来源:https://www.cnblogs.com/javacoffeenet/p/17560899.html文章来源地址 https://www.toymoban.com/diary/java/481.html
到此这篇关于使用 Apache POI 导出 Word 文件的文章就介绍到这了, 更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持 TOY 模板网!