poi模板操作word两种实现方式

前言:poi模板操作word-doc有两种方式
1.手动创建模板
2.使用已有模板进行填充
3.知识补充

1.手动创建模板

1.1 jar包导入

 pom.xml中添加以下依赖
 <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>4.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-excelant</artifactId>
        <version>4.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>4.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-scratchpad</artifactId>
        <version>4.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.deepoove</groupId>
        <artifactId>poi-tl</artifactId>
        <version>1.6.0</version>
    </dependency>

    <dependency>
        <groupId>org.jeecg</groupId>
        <artifactId>easypoi-base</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.jeecg</groupId>
        <artifactId>easypoi-web</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.jeecg</groupId>
        <artifactId>easypoi-annotation</artifactId>
        <version>2.3.1</version>
    </dependency>

1.2 Excel工具编写

package com.yu.utils;

import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ExcelUtils {
    // 2003- 版本的excel
    private final static String excel2003L = ".xls";
    // 2007+ 版本的excel
    private final static String excel2007U = ".xlsx";

    private static NumberFormat numberFormat = NumberFormat.getNumberInstance();

    static {
        numberFormat.setGroupingUsed(false);
    }

    /**
     * 校验文件格式
     *
     * @param filename
     * @return
     */
    public static boolean validateFileType(String filename) {
        if (!filename.contains(".")) {
            return false;
        } else {
            String fileType = filename.substring(filename.lastIndexOf("."));
            switch (fileType) {
                case excel2003L:
                case excel2007U: {
                    return true;
                }
                default: {
                    return false;
                }
            }
        }
    }


    /**
     * 根据版本获取excel对象
     *
     * @param url
     * @param inputStream
     * @return
     * @throws Exception
     */
    public static Workbook getWork(String url, InputStream inputStream) throws IOException {
        Workbook wb = null;
        String str = url.substring(url.lastIndexOf("."));

        if (excel2003L.equals(str)) {
            wb = new HSSFWorkbook(inputStream);  // 2003-
        } else if (excel2007U.equals(str)) {
            wb = new XSSFWorkbook(inputStream);  // 2007+
        } else {
            throw new IOException("解析文件格式有误!");
        }
        return wb;
    }


    /**
     * 获取单元格的值
     *
     * @param cell
     * @return
     */
    public static String getCellValue(Cell cell) {
        Object result = "";
        if (cell != null) {
            switch (cell.getCellType()) {
                case STRING:
                    result = cell.getStringCellValue();
                    break;
                case NUMERIC:
                    // 在excel里,日期也是数字,在此要进行判断
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        Date date = cell.getDateCellValue();
                        result = sdf.format(date);
                    } else {
                        double d = cell.getNumericCellValue();
                        result = numberFormat.format(d);
                    }
                    break;
                case BOOLEAN:// 布尔
                    result = cell.getBooleanCellValue();
                    break;
                case FORMULA:// 公式
                    result = cell.getCellFormula();
                    break;
                case ERROR:
                    result = cell.getErrorCellValue();
                    break;
                case BLANK: // null
                    break;
                default:
                    break;
            }
        }
        return result.toString().trim();
    }


    public static boolean validateExcelHeader(Sheet sheet, int firstRowNum, List<String> columnInfoList) {
        Row row = sheet.getRow(firstRowNum);
        List<Boolean> flags = new ArrayList<>();
        for (int i = 0; i < columnInfoList.size(); i++) {
            boolean flag = true;
            if (!StringUtils.equals(columnInfoList.get(i).toLowerCase(), ExcelUtils.getCellValue(row.getCell(i)).toLowerCase())) {
                flag = false;
                break;
            }
            flags.add(flag);
        }

        boolean headerFlag = false;
        for (Boolean flag : flags) {
            headerFlag = (headerFlag || flag);
        }
        return headerFlag;
    }


    public static Workbook getWorkBookFromMultipartFile(MultipartFile multipartFile) throws Exception {
        Workbook work = null;
        try {
            work = ExcelUtils.getWork(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
        } catch (IOException e) {
            throw new Exception("获取excel表对象异常!");
        } finally {
            if (null != work) {
                IOUtils.closeQuietly(work);
            }
        }
        return work;
    }


    public static void readExcel(Sheet sheet) {
        Row row = null;
        for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
            row = sheet.getRow(i);
            for (int j = 0; j < row.getLastCellNum(); j++) {
                Cell c = row.getCell(j);
                boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex());
                //判断是否具有合并单元格
                if (isMerge) {
                    String rs = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex());
                    System.out.print(rs + " ");
                } else {

                    if (c == null) {
                        System.out.print(" ");
                        continue;
                    }
                    c.setCellType(CellType.STRING);
                    System.out.print(c.getStringCellValue() + " ");
                }
            }

        }

    }

    /**
     * 获取合并单元格的值
     *
     * @param sheet
     * @param row
     * @param column
     * @return
     */
    public static String getMergedRegionValue(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();   //获得该sheet所有合并单元格数量

        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress ca = sheet.getMergedRegion(i);    // 获得合并区域
            int firstColumn = ca.getFirstColumn();
            int lastColumn = ca.getLastColumn();
            int firstRow = ca.getFirstRow();
            int lastRow = ca.getLastRow();


            //判断传入的单元格的行号列号是否在合并单元格的范围内,如果在合并单元格的范围内,择返回合并区域的首单元格格值
            if (row >= firstRow && row <= lastRow) {

                if (column >= firstColumn && column <= lastColumn) {
                    Row fRow = sheet.getRow(firstRow);
                    Cell fCell = fRow.getCell(firstColumn);
                    return getCellValue(fCell);
                }
            }
        }
        //如果该单元格行号列号不在任何一个合并区域,择返回null
        return null;
    }

    /**
     * 判断合并了行
     *
     * @param sheet
     * @param row
     * @param column
     * @return
     */
    private boolean isMergedRow(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row == firstRow && row == lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断指定的单元格是否是合并单元格
     *
     * @param sheet
     * @param row    行下标
     * @param column 列下标
     * @return
     */
    public static boolean isMergedRegion(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断sheet页中是否含有合并单元格
     *
     * @param sheet
     * @return
     */
    private boolean hasMerged(Sheet sheet) {
        return sheet.getNumMergedRegions() > 0 ? true : false;
    }

    /**
     * 合并单元格
     *
     * @param sheet
     * @param firstRow 开始行
     * @param lastRow  结束行
     * @param firstCol 开始列
     * @param lastCol  结束列
     */
    private void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
        sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
    }

    public static int getMaxColumn(MultipartFile multipartFile) throws Exception {
        boolean a = false;
        String modelFilename = multipartFile.getOriginalFilename();
        if (modelFilename.equals("")) {
            throw new Exception("未选择模板,请重新选择模板!");
        }

        //文件格式校验
        a = ExcelUtils.validateFileType(modelFilename);
        if (a) {
            //获取excel对象
            Workbook workbook = null;
            try {
                workbook = ExcelUtils.getWorkBookFromMultipartFile(multipartFile);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("异常信息为:" + e.getMessage());
            }

            int number = 0;
            if (workbook != null) {
                //获取电子表格数量
                number = workbook.getNumberOfSheets();
            }
            for (int i = 0; i < number; i++) {
                //获取当前sheet表对象
                Sheet sheet = workbook.getSheetAt(i);
                Row row = null;
                int lastRowNum = sheet.getLastRowNum();
                for (int y = 0; y <= lastRowNum; y++) {

                    //获取行数
                    row = sheet.getRow(0);
                    int num = row.getLastCellNum();
                    return num;
                }
            }
        }
        return 0;
    }
}

