java word - 2:POI开发流程

接上文,本章介绍下POI的开发流程

不同于Freemarker那样将模板和数据分离的方式,POI是没有模板的,模板和数据是糅合在一起的。

POI的开发流程其实网上教程都比较多了,我这边就将我写好的工具类贴在这里,大家自取

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>4.1.0</version>
</dependency>

<!-- poi处理xlsx格式,用于处理word中的表格 -->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>4.1.0</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-excelant</artifactId>
	<version>4.1.0</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>ooxml-schemas</artifactId>
	<version>1.4</version>
</dependency>
<!-- poi-tl基于poi的word模板引擎 -->
<dependency>
	<groupId>com.deepoove</groupId>
	<artifactId>poi-tl</artifactId>
	<version>1.5.0</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions> 
		<exclusion>
			<groupId>ch.qos.logback</groupId>
			<artifactId>*</artifactId>
		</exclusion>
		<exclusion>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>*</artifactId>
		</exclusion>
	</exclusions>
</dependency>
package com.shr.service.inspect.util.word;

import com.deepoove.poi.data.MiniTableRenderData;
import com.deepoove.poi.util.TableTools;
import com.shr.service.inspect.entity.task.word.BasicInfoEntity;
import com.shr.service.inspect.entity.task.word.ResultItemEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFStyles;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHeightRule;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STShd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

 
@Component
@Slf4j
public class GeneratePoiWord {
    @Autowired
    private DocUtil docUtil;

    private static final int TABLE_WIDTH = 13698;

    private static List<TableHeadEntity> pointTableColHeads = new ArrayList<>();

    private void initPointTableColHeads()
    {
        pointTableColHeads.add(TableHeadEntity.builder().title("序号").width(740).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("点位名称").width(1058).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("设备类型").width(1058).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("设备部件").width(1058).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("巡检时间").width(1058).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("巡检结果").width(1058).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("人工确认结果").width(1058).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("巡检图片").width(5000).build());
        pointTableColHeads.add(TableHeadEntity.builder().title("审核状态").width(1058).build());
    }

    public void createWordDocument(Map<String, Object> root, File outFile)
    {
        if (Objects.isNull(root)) {
            log.error("--- createWordDocument root is null");
            return;
        }
        log.info("--- createWordDocument start");
        // new 空白的文档
        XWPFDocument doc = new XWPFDocument();
        FileOutputStream out = null;
        try {
            initPointTableColHeads();
            out = new FileOutputStream(outFile);
            //将word排版设置成横向
            docUtil.setPageSize(doc, 16840, 11907);
            XWPFStyles newStyles = doc.createStyles();

            String firstTitle = "My Heading 1";
            docUtil.createHeadingStyle(newStyles, firstTitle, 1, 52, "000000", "楷体_GB2312");
            String secondTitle = "My Heading 2";
            docUtil.createHeadingStyle(newStyles, secondTitle, 1, 24, "000000", "楷体_GB2312");

            BasicInfoEntity basicInfo = (BasicInfoEntity) root.get("basicInfo");

            if (Objects.isNull(basicInfo)) {
                log.error("--- createWordDocument basicInfo is null");
                return;
            }
            docUtil.createFirstTitle(doc, firstTitle, basicInfo.getTitle(), true);

            docUtil.createSecondTitle(doc, secondTitle, "一、概述", true);
            createBaseInfoTable(doc, basicInfo);

            docUtil.createSecondTitle(doc, secondTitle, "二、异常点位结果", true);
            List<List<ResultItemEntity>> abnormalList = (List) root.get("abnormalList");
            if (CollectionUtils.isEmpty(abnormalList)) {
                docUtil.createContent(doc, "无", true);
            }
            else {
                int abnormalNum = (int) root.get("abnormalNum");
                creatTable(doc, abnormalList, abnormalNum);
            }

            docUtil.createSecondTitle(doc, secondTitle, "三、失败点位结果", true);
            List<List<ResultItemEntity>> failList = (List) root.get("failList");
            if (CollectionUtils.isEmpty(failList)) {
                docUtil.createContent(doc, "无", true);
            }
            else {
                int failNum = (int) root.get("failNum");
                creatTable(doc, failList, failNum);
            }

            docUtil.createSecondTitle(doc, secondTitle, "四、正常点位结果", true);
            List<List<ResultItemEntity>> normalList = (List) root.get("normalList");
            if (CollectionUtils.isEmpty(normalList)) {
                docUtil.createContent(doc, "无", true);
            }
            else {
                int normalNum = (int) root.get("normalNum");
                creatTable(doc, normalList, normalNum);
            }

            doc.write(out);
            out.close();
        } catch (Exception e) {
            log.error("-- CreateWordDocument error, {}", e.getMessage());
        } finally {
            try {
                if (Objects.nonNull(doc)) {
                    doc.close();
                }
                if (Objects.nonNull(out)) {
                    out.close();
                }
            } catch (Exception e1) {

            }

        }
    }

