使用java集成poi实现试卷模版

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.xmlbeans</groupId>
    <artifactId>xmlbeans</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>ooxml-schemas</artifactId>
    <version>1.1</version>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>4.1.2</version>
</dependency>

 

package com.springbooot.tree.dock.template;

import java.io.FileOutputStream;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xwpf.usermodel.XWPFTableCell.XWPFVertAlign;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;


/**
 * poi操作word向word中写入复杂的表格(合并行、合并列)
 *
 * @author Christmas_G
 */
public class PaperTemplate {

    public static void main(String[] args) throws Exception {

        XWPFDocument document = new XWPFDocument();

        CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();

        //设置装订线
        setBinding(document);

        //设置页面大小和边距
        setPageMargin(sectPr);

        //设置保密★启用前
        setConfidentiality(document);

        //设置主标题
        setMainHeading(document);

        //设置副标题
        setSubHeading(document);

        //设置考试范围
        setExamRange(document);

        //设置个人信息
        setPersonalInfo(document);

        //设置誉分栏
        setScoreColumn(document);

        //设置注意事项
        setAttention(document);

        //设置空一行
        setEmptyLine(document);

        //设置大题及注释
        setBigQuestionAndComment(document);

        //设置大题评分区
        //setBigQuestionScore(document);

        //设置大题及注释评分区
       // setBigQuestionAndCommentScore(document);

        //设置页码
        setPageNumber(document);


        FileOutputStream out = new FileOutputStream("G:\\lyj\\bootmybatis\\src\\main\\resources\\templatesWord\\1.docx");

        document.write(out);
        out.close();
    }

    private static void setBinding(XWPFDocument document) {
        //doc.getDocument().getBody().addNewSectPr();
        CTSectPr sectPr = document.getDocument().getBody().getSectPr();
        sectPr.addNewPgBorders();
        CTPageBorders pgBorders = sectPr.getPgBorders();
        CTBorder ctBorder = pgBorders.addNewBottom();
        ctBorder.setVal(STBorder.DASH_DOT_STROKED);
        ctBorder.setSz(BigInteger.valueOf(24));
        ctBorder.setSpace(BigInteger.valueOf(24));
        //Top Bottom Left Right
        pgBorders.setLeft(ctBorder);
        //以页面为基准
        pgBorders.setOffsetFrom(STPageBorderOffset.PAGE);
        //以文本为基准
        //pgBorders.setOffsetFrom(STPageBorderOffset.TEXT);

    }

    private static void setPageNumber(XWPFDocument document) {
        // 创建页眉和页脚策略
        XWPFHeaderFooterPolicy headerFooterPolicy = document.createHeaderFooterPolicy();

        // 创建页脚
        XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT);

        // 创建一个段落
        XWPFParagraph paragraph = footer.createParagraph();

        // 设置段落对齐方式
        paragraph.setAlignment(ParagraphAlignment.CENTER);

        // 创建一个run
        XWPFRun run = paragraph.createRun();

        // 插入页码域
        run.setText("试卷第");
        //run.addBreak(BreakType.TEXT_WRAPPING);
        // 创建一个页码域
        CTSimpleField field = paragraph.getCTP().addNewFldSimple();
        field.setInstr("PAGE \\* MERGEFORMAT");