1.3 创建模板

package com.yu.service;

import com.deepoove.poi.data.MiniTableRenderData;
import com.deepoove.poi.util.TableTools;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.jeecg.common.util.ExcelUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileOutputStream;
import java.io.InputStream;

public class CreateWordService {


    XWPFDocument doc = new XWPFDocument();// 创建Word文件
    public void createWord(MultipartFile file, MultipartFile multipartFile) throws Exception {
        XWPFParagraph firstP = doc.createParagraph();// 新建一个段落
        firstP.setAlignment(ParagraphAlignment.LEFT);// 设置段落的对齐方式
        XWPFRun firstRun = firstP.createRun();//创建段落文本
        firstRun.setText("一.大事记");
        firstRun.setFontSize(16);
        firstRun.setFontFamily("宋体");
        firstRun.setBold(true);//设置为粗体
        firstRun.addCarriageReturn();
        XWPFRun secondRun = firstP.createRun();
        secondRun.setText("  {{dsj}}");
        secondRun.setFontFamily("宋体");
        secondRun.setFontSize(14);
        secondRun.addCarriageReturn();

        XWPFParagraph secondP = doc.createParagraph();// 新建一个段落
        secondP.setAlignment(ParagraphAlignment.LEFT);// 设置段落的对齐方式
        secondP.setIndentationFirstLine(2);
        XWPFRun SecondPRunOne = secondP.createRun();//创建段落文本
        SecondPRunOne.setText("二.情况");
        SecondPRunOne.setFontSize(16);
        SecondPRunOne.setFontFamily("宋体");
        SecondPRunOne.setBold(true);//设置为粗体
        SecondPRunOne.addCarriageReturn();

        XWPFRun SecondPRunTwo = secondP.createRun();//创建段落文本
        SecondPRunTwo.setText("1.整治工程");
        SecondPRunTwo.setFontSize(15);
        SecondPRunTwo.setFontFamily("宋体");
        SecondPRunTwo.setBold(true);//设置为粗体
        SecondPRunTwo.addCarriageReturn();

        XWPFRun SecondPRunThree = secondP.createRun();//创建段落文本
        SecondPRunThree.setText("1.1面貌(图片)");
        SecondPRunThree.setFontSize(14);
        SecondPRunThree.setFontFamily("宋体");
        SecondPRunThree.setBold(true);//设置为粗体
        SecondPRunThree.addCarriageReturn();

        XWPFRun SecondPRunFour = secondP.createRun();//创建图片
        InputStream fis = file.getInputStream();
        SecondPRunFour.addPicture(fis, XWPFDocument.PICTURE_TYPE_PNG, "Generated", Units.toEMU(256), Units.toEMU(256));
        SecondPRunFour.addCarriageReturn();

        XWPFRun SecondPRunFive = secondP.createRun();//创建段落文本
        SecondPRunFive.setText("1.2 评价");
        SecondPRunFive.setFontSize(14);
        SecondPRunFive.setFontFamily("宋体");
        SecondPRunFive.setBold(true);//设置为粗体
        SecondPRunFive.addCarriageReturn();

        XWPFRun SecondPRunSix = secondP.createRun();//创建段落文本
        SecondPRunSix.setText("  部分:{{slgcbf}}" + "\r\n" + "部分:{{szgcbf}}" + "\r\n" + "{{qtbf}}");
        SecondPRunSix.setFontSize(14);
        SecondPRunSix.setFontFamily("宋体");
        SecondPRunSix.addCarriageReturn();

        XWPFRun SecondPRunSev = secondP.createRun();//创建段落文本
        SecondPRunSev.setText("1.3控制");
        SecondPRunSev.setFontSize(14);
        SecondPRunSev.setFontFamily("宋体");
        SecondPRunSev.setBold(true);//设置为粗体
        SecondPRunSev.addCarriageReturn();

        XWPFRun SecondPRunEight = secondP.createRun();//创建段落文本
        SecondPRunEight.setText("  {{zlkzjpj}} ");
        SecondPRunEight.setFontSize(14);
        SecondPRunEight.setFontFamily("宋体");
        SecondPRunEight.addCarriageReturn();


        XWPFRun SecondPRunNine = secondP.createRun();//创建段落文本
        SecondPRunNine.setText("1.4安全");
        SecondPRunNine.setFontSize(14);
        SecondPRunNine.setFontFamily("宋体");
        SecondPRunNine.setBold(true);//设置为粗体
        SecondPRunNine.addCarriageReturn();

        XWPFRun SecondPRunTen = secondP.createRun();//创建段落文本
        SecondPRunTen.setText("  1.理。{{yqgl}}" + "\t\r\n" + "2.理。{{xcaqgl}}" + "\t\r\n" + "3.编。{{zdxb}}" + "\r\n" + "4.整理。{{dzzlzl}}" + "\r\n" + "{{aqwmqt}}");
        SecondPRunTen.setFontSize(14);
        SecondPRunTen.setFontFamily("宋体");
        SecondPRunTen.addCarriageReturn();


        XWPFRun SecondPRunElv = secondP.createRun();//创建段落文本
        SecondPRunElv.setText("1.5控制");
        SecondPRunElv.setFontSize(14);
        SecondPRunElv.setFontFamily("宋体");
        SecondPRunElv.setBold(true);//设置为粗体
        SecondPRunElv.addCarriageReturn();

        XWPFRun SecondPRunTwe = secondP.createRun();//创建段落文本
        SecondPRunTwe.setText("  产值_{{cz}}_万元,完成计划率_{{wcjhl}}_;累计完成产值约_{{ljcz}}_万元。");
        SecondPRunTwe.setFontSize(14);
        SecondPRunTwe.setFontFamily("宋体");
        SecondPRunTwe.addCarriageReturn();

        XWPFRun SecondPRunThir = secondP.createRun();//创建段落文本
        SecondPRunThir.setText("1.6投入");
        SecondPRunThir.setFontSize(14);
        SecondPRunThir.setFontFamily("宋体");
        SecondPRunThir.setBold(true);//设置为粗体
        SecondPRunThir.addCarriageReturn();

        this.autoDyTable(multipartFile);

        FileOutputStream out = new FileOutputStream("d:\\POI\\sample.docx");
        doc.write(out);
        out.close();
    }
    //自定解析模板bong在word中插入表格
    public void autoDyTable(MultipartFile multipartFile) throws Exception {

        boolean a = false;
        String modelFilename = multipartFile.getOriginalFilename();
        if (StringUtils.isBlank(modelFilename)) {
            throw new Exception("文件名不能为空!!");
        }

        //文件格式校验
        a = ExcelUtils.validateFileType(modelFilename);
        if (a) {
            //获取excel对象
            Workbook workbook = null;
            try {
                workbook = ExcelUtils.getWorkBookFromMultipartFile(multipartFile);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("异常信息为:" + e.getMessage());
            }

            int number = 0;
            if (workbook != null) {
                //获取电子表格数量
                number = workbook.getNumberOfSheets();
            }
            for (int i = 0; i < number; i++) {
                //获取当前sheet表对象
                Sheet sheet = workbook.getSheetAt(i);

                Row row = null;
                //获取表的最大行数
                int lastRowNum = sheet.getLastRowNum();
                //获取表最大列数
                int lastLastColumnNum = ExcelUtils.getMaxColumn(multipartFile);
                XWPFTable table = doc.createTable(lastRowNum + 1, lastLastColumnNum);
                TableTools.widthTable(table, MiniTableRenderData.WIDTH_A4_FULL, 10);
                int sheetMergeCount = sheet.getNumMergedRegions();   //获得该sheet所有合并单元格数量

                for (int y = 0; y <= lastRowNum; y++) {
                    //获取行数
                    row = sheet.getRow(y);
                    row.setHeight((short) 10);
                    if (null != row) {
                        //获取每一列值
                        for (int j = 0; j < lastLastColumnNum; j++) {
                            //获取每一行的单元格值
                            Cell cell = row.getCell(j);
                            if (cell == null || cell.equals("")) {
                                table.getRow(y).getCell(j).setText("");
                                continue;
                            }
                            //单元格转换成String类型
                            cell.setCellType(CellType.STRING);
                            String value = cell.getStringCellValue();
                            System.out.println("-----------------------------" + j);
                            table.getRow(y).getCell(j).setText(value);

                        }
                    } else {
                        throw new Exception("excel表内容为空!");
                    }
                }
            //必须要先给表格进行赋值,然后再进行单元格合并
                for (int m = 0; m < sheetMergeCount; m++) {
                    CellRangeAddress ca = sheet.getMergedRegion(m);    // 获得合并区域
                    int firstColumn = ca.getFirstColumn();
                    int lastColumn = ca.getLastColumn();
                    int firstRow = ca.getFirstRow();
                    int lastRow = ca.getLastRow();
                    if (firstColumn < lastColumn && firstRow == lastRow) {
                        TableTools.mergeCellsHorizonal(table, firstRow, firstColumn, lastColumn);
                    }
                    if (firstRow < lastRow && firstColumn == lastColumn) {
                        TableTools.mergeCellsVertically(table, firstColumn, firstRow, lastRow);
                    }
                    if (firstRow < lastRow && firstColumn == lastColumn) {
                        for (int t = firstRow; t <= lastRow; t++) {
                            TableTools.mergeCellsHorizonal(table, t, firstColumn, lastColumn);
                        }
                        TableTools.mergeCellsVertically(table, firstColumn, firstRow, lastRow);
                    }
                }
            }
        } else {
            throw new Exception("excel模板命名异常,请重新命名后上传!");
        }
    }


}

}