    private void createBaseInfoTable(XWPFDocument doc, BasicInfoEntity basicInfo)
    {
        //创建一个表格,并指定宽度
        XWPFTable infoTable = doc.createTable(6, 4);
        TableTools.widthTable(infoTable, MiniTableRenderData.WIDTH_A4_FULL, 4);
        infoTable.getCTTbl().getTblPr().getTblW().setType(STTblWidth.DXA);
        infoTable.getCTTbl().getTblPr().getTblW().setW(BigInteger.valueOf(TABLE_WIDTH));

        CTJc ctJc = infoTable.getCTTbl().getTblPr().addNewJc();
        ctJc.setVal(STJc.CENTER);
        List<XWPFTableRow> rows = infoTable.getRows();
        for (int i = 0; i < rows.size(); i++) {
            XWPFTableRow row = rows.get(i);
            //设置每一行的高度和居中
            row.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(750));
            row.getCtRow().addNewTrPr().addNewTrHeight().setHRule(STHeightRule.AT_LEAST);
            row.getCtRow().addNewTrPr().addNewJc().setVal(STJc.CENTER);

            //设置每一列的宽度和居中
            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewTcW().setType(STTblWidth.DXA);
            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(2519));
            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);
            //设置单元格背景颜色
            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewShd().setVal(STShd.CLEAR);
            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewShd().setColor("auto");
            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewShd().setFill("C5E0B3");
//            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewShd().setThemeFill(STThemeColor.ACCENT_6);
//            row.getTableCells().get(0).getCTTc().addNewTcPr().addNewShd().setThemeFillTint(intToByteArray(66));

            row.getTableCells().get(1).getCTTc().addNewTcPr().addNewTcW().setType(STTblWidth.DXA);
            row.getTableCells().get(1).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(4126));
            row.getTableCells().get(1).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);

            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewTcW().setType(STTblWidth.DXA);
            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(2407));
            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);
            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewShd().setVal(STShd.CLEAR);
            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewShd().setColor("auto");
            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewShd().setFill("C5E0B3");
