功能说明:

将试卷导出word,并可以打印,装订,效果图:

下面是实现代码:

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;
}
}

java使用apache.poi导出word文件的更多相关文章

  1. java工具类POI导出word

    1.新建一个word,里面填写内容,如: 2.导出wordjava类 /** * POI导出word测试 * @throws Exception */ @RequestMapping(value=&q ...

  2. java 通过Apache poi导出excel代码demo实例

    package com.zuidaima.excel.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutput ...

  3. java使用Apache POI操作excel文件

    官方介绍 HSSF is the POI Project's pure Java implementation of the Excel '97(-2007) file format. XSSF is ...

  4. Java利用Apache poi导出图表

    jar compile('org.apache.poi:poi:4.0.1') compile('org.apache.poi:poi-scratchpad:4.0.1') compile('org. ...

  5. SpringBoot集成文件 - 如何使用POI导出Word文档?

    前文我们介绍了通过Apache POI导出excel,而Apache POI包含是操作Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API.所以 ...

  6. java导出word文件

    java导出word文件 test5.ftl文件生存方法, 第一步:用word新建test5.doc,填写完整模板,将需导出数据用${}代替 第二步:将test5.doc另存为test5.xml 第三 ...

  7. 使用POI导出Word(含表格)的实现方式及操作Word的工具类

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  8. poi导出word

    最近做了个poi导出word的功能 下面是代码: 一个可以参考的例子: package com.lzb.crm.web; import java.io.FileOutputStream; import ...

  9. 使用Apache POI导出Excel小结--导出XLS格式文档

    使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI ...

  10. Read / Write Excel file in Java using Apache POI

    Read / Write Excel file in Java using Apache POI 2014-04-18 BY DINESH LEAVE A COMMENT About a year o ...

随机推荐

  1. [Pytorch框架] 4.5 多GPU并行训练

    文章目录 4.5 多GPU并行训练 4.5.1 torch.nn.DataParalle 4.5.2 torch.distributed 4.5.3 torch.utils.checkpoint im ...

  2. Spring 之bean的生命周期

    文章目录 IOC Bean的生命周期 运行结果 实例演示 实体类 实例化前后置代码 初始化的前后置代码 application.xml 总结 今天我们来聊一下Spring Bean的生命周期,这是一个 ...

  3. Websocket 60秒断开,连接不稳定

    本地测试都是正常的,线上测试总是过一会就断开... 线上新增了https协议,导致页面中的链接必须也是ssl Websocket链接地址从ws://ws.xxx.com改成了wss://ws.xxx. ...

  4. Grafana系列-统一展示-7-ElasticSearch数据源

    系列文章 Grafana 系列文章 ElasticSearch 数据源 Grafana内置了对Elasticsearch的支持.你可以进行多种类型的查询,以可视化存储在Elasticsearch中的日 ...

  5. 2022-02-27:k8s安装yapi,yaml如何写?

    2022-02-27:k8s安装yapi,yaml如何写? 答案2022-02-27: yaml如下: apiVersion: apps/v1 kind: Deployment metadata: l ...

  6. Python对word文档重排版

    介绍 舍友从网上下载的word题库文档很乱,手动改了大半天才改了一点,想起python是大名鼎鼎的自动化脚本,于是乎开始了python对word的一顿瞎操作. 分析需求 对文档中的内容进行分析,只留下 ...

  7. shader编程经典:分形--科赫曲线

    序言 科赫(雪花)曲线是一个经典分形图案,来一起领略下分形之美.本篇内容用到一些基础的内容,例如UV的理解和画线技巧,有需要的话可以参考合集的画圆和画线两篇文章. 示例 shadertoy 代码: # ...

  8. Application of Permutation and Combination

    Reference https://www.shuxuele.com/combinatorics/combinations-permutations.html Online Tool https:// ...

  9. 有哪些ASIC加速技术可以实现低功耗运行?

    目录 文章主题: 10. 有哪些ASIC加速技术可以实现低功耗运行? 背景介绍:随着移动设备.物联网.云计算等应用场景的不断增长,功耗成为了一个日益重要的技术问题.为了在移动设备上实现更长时间的运行, ...

  10. influxdb常用sql总结

    本文为博主原创,转载请注明出处: 1.登录influxdb influx -username admin -password "password" 2.查看数据库 ##查看有哪些数 ...