1.4 调用模板生成接口

@RestController
@Api(tags = "测试")
@RequestMapping("/dest")
public class TestController {
    @GetMapping("/aa")
    public String getName(String name) {
        return name;
    }

      @PostMapping("/dt")
    public void mm(@RequestParam("file") MultipartFile file, @RequestParam("multipartFile") MultipartFile multipartFile, String dsj, String slgcbf, String szgcbf, String qtbf, String yqgl, String zlkzjpj, String xcaqgl, String zdxb, String dzzlzl, String aqwmqt, String cz, String wcjhl, String ljcz) throws Exception {

        CreateWordService createWordService = new CreateWordService();
        createWordService.createWord(file, multipartFile);

        File templateFile = new File("d:\\POI\\sample.docx");

        //准备数据
        Map<String, Object> params = new HashMap<>();
        params.put("dsj", dsj);
        params.put("slgcbf", slgcbf);
        params.put("szgcbf", szgcbf);
        params.put("qtbf", qtbf);
        params.put("yqgl", yqgl);
        params.put("zlkzjpj", zlkzjpj);
        params.put("xcaqgl", xcaqgl);
        params.put("zdxb", zdxb);
        params.put("dzzlzl", dzzlzl);
        params.put("aqwmqt", aqwmqt);
        params.put("cz", cz);
        params.put("wcjhl", wcjhl);
        params.put("ljcz", ljcz);
        XWPFDocument word = WordExportUtil.exportWord07(templateFile.getPath(), params);
        FileOutputStream out = new FileOutputStream("d:\\POI\\sample.docx");
        word.write(out);
    }
    }

