前言:poi模板操作word-doc有两种方式
1.手动创建模板
2.使用已有模板进行填充
3.知识补充
1.手动创建模板
1.1 jar包导入
pom.xml中添加以下依赖
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
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
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
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
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
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
3.知识补充
3.1 poi入门基础知识
3.2 poi模板插入处理
3.3 文档/表格
文档模板
表格