[测评系统]--测评系统核心代码库
linzhijie
2021-08-06 17ac23e93792f1403297dfa783c85db0c10abb20
src/main/java/com/ots/common/utils/poi/WordUtil.java
@@ -1,5 +1,6 @@
package com.ots.common.utils.poi;
import cn.hutool.core.collection.CollUtil;
import com.ots.common.enums.ReportTypeEnum;
import com.ots.common.enums.ReportTypeNameEnum;
import com.ots.common.enums.TemplateTypeEnum;
import com.ots.common.utils.StringUtils;
@@ -8,6 +9,7 @@
import com.ots.project.exam.domain.TReportTemplate;
import com.ots.project.exam.dto.JAQTableStyle;
import com.ots.project.exam.dto.WordParam;
import com.ots.project.tool.PdfUtil;
import com.ots.project.tool.ShellTool;
import com.ots.project.tool.exam.ExamUtil;
import com.ots.project.tool.exam.ImageUtil;
@@ -16,61 +18,43 @@
import com.ots.project.tool.report.JAQ.condition.Table2;
import com.ots.project.tool.report.JAQ.condition.Table3;
import com.ots.project.tool.report.JAQ.condition.Table4;
import com.ots.project.tool.report.SAQ.chart.SAQChart;
import org.apache.commons.collections.map.HashedMap;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.IRunElement;
import org.apache.poi.xwpf.usermodel.XWPFChart;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.dom4j.DocumentException;
import org.jetbrains.annotations.Nullable;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumVal;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WordUtil {
    private static final Logger log = LoggerFactory.getLogger(WordUtil.class);
    public static String tempFilePath = "/Users/shawnli/Downloads/";
    private static String noRunChange = "";
    private static Map<String, String> colorLabel = new HashMap<String, String>() {{
        put("<YellowText>", "</YellowText>");
    }};
    private static Map<String, String> fontSize = new HashMap<String, String>() {{
        put("<FontSize_11>", "</FontSize_11>");
    }};
    public static final int DEFAULT_FONT_SIZE = 10;
    
    public static boolean changWord(String inputUrl, String outputUrl,
@@ -197,6 +181,9 @@
                if (run.toString().indexOf("%TTime%") != -1) {
                    run.setText(textMap.get("reportGenerationDate").toString(), 0);
                }
                if (run.toString().indexOf("%LIBSAQGS0018%") != -1) {
                    run.setText(textMap.get("LIBSAQGS0018").toString(), 0);
                }
            }
        }
    }