//            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewShd().setThemeFill(STThemeColor.ACCENT_6);
//            row.getTableCells().get(2).getCTTc().addNewTcPr().addNewShd().setThemeFillTint(intToByteArray(66));

            row.getTableCells().get(3).getCTTc().addNewTcPr().addNewTcW().setType(STTblWidth.DXA);
            row.getTableCells().get(3).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(4646));
            row.getTableCells().get(3).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);
        }

        //将表格的单元格进行合并:从第六行的第二列到第四列进行合并;合并后的单元格,算做此行的第二列
        docUtil.mergeCellsHorizontal(infoTable, 5, 1, 3);

        //设置第1行数据
        docUtil.setTableCell(rows.get(0).getTableCells().get(0), "变电站");
        docUtil.setTableCell(rows.get(0).getTableCells().get(1), basicInfo.getUnit());
        docUtil.setTableCell(rows.get(0).getTableCells().get(2), "任务名称");
        docUtil.setTableCell(rows.get(0).getTableCells().get(3), basicInfo.getTaskName());

        //设置第2行数据
        docUtil.setTableCell(rows.get(1).getTableCells().get(0), "开始时间");
        docUtil.setTableCell(rows.get(1).getTableCells().get(1), basicInfo.getTaskStartTime());
        docUtil.setTableCell(rows.get(1).getTableCells().get(2), "结束时间");
        docUtil.setTableCell(rows.get(1).getTableCells().get(3), basicInfo.getTaskEndTime());

        //设置第3行数据
        docUtil.setTableCell(rows.get(2).getTableCells().get(0), "审核人员");
        docUtil.setTableCell(rows.get(2).getTableCells().get(1), basicInfo.getAuditor());
        docUtil.setTableCell(rows.get(2).getTableCells().get(2), "审核时间");
        docUtil.setTableCell(rows.get(2).getTableCells().get(3), basicInfo.getAuditTime());
        //设置第4行数据
        docUtil.setTableCell(rows.get(3).getTableCells().get(0), "任务巡视点总数");
        docUtil.setTableCell(rows.get(3).getTableCells().get(1), basicInfo.getPointTotal() + "");
        docUtil.setTableCell(rows.get(3).getTableCells().get(2), "正常巡视点数");
        docUtil.setTableCell(rows.get(3).getTableCells().get(3), basicInfo.getNormalNum() + "");

        //设置第5行数据
        docUtil.setTableCell(rows.get(4).getTableCells().get(0), "告警巡视点数");
        docUtil.setTableCell(rows.get(4).getTableCells().get(1), basicInfo.getAlarmNum() + "");
        docUtil.setTableCell(rows.get(4).getTableCells().get(2), "失败巡视点数");
        docUtil.setTableCell(rows.get(4).getTableCells().get(3), basicInfo.getFailNum() + "");
        //设置第5行数据
        docUtil.setTableCell(rows.get(5).getTableCells().get(0), "当前天气");
        docUtil.setTableCell(rows.get(5).getTableCells().get(1), basicInfo.getMicroclimateData());
    }

    private void creatTable(XWPFDocument doc, List<List<ResultItemEntity>> listList, int rowsCount)
    {
        int colCount = 9;  //列数
//        File file = new File("E:\\11\\image\\pre_image");//File类型可以是文件也可以是文件夹
//        File[] files = file.listFiles();
//        rowsCount = 3000;//行数

        XWPFTable infoTable = doc.createTable(rowsCount + 1, colCount);
        TableTools.widthTable(infoTable, MiniTableRenderData.WIDTH_A4_FULL, 4);
        infoTable.getCTTbl().getTblPr().getTblW().setType(STTblWidth.DXA);
        infoTable.getCTTbl().getTblPr().getTblW().setW(BigInteger.valueOf(TABLE_WIDTH));

        CTJc ctJc1 = infoTable.getCTTbl().getTblPr().addNewJc();
        ctJc1.setVal(STJc.CENTER);

        List<XWPFTableRow> rows = infoTable.getRows();

        XWPFTableRow firstRow = rows.get(0);
        for (int w = 0; w < pointTableColHeads.size(); w++) {
            TableHeadEntity tableHeadEntity = pointTableColHeads.get(w);
            firstRow.getTableCells().get(w).getCTTc().addNewTcPr().addNewTcW().setType(STTblWidth.DXA);
            firstRow.getTableCells().get(w).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(tableHeadEntity.getWidth()));
            firstRow.getTableCells().get(w).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);

            firstRow.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(750));
            firstRow.getCtRow().addNewTrPr().addNewTrHeight().setHRule(STHeightRule.AT_LEAST);
            firstRow.getCtRow().addNewTrPr().addNewJc().setVal(STJc.CENTER);
            docUtil.setPointTableCell(firstRow.getTableCells().get(w), tableHeadEntity.getTitle(), true);
        }

        int currentRow = 0;
        int fromRow = 1;
        for (List<ResultItemEntity> list : listList) {
            int toRow = fromRow + list.size();
            docUtil.mergeCellsVertically(infoTable, 0, fromRow, toRow);
            docUtil.mergeCellsVertically(infoTable, 1, fromRow, toRow);
            docUtil.mergeCellsVertically(infoTable, 2, fromRow, toRow);
            docUtil.mergeCellsVertically(infoTable, 3, fromRow, toRow);
            docUtil.mergeCellsVertically(infoTable, 4, fromRow, toRow);
            fromRow = toRow;

            for (ResultItemEntity resultItemEntity : list) {
                currentRow++;
                log.info("----" + currentRow);
                XWPFTableRow row = rows.get(currentRow);
                row.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(750));
                row.getCtRow().addNewTrPr().addNewTrHeight().setHRule(STHeightRule.AT_LEAST);
                row.getCtRow().addNewTrPr().addNewJc().setVal(STJc.CENTER);

                docUtil.setPointTableCell(row.getTableCells().get(0), resultItemEntity.getIndex(), false);
                docUtil.setPointTableCell(row.getTableCells().get(1), resultItemEntity.getPointName(), false);
                docUtil.setPointTableCell(row.getTableCells().get(2), resultItemEntity.getDeviceType(), false);
                docUtil.setPointTableCell(row.getTableCells().get(3), resultItemEntity.getComponentName(), false);
                docUtil.setPointTableCell(row.getTableCells().get(4), resultItemEntity.getExecuteTime(), false);
                docUtil.setPointTableCell(row.getTableCells().get(5), resultItemEntity.getTaskResult(), false);
                docUtil.setPointTableCell(row.getTableCells().get(6), resultItemEntity.getManualConfirmResult(), false);
                docUtil.setCellImage(row.getTableCells().get(7), resultItemEntity.getImageUrl());
                docUtil.setPointTableCell(row.getTableCells().get(8), resultItemEntity.getAuditStatus(), false);

            }
        }
    }
}
package com.shr.service.inspect.util.word;