1.5 重写 WordExportUtil.exportWord07(templateFile.getPath(), params)方法

重写原因,自动的方法里面会有7天缓存,表格/图片只能启动之后修改,如果实时更新,就需要重写此方法

1.5.1 重写 WordExportUtil
package org.jeecg.config;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jeecg.config.ParseWord07;

import java.util.Map;

/**
 * Word使用模板导出工具类
 *
 * @author JEECG
 * @date 2013-11-16
 * @version 1.0
 */
public final class WordExportUtil {

    private WordExportUtil() {

    }

    /**
     * 解析Word2007版本
     *
     * @param url 模板地址
     * @param map 解析数据源
     * @return
     */
    public static XWPFDocument exportWord07(String url, Map<String, Object> map) throws Exception {
        return new ParseWord07().parseWord(url, map);
    }

    /**
     * 解析Word2007版本
     *
     * @param
     * @param map 解析数据源
     * @return
     */
    public static void exportWord07(XWPFDocument document, Map<String, Object> map) throws Exception {
        new ParseWord07().parseWord(document, map);
    }
}
1.5.2 重写ParseWord07
package org.jeecg.config;

/**
 * Copyright 2013-2015 JEECG (jeecgos@163.com)
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jeecg.config.WordCache;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
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.jeecgframework.poi.util.PoiPublicUtil;
import org.jeecgframework.poi.word.entity.MyXWPFDocument;
import org.jeecgframework.poi.word.entity.WordImageEntity;
import org.jeecgframework.poi.word.entity.params.ExcelListEntity;
import org.jeecgframework.poi.word.parse.excel.ExcelEntityParse;
import org.jeecgframework.poi.word.parse.excel.ExcelMapParse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 解析07版的Word,替换文字,生成表格,生成图片
 *
 * @author JEECG
 * @date 2013-11-16
 * @version 1.0
 */
