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

1.手动创建模板

1.1 jar包导入

pom.xml中添加以下依赖 org.apache.poi poi-ooxml 4.0.0 org.apache.poi poi-excelant 4.0.0 org.apache.poi poi-ooxml-schemas 4.0.0 org.apache.poi poi-scratchpad 4.0.0 com.deepoove poi-tl 1.6.0 org.jeecg easypoi-base 2.3.1 org.jeecg easypoi-web 2.3.1 org.jeecg easypoi-annotation 2.3.1

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 columnInfoList) { Row row = sheet.getRow(firstRowNum); List 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}}" + "rn" + "部分:{{szgcbf}}" + "rn" + "{{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}}" + "trn" + "2.理。{{xcaqgl}}" + "trn" + "3.编。{{zdxb}}" + "rn" + "4.整理。{{dzzlzl}}" + "rn" + "{{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 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 map) throws Exception { return new ParseWord07().parseWord(url, map); } /** * 解析Word2007版本 * * @param * @param map 解析数据源 * @return */ public static void exportWord07(XWPFDocument document, Map map) throws Exception { new ParseWord07().parseWord(document, map); } }

1.5.2 重写ParseWord07

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.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 runIndex, Map 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 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 paragraphs, Map 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 map) throws Exception { XWPFRun run; XWPFRun currentRun = null;// 拿到的第一个run,用来set值,可以保存格式 String currentText = "";// 存放当前的text String text; Boolean isfinde = false;// 判断是不是已经遇到{{ List runIndex = new ArrayList();// 存储遇到的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 cells, Map 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 map) throws Exception { XWPFTableRow row; List 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 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 map) throws Exception { parseWordSetValue((MyXWPFDocument) document, map); } private void parseWordSetValue(MyXWPFDocument doc, Map map) throws Exception { // 第一步解析文档 parseAllParagraphic(doc.getParagraphs(), map); // 第二步解析页眉,页脚 parseHeaderAndFoot(doc, map); // 第三步解析所有表格 XWPFTable table; Iterator 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 map) throws Exception { List headerList = doc.getHeaderList(); for (XWPFHeader xwpfHeader : headerList) { for (int i = 0; i < xwpfHeader.getListParagraph().size(); i++) { parseThisParagraph(xwpfHeader.getListParagraph().get(i), map); } } List 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 loadingCache; static { loadingCache = CacheBuilder.newBuilder().expireAfterWrite(0, TimeUnit.DAYS).maximumSize(50).build(new CacheLoader() { @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) *

* 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.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 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 = 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 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入门基础知识

3.2 poi模板插入处理



3.3 文档/表格

文档模板

表格