import com.shr.service.inspect.entity.common.ConstantInterface;
import com.shr.service.inspect.util.file.FileManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFStyle;
import org.apache.poi.xwpf.usermodel.XWPFStyles;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTColor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
 
@Component
@Slf4j
public class DocUtil {
    @Autowired
    private FileManager fileManager;

    /**
     * 设置纸张大小
     *
     * @param document doc对象
     * @param width    宽
     * @param height   长
     */
    public void setPageSize(XWPFDocument document, long width, long height)
    {
        CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
        CTPageSz pgsz = sectPr.isSetPgSz() ? sectPr.getPgSz() : sectPr.addNewPgSz();
        pgsz.setW(BigInteger.valueOf(width));
        pgsz.setH(BigInteger.valueOf(height));
        pgsz.setOrient(STPageOrientation.LANDSCAPE);
    }

    /**
     * @param styles
     * @param strStyleId   标题id
     * @param headingLevel 标题级别
     * @param pointSize    字体大小(/2)
     * @param hexColor     字体颜色
     * @param typefaceName 字体名称(默认宋体)
     */
    public void createHeadingStyle(XWPFStyles styles, String strStyleId, int headingLevel, int pointSize, String hexColor, String typefaceName)
    {
        //创建样式
        CTStyle ctStyle = CTStyle.Factory.newInstance();
        //设置id
        ctStyle.setStyleId(strStyleId);

        CTString styleName = CTString.Factory.newInstance();
        styleName.setVal(strStyleId);
        ctStyle.setName(styleName);


        CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
        indentNumber.setVal(BigInteger.valueOf(headingLevel));

        // 数字越低在格式栏中越突出
        ctStyle.setUiPriority(indentNumber);

        CTOnOff onoffnull = CTOnOff.Factory.newInstance();
        ctStyle.setUnhideWhenUsed(onoffnull);

        // 样式将显示在“格式”栏中
        ctStyle.setQFormat(onoffnull);

        // 样式定义给定级别的标题
        CTPPr ppr = CTPPr.Factory.newInstance();
        ppr.setOutlineLvl(indentNumber);
        ctStyle.setPPr(ppr);

        XWPFStyle style = new XWPFStyle(ctStyle);

        CTHpsMeasure size = CTHpsMeasure.Factory.newInstance();
        size.setVal(new BigInteger(String.valueOf(pointSize)));
        CTHpsMeasure size2 = CTHpsMeasure.Factory.newInstance();
        size2.setVal(new BigInteger(String.valueOf(pointSize)));

        CTFonts fonts = CTFonts.Factory.newInstance();
        if (typefaceName == null || typefaceName.equals("")) {
            typefaceName = "宋体";
        }
        fonts.setAscii(typefaceName);    //字体
        fonts.setEastAsia(typefaceName); //中文字体
        CTRPr rpr = CTRPr.Factory.newInstance();
        rpr.setRFonts(fonts);
        rpr.setSz(size);
        rpr.setSzCs(size2);    //字体大小

        CTColor color = CTColor.Factory.newInstance();
        color.setVal(hexToBytes(hexColor));
        rpr.setColor(color);    //字体颜色
        style.getCTStyle().setRPr(rpr);
        // is a null op if already defined

        style.setType(STStyleType.PARAGRAPH);


        styles.addStyle(style);
    }