@SuppressWarnings({"unchecked", "rawtypes"})
public class ParseWord07 {

    private static final Logger LOGGER = LoggerFactory.getLogger(org.jeecgframework.poi.word.parse.ParseWord07.class);

    /**
     * 添加图片
     *
     * @Author JEECG
     * @date 2013-11-20
     * @param obj
     * @param currentRun
     * @throws Exception
     */
    private void addAnImage(WordImageEntity obj, XWPFRun currentRun) throws Exception {
        Object[] isAndType = PoiPublicUtil.getIsAndType(obj);
        String picId;
        try {
            picId = currentRun.getParagraph().getDocument().addPictureData((byte[]) isAndType[0], (Integer) isAndType[1]);
            ((MyXWPFDocument) currentRun.getParagraph().getDocument()).createPicture(currentRun, picId, currentRun.getParagraph().getDocument().getNextPicNameNumber((Integer) isAndType[1]), obj.getWidth(), obj.getHeight());

        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }

    }

    /**
     * 根据条件改变值
     *
     * @param map
     * @Author JEECG
     * @date 2013-11-16
     */
    private void changeValues(XWPFParagraph paragraph, XWPFRun currentRun, String currentText, List<Integer> runIndex, Map<String, Object> map) throws Exception {
        Object obj = PoiPublicUtil.getRealValue(currentText, map);
        if (obj instanceof WordImageEntity) {// 如果是图片就设置为图片
            currentRun.setText("", 0);
            addAnImage((WordImageEntity) obj, currentRun);
        } else {
            currentText = obj.toString();
            currentRun.setText(currentText, 0);
        }
        for (int k = 0; k < runIndex.size(); k++) {
            paragraph.getRuns().get(runIndex.get(k)).setText("", 0);
        }
        runIndex.clear();
    }

