功能说明:

将试卷导出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. 一文梳理z-index和层叠上下文

    前言 最近参与某前端项目架构改造,发现项目中滥用z-index,设置的值有几十种并且不统一.在对项目的z-index进行梳理和统一过程中也深入学习了一下z-index,并撰写成文,希望也能帮助到陌生的 ...

  2. 2023-02-22:请用go语言调用ffmpeg,保存mp4文件的视频帧,每帧用ppm图片保存。

    2023-02-22:请用go语言调用ffmpeg,保存mp4文件的视频帧,每帧用ppm图片保存. 答案2023-02-22: 使用 github.com/moonfdd/ffmpeg-go 库. 先 ...

  3. 2020-11-08:在Mysql中,三个字段A、B、C的联合索引,查询条件是B、A、C,会用到索引吗?

    福哥答案2020-11-08: 会走索引,原因是mysql优化器会把BAC优化成ABC. CREATE TABLE `t_testabc2` ( `id` int(11) NOT NULL AUTO_ ...

  4. 2021-11-14:Fizz Buzz。给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:answer[i

    2021-11-14:Fizz Buzz.给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:answer[i ...

  5. vue CLI 4 创建项目fetchMetadata资源拉取过慢解决方法

    最近将vue cli 升级到了 v4.0.5 创建项目的时候发现慢得想个蜗牛 仔细看这个日志会发现,mapToRegistry uri 是 taobao 这个一拉就是半天,还指不定那个时候就卡死在那里 ...

  6. vue+iview 动态调整Table的列顺序

    需求:因table列太多,且每个部门关注的信息不一样,拖来拖去不方便观看,客户想让Table列可以拖动,且可以保存顺序. 但是搞动态拖动太难了,我不会,于是改为操作columns数据 思路: < ...

  7. Android SmartTable表格框架1_如何使用

    SmartTable github地址:https://github.com/huangyanbin/smartTable 参考:https://juejin.cn/post/684490354910 ...

  8. 【后端面经】MySQL主键、唯一索引、联合索引的区别和作用

    目录 0. 简介 1. 主键 2. 唯一索引 3. 联合索引 4. 索引对数据库操作的影响 5. 其他索引 5.1 普通索引 5.2 全文索引 5.3 前缀索引 6. 总结 7. 参考资料 0. 简介 ...

  9. 一次性掌握innodb引擎如何解决幻读和不可重复读

    了解mysql的都知道,在mysql的RR(可重复)隔离级别下解决了幻读和不可重复.你知道RR下是怎么解决的吗,很多人会回答是通过MVCC和next-key解决的,具体是怎么解决的,今天来重点分析下. ...

  10. 【Netty】02-入门

    二. Netty 入门 1. 概述 1.1 Netty 是什么? Netty is an asynchronous event-driven network application framework ...