    public static byte[] hexToBytes(String hexString)
    {
        HexBinaryAdapter adapter = new HexBinaryAdapter();
        byte[] bytes = adapter.unmarshal(hexString);
        return bytes;
    }

    public void setTableCell(XWPFTableCell cell01, String text)
    {
        int fontSize = 11;
        String fontFamily = "楷体_GB2312";
        ParagraphAlignment alignment = ParagraphAlignment.LEFT;
        boolean isBold = false;
        CTP ctP = (cell01.getCTTc().sizeOfPArray() == 0) ? cell01.getCTTc().addNewP() : cell01.getCTTc().getPArray(0);
        XWPFParagraph p = cell01.getParagraph(ctP);
        XWPFRun headRun0 = p.createRun();
        headRun0.setText("  " + text);
        headRun0.setFontSize(fontSize);
        p.setAlignment(alignment);
        headRun0.setFontFamily(fontFamily);
        headRun0.setBold(isBold);//是否粗体
    }

    public void setPointTableCell(XWPFTableCell cell01, String text, boolean isBold)
    {
        int fontSize = 9;
        String fontFamily = "宋体 (正文)";
        ParagraphAlignment alignment = ParagraphAlignment.CENTER;

        CTP ctP = (cell01.getCTTc().sizeOfPArray() == 0) ? cell01.getCTTc().addNewP() : cell01.getCTTc().getPArray(0);
        //单元格内容垂直居中
        cell01.getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);
        XWPFParagraph p = cell01.getParagraph(ctP);
        XWPFRun headRun0 = p.createRun();
        headRun0.setText(text);
        headRun0.setFontSize(fontSize);
        p.setAlignment(alignment);
        headRun0.setFontFamily(fontFamily);
        headRun0.setBold(isBold);//是否粗体
    }

    /**
     * 合并单元格
     *
     * @param table         表格对象
     * @param beginRowIndex 开始行索引
     * @param endRowIndex   结束行索引
     * @param colIndex      合并列索引
     */
    public void mergeRowCell(XWPFTable table, int beginRowIndex, int endRowIndex, int colIndex)
    {
        try {
            if (beginRowIndex == endRowIndex || beginRowIndex > endRowIndex) {
                return;
            }
            //合并行单元格的第一个单元格
            CTVMerge startMerge = CTVMerge.Factory.newInstance();
            startMerge.setVal(STMerge.RESTART);
            //合并行单元格的第一个单元格之后的单元格
            CTVMerge endMerge = CTVMerge.Factory.newInstance();
            endMerge.setVal(STMerge.CONTINUE);
            table.getRow(beginRowIndex).getCell(colIndex).getCTTc().getTcPr().setVMerge(startMerge);
            for (int i = beginRowIndex + 1; i <= endRowIndex; i++) {
                table.getRow(i).getCell(colIndex).getCTTc().getTcPr().setVMerge(endMerge);
            }
        } catch (Exception e) {
            log.error("-- mergeRowCell error, {}", e.getMessage());
        }
    }


    /**
     * word跨列合并单元格
     * table 表单对象
     * row  合并行
     * fromCell 起始列
     * toCell  结束列
     */
    public void mergeCellsHorizontal(XWPFTable table, Integer row, Integer fromCell, Integer toCell)
    {
        try {
            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);
                }
            }
        } catch (Exception e) {
            log.error("--- mergeCellsHorizontal error, {}", e.getMessage());
        }
    }

    /**
     * 跨行合并单元格
     *
     * @param table   表单对象
     * @param col     合并列
     * @param fromRow 起始行
     * @param toRow   结束行
     */
    public void mergeCellsVertically(XWPFTable table, Integer col, Integer fromRow, Integer toRow)
    {
        try {

            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);
                }
            }
        } catch (Exception e) {
            log.error("--- mergeCellsVertically error, {}", e.getMessage());
        }
    }

    /**
     * 设置一级标题
     *
     * @param doc
     * @param secondTitle
     * @param title
     * @param isBold
     */
    public void createFirstTitle(XWPFDocument doc, String secondTitle, String title, boolean isBold)
    {
        try {
            XWPFParagraph para = doc.createParagraph();
            para.setAlignment(ParagraphAlignment.CENTER); //标题设置水平居中
            para.setStyle(secondTitle);
            XWPFRun run2 = para.createRun();
            run2.setText(title);
            run2.setBold(isBold);
        } catch (Exception e) {
            log.error("--- createFirstTitle error, {}", e.getMessage());
        }
    }

    /**
     * 设置二级标题
     *
     * @param doc
     * @param secondTitle
     * @param title
     * @param isBold
     */
    public void createSecondTitle(XWPFDocument doc, String secondTitle, String title, boolean isBold)
    {
        try {
            XWPFParagraph para = doc.createParagraph();
            para.createRun().addBreak();
            para.setStyle(secondTitle);
            XWPFRun run2 = para.createRun();
            run2.setText(title);
            run2.setBold(isBold);
        } catch (Exception e) {
            log.error("--- createSecondTitle error, {}", e.getMessage());
        }
    }

    /**
     * 设置正文
     *
     * @param doc
     * @param title
     * @param isBold
     */
    public void createContent(XWPFDocument doc, String title, boolean isBold)
    {
        try {
            XWPFParagraph para = doc.createParagraph();
            para.createRun().addBreak();
            XWPFRun run2 = para.createRun();
            run2.setText(title);
            run2.setBold(isBold);
            run2.setFontFamily("楷体_GB2312");
        } catch (Exception e) {
            log.error("--- createSecondTitle error, {}", e.getMessage());
        }
    }

    private void copyFileUsingFileStreams(File source, File dest)
            throws IOException
    {
        InputStream input = null;
        OutputStream output = null;
        try {
            input = new FileInputStream(source);
            output = new FileOutputStream(dest);
            byte[] buf = new byte[1024];
            int bytesRead;
            while ((bytesRead = input.read(buf)) > 0) {
                output.write(buf, 0, bytesRead);
            }
        } finally {
            input.close();
            output.close();
        }
    }

    /**
     * 单元格写入图片
     *
     * @param cell
     * @param url
     * @throws IOException
     */
    public void setCellImage(XWPFTableCell cell, String url)
    {
        InputStream in = null;
        try {
            List<XWPFParagraph> paragraphs = cell.getParagraphs();
            XWPFParagraph newPara = paragraphs.get(0);
            XWPFRun imageCellRunn = newPara.createRun();
            newPara.setAlignment(ParagraphAlignment.CENTER);

            String newFileName = UUID.randomUUID().toString();
            File newFile = File.createTempFile(newFileName, ConstantInterface.PNG_SUFFIX);


            if (StringUtils.isBlank(url) || url.split(ConstantInterface.SPACE_SEPARATOR).length != 2) {
                return;
            }
            String[] split = url.split(ConstantInterface.SPACE_SEPARATOR);
            String fileName = split[1];
            in = fileManager.getFile(split[0], fileName);

            int format;
            if (url.endsWith(".emf")) {
                format = XWPFDocument.PICTURE_TYPE_EMF;
            }
            else if (url.endsWith(".wmf")) {
                format = XWPFDocument.PICTURE_TYPE_WMF;
            }
            else if (url.endsWith(".pict")) {
                format = XWPFDocument.PICTURE_TYPE_PICT;
            }
            else if (url.endsWith(".jpeg") || url.endsWith(".jpg")) {
                format = XWPFDocument.PICTURE_TYPE_JPEG;
            }
            else if (url.endsWith(".png")) {
                format = XWPFDocument.PICTURE_TYPE_PNG;
            }
            else if (url.endsWith(".dib")) {
                format = XWPFDocument.PICTURE_TYPE_DIB;
            }
            else if (url.endsWith(".gif")) {
                format = XWPFDocument.PICTURE_TYPE_GIF;
            }
            else if (url.endsWith(".tiff")) {
                format = XWPFDocument.PICTURE_TYPE_TIFF;
            }
            else if (url.endsWith(".eps")) {
                format = XWPFDocument.PICTURE_TYPE_EPS;
            }
            else if (url.endsWith(".bmp")) {
                format = XWPFDocument.PICTURE_TYPE_BMP;
            }
            else if (url.endsWith(".wpg")) {
                format = XWPFDocument.PICTURE_TYPE_WPG;
            }
            else {
                log.error("Unsupported picture: " + url + ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
                return;
            }
            imageCellRunn.addPicture(in, format, newFile.getName(), Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels

        } catch (Exception e) {
            log.error("--- setCellImage error, {}", e.getMessage());
        } finally {
            try {
                if (Objects.nonNull(in)) {
                    in.close();
                }
            } catch (Exception e1) {

            }
        }
    }

    /**
     * 单元格写入图片
     *
     * @param cell
     * @param file
     */
    public void setCellImageFromFile(XWPFTableCell cell, File file)
    {
        try {
            List<XWPFParagraph> paragraphs = cell.getParagraphs();
            XWPFParagraph newPara = paragraphs.get(0);
            XWPFRun imageCellRunn = newPara.createRun();
            newPara.setAlignment(ParagraphAlignment.CENTER);

            if (!file.exists()) {
                return;
            }
            String url = file.getPath();

            int format;
            if (url.endsWith(".emf")) {
                format = XWPFDocument.PICTURE_TYPE_EMF;
            }
            else if (url.endsWith(".wmf")) {
                format = XWPFDocument.PICTURE_TYPE_WMF;
            }
            else if (url.endsWith(".pict")) {
                format = XWPFDocument.PICTURE_TYPE_PICT;
            }
            else if (url.endsWith(".jpeg") || url.endsWith(".jpg")) {
                format = XWPFDocument.PICTURE_TYPE_JPEG;
            }
            else if (url.endsWith(".png")) {
                format = XWPFDocument.PICTURE_TYPE_PNG;
            }
            else if (url.endsWith(".dib")) {
                format = XWPFDocument.PICTURE_TYPE_DIB;
            }
            else if (url.endsWith(".gif")) {
                format = XWPFDocument.PICTURE_TYPE_GIF;
            }
            else if (url.endsWith(".tiff")) {
                format = XWPFDocument.PICTURE_TYPE_TIFF;
            }
            else if (url.endsWith(".eps")) {
                format = XWPFDocument.PICTURE_TYPE_EPS;
            }
            else if (url.endsWith(".bmp")) {
                format = XWPFDocument.PICTURE_TYPE_BMP;
            }
            else if (url.endsWith(".wpg")) {
                format = XWPFDocument.PICTURE_TYPE_WPG;
            }
            else {
                log.error("Unsupported picture: " + url + ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
                return;
            }
            FileInputStream is = new FileInputStream(url);
            imageCellRunn.addPicture(is, format, file.getName(), Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels
        } catch (Exception e) {
            log.error("--- setCellImageFromFile error, {}", e.getMessage());
        }
    }
}

我总结下POI的优缺点:

先说缺点:

1.需要把数据和模板糅合在一起,两者强关联;

2.POI的文档效果不像Freemarker那么方便,一些单元格合并、单元格底色、页边距这些,都要自己在代码里写死,如果要二次修改,就需要自己在代码里进行修改,查看效果也要通过重复生成新文件来验证,很不方便。

优点:

1.文件小!打开快!这是POI的最大的优势!我做过实验,发现,如果我重复插入相同的图片,POI自身会做优化,生成的文件解析成xml后发现,它会把相同的图片只保存一份,哪怕图片来源于不同的文件,它也会只保存一份,这是非常恐怖的。

下图里,文件名里的数字代表的是塞入的相同图片数量,可以看到,在单张图片size是591KB的情况下,1000张图片的文件是645K,2000张图片是701K,3000张图片是758K,文件大小几乎没有增长。这对于特殊场景的需求,还是有很大优化的。

下图是塞入不同图片的情况,可以看到生成的文件大小也非常的小,而且打开速度也很快。

对于使用Freemarker生成的文件,动辄300M的,多则800M的情况,这是一个很大的优化!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高考我军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值