    /**
     * 判断是不是迭代输出
     *
     * @Author JEECG
     * @date 2013-11-18
     * @return
     * @throws Exception
     */
    private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map<String, Object> map) throws Exception {
        String text = cell.getText().trim();
        //begin-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
        // 判断是不是迭代输出
        if (text != null && text.startsWith("{{") && text.indexOf("$fe:") != -1) {
            return PoiPublicUtil.getRealValue(text.replace("$fe:", "").trim(), map);
        }
        //end-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
        return null;
    }

    /**
     * 解析所有的文本
     *
     * @Author JEECG
     * @date 2013-11-17
     * @param paragraphs
     * @param map
     */
    private void parseAllParagraphic(List<XWPFParagraph> paragraphs, Map<String, Object> map) throws Exception {
        XWPFParagraph paragraph;
        for (int i = 0; i < paragraphs.size(); i++) {
            paragraph = paragraphs.get(i);
            if (paragraph.getText().indexOf("{{") != -1) {
                parseThisParagraph(paragraph, map);
            }

        }

    }

    /**
     * 解析这个段落
     *
     * @Author JEECG
     * @date 2013-11-16
     * @param paragraph
     * @param map
     */
    private void parseThisParagraph(XWPFParagraph paragraph, Map<String, Object> map) throws Exception {
        XWPFRun run;
        XWPFRun currentRun = null;// 拿到的第一个run,用来set值,可以保存格式
        String currentText = "";// 存放当前的text
        String text;
        Boolean isfinde = false;// 判断是不是已经遇到{{
        List<Integer> runIndex = new ArrayList<Integer>();// 存储遇到的run,把他们置空
        for (int i = 0; i < paragraph.getRuns().size(); i++) {
            run = paragraph.getRuns().get(i);
            text = run.getText(0);
            if (StringUtils.isEmpty(text)) {
                continue;
            }// 如果为空或者""这种这继续循环跳过
            if (isfinde) {
                currentText += text;
                if (currentText.indexOf("{{") == -1) {
                    isfinde = false;
                    runIndex.clear();
                } else {
                    runIndex.add(i);
                }
                if (currentText.indexOf("}}") != -1) {
                    changeValues(paragraph, currentRun, currentText, runIndex, map);
                    currentText = "";
                    isfinde = false;
                }
            } else if (text.indexOf("{") >= 0) {// 判断是不是开始
                currentText = text;
                isfinde = true;
                currentRun = run;
            } else {
                currentText = "";
            }
            if (currentText.indexOf("}}") != -1) {
                changeValues(paragraph, currentRun, currentText, runIndex, map);
                isfinde = false;
            }
        }

    }

    private void parseThisRow(List<XWPFTableCell> cells, Map<String, Object> map) throws Exception {
        for (XWPFTableCell cell : cells) {
            parseAllParagraphic(cell.getParagraphs(), map);
        }
    }

    /**
     * 解析这个表格
     *
     * @Author JEECG
     * @date 2013-11-17
     * @param table
     * @param map
     */
    private void parseThisTable(XWPFTable table, Map<String, Object> map) throws Exception {
        XWPFTableRow row;
        List<XWPFTableCell> cells;
        Object listobj;
        for (int i = 0; i < table.getNumberOfRows(); i++) {
            row = table.getRow(i);
            cells = row.getTableCells();
            //begin-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
            listobj = checkThisTableIsNeedIterator(cells.get(0), map);
            if (listobj == null) {
                parseThisRow(cells, map);
            } else if (listobj instanceof ExcelListEntity) {
                new ExcelEntityParse().parseNextRowAndAddRow(table, i, (ExcelListEntity) listobj);
                i = i + ((ExcelListEntity) listobj).getList().size() - 1;//删除之后要往上挪一行,然后加上跳过新建的行数
            } else {
                ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listobj);
                i = i + ((List) listobj).size() - 1;//删除之后要往上挪一行,然后加上跳过新建的行数
            }
			/*if (cells.size() == 1) {
				listobj = checkThisTableIsNeedIterator(cells.get(0), map);
				if (listobj == null) {
					parseThisRow(cells, map);
				} else if (listobj instanceof ExcelListEntity) {
					table.removeRow(i);// 删除这一行
					excelEntityParse.parseNextRowAndAddRow(table, i, (ExcelListEntity) listobj);
				} else {
					table.removeRow(i);// 删除这一行
					ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listobj);
				}
			} else {
				parseThisRow(cells, map);
			}*/
            //end-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------
        }
    }

    /**
     * 解析07版的Word并且进行赋值
     *
     * @Author JEECG
     * @date 2013-11-16
     * @return
     * @throws Exception
     */
    public XWPFDocument parseWord(String url, Map<String, Object> map) throws Exception {
        MyXWPFDocument doc = WordCache.getXWPFDocumen(url);
        parseWordSetValue(doc, map);
        return doc;
    }

    /**
     * 解析07版的Word并且进行赋值
     *
     * @Author JEECG
     * @date 2013-11-16
     * @return
     * @throws Exception
     */
    public void parseWord(XWPFDocument document, Map<String, Object> map) throws Exception {
        parseWordSetValue((MyXWPFDocument) document, map);
    }

    private void parseWordSetValue(MyXWPFDocument doc, Map<String, Object> map) throws Exception {
        // 第一步解析文档
        parseAllParagraphic(doc.getParagraphs(), map);
        // 第二步解析页眉,页脚
        parseHeaderAndFoot(doc, map);
        // 第三步解析所有表格
        XWPFTable table;
        Iterator<XWPFTable> itTable = doc.getTablesIterator();
        while (itTable.hasNext()) {
            table = itTable.next();
            if (table.getText().indexOf("{{") != -1) {
                parseThisTable(table, map);
            }
        }

    }

    /**
     * 解析页眉和页脚
     *
     * @param doc
     * @param map
     * @throws Exception
     */
    private void parseHeaderAndFoot(MyXWPFDocument doc, Map<String, Object> map) throws Exception {
        List<XWPFHeader> headerList = doc.getHeaderList();
        for (XWPFHeader xwpfHeader : headerList) {
            for (int i = 0; i < xwpfHeader.getListParagraph().size(); i++) {
                parseThisParagraph(xwpfHeader.getListParagraph().get(i), map);
            }
        }
        List<XWPFFooter> footerList = doc.getFooterList();
        for (XWPFFooter xwpfFooter : footerList) {
            for (int i = 0; i < xwpfFooter.getListParagraph().size(); i++) {
                parseThisParagraph(xwpfFooter.getListParagraph().get(i), map);
            }
        }

    }
}
1.5.3 重写WordCache
package org.jeecg.config;