@@ -256,7 +243,7 @@
        int width = (int) Math.round(bufferedImage.getWidth());
        int height = (int) Math.round(bufferedImage.getHeight());
        int emuSelf = 3000;
        run.addPicture(in, Document.PICTURE_TYPE_PNG, "TEST",  width * emuSelf, height * emuSelf);
        run.addPicture(in, Document.PICTURE_TYPE_PNG, "TEST", width * emuSelf, height * emuSelf);
        in.close();
        if (wordParam.isMove()) {
            
@@ -274,7 +261,7 @@
    public static CTAnchor getAnchorWithGraphic(CTGraphicalObject ctGraphicalObject,
                                                String deskFileName, int width, int height,
                                                int leftOffset, int topOffset, boolean behind, int topPosition) {
        long relativeHeight = 251649024l + topPosition;
        long relativeHeight = 251649024L + topPosition;
        String anchorXML =
                "<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "
                        + "simplePos=\"0\" relativeHeight=\"" + relativeHeight + "\" behindDoc=\"" + ((behind) ? 1 : 0) + "\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
@@ -314,7 +301,7 @@
                XWPFTable table = tables.get(i);
                if (table.getRows().size() > 0) {
                    
                    log.info("表格数据:"+ table.getText());
                    log.info("表格数据:" + table.getText());
                    if (checkText(table.getText())) {
                        List<XWPFTableRow> rows = table.getRows();
                        
@@ -389,17 +376,19 @@
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                
                //如果当前表格包含%就代表需要替换
                if (checkText(cell.getText())) {
                    List<XWPFParagraph> paragraphs = cell.getParagraphs();
                    for (XWPFParagraph paragraph : paragraphs) {
                        //获取所有行
                        List<IRunElement> iRunElements = paragraph.getIRuns();
                        List<XWPFRun> runs = new ArrayList<>();
                        //遍历所有行
                        for (IRunElement iRunElement : iRunElements) {
                            runs.add((XWPFRun) iRunElement);
                        }
                        int runPosition = 0;
                        //替换所有表格的文字
                        for (XWPFRun run : runs) {
                            setTextValue(textMap, document, paragraph, runPosition, run);
                        }
@@ -409,7 +398,7 @@
        }
    }
    private static void setTextValue(Map<String, Object> textMap, XWPFDocument document, XWPFParagraph paragraph, int runPosition, XWPFRun run) {
        System.out.println("表格的:" + run.toString());
        log.info("表格的:{}", run.toString());
        try {
            run.setText(changeValue(run.toString(), textMap, run, paragraph, document, runPosition), 0);
        } catch (Exception e) {
@@ -439,8 +428,10 @@
            }
        }
    }
    //校验文本是否需要替换
    public static boolean checkText(String text) {
        //替换文本包含%
        if (text.indexOf("%") != -1 || StringUtils.equals(text, "N/A NONE")) {
            return true;
        }
@@ -448,7 +439,7 @@
    }
    
    public static String changeValue(String runValue, Map<String, Object> textMap, XWPFRun run, XWPFParagraph paragraph, XWPFDocument document, int runPosition) throws IOException, org.apache.poi.openxml4j.exceptions.InvalidFormatException {
        log.debug("changeText:{}",runValue);
        Set<Map.Entry<String, Object>> textSets = textMap.entrySet();
        for (Map.Entry<String, Object> textSet : textSets) {
            
@@ -466,7 +457,11 @@
                if (runValue.indexOf("<BoldText>") != -1) {
                    return setOtherStyle(runValue, paragraph, runPosition, run);
                }
                break;
                //有些表格可能存在多个字典 需替换多次不能轻易break
                //没有可替换内容直接break
                if(getTextSize(runValue) == 0){
                    break;
                }
            }
        }
        
@@ -497,6 +492,7 @@
                    insertRun.setText(originalRunStr);
                    insertRun.setBold(oldRun.isBold());
                    insertRun.setColor(oldRun.getColor());
                    insertRun.setFontFamily(oldRun.getFontFamily());
                    int fontSize = oldRun.getFontSize();
                    insertRun.setFontSize((fontSize == -1) ? DEFAULT_FONT_SIZE : fontSize);
                }
@@ -507,12 +503,24 @@
                if (StringUtils.isNotEmpty(newRunStr)) {
                    newRunStr = newRunStr.replaceAll("<BoldText>", "");
                    newRunStr = newRunStr.replaceAll("</BoldText>", "");
                    String rgbStr = getRGBStr(newRunStr, oldRun);
                    if (rgbStr == null) {
                        rgbStr = oldRun.getColor();
                    }
                    int fontSize = getFontSize(newRunStr, oldRun);
                    if (fontSize == -1) {
                        fontSize = oldRun.getFontSize();
                    }
                    newRunStr = getfinalStr(newRunStr);
                    stringList.add(newRunStr);
                    XWPFRun insertRun = paragraph.insertNewRun(runPosition++);
                    insertRun.setText(newRunStr);
                    insertRun.setBold(true);
                    insertRun.setColor(oldRun.getColor());
                    int fontSize = oldRun.getFontSize();
                    insertRun.setColor(rgbStr);
                    String fontFamily = oldRun.getFontFamily();
                    insertRun.setFontFamily(fontFamily);
                    insertRun.setFontSize((fontSize == -1) ? DEFAULT_FONT_SIZE : fontSize);
                }
                pointer = position;
@@ -522,6 +530,7 @@
                insertRun.setText(runValue.substring(pointer, end));
                insertRun.setBold(oldRun.isBold());
                insertRun.setColor(oldRun.getColor());
                insertRun.setFontFamily(oldRun.getFontFamily());
                int fontSize = oldRun.getFontSize();
                insertRun.setFontSize((fontSize == -1) ? DEFAULT_FONT_SIZE : fontSize);
                pointer = end;
@@ -530,6 +539,71 @@
        
        paragraph.removeRun(runPosition);
        return "NoChangValue";
    }
    private static int getFontSize(String newRunStr, XWPFRun oldRun) {
        int font = -1;
        for (String lab : fontSize.keySet()) {
            if (newRunStr.contains(lab)) {
                int fontSize = getFontSize(lab);
                if (fontSize != -1) {
                    font = fontSize;
                    break;
                }
            }
        }
        return font;
    }
    private static int getFontSize(String lab) {
        int font = -1;
        int index = lab.indexOf("_");
        String size = lab.substring(index + 1, lab.length() - 1);
        try{
            font = Integer.parseInt(size);
        }catch (Exception e){}
        return font;
    }
    private static String getfinalStr(String newRunStr) {
        String result = newRunStr;
        for (String lab : colorLabel.keySet()) {
            if (newRunStr.contains(lab)) {
                newRunStr = newRunStr.replaceAll(lab, "");
                newRunStr = newRunStr.replaceAll(colorLabel.get(lab), "");
                result = newRunStr;
            }
        }
        for (String lab : fontSize.keySet()) {
            if (newRunStr.contains(lab)) {
                newRunStr = newRunStr.replaceAll(lab, "");
                newRunStr = newRunStr.replaceAll(fontSize.get(lab), "");
                result = newRunStr;
            }
        }
        return result;
    }
    private static String getRGBStr(String newRunStr, XWPFRun oldRun) {
        String rgbStr = null;
        for (String lab : colorLabel.keySet()) {
            if (newRunStr.contains(lab)) {
                String colorByLab = getColorByLab(lab);
                if (colorByLab != null) {
                    rgbStr = colorByLab;
                    break;
                }
            }
        }
        return rgbStr;
    }
    private static String getColorByLab(String lab) {
        String rgbStr = null;
        switch (lab) {
            case "<YellowText>":
                rgbStr = "ff9900";
                break;
            default:
                rgbStr = "000000";
                break;
        }
        return rgbStr;
    }
@@ -694,10 +768,15 @@
            setChageWord(fileName, out, textMap, tReportTemplate.getReportType(), templateType, autoTableMap);
            out.flush();
            changColorIfJAQ(textMap, out, reportName, tReportTemplate.getReportType());
            ShellTool.execLibreofficeCommand("pdf", EssConfig.getProfile() + "/" + reportName, EssConfig.getProfile() + "/");
            //PAQ采用新的doc转pdf
            if(!ReportTypeEnum.PAQ.getCode().equals(reportType)){
                ShellTool.execLibreofficeCommand("pdf", EssConfig.getProfile() + "/" + reportName, EssConfig.getProfile() + "/");
            }else{
                PdfUtil.convertPDF(EssConfig.getProfile() + "/" + reportName);
            }
            zipFilePath = getPdfPath(reportName);
            
             deleteFileStrList.add(EssConfig.getProfile() + "/" + reportName);
            deleteFileStrList.add(EssConfig.getProfile() + "/" + reportName);
        } catch (Exception ex) {
            returnMessage = returnMessage + ex.getMessage();
            deleteFileStrList.add(EssConfig.getProfile() + "/" + reportName);
@@ -717,7 +796,7 @@
    }
    private static void changColorIfJAQ(Map<String, Object> textMap, FileOutputStream out, String reportName, String reportType) throws IOException {
        if (Objects.equals(reportType, "JAQ")) {
            changTableColor(reportName, out, (List<JAQTableStyle>)textMap.get("JAQTableStyle"));
            changTableColor(reportName, out, (List<JAQTableStyle>) textMap.get("JAQTableStyle"));
        }
    }
    private static String getTypeIfIsSAQ(TReportTemplate tReportTemplate, String reportType) {
@@ -727,7 +806,7 @@
        return reportType;
    }
    private static String getPdfPath(String reportName) {
        return reportName.substring(0,reportName.lastIndexOf(".")) + ".pdf";
        return reportName.substring(0, reportName.lastIndexOf(".")) + ".pdf";
    }
    public static void deleteFileByStr(List<String> deleteFileStrList) {
        
@@ -772,19 +851,84 @@
        }
        return new FileOutputStream(outFile);
    }
    private static void setChageWord(String fileName, OutputStream out, Map<String, Object> textMap, String reportType, String templateType, Map<Integer, Map<Integer, List<String[]>>> autoTableMap) throws IOException, org.apache.poi.openxml4j.exceptions.InvalidFormatException {
    private static void setChageWord(String fileName, OutputStream out, Map<String, Object> textMap, String reportType, String templateType, Map<Integer, Map<Integer, List<String[]>>> autoTableMap) throws IOException, org.apache.poi.openxml4j.exceptions.InvalidFormatException, DocumentException {
        String filePath = getTemplateDownLoadPathByUpLoad(fileName);
        
        XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(getTemplateDownLoadPathByUpLoad(fileName)));
        //设置文本
        changeText(document, textMap);
        //设置文本框
        changeTextBox(document, textMap);
        //设置图表
        if (Objects.equals(reportType, ReportTypeEnum.SAQ.getCode()) || Objects.equals(reportType, ReportTypeEnum.PAQ.getCode())) {
            SAQChart.changeChart(document, textMap);
        }
        //插入表格
        addTableValue(document, autoTableMap);
        //更改表格的值
        changeTable(document, textMap);
        changChar(textMap, document, reportType, templateType);
        //设置图表控件
        //changChar(textMap, document, reportType, templateType);
        document.write(out);
    }
    private static void changeTextBox(XWPFDocument document, Map<String, Object> textMap) throws DocumentException {
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (XWPFParagraph paragraph : paragraphs) {
            CTR[] rArray = paragraph.getCTP().getRArray();
            for (XmlObject ctr : rArray) {
                Node domNode = ctr.getDomNode();
                setTextVal(domNode, textMap);
            }
        }
    }
    private static void setTextVal(Node node, Map<String, Object> textMap) {
        if ("w:t".equalsIgnoreCase(node.getNodeName())) {
            Node wtItem = node.getChildNodes().item(0);
            if (wtItem != null) {
                wtItem.setNodeValue(getValByKey(wtItem.getNodeValue(), textMap));
            }
            return;
        }
        NodeList childNodes = node.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            setTextVal(childNodes.item(i), textMap);
        }
    }
    private static String getValByKey(String text, Map<String, Object> textMap) {
        log.debug("changeTextBox:{}",text);
        if (!checkText(text)) {
            return text;
        }
        String repText = "";
        Set<Map.Entry<String, Object>> textSets = textMap.entrySet();
        for (Map.Entry<String, Object> textSet : textSets) {
            String key = "%" + textSet.getKey() + "%";
            if (text.indexOf(key) != -1) {
                text = text.replaceAll(key, (String) textMap.get(textSet.getKey()));
                repText = text;
                if (checkText(text)) {
                    continue;
                } else {
                    break;
                }
            }
        }
        if (repText.indexOf("<BoldText>") != -1) {
            repText = repText.replaceAll("<BoldText>", "");
            repText = repText.replaceAll("</BoldText>", "");
        }
        if (repText.indexOf("N/A NONE") != -1) {
            repText = repText.replaceAll("N/A NONE", "");
        }
        return repText;
    }
    public static void changTableColor(String fileName, OutputStream out, List<JAQTableStyle> jaqTableStyleList) throws IOException {
        if (StringUtils.isEmpty(fileName) || CollUtil.isEmpty(jaqTableStyleList)) {
@@ -814,6 +958,14 @@
        document.write(out);
        out.flush();
    }
    /**
     * 设置图标控件
     * @param textMap
     * @param document
     * @param reportType
     * @param templateType
     */
    private static void changChar(Map<String, Object> textMap, XWPFDocument document, String reportType, String templateType) {
        if (StringUtils.isEmpty(reportType) || StringUtils.isEmpty(templateType)) {
            return;
@@ -822,13 +974,55 @@
        if (ExamUtil.isListEmpty(charts)) {
            return;
        }
        if (StringUtils.equals(reportType, "MAQ")) {
        if (StringUtils.equals(reportType, ReportTypeEnum.MAQ.getCode())) {
            setMAQCompleteChars(textMap, charts);
        } else if (StringUtils.equals(reportType, "RuiLin")){
        } else if (StringUtils.equals(reportType, ReportTypeEnum.MAQV2.getCode())) {
            setMAQ_V2CompleteChars(textMap, charts);
        } else if (StringUtils.equals(reportType, ReportTypeEnum.RuiLin.getCode())) {
            setRuiLinChar(textMap, charts);
        } else {
            return;
        }
    }
    private static void setMAQ_V2CompleteChars(Map<String, Object> textMap, List<XWPFChart> charts) {
        String p_Task31 = textMap.get("P_Task31").toString();
        String p_People32 = textMap.get("P_People32").toString();
        String P_INCON25 = textMap.get("P_INCON25").toString();
        String P_IM24 = textMap.get("P_IM24").toString();
        String P_SDE23 = textMap.get("P_SDE23").toString();
        for (XWPFChart xwpfChart : charts) {
            try {
                CTChart ctChart = xwpfChart.getCTChart();
                CTPlotArea ctPlotArea = ctChart.getPlotArea();
                List<CTScatterChart> scatterChartList = ctPlotArea.getScatterChartList();
                List<CTBarChart> barChartList = ctPlotArea.getBarChartList();
                if (scatterChartList.size() != 0 && barChartList.size() != 0) {
                    CTScatterChart ctScatterChart = scatterChartList.get(0);
                    CTScatterSer ctScatterSer = ctScatterChart.getSerList().get(0);
                    CTAxDataSource xVal = ctScatterSer.getXVal();
                    List<CTNumVal> ptList = xVal.getNumRef().getNumCache().getPtList();
                    ptList.get(0).setV(P_INCON25);
                    ptList.get(1).setV(P_IM24);
                    ptList.get(2).setV(P_SDE23);
                } else if (scatterChartList.size() != 0 && barChartList.size() == 0) {
                    CTScatterChart ctScatterChart = scatterChartList.get(0);
                    CTScatterSer ctScatterSer = ctScatterChart.getSerList().get(0);
                    CTAxDataSource xVal = ctScatterSer.getXVal();
                    CTNumDataSource yVal = ctScatterSer.getYVal();
                    xVal.getNumRef().getNumCache().getPtList().get(0).setV(p_Task31);
                    yVal.getNumRef().getNumCache().getPtList().get(0).setV(p_People32);
                } else if (barChartList.size() != 0) {
                    CTBarChart ctBarChart = barChartList.get(0);
                    List<CTBarSer> serList = ctBarChart.getSerList();
                    CTBarSer ctBarSer = serList.get(0);
                    CTNumDataSource val = ctBarSer.getVal();
                    val.getNumRef().getNumCache().getPtList().get(0).setV(p_People32);
                    val.getNumRef().getNumCache().getPtList().get(1).setV(p_Task31);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private static void setRuiLinChar(Map<String, Object> textMap, List<XWPFChart> charts) {
@@ -1101,4 +1295,21 @@
            textMap.put("JAQTableStyle", jaqTableStyleList);
        }
    }
    public static int getTextSize(String runValue){
        Pattern pattern = Pattern.compile("%\\w+%");
        Matcher matcher = pattern.matcher(runValue);
        List<String> result = new ArrayList<>();
        while(matcher.find()){
            result.add(matcher.group());
        }
        return result.size();
    }
    public static void main(String[] args) {
        if (!checkText("人才选拔的目的就是找到能够胜任工作、愿意承担工作,且与组织的需求、文化、价值观相匹配的人。PAQ报告是根据候选人对PAQ问卷中题目的作答信息而生成的,测量的是候选人在工作中偏好的行为风格。PAQ也包括了对作答真实性的测量,同时也装入了TAI专有的作假防范程序,可以有效降低候选人的伪装好倾向(全球30%的自评问卷中都出现了伪装好现象)。")) {
            System.out.println("11");
        }
    }
}