Browse Source

武汉电站巡视报告支持word格式

master
WangGuangYuan 8 months ago
parent
commit
0fe8ff41aa
2 changed files with 448 additions and 9 deletions
  1. +5
    -0
      inspect-base/inspect-base-core/pom.xml
  2. +443
    -9
      inspect-main/inspect-main-task/src/main/java/com/inspect/resultmain/controller/PatrolTaskResultMainController.java

+ 5
- 0
inspect-base/inspect-base-core/pom.xml View File

@ -90,6 +90,11 @@
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>


+ 443
- 9
inspect-main/inspect-main-task/src/main/java/com/inspect/resultmain/controller/PatrolTaskResultMainController.java View File

@ -29,19 +29,15 @@ import com.inspect.task.service.IPatrolTaskService;
import com.inspect.taskinfo.service.IPatrolTaskInfoService;
import com.inspect.taskstatus.service.IPatrolTaskStatusService;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.*;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.function.IOConsumer;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
@ -58,9 +54,12 @@ import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.streaming.SXSSFDrawing;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@ -198,7 +197,7 @@ public class PatrolTaskResultMainController extends BaseController {
(new Thread(() -> {
long beginTime = (new Date()).getTime();
logger.info("[EXPORT REPORTS] StartTime: {}, reportId: {}", DateUtil.now(), reportId);
exportToExcel(String.valueOf(reportId));
exportExcelAndWord(String.valueOf(reportId));
PrintUtil.useTime("EXPORT REPORTS END", beginTime);
})).start();
return toAjax(1);
@ -250,6 +249,353 @@ public class PatrolTaskResultMainController extends BaseController {
return areaName;
}
private XWPFDocument getXWPFDocument(InspectionReport report, Map<String, byte[]> images) {
XWPFDocument doc = new XWPFDocument();
// 标题
addTitle(doc, "巡视报告");
// 基本信息表格
XWPFTable baseInfoTable = doc.createTable(7, 4);
baseInfoTable.setWidth("100%");
// 设置表格样式
setTableStyle(baseInfoTable);
// 填充基础信息
fillBaseInfo(baseInfoTable, report);
// 点位汇总
List<String> statusList = Arrays.asList("异常", "待人工确认", "正常");
for (String status : statusList) {
addStatusSection(doc, report, status, images);
}
return doc;
}
private void addTitle(XWPFDocument doc, String title) {
XWPFParagraph titlePara = doc.createParagraph();
titlePara.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleRun = titlePara.createRun();
titleRun.setText(title);
titleRun.setFontFamily("宋体");
titleRun.setFontSize(20);
titleRun.setBold(true);
addEmptyParagraph(doc); // 空行
}
// 样式设置方法
private void setTableStyle(XWPFTable table) {
table.setCellMargins(100, 100, 100, 100); // 设置单元格边距
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
setCellStyle(cell);
}
}
}
private void fillBaseInfo(XWPFTable table, InspectionReport report) {
fillRow(table, 0, "变电站", report.getStationName(), "电压等级", report.getVoltLevel());
fillRow(table, 1, "巡视计划创建日期", formatDate(report.getInspectionDate()),
"变电站类别", report.getStationType());
fillRow(table, 2, "巡视任务", report.getInspectionTaskName(),
"环境信息", report.getEnvInfo());
fillRow(table, 3, "审核人", report.getCheckPerson(),
"审核时间", formatDateTime(report.getCheckTime()));
fillRow(table, 4, "巡视开始时间", formatDateTime(report.getInspectionStartTime()),
"巡视结束时间", formatDateTime(report.getInspectionEndTime()));
fillRowWithMerge(table, 5, "巡视统计", report.getPatrolStatistics(), 3);
// 新增巡视结论合并右侧3列
fillRowWithMerge(table, 6, "巡视结论", report.getDescription(), 3);
}
private void fillRow(XWPFTable table, int rowNum, String... values) {
XWPFTableRow row = table.getRow(rowNum);
for (int i = 0; i < values.length; i++) {
XWPFTableCell cell = row.getCell(i);
CTP ctP = cell.getCTTc().sizeOfPArray() == 0 ? cell.getCTTc().addNewP() : cell.getCTTc().getPArray(0);
XWPFParagraph par = cell.getParagraph(ctP);
par.createRun().setText(values[i]);
// 左侧标题列索引0,2设置特殊样式
if (i % 2 == 0) {
setTitleCellStyle(cell);
} else {
setValueCellStyle(cell);
}
}
}
// 标题单元格样式宋体小五加粗
private void setTitleCellStyle(XWPFTableCell cell) {
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
for (XWPFParagraph para : cell.getParagraphs()) {
para.setAlignment(ParagraphAlignment.CENTER);
for (XWPFRun run : para.getRuns()) {
run.setFontFamily("宋体");
run.setFontSize(9);
run.setBold(true);
run.setColor("000000");
}
}
// 单元格背景色浅灰色
CTTcPr tcPr = cell.getCTTc().addNewTcPr();
CTShd shading = tcPr.addNewShd();
shading.setFill("D3D3D3");
shading.setVal(STShd.Enum.forString("clear"));
}
// 值单元格样式
private void setValueCellStyle(XWPFTableCell cell) {
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
for (XWPFParagraph para : cell.getParagraphs()) {
para.setAlignment(ParagraphAlignment.CENTER);
for (XWPFRun run : para.getRuns()) {
run.setFontFamily("宋体");
run.setFontSize(9);
run.setColor("000000");
}
}
}
/**
* 填充带合并的表格行
* @param table 表格对象
* @param rowNum 行号
* @param title 左侧标题
* @param content 右侧内容
* @param mergeCols 需要合并的列数
*/
private void fillRowWithMerge(XWPFTable table, int rowNum, String title, String content, int mergeCols) {
XWPFTableRow row = table.getRow(rowNum);
// 设置左侧标题单元格
XWPFTableCell titleCell = row.getCell(0);
CTP ctPTitle = titleCell.getCTTc().sizeOfPArray() == 0 ? titleCell.getCTTc().addNewP() : titleCell.getCTTc().getPArray(0);
XWPFParagraph parTitle = titleCell.getParagraph(ctPTitle);
parTitle.createRun().setText(title);
setTitleCellStyle(titleCell);
// 设置右侧合并内容单元格
XWPFTableCell contentCell = row.getCell(1);
CTP ctPContent = contentCell.getCTTc().sizeOfPArray() == 0 ? contentCell.getCTTc().addNewP() : contentCell.getCTTc().getPArray(0);
XWPFParagraph parContent = contentCell.getParagraph(ctPContent);
parContent.createRun().setText(content);
// 合并右侧单元格
for (int i = 1; i <= mergeCols; i++) {
if (i > 1) {
row.getCell(i).removeParagraph(0);
mergeCellsHorizontal(table, rowNum, 1, i);
}
setMergedContentStyle(row.getCell(i)); // 内容样式
}
}
// 合并单元格工具方法横向
private void mergeCellsHorizontal(XWPFTable table, int row, int startCol, int endCol) {
for (int i = startCol; i <= endCol; i++) {
CTTcPr tcPr = table.getRow(row).getCell(i).getCTTc().getTcPr();
if (tcPr == null) tcPr = table.getRow(row).getCell(i).getCTTc().addNewTcPr();
if (i == startCol) {
tcPr.addNewHMerge().setVal(STMerge.RESTART);
} else {
tcPr.addNewHMerge().setVal(STMerge.CONTINUE);
}
}
}
/**
* 合并内容单元格样式
*/
private void setMergedContentStyle(XWPFTableCell cell) {
for (XWPFParagraph para : cell.getParagraphs()) {
para.setAlignment(ParagraphAlignment.LEFT);
para.setSpacingAfter(0);
para.setIndentationFirstLine(400); // 首行缩进
for (XWPFRun run : para.getRuns()) {
run.setFontFamily("宋体");
run.setFontSize(9);
run.setColor("000000");
}
}
// 自动换行设置
CTTcPr tcPr = cell.getCTTc().addNewTcPr();
tcPr.addNewNoWrap().setVal(STOnOff.FALSE);
}
private void addStatusSection(XWPFDocument doc, InspectionReport report,
String status, Map<String, byte[]> images) {
addSectionHeader(doc, status + "点位汇总");
XWPFTable table = doc.createTable(1, 9);
table.setWidth("100%");
// 创建表头
String[] headers = {"编号", "区域", "设备", "点位", "数据来源",
"采集时间", "巡视结果", "点位状态", "巡视图像"};
XWPFTableRow headerRow = table.getRow(0);
for (int i = 0; i < headers.length; i++) {
XWPFTableCell cell = headerRow.getCell(i);
CTP ctP = cell.getCTTc().sizeOfPArray() == 0 ? cell.getCTTc().addNewP() : cell.getCTTc().getPArray(0);
XWPFParagraph par = cell.getParagraph(ctP);
par.createRun().setText(headers[i]);
}
setTableHeaderStyle(table);
// 填充数据
List<InspectionReportData> dataList = report.getReportDatalist().stream()
.filter(d -> status.equals(d.getPointStatus()))
.collect(Collectors.toList());
for (InspectionReportData data : dataList) {
XWPFTableRow row = table.createRow();
fillDataRow(row, data, images);
}
addEmptyParagraph(doc);
}
private void addSectionHeader(XWPFDocument doc, String text) {
XWPFParagraph para = doc.createParagraph();
para.setSpacingBefore(200); // 段前间距
XWPFRun run = para.createRun();
run.setText(text);
run.setFontSize(14);
run.setBold(true);
}
private void setTableHeaderStyle(XWPFTable table) {
if (table == null || table.getRows().isEmpty()) return;
// 获取表头行第一行
XWPFTableRow headerRow = table.getRow(0);
// 设置表格整体边框
CTTblPr tblPr = table.getCTTbl().getTblPr();
if (tblPr == null) {
tblPr = table.getCTTbl().addNewTblPr();
}
// 表格边框设置
CTTblBorders borders = tblPr.addNewTblBorders();
borders.addNewBottom().setVal(STBorder.SINGLE);
borders.addNewLeft().setVal(STBorder.SINGLE);
borders.addNewRight().setVal(STBorder.SINGLE);
borders.addNewTop().setVal(STBorder.SINGLE);
borders.addNewInsideH().setVal(STBorder.SINGLE);
borders.addNewInsideV().setVal(STBorder.SINGLE);
// 设置表头单元格样式
for (XWPFTableCell cell : headerRow.getTableCells()) {
CTTcPr tcPr = cell.getCTTc().addNewTcPr();
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
// 单元格边距设置
tcPr.addNewTcMar();
CTTcMar tcMar = tcPr.getTcMar();
tcMar.addNewLeft().setW(BigInteger.valueOf(100));
tcMar.addNewRight().setW(BigInteger.valueOf(100));
tcMar.addNewTop().setW(BigInteger.valueOf(50));
tcMar.addNewBottom().setW(BigInteger.valueOf(50));
// 背景色填充浅灰色
CTShd shading = tcPr.addNewShd();
shading.setFill("D3D3D3");
shading.setVal(STShd.Enum.forString("clear"));
// 设置文本样式为宋体小五号加粗
for (XWPFParagraph para : cell.getParagraphs()) {
para.setAlignment(ParagraphAlignment.CENTER);
for (XWPFRun run : para.getRuns()) {
run.setBold(true);
run.setFontSize(9);
run.setFontFamily("宋体");
run.setColor("000000");
}
}
}
}
private void fillDataRow(XWPFTableRow row, InspectionReportData data,
Map<String, byte[]> images) {
String[] values = {
String.valueOf(data.getCode()),
data.getArea(),
data.getEqName(),
data.getPointName(),
data.getDataSources(),
formatDateTime(data.getAcquisitionTime()),
data.getInspectionResults(),
data.getPointStatus(),
"" // 图片占位
};
for (int i = 0; i < values.length; i++) {
XWPFTableCell cell = row.getTableCells().get(i);
CTP ctP = cell.getCTTc().sizeOfPArray() == 0 ? cell.getCTTc().addNewP() : cell.getCTTc().getPArray(0);
XWPFParagraph par = cell.getParagraph(ctP);
par.createRun().setText(values[i]);
setCellStyle(cell);
}
// 插入图片
if (data.getReportImgList() != null) {
data.getReportImgList().stream()
.filter(img -> "0".equals(img.getImgType()))
.forEach(img -> insertImageToCell(row.getCell(8),
images.get(img.getImgSrc())));
}
}
private void insertImageToCell(XWPFTableCell cell, byte[] imageData) {
if (imageData == null) return;
try (ByteArrayInputStream bis = new ByteArrayInputStream(imageData)) {
CTP ctP = cell.getCTTc().sizeOfPArray() == 0 ? cell.getCTTc().addNewP() : cell.getCTTc().getPArray(0);
XWPFParagraph par = cell.getParagraph(ctP);
XWPFRun run = par.createRun();
run.addPicture(bis, XWPFDocument.PICTURE_TYPE_JPEG,
"image.jpg", Units.toEMU(100), Units.toEMU(100));
} catch (Exception e) {
e.printStackTrace();
}
}
private void setCellStyle(XWPFTableCell cell) {
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
XWPFParagraph para = cell.getParagraphs().get(0);
para.setAlignment(ParagraphAlignment.CENTER);
para.setSpacingAfter(0);
para.setSpacingBefore(0);
XWPFRun run = para.getRuns().isEmpty() ? para.createRun() : para.getRuns().get(0);
run.setFontSize(9);
run.setFontFamily("宋体");
}
private void addEmptyParagraph(XWPFDocument doc) {
doc.createParagraph().createRun().addBreak();
}
private String formatDate(Date date) {
return date != null ? DateUtils.format(DateUtils.yyyyMMdd2, date) : "";
}
private String formatDateTime(Date date) {
return date != null ? DateUtils.format(DateUtils.yyyyMMddHHmmss2, date) : "";
}
public void exportToExcel(String lineId) {
List<String> images = new ArrayList<>();
InspectionReport inspectionReport =
@ -315,6 +661,94 @@ public class PatrolTaskResultMainController extends BaseController {
}
}
public void exportExcelAndWord(String lineId) {
List<String> images = new ArrayList<>();
InspectionReport inspectionReport =
inspectionReportService.selectInspectionReportByLineId(Long.valueOf(lineId));
InspectionReportData inspectionReportData = new InspectionReportData();
inspectionReportData.setReportId(String.valueOf(inspectionReport.getLineId()));
List<InspectionReportData> inspectionReportDataList =
inspectionReportDataService.selectInspectionReportDataList(inspectionReportData);
if (!inspectionReportDataList.isEmpty()) {
inspectionReport.setReportDatalist(inspectionReportDataList);
}
for (InspectionReportData reportData : inspectionReportDataList) {
InspectionReportImg inspectionReportImg = new InspectionReportImg();
inspectionReportImg.setReportInfoId(reportData.getLineId());
List<InspectionReportImg> reportImgList =
inspectionReportImgService.selectInspectionReportImgList(inspectionReportImg);
reportData.setReportImgList(reportImgList);
for (InspectionReportImg reportImg : reportImgList) {
if (StringUtils.isNotEmpty(reportImg.getImgSrc()) && reportImg.getImgType().equals("0")) {
images.add(reportImg.getImgSrc());
}
}
}
Map<String, byte[]> streamHashMap = new HashMap<>();
for (String algorithmBaseImagePath : images) {
try {
sftpClient.downLoad(algorithmBaseImagePath, (inputStream) -> {
byte[] bytes = streamHashMap.get(algorithmBaseImagePath);
byte[] byInputStream = getStringByInputStream(inputStream);
if (bytes == null) {
streamHashMap.put(algorithmBaseImagePath, byInputStream);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
HSSFWorkbook hssfWorkbook = getHSSFWorkbook(inspectionReport, streamHashMap);
XWPFDocument wordDocument = getXWPFDocument(inspectionReport, streamHashMap);
logger.info("[ARCHIVE] hssfWorkbook: {}", hssfWorkbook);
try {
String basePath = this.basePath + stationCode + "/Model/";
Date startTime = inspectionReport.getInspectionStartTime() != null ?
inspectionReport.getInspectionStartTime() : new Date();
String timestamp = DateUtils.format(DateUtils.yyyyMMddHHmmss2, startTime) + "_" + System.currentTimeMillis();
String reportName = inspectionReport.getInspectionTaskName() + "_" + timestamp;
// 上传Excel
uploadFile(basePath, reportName, ".xls", hssfWorkbook::write);
// 上传Word
uploadFile(basePath, reportName, ".docx", wordDocument::write);
inspectionReport.setFilePath(basePath + reportName + ".xls");
inspectionReportService.updateInspectionReport(inspectionReport);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 上传文件到SFTP服务器
*
* @param basePath 文件上传的基础路径
* @param fileName 文件名
* @param suffix 文件后缀
* @param writer 文件写入器用于将文件内容写入到输出流中
* @throws Exception 如果上传过程中发生异常则抛出异常
*/
private void uploadFile(String basePath, String fileName, String suffix, IOConsumer<OutputStream> writer) {
SftpUploadEntity sftpUploadEntity = new SftpUploadEntity();
sftpUploadEntity.setFilePath(basePath);
sftpUploadEntity.setFileName(fileName);
sftpUploadEntity.setSuffix(suffix);
try {
String filePath = sftpClient.upload(sftpUploadEntity, outputStream -> {
writer.accept(outputStream);
outputStream.flush();
});
logger.info("文件上传成功: {}", filePath);
} catch (Exception e) {
logger.error("文件上传失败", e);
}
}
public HSSFWorkbook getHSSFWorkbook(InspectionReport inspectionReport, Map<String, byte[]> inputStreamMap) {
HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
HSSFSheet hssfSheet = hssfWorkbook.createSheet(String.valueOf(System.currentTimeMillis()));


Loading…
Cancel
Save