/**
 * Copyright 2013-2015 JEECG (jeecgos@163.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.io.InputStream;

import org.jeecgframework.poi.word.entity.MyXWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * word 缓存中心
 *
 * @author JEECG
 * @date 2014年7月24日 下午10:54:31
 */
public class WordCache {

    private static final Logger LOGGER = LoggerFactory.getLogger(org.jeecgframework.poi.cache.WordCache.class);

    public static MyXWPFDocument getXWPFDocumen(String url) {
        InputStream is = null;
        try {
            is = POICacheManager.getFile(url);
            MyXWPFDocument doc = new MyXWPFDocument(is);
            return doc;
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        } finally {
            try {
                is.close();
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
        return null;
    }

}

1.5.4 重写POICacheManager

package org.jeecg.config;

/**
 * Copyright 2013-2015 JEECG (jeecgos@163.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

/**
 * 缓存管理
 *
 * @author JEECG
 * @date 2014年2月10日
 * @version 1.0
 */
public final class POICacheManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(org.jeecgframework.poi.cache.manager.POICacheManager.class);

    private static LoadingCache<String, byte[]> loadingCache;

    static {
        loadingCache = CacheBuilder.newBuilder().expireAfterWrite(0, TimeUnit.DAYS).maximumSize(50).build(new CacheLoader<String, byte[]>() {
            @Override
            public byte[] load(String url) throws Exception {
                return new FileLoade().getFile(url);
            }
        });
    }

    public static InputStream getFile(String id) {
        try {
            // 复杂数据,防止操作原数据
            byte[] result = Arrays.copyOf(loadingCache.get(id), loadingCache.get(id).length);
            return new ByteArrayInputStream(result);
        } catch (ExecutionException e) {
            LOGGER.error(e.getMessage(), e);
        }
        return null;
    }

}
1.5.5 重写FileLoade
package org.jeecg.config;

/**
 * Copyright 2013-2015 JEECG (jeecgos@163.com)
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 文件加载类,根据路径加载指定文件
 *
 * @author JEECG
 * @date 2014年2月10日
 * @version 1.0
 */
class FileLoade {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileLoade.class);

    public byte[] getFile(String url) {
        FileInputStream fileis = null;
        ByteArrayOutputStream baos = null;
        try {
            // 先用绝对路径查询,再查询相对路径
            try {
                fileis = new FileInputStream(url);
            } catch (FileNotFoundException e) {
                String path = PoiPublicUtil.getWebRootPath(url);
                fileis = new FileInputStream(path);
            }
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fileis.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos.toByteArray();
        } catch (FileNotFoundException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
        } finally {
            try {
                if (fileis != null)
                    fileis.close();
                if (fileis != null)
                    baos.close();
            } catch (IOException e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
        LOGGER.error(fileis + "这个路径文件没有找到,请查询");
        return null;
    }

}

2.使用已有接口进行填充

package org.jeecg.controller;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.jeecg.common.util.ExcelUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;


@RestController
@Api(tags = "测试poi")
@RequestMapping("/word")
public class WordTestController {
    public WordTestController() throws FileNotFoundException {
    }

    @GetMapping(value = "/download")
    public void test(MultipartFile multipartFile) throws Exception {
        RowRenderData header = null;
        RowRenderData body = null;
        List<RowRenderData> tableDatas = null;

        boolean a = false;

        String modelFilename = multipartFile.getOriginalFilename();
        if (StringUtils.isBlank(modelFilename)) {
            throw new Exception("文件名不能为空!!");
        }

        //文件格式校验
        a = ExcelUtils.validateFileType(modelFilename);
        if (a) {
            //获取excel对象
            Workbook workbook = null;
            try {
                workbook = ExcelUtils.getWorkBookFromMultipartFile(multipartFile);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("异常信息为:" + e.getMessage());
            }

            int number = 0;
            if (workbook != null) {
                //获取电子表格数量
                number = workbook.getNumberOfSheets();
            }
            for (int i = 0; i < number; i++) {
                //获取当前sheet表对象
                Sheet sheet = workbook.getSheetAt(i);

                Row row = null;
                //获取表的最大行数
                int lastRowNum = sheet.getLastRowNum();

                List<RowRenderData> rowRenderData = new ArrayList<>();
                for (int y = 0; y <= lastRowNum; y++) {
                    //获取行数
                    row = sheet.getRow(y);
                    row.setHeight((short) 10);
                    if (null != row) {
                        //获取每一列值
                        if (y == 0) {
                            CellRenderData[] cellRenderDatas = new CellRenderData[row.getLastCellNum()];
                            //获取每一行的单元格值
                            for (int j = 0; j < row.getLastCellNum(); j++) {

                                Cell cell = row.getCell(j);
                                if (cell == null || cell.equals("")) {
                                    cellRenderDatas[j] = new CellRenderData(new TextRenderData(""));
                                    continue;
                                }
                                //单元格转换成String类型
                                cell.setCellType(CellType.STRING);
                                String value = cell.getStringCellValue();
                                cellRenderDatas[j] = new CellRenderData(new TextRenderData(value));
                            }
                            header = new RowRenderData();
                            header.setCellDatas(Arrays.asList(cellRenderDatas));
                        }

                        if (y != 0) {
                            CellRenderData[] cellRenderDatas = new CellRenderData[row.getLastCellNum()];
                            //获取每一行的单元格值
                            for (int j = 0; j < row.getLastCellNum(); j++) {
                                Cell cell = row.getCell(j);
                                if (cell == null || cell.equals("")) {
                                    cellRenderDatas[j] = new CellRenderData(new TextRenderData(""));
                                    continue;
                                }
                                //单元格转换成String类型
                                cell.setCellType(CellType.STRING);
                                String value = cell.getStringCellValue();
                                cellRenderDatas[j] = new CellRenderData(new TextRenderData(value));
                            }
                            body = new RowRenderData();
                            body.setCellDatas(Arrays.asList(cellRenderDatas));
                            rowRenderData.add(body);
                        }
                    }
                }
                tableDatas = rowRenderData;

                //获取模板文档
                File templateFile = new File("D:\\Idea_proj\\123\\engineering-manage\\jeecg-boot-framework\\jeecg-cloud-module\\sjwsjy-cloud-ddmo\\src\\main\\resources\\word\\demo.docx");

                //准备数据
                Map<String, Object> params = new HashMap<>();
                params.put("dsj", "123");
                params.put("slgcbf", "2022");
                params.put("szgcbf", "123456");
                params.put("qtbf", "123456");
                params.put("aaa", new PictureRenderData(100, 120, "D:\\zpp.png"));
//        params.put("table", new DefaultTableCellRenderer());
                params.put("table", new MiniTableRenderData(header, tableDatas));
//        XWPFDocument word = WordExportUtil.exportWord07(templateFile.getPath(), params);
                XWPFTemplate template = XWPFTemplate.compile(templateFile.getPath())
                        .render(params);

                FileOutputStream out = new FileOutputStream("d:\\POI\\demo.docx");
//        word.write(out);
                template.write(out);
            }


        }
    }
}

3.知识补充

3.1 poi入门基础知识

poi入门基础知识

3.2 poi模板插入处理

在这里插入图片描述

3.3 文档/表格

文档模板
在这里插入图片描述
在这里插入图片描述
表格
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值