根据手动输入的数据存入数据后,取出以word文档的形式导出。
数据有填入、插入表格、复选框(支持单选及多选)。
一:建立word模板
二、导出word效果
首先要在xml导入配置:
<dependency> <groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
1、controller层
package cn.galaiot.modules.form.controller;import cn.galaiot.common.utils.PoiUtils;
import cn.galaiot.common.utils.R;
import cn.galaiot.modules.form.entity.Form67Entity;
import cn.galaiot.modules.form.service.Form67Service;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/project")
@Api(tags = "表格导出")
@Slf4j
public class Form67Controller {
@Autowired
private Form67Service form67Service;
@ApiOperation("导出")@GetMapping("/download/67")
public void downloadForm(@RequestParam("pfiId") Integer pfiId, HttpServletResponse response) {
try {
byte[] bytes = form67Service.download(pfiId);
PoiUtils.downloadFileByEncode_gb2312(response, bytes,
java.net.URLEncoder.encode("连续管内胀(外螺纹)连接接头平行检验记录", "UTF-8") + ".docx");
log.info("success to downloadForm67, id:{}", pfiId);
} catch (Exception e) {
e.printStackTrace();
log.error("error to downloadForm67", e);
}
}
}
2、Entity层
package cn.galaiot.modules.form.entity;import cn.galaiot.common.utils.DateUtils;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 平检:压力检测仪表安装平行检验记录
*
* @author jiangtie
* @email xxx@gmail.com
* @date 2021-10-20 13:45:13
*/
@Data
@TableName("project_form_67")
public class Form67Entity implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private Integer pfId;
/**
* 项目ID
*/
@TableField(exist = false)
private Integer pmId;
/**
* 检验部位
*/
private String positionCheck;
/**
* 接头形式
*/
private Integer jointForm;
/**
* 规格型号
*/
private String standardModel;
/**
* 接头材质
*/
private String jointMaterial;
/**
* 执行标准
*/
private String standardExecute;
/**
* 材料报审表签章是否齐全
*/
private Integer zlCheck11;
/**
* 出厂合格证或质量证明文件
*/
private Integer zlCheck21;
/**
* 标记检查
*/
private Integer swCheck11;
/**
* 外观检查检查内容
*/
private String swCheck21;
/**
* 外观检查结果
*/
private Integer swCheck22;
/**
* 数据记录
*/
private String swCheck31;
/**
* 备注
*/
private String remark;
/**
* 标准规范
*/
private String standardSpecification;
/**
* 不合格项
*/
private Integer unqualifyTerm;
/**
* 不合格编号
*/
private String unqualifyNumber;
/**
* 不合格规定
*/
private Integer unqualifyRule;
/**
* 检验员
*/
private String people;
/**
* 日期
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Date date;
/**
* 正常:0,已删除:1
*/
private Integer isDelete;
/**
* 更新时间
*/
private Date updatedAt;
public HashMap<String, String> getWordData() {
HashMap<String, String> wordData = new HashMap<>();
wordData.put("positionCheck", positionCheck);
wordData.put("standardModel", standardModel);
wordData.put("jointMaterial", jointMaterial);
wordData.put("standardExecute", standardExecute);
wordData.put("remark", remark);
wordData.put("standardSpecification", standardSpecification);
wordData.put("unqualifyTerm", unqualifyTerm.toString());
wordData.put("unqualifyNumber", unqualifyNumber);
wordData.put("unqualifyRule", unqualifyRule.toString());
wordData.put("people", people);
wordData.put("date", DateUtils.format(date, "yyyy年MM月dd日"));
return wordData;
}
//插入列表数据
public List<String> getList() {
List<String> list = new ArrayList<>();
list.add(swCheck31);
return list;
}
//多选或单选
public List<String> getChoice() {
List<String> list = new ArrayList<>();
list.add(jointForm.toString());
list.add(zlCheck11.toString());
list.add(zlCheck21.toString());
list.add(swCheck11.toString());
list.add(swCheck21);
list.add(swCheck22.toString());
return list;
}
}
3、service
package cn.galaiot.modules.form.service;import cn.galaiot.modules.form.entity.Form67Entity;
import com.baomidou.mybatisplus.extension.service.IService;
public interface Form67Service extends IService<Form67Entity> {
Form67Entity selectByPfiId(Integer pfiId);
String checkAdd(Form67Entity form67);
String checkUpdate(Form67Entity form67);
byte[] download(Integer pfiId);
String checkDelete(Integer pfiId);
}
4、serviceImpl
@Service("Form67Service")public class Form67ServiceImpl extends ServiceImpl<Form67Dao, Form67Entity> implements Form67Service {
@Resource
private Form67Dao form67Dao;
@Resource
private FormIndexDao formIndexDao;
@Resource
private ProjectManagementDao projectManagementDao;
@Overridepublic byte[] download(Integer pfiId) {
FormIndexEntity formIndexEntity = formIndexDao.selectById(pfiId);
Form67Entity form67 = form67Dao.selectById(formIndexEntity.getPfId());
String projectName = projectManagementDao.selectProjectName(formIndexEntity.getPmId());
Map<String, String> map = new HashMap<>();
map.put("projectName", projectName);
Map<String, String> tableMap = form67.getWordData();
List<String> list = form67.getList();
List<String> choice = form67.getChoice();
ByteArrayOutputStream bo = new ByteArrayOutputStream();
String inputUrl = Constant.ADDRESS + "67连续管内胀(外螺纹)连接接头平行检验记录.docx";
XWPFDocument document = null;
try {
document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
ExportWordUtil.changeParagraphText(document, map);
ExportWordUtil.changeTableText(document, tableMap);
ExportWordUtil.multipleChoice(document, choice);
ExportWordUtil.insertTableData(document, list);
document.write(bo);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document != null) {
try {
bo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bo.toByteArray();
}
}
5、导出word方法(poi)
package cn.galaiot.common.utils;import cn.galaiot.common.fastdfs.FastDFSClient;
import cn.galaiot.modules.conference.controller.WorderToNewWordUtils;
import cn.galaiot.modules.project.dto.ProjectQualityPictureDTO;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.IOException;
import java.util.*;
import static cn.galaiot.modules.conference.controller.WorderToNewWordUtils.checkPicture;
public class ExportWordUtil {
public static FastDFSClient fastDFSClient;
private ExportWordUtil() {
}
/**
* 替换文档中段落文本
*
* @param document docx解析对象
* @param textMap 需要替换的信息集合
*/
public static void changeParagraphText(XWPFDocument document, Map<String, String> textMap) {
//获取段落集合
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
//判断此段落时候需要进行替换
String text = paragraph.getText();
if (checkText(text)) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
//替换模板原来位置
run.setText(changeValue(run.toString(), textMap), 0);
}
}
}
}
/**
* 复制表头 插入行数据,这里样式和表头一样
*
* @param document docx解析对象
* @param tableList 需要插入数据集合
* @param headerIndex 表头的行索引,从0开始
*/
public static void copyHeaderInsertText(XWPFDocument document, List<String[]> tableList, int headerIndex) {
if (null == tableList) {
return;
}
//获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (XWPFTable table : tables) {
XWPFTableRow copyRow = table.getRow(headerIndex);
List<XWPFTableCell> cellList = copyRow.getTableCells();
if (null == cellList) {
break;
}
//遍历要添加的数据的list
for (int i = 0; i < tableList.size(); i++) {
//插入一行
XWPFTableRow targetRow = table.insertNewTableRow(headerIndex + 1 + i);
//复制行属性
targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
String[] strings = tableList.get(i);
for (int j = 0; j < strings.length; j++) {
XWPFTableCell sourceCell = cellList.get(j);
//插入一个单元格
XWPFTableCell targetCell = targetRow.addNewTableCell();
//复制列属性
targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
targetCell.setText(strings[j]);
}
}
}
}
/**
* 替换表格对象方法
*
* @param document docx解析对象
*/
static Integer num1 = 0;
public static void insertTableData(XWPFDocument document, List<String> list) {
HashMap<Integer, List<String>> dataList = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
List<String> list1 = new ArrayList<>();
JSONArray objects = JSONArray.parseArray(list.get(i));
objects.forEach(o -> {
list1.add(o.toString());
});
dataList.put(i, list1);
}
//获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (int i = 0; i < tables.size(); i++) {
//只处理行数大于等于2的表格
XWPFTable table = tables.get(i);
if (table.getRows().size() > 1 && dataList.size() > 0) {
List<XWPFTableRow> rows = table.getRows();
//插入数据列表
insertRows(rows, dataList, table);
}
}
num1 = 0;
}
public static void changeTableText(XWPFDocument document, Map<String, String> textMap) {
//获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (int i = 0; i < tables.size(); i++) {
//只处理行数大于等于2的表格
XWPFTable table = tables.get(i);
if (table.getRows().size() > 0) {
List<XWPFTableRow> rows = table.getRows();
//遍历表格,并替换模板
eachTable(rows, textMap, num);
}
}
}
private static void insertRows(List<XWPFTableRow> rows, HashMap<Integer, List<String>> dataList, XWPFTable table) {
Integer line;
Integer column;
for (int i = 0; i < rows.size(); i++) {
List<XWPFTableCell> cells = rows.get(i).getTableCells();
for (int j = 0; j < cells.size(); j++) {
if (checkNotation(cells.get(j).getText())) {
line = i;
column = j;
List<String> data = dataList.get(num1);
String str1 = "";
for (int n = 0; n < cells.get(j).getText().length(); n++) {
if (cells.get(j).getText().charAt(n) >= 48 && cells.get(j).getText().charAt(n) <= 57) {
str1 += cells.get(j).getText().charAt(n);
}
}
for (int n = 1; n <= (data.size() - Integer.parseInt(str1)); n++) {
insertRow(table, line, line + n);
}
List<XWPFRun> runs = rows.get(line).getTableCells().get(column).getParagraphs().get(0).getRuns();
runs.forEach(r -> {
r.setText(null, 0);
});
if (data.size() > 0) {
JSONArray objects = JSONArray.parseArray(data.toString());
for (int m = 0; m < data.size(); m++) {
JSONObject jsonObject = JSONObject.parseObject(objects.get(m).toString());
Set<Map.Entry<String, Object>> entries = jsonObject.entrySet();
ArrayList<String> list = new ArrayList<>();
for (int n = 0; n < entries.size(); n++) {
list.add("0");
}
entries.forEach(e -> {
String value = StringUtils.defaultIfEmpty((String) e.getValue(), "");
String str2 = "";
for (int n = 0; n < e.getKey().length(); n++) {
if (e.getKey().charAt(n) >= 48 && e.getKey().charAt(n) <= 57) {
str2 += e.getKey().charAt(n);
}
}
list.set(Integer.parseInt(str2), value);
});
for (int n = 0; n < list.size(); n++) {
XWPFTableCell cell = rows.get(line + m).getTableCells().get(column + n);
cell.setText(list.get(n));
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);//垂直对齐
CTTc cttc = cell.getCTTc();
CTP ctp = cttc.getPList().get(0);
CTPPr ctppr = ctp.getPPr();
if (ctppr == null) {
ctppr = ctp.addNewPPr();
}
CTJc ctjc = ctppr.getJc();
if (ctjc == null) {
ctjc = ctppr.addNewJc();
}
ctjc.setVal(STJc.CENTER); //水平居中
}
}
}
num1++;
}
}
}
}
/**
* 遍历表格,并替换模板
*
* @param rows 表格行对象
* @param textMap 需要替换的信息集合
*/
public static void eachTable(List<XWPFTableRow> rows, Map<String, String> textMap, Integer num) {
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
//判断单元格是否需要替换
if (checkText(cell.getText())) {//判断$替换
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
if (checkText(run.toString())) {
run.setText(changeValue(run.toString(), textMap), 0);
}
}
}
}
if (checkChoice(cell.getText())) {//判断#替换
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
if (checkChoice(run.toString())) {
run.setText(changeValues(run.toString(), textMap), 0);
run.setFontFamily("Wingdings 2");//设置字体
}
}
}
}
if (checkChoices(cell.getText())) {//判断@替换
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
if (checkChoices(run.toString())) {
run.setText(changeValuess(run.toString(), textMap, num), 0);
run.setFontFamily("Wingdings 2");//设置字体
}
}
}
num++;
}
}
}
}
/**
* 匹配传入信息集合与模板
*
* @param value 模板需要替换的区域
* @param textMap 传入信息集合
* @return 模板需要替换区域信息集合对应值
*/
public static String changeValue(String value, Map<String, String> textMap) {
Set<Map.Entry<String, String>> textSets = textMap.entrySet();
for (Map.Entry<String, String> textSet : textSets) {
//匹配模板与替换值 格式${key}
String key = "${" + textSet.getKey() + "}";
if (value.contains(key)) {
value = textSet.getValue();
}
}
//模板未匹配到区域替换为空
if (checkText(value)) {
value = "";
}
return value;
}
/**
* 判断文本中时候包含$
*
* @param text 文本
* @return 包含返回true, 不包含返回false
*/
public static boolean checkText(String text) {
boolean check = false;
if (text.contains("$")) {
check = true;
}
return check;
}
public static Boolean checkChoice(String text) {
boolean check = false;
if (text.contains("#")) {
check = true;
}
return check;
}
public static Boolean checkChoices(String text) {
boolean check = false;
if (text.contains("@{")) {
check = true;
}
return check;
}
public static Boolean checkNotation(String text) {
boolean check = false;
if (text.contains("%{")) {
check = true;
}
return check;
}
public static Boolean checkDx(String text) {
boolean check = false;
if (text.contains("&{")) {
check = true;
}
return check;
}
//二选一
public static String changeValues(String value, Map<String, String> textMap) {
if (textMap.get("decide") != null) {
String decide = textMap.get("decide");
int i;
int j;
for (i = 0; i < decide.length(); i++) {
j = 2 * i;
if (Integer.parseInt(decide.substring(i, i + 1)) == 0) {
if (value.contains("#{" + j + "}")) {
value = "\u002A";
}
if (value.contains("#{" + (j + 1) + "}")) {
value = "\u002A";
}
continue;
}
if (Integer.parseInt(decide.substring(i, i + 1)) == 1) {
if (value.contains("#{" + j + "}")) {
value = "\u0052";
}
if (value.contains("#{" + (j + 1) + "}")) {
value = "\u002A";
}
} else {
if (value.contains("#{" + j + "}")) {//包含判断
value = "\u002A";
}
if (value.contains("#{" + (j + 1) + "}")) {//包含判断
value = "\u0052";
}
}
}
}
Set<Map.Entry<String, String>> textSets = textMap.entrySet();
for (Map.Entry<String, String> textSet : textSets) {
if (textSet.getKey().equals("decide")) {
continue;
}
//匹配模板与替换值 格式#{key}
String key = "#{" + textSet.getKey() + "}";
if (value.contains(key)) {
value = textSet.getValue();
}
}
//模板未匹配到区域替换为空
if (checkChoice(value)) {
value = "";
}
return value;
}
//多选一
public static String changeValuess(String value, Map<String, String> textMap, Integer num) {
if (textMap.get("decides") != null) {
String decide = textMap.get("decides").substring(num, num + 1);
if (value.equals("@{" + decide + "}")) {
value = "\u0052";
} else {
value = "\u002A";
}
}
return value;
}
/**
* insertRow 在word表格中指定位置插入一行,并将某一行的样式复制到新增行
*
* @param copyrowIndex 需要复制的行位置
* @param newrowIndex 需要新增一行的位置
*/
public static void insertRow(XWPFTable table, int copyrowIndex, int newrowIndex) {
// 在表格中指定的位置新增一行
XWPFTableRow targetRow = table.insertNewTableRow(newrowIndex);
// 获取需要复制行对象
XWPFTableRow copyRow = table.getRow(copyrowIndex);
//复制行对象
targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
//或许需要复制的行的列
List<XWPFTableCell> copyCells = copyRow.getTableCells();
//复制列对象
XWPFTableCell targetCell = null;
for (int i = 0; i < copyCells.size(); i++) {
XWPFTableCell copyCell = copyCells.get(i);
targetCell = targetRow.addNewTableCell();
targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {
targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
if (copyCell.getParagraphs().get(0).getRuns() != null
&& copyCell.getParagraphs().get(0).getRuns().size() > 0) {
XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());
}
}
}
}
static Integer num = 0;
public static void multipleChoice(XWPFDocument document, List<String> choice) {
//获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (int i = 0; i < tables.size(); i++) {
//只处理行数大于等于2的表格
XWPFTable table = tables.get(i);
if (table.getRows().size() > 1) {
List<XWPFTableRow> rows = table.getRows();
//遍历表格,并替换模板
choose(rows, choice);
}
}
num = 0;
}
private static void choose(List<XWPFTableRow> rows, List<String> choice) {
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
if (checkDx(cell.getText())) {//判断&替换
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
if (checkDx(run.toString())) {
run.setText(election(run.toString(), choice, num), 0);
run.setFontFamily("Wingdings 2");//设置字体
}
}
}
num++;
}
}
}
}
private static String election(String value, List<String> choice, Integer num) {
if (choice != null) {
String[] s = choice.get(num).split(",");
List<String> ss = Arrays.asList(s);
String str1 = "";
for (int n = 0; n < value.length(); n++) {
if (value.charAt(n) >= 48 && value.charAt(n) <= 57) {
str1 += value.charAt(n);
}
}
if (ss.contains(str1)) {
value = "\u0052";
} else {
value = "\u002A";
}
}
return value;
}
public static void changePictureText(XWPFDocument document, List<ProjectQualityPictureDTO> photos) throws IOException, InvalidFormatException {
//获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (int i = 0; i < tables.size(); i++) {
//只处理行数大于等于2的表格
XWPFTable table = tables.get(i);
if (table.getRows().size() > 1) {
List<XWPFTableRow> rows = table.getRows();
//遍历表格,并替换模板
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
//判断单元格是否需要替换
if (checkPicture(cell.getText())) {//判断$替换
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
//替换模板原来位置
run.setText("", 0);
}
for (ProjectQualityPictureDTO photo : photos) {
byte[] dd = fastDFSClient.downloadFile(photo.getGroupName(), photo.getRemoteFileName());
String ind = document.addPictureData(dd, XWPFDocument.PICTURE_TYPE_GIF);
int id = document.getNextPicNameNumber(XWPFDocument.PICTURE_TYPE_GIF);
WorderToNewWordUtils.createPicture(ind, id, 120, 160, paragraph);
}
}
}
}
}
}
}
}
}