        XWPFRun run1 = paragraph.createRun();
        run1.setText("页,共");
        // 创建一个页码域
        CTSimpleField totalPagesField = paragraph.getCTP().addNewFldSimple();
        totalPagesField.setInstr("NUMPAGES \\* MERGEFORMAT");
        //run.addBreak(BreakType.TEXT_WRAPPING);
        XWPFRun run2 = paragraph.createRun();
        run2.setText("页");


    }

    private static void setBigQuestionAndCommentScore(XWPFDocument document) {
        //设置大题及注释评分区
        XWPFTable table = document.createTable(2, 3);

        XWPFTableRow row = table.getRow(1);
        row.setHeight(400);

        mergeCellsVertically(table, 2, 0, 1);
        //设置表单的宽度
        XWPFTableCell cell = table.getRow(0).getCell(0);
        cell.setText("评卷人");
        XWPFTableCell cell2 = table.getRow(0).getCell(1);
        cell2.setText("得分");
        XWPFTableCell cell3 = table.getRow(0).getCell(2);
        cell3.setText("一、填空题");
        setCellBorder(cell3);

        XWPFTableCell cell4 = table.getRow(1).getCell(2);
        setCellBorder(cell4);

        setTableCenter(table, 50, 175, 50, 175);

    }

    private static void setCellBorder(XWPFTableCell cell3) {
        CTTcBorders ctTcBorders = cell3.getCTTc().addNewTcPr().addNewTcBorders();
        ctTcBorders.addNewTop().setVal(STBorder.NONE);
        ctTcBorders.addNewBottom().setVal(STBorder.NONE);
        ctTcBorders.addNewRight().setVal(STBorder.NONE);
    }


    /**
     * @Description: 跨列合并
     */
    public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {
        for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
            if (cellIndex == fromCell) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            } else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    /**
     * @Description: 跨行合并
     * @see
     */
    public static void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
        for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
            if (rowIndex == fromRow) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
            } else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    //将表单内的字体设置居中
    private static void setTableCenter(XWPFTable table, int top, int left, int bottom, int right) {
        table.setCellMargins(top, left, bottom, right);

        for (XWPFTableRow row : table.getRows()) {
            for (XWPFTableCell cell : row.getTableCells()) {
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                for (XWPFParagraph paragraph : cell.getParagraphs()) {
                    paragraph.setAlignment(ParagraphAlignment.CENTER);
                    for (XWPFRun run : paragraph.getRuns()) {
                        run.setFontSize(12);
                        run.setBold(true);
                    }
                }
            }
        }
    }

    private static XWPFTable setBigQuestionScore(XWPFDocument document) {
        XWPFTable table = document.createTable(2, 2);
        document.createParagraph().createRun();
        CTTblPr tableProps = table.getCTTbl().getTblPr();

        CTTblWidth tableWidth = tableProps.addNewTblW();
        tableWidth.setType(STTblWidth.DXA);
        tableWidth.setW(BigInteger.valueOf(1800));

        // 设置表格行高
        for (int row = 0; row < 2; row++) {
            XWPFTableRow tableRow = table.getRow(row);

            CTRow ctRow = tableRow.getCtRow();
            CTTrPr trPr = ctRow.addNewTrPr();
            CTHeight trHeight = trPr.addNewTrHeight();
            if (row == 0) {
                trHeight.setVal(BigInteger.valueOf(400)); // 第一行高度设置
            } else if (row == 1) {
                trHeight.setVal(BigInteger.valueOf(560)); // 第二行高度设置
            }

        }

        // 设置表格中的内容水平居中垂直居中
        setTableCenter(table, 50, 200, 50, 200);
        return table;
    }

    private static void setEmptyLine(XWPFDocument document) {
        XWPFParagraph p = document.createParagraph();
        p.setSpacingBetween(2.5);
        XWPFRun r = p.createRun();
        r.setFontSize(25);
    }

    private static void setBigQuestionAndComment(XWPFDocument document) {

        XWPFParagraph p = document.createParagraph();
        p.setVerticalAlignment(TextAlignment.CENTER);
        XWPFRun r = p.createRun();
        r.setText("一、填空题");
        r.setFontSize(10);
        r.setFontFamily("宋体");
        r.setBold(true);

    }

    private static void setScoreColumn(XWPFDocument document) {
        XWPFTable table = document.createTable(2, 3); // 创建2行3列的表格

        document.createParagraph().createRun();


        // 设置表格样式
        CTTblPr tableProps = table.getCTTbl().getTblPr();
        CTJc ctJc = tableProps.addNewJc();
        ctJc.setVal(STJc.CENTER);

        CTTblWidth tableWidth = tableProps.addNewTblW();
        tableWidth.setType(STTblWidth.DXA);
        //tableWidth.setW(BigInteger.valueOf(2400));


        // 设置表格行高
        for (int row = 0; row < 2; row++) {
            XWPFTableRow tableRow = table.getRow(row);
            CTTrPr trPr = tableRow.getCtRow().addNewTrPr();
            CTHeight trHeight = trPr.addNewTrHeight();
            if (row == 0) {
                trHeight.setVal(BigInteger.valueOf(400)); // 第一行高度设置
            } else if (row == 1) {
                trHeight.setVal(BigInteger.valueOf(560)); // 第二行高度设置
            }
        }
        setTableCenter(table, 50, 200, 50, 200);
    }

    private static void setAttention(XWPFDocument document) {
        XWPFParagraph p = document.createParagraph();
        p.setVerticalAlignment(TextAlignment.CENTER);
        XWPFRun r = p.createRun();
        r.setText("注意事项:");
        r.setFontSize(10);
        r.setFontFamily("宋体");

        XWPFParagraph p1 = document.createParagraph();
        p.setVerticalAlignment(TextAlignment.CENTER);
        XWPFRun r1 = p1.createRun();
        r1.setText("1.答题前填写好自己的姓名、班级、考号等信息");
        r1.setFontSize(10);
        r1.setFontFamily("宋体");

        XWPFParagraph p2 = document.createParagraph();
        p.setVerticalAlignment(TextAlignment.CENTER);
        XWPFRun r2 = p2.createRun();
        r2.setText("2.请将答案正确填写在答题卡上");
        r2.setFontSize(10);
        r2.setFontFamily("宋体");
    }


    private static void setPersonalInfo(XWPFDocument document) {
        XWPFParagraph p = document.createParagraph();
        p.setAlignment(ParagraphAlignment.CENTER);
        p.setVerticalAlignment(TextAlignment.CENTER);

        XWPFRun r = p.createRun();
        r.setText("学校:___________姓名:___________班级:___________考号:___________");
        r.setFontSize(10);
        r.setFontFamily("Calibri");
    }


    private static void setExamRange(XWPFDocument document) {
        XWPFParagraph p = document.createParagraph();
        p.setAlignment(ParagraphAlignment.CENTER);
        p.setVerticalAlignment(TextAlignment.CENTER);

        XWPFRun r = p.createRun();
        r.setText("考试范围:xxx;考试1间:100分钟;命题人:xxx");
        r.setFontFamily("宋体");
        r.setFontSize(10);
    }


    private static void setSubHeading(XWPFDocument document) {
        XWPFParagraph p = document.createParagraph();
        p.setSpacingBetween(1.5);
        p.setAlignment(ParagraphAlignment.CENTER);
        p.setVerticalAlignment(TextAlignment.CENTER);

        XWPFRun r = p.createRun();
        r.setText("试卷副标题");
        r.setFontSize(18);
        r.setFontFamily("黑体");
        r.setBold(true);
    }


    private static void setMainHeading(XWPFDocument document) {
        XWPFParagraph p = document.createParagraph();
        p.setSpacingBefore(0);
        p.setSpacingAfter(0);
        p.setSpacingAfterLines(0);
        p.setSpacingBeforeLines(0);
        p.setIndentationFirstLine(0);


        p.setSpacingBetween(1.5);
        p.setAlignment(ParagraphAlignment.CENTER);
        p.setVerticalAlignment(TextAlignment.CENTER);
        //p.setVerticalAlignment(TextAlignment.CENTER);

        XWPFRun r = p.createRun();
        r.setText("2023-2024学年度高中数学期末考试卷");
        r.setFontSize(15);
        r.setFontFamily("宋体");
        r.setBold(true);
    }


    private static void setPageMargin(CTSectPr sectPr) {
        CTPageSz pgSz = sectPr.isSetPgSz() ? sectPr.getPgSz() : sectPr.addNewPgSz();
        pgSz.setW(BigInteger.valueOf(595 * 20));
        pgSz.setH(BigInteger.valueOf(842 * 20));


        CTPageMar pageMar = sectPr.addNewPgMar();
        pageMar.setLeft(BigInteger.valueOf(1995));   // 1 inch
        pageMar.setRight(BigInteger.valueOf(1995));  // 1 inch
        pageMar.setTop(BigInteger.valueOf(900));    // 1 inch
        pageMar.setBottom(BigInteger.valueOf(900)); // 1 inch
    }

    private static void setConfidentiality(XWPFDocument document) {
        XWPFParagraph p = document.createParagraph();
        XWPFRun r = p.createRun();
        r.setText("保密★启用前");
        r.setFontSize(10);
        r.setBold(true);
        r.setFontFamily("黑体");
    }

    /**
     * 向word中写表格
     *
     * @param element
     * @return
     * @throws Exception
     * @author Christmas_G
     */
    private static XWPFDocument setTable(Element element) throws Exception {
        Document tableDoc = element.ownerDocument();

        Elements trList = tableDoc.getElementsByTag("tr");
        Elements tdList = trList.first().getElementsByTag("td");

        XWPFDocument document = new XWPFDocument();
        XWPFTable table = document.createTable(trList.size(), tdList.size());

        boolean[][] colspanFlag = new boolean[trList.size()][tdList.size()];
        boolean[][] rowspanFlag = new boolean[trList.size()][tdList.size()];
        for (int row = 0; row < trList.size(); row++) {
            Element tr = trList.get(row);
            Elements tds = tr.getElementsByTag("td");

            for (int col = 0; col < tds.size(); col++) {
                Element td = tds.get(col);

                String colspan = td.attr("colspan");
                String rowspan = td.attr("rowspan");

                String align = td.attr("align");
                String widthStyle = td.attr("width");
                String style = td.attr("style");

                // 记录需要合并的列
                if (!StringUtils.isEmpty(colspan)) {
                    int colCount = Integer.parseInt(colspan);
                    for (int i = 0; i < colCount - 1; i++) {
                        colspanFlag[row][col + i + 1] = true;
                    }
                }
                // 记录需要合并的行
                if (!StringUtils.isEmpty(rowspan)) {
                    int rowCount = Integer.parseInt(rowspan);
                    for (int i = 0; i < rowCount - 1; i++) {
                        rowspanFlag[row + i + 1][col] = true;
                    }
                }
                // 处理合并
                XWPFTableCell cell = table.getRow(row).getCell(col);
                if (colspanFlag[row][col]) {
                    setColMerge(cell, STMerge.CONTINUE);
                    continue;
                } else {
                    setColMerge(cell, STMerge.RESTART);
                }
                if (rowspanFlag[row][col]) {
                    setRowMerge(cell, STMerge.CONTINUE);
                    continue;
                } else {
                    setRowMerge(cell, STMerge.RESTART);
                }
                // 设置列宽
                if (!StringUtils.isAnyBlank(widthStyle) && !"0".equals(widthStyle)) {
                    int width = Integer.parseInt(widthStyle);

                    setWidth(cell, width);
                }

                XWPFParagraph paragraph = null;
                int size = cell.getParagraphs().size();
                if (size == 0) {
                    paragraph = cell.addParagraph();
                } else {
                    paragraph = cell.getParagraphs().get(size - 1);
                }
                // 设置水平样式
                if ("CENTER".equalsIgnoreCase(align)) {
                    paragraph.setAlignment(ParagraphAlignment.CENTER);
                } else if ("LEFT".equalsIgnoreCase(align)) {
                    paragraph.setAlignment(ParagraphAlignment.LEFT);
                }
                // 设置垂直居中
                cell.setVerticalAlignment(XWPFVertAlign.CENTER);

                // 设置没有边框
                if (!style.contains("border:")) {
                    setNotBorder(cell);
                }

                XWPFRun run = paragraph.createRun();
                run.setText(td.text());
            }
        }
        return document;
    }

    /**
     * 设置行合并属性
     *
     * @param tableCell
     * @param mergeVlaue
     * @author Christmas_G
     * @date 2019-05-31 14:08:02
     */
    private static void setRowMerge(XWPFTableCell tableCell, STMerge.Enum mergeVlaue) {
        CTTc ctTc = tableCell.getCTTc();
        CTTcPr cpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr();
        CTVMerge merge = cpr.isSetVMerge() ? cpr.getVMerge() : cpr.addNewVMerge();
        merge.setVal(mergeVlaue);
    }

    /**
     * 设置列合并属性
     *
     * @param tableCell
     * @param mergeVlaue
     * @author Christmas_G
     * @date 2019-05-31 14:07:50
     */
    private static void setColMerge(XWPFTableCell tableCell, STMerge.Enum mergeVlaue) {
        CTTc ctTc = tableCell.getCTTc();
        CTTcPr cpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr();
        CTHMerge merge = cpr.isSetHMerge() ? cpr.getHMerge() : cpr.addNewHMerge();
        merge.setVal(mergeVlaue);
    }

    /**
     * 补全表格
     *
     * @param tableHtml
     * @return
     * @author Christmas_G
     * @date 2019-05-31 13:32:52
     */
    private static Element supplementTable(String tableHtml) {
        Document tableDoc = Jsoup.parse(tableHtml);
        Elements trels = tableDoc.getElementsByTag("tr");
        // 补全合并的列
        supplementMergedColumns(trels);
        // 补全合并的行
        supplementMergedRows(trels);
        return tableDoc.getElementsByTag("table").first();
    }

    /**
     * 补全合并的列
     *
     * @param trels
     * @author Christmas_G
     * @date 2019-05-31 11:57:36
     */
    private static void supplementMergedColumns(Elements trels) {
        // 所有tr
        Iterator<Element> trelIter = trels.iterator();
        while (trelIter.hasNext()) {
            Element trel = trelIter.next();
            // 获取所有td
            Elements tdels = trel.getElementsByTag("td");
            Iterator<Element> tdelIter = tdels.iterator();
            while (tdelIter.hasNext()) {
                Element tdel = tdelIter.next();
                // 删除样式
                tdel.removeAttr("class");
                // 取到合并的列数量
                String colspanIndex = tdel.attr("colspan");
                if (StringUtils.isEmpty(colspanIndex)) {
                    continue;
                }
                Integer colspanVal = Integer.parseInt(colspanIndex);
                for (int i = 1; i < colspanVal; i++) {
                    trel.appendElement("td");
                }
            }
        }
    }

    /**
     * 补全合并的行(调用此方法前 需要调用 “补全合并的列”方法)
     *
     * @param trels
     * @author Christmas_G
     * @date 2019-05-31 11:57:47
     */
    private static void supplementMergedRows(Elements trels) {
        // 获取最大的列
        int tdSize = 0;
        Iterator<Element> iterator = trels.iterator();
        while (iterator.hasNext()) {
            Element element = iterator.next();
            int size = element.getElementsByTag("td").size();
            if (size > tdSize) {
                tdSize = size;
            }
        }

        for (int i = 0; i < trels.size(); i++) {
            Element currTr = trels.get(i);
            int currTrTds = currTr.getElementsByTag("td").size();
            if (currTrTds == tdSize) {
                continue;
            }

            int count = tdSize - currTrTds;
            for (int j = 0; j < count; j++) {
                currTr.appendElement("td");
            }
        }
    }

    /**
     * 设置列宽
     *
     * @param cell
     * @param width
     * @author Christmas_G
     * @date 2019-06-28 11:30:22
     */
    private static void setWidth(XWPFTableCell cell, int width) {
        CTTblWidth ctTblWidth = cell.getCTTc().addNewTcPr().addNewTcW();
        // 此处乘以20是我以最接近A4上创建表格的宽度手动设置的
        // 目前没有找到将px转换为word里单位的方式
        ctTblWidth.setW(BigInteger.valueOf(width).multiply(BigInteger.valueOf(20)));
        ctTblWidth.setType(STTblWidth.DXA);
    }

    /**
     * 设置表格为没有边框线
     *
     * @param cell
     * @author Christmas_G
     * @date 2019-06-28 11:33:48
     */
    private static void setNotBorder(XWPFTableCell cell) {
        CTTcBorders cTTcBorders = cell.getCTTc().getTcPr().addNewTcBorders();
        CTBorder clBorder = cTTcBorders.addNewLeft();
        clBorder.setVal(STBorder.Enum.forString("none"));
        clBorder.setShadow(STOnOff.ON);
        CTBorder crBorder = cTTcBorders.addNewRight();
        crBorder.setVal(STBorder.Enum.forString("none"));
        crBorder.setShadow(STOnOff.ON);
        CTBorder cbBorder = cTTcBorders.addNewBottom();
        cbBorder.setVal(STBorder.Enum.forString("none"));
        cbBorder.setShadow(STOnOff.ON);
        CTBorder ctBorder = cTTcBorders.addNewTop();
        ctBorder.setVal(STBorder.Enum.forString("none"));
        ctBorder.setShadow(STOnOff.ON);
    }

}

效果

装订线暂时没有实现

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值