前言:poi模板操作word-doc有两种方式
1.手动创建模板
2.使用已有模板进行填充
3.知识补充
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>
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;
}
}
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模板命名异常,请重新命名后上传!");
}
}
}
}
@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);
}
}
重写原因,自动的方法里面会有7天缓存,表格/图片只能启动之后修改,如果实时更新,就需要重写此方法
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);
}
}
package org.jeecg.config;
/**
* Copyright 2013-2015 JEECG ([email protected])
*
* 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<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);
}
}
}
}
package org.jeecg.config;
/**
* Copyright 2013-2015 JEECG ([email protected])
*
* 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 ([email protected])
*
* 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;
}
}
package org.jeecg.config;
/**
* Copyright 2013-2015 JEECG ([email protected])
*
* 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;
}
}
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);
}
}
}
}
poi入门基础知识