根据手动输入的数据存入数据后,取出以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;
@Override public 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); } } } } } } } } }