package com.mingx.pms.web.system.file;
import cn.hutool.core.date.DateUtil;
import com.mingx.pms.constant.SystemInfo;
import com.mingx.pms.entities.workplan.plan.vo.WorkPlanDetailExportVO;
import com.mingx.pms.entities.workplan.plan.vo.WorkPlanDetailQueryRO;
import com.mingx.pms.entities.workplan.plan.vo.WorkPlanDetailVO;
import com.mingx.pms.entities.workplan.report.constant.ReportTypeDict;
import com.mingx.pms.entities.workplan.report.vo.*;
import com.mingx.pms.entity.PageResult;
import com.mingx.pms.entity.Paginator;
import com.mingx.pms.exception.CustomException;
import com.mingx.pms.tools.BillCodeUtil;
import com.mingx.pms.workplan.service.plan.IWorkPlanDetailService;
import com.mingx.pms.workplan.service.report.IWorkReportService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.xwpf.usermodel.*;
import org.camunda.feel.syntaxtree.In;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* @Description: 生产计划报告模块导出
* @Author: gch
* @Date: 2023/8/18 10:34
*/
@Api(value = "WorkPlanReportExportProvider", tags = "导出-生产计划报告模块")
@Controller
public class WorkPlanReportExportProvider extends BaseExportProvider{
@Resource
private IWorkReportService workReportService;
@PostMapping("/workPlanReport/export")
@ApiOperation(value = "导出生产计划报告Word", notes = "导出生产计划报告Word", produces = "application/octet-stream")
public void exportWord(@RequestBody GenerateDetailRO generateDetailRO, HttpServletResponse response) throws IOException {
String reportTypeDesc;
String descByType;
if (ReportTypeDict.MONTH.getCode().equals(generateDetailRO.getReportType())) {
reportTypeDesc = ReportTypeDict.MONTH.getDesc();
descByType = "本月";
} else if (ReportTypeDict.WEEK.getCode().equals(generateDetailRO.getReportType())) {
reportTypeDesc = ReportTypeDict.WEEK.getDesc();
descByType = "本周";
} else {
throw new CustomException("报告类型错误", WorkPlanReportExportProvider.class.toString());
}
if (Objects.isNull(generateDetailRO.getReportId())) {
throw new CustomException("报告id必填", WorkPlanReportExportProvider.class.toString());
}
WorkReportDetailVO workReportDetailVO = workReportService.generateDetailInfo(generateDetailRO);
// 创建一个新的Word文档
XWPFDocument document = new XWPFDocument();
String formatStart = DateUtil.format(workReportDetailVO.getReportStartTime(), SystemInfo.DATE_CHINESE);
String formatEnd = DateUtil.format(workReportDetailVO.getReportEndTime(), SystemInfo.DAY_CHINESE);
String title = workReportDetailVO.getProjectDepartName() +
"生产作业" + reportTypeDesc + "(" + formatStart + "-" + formatEnd + " )";
addParagraphCenter(document, title);
// 添加段落
addParagraph(document, "一、电网运行总体情况:");
addContent(document,"1、电网安全情况:");
if (workReportDetailVO.getSafeSituationTextList().isEmpty()) {
addContent(document, "");
} else {
for (String content : workReportDetailVO.getSafeSituationTextList()) {
addContent(document, content);
}
}
addContent(document,"2、电网运行情况:");
if (workReportDetailVO.getRunSituationTextList().isEmpty()) {
addContent(document, "");
} else {
for (String content : workReportDetailVO.getRunSituationTextList()) {
addContent(document, content);
}
}
addParagraph(document, "二、违章情况");
addContent(document, "1、本周发生恶性违章" + workReportDetailVO.getMalignancyBreakRuleNum() + "条,严重违章 " +
workReportDetailVO.getSeriousBreakRuleNum() + " 条,一般违章 " + workReportDetailVO.getNormalBreakRuleNum() + " 条。");
addParagraph(document, "三、作业计划执行情况");
addContent(document, "1、月作业计划中本周(本月)应完成 " + workReportDetailVO.getShouldFinish() + " 条,实际完成 " +
workReportDetailVO.getRealFinish() + " 条");
// 添加表格
List<String> headers = Arrays.asList("序号", "作业计划内容", "时间", "未执行原因");
// 对象集合 转换为表格识别的 列表类型
List<List<String>> data = new ArrayList<>();
Integer order = 1;
for (WorkPlanStatisticTableVO unExecutePlan : workReportDetailVO.getUnExecutePlans()) {
List<String> attributeValues = getAttributeValues(unExecutePlan);
// 在列表最前面添加序号
attributeValues.add(0, order.toString());
order++;
data.add(attributeValues);
}
addTable(document, headers, data);
addContent(document, "2、" + descByType + "新增其他作业计划 " + workReportDetailVO.getAddWorkPlanNum() + " 条(月计划中未计划的)");
// 添加表格
List<String> headers2 = Arrays.asList("序号", "作业计划内容", "时间");
List<List<String>> data2 = new ArrayList<>();
Integer order2 = 1;
for (WorkPlanStatisticTableVO vo : workReportDetailVO.getAddPlans()) {
List<String> attributeValues = getAttributeValues(vo);
attributeValues.add(0, order2.toString());
order2++;
data.add(attributeValues);
}
addTable(document, headers2, data2);
if (ReportTypeDict.WEEK.getCode().equals(generateDetailRO.getReportType())) {
addContent(document, "3、下周新增其他作业计划 " + workReportDetailVO.getNextWeekAddWorkPlanNum() + " 条(月计划中未计划的)");
// 添加表格
List<String> headers3 = Arrays.asList("序号", "作业计划内容", "时间");
List<List<String>> data3 = new ArrayList<>();
Integer order3 = 1;
for (WorkPlanStatisticTableVO vo : workReportDetailVO.getNextWeekAddPlans()) {
List<String> attributeValues = getAttributeValues(vo);
attributeValues.add(0, order3.toString());
order3++;
data.add(attributeValues);
}
addTable(document, headers3, data3);
}
addParagraph(document, "四、停电情况");
addContent(document, "1、" + descByType + "主网停电 " + workReportDetailVO.getMainNetPowerCutNum() + " 次。");
addContent(document, "2、" + descByType + "公司计划停电应执行 " + workReportDetailVO.getCompanyPlanNum() + " 次,实际执行 " +
workReportDetailVO.getRealExecutePowerCutNum() + " 次,临时停电" + workReportDetailVO.getTempPowerCutNum()
+ "次,故障停电 " + workReportDetailVO.getBreakdownPowerCutNum() + " 次。重复停电 " + workReportDetailVO.getRepeatPowerCutNum() + " 次");
addContent(document,descByType + "公司计划停电未执行情况");
// 添加表格
List<String> headers4 = Arrays.asList("序号", "项目部", "变电站/线路名称", "计划停电时间", "未执行原因");
List<List<String>> data4 = new ArrayList<>();
Integer order4 = 1;
for (PowerCutUnExecuteStatisticTableVO vo : workReportDetailVO.getPowerCutUnExecuteInfos()) {
List<String> attributeValues = getAttributeValues(vo);
attributeValues.add(0, order4.toString());
order4++;
data.add(attributeValues);
}
addTable(document, headers4, data4);
addContent(document, descByType + "临时停电情况");
// 添加表格
List<String> headers5 = Arrays.asList("序号", "项目部", "变电站/线路名称", "停电时间", "送电时间", "停电时长(h)", "损失电量(kWh)", "停电具体原因", "处理经过");
List<List<String>> data5 = new ArrayList<>();
Integer order5 = 1;
for (PowerCutStatisticTableVO vo : workReportDetailVO.getTempPowerCutInfos()) {
List<String> attributeValues = getAttributeValues(vo);
attributeValues.add(0, order5.toString());
order5++;
data.add(attributeValues);
}
addTable(document, headers5, data5);
addContent(document, descByType + "故障停电情况");
// 添加表格
List<String> headers6 = Arrays.asList("序号", "项目部", "变电站/线路名称", "停电时间", "送电时间", "停电时长(h)", "损失电量(kWh)", "停电具体原因", "处理经过");
List<List<String>> data6 = new ArrayList<>();
Integer order6 = 1;
for (PowerCutStatisticTableVO vo : workReportDetailVO.getBreakdownPowerCutInfos()) {
List<String> attributeValues = getAttributeValues(vo);
attributeValues.add(0, order6.toString());
order6++;
data.add(attributeValues);
}
addTable(document, headers6, data6);
addParagraph(document, "五、隐患及缺陷消除情况");
// 添加表格
List<List<String>> data7 = new ArrayList<>();
Integer order7 = 1;
for (DefectHandleStatisticTableVO vo : workReportDetailVO.getDefectHandleInfos()) {
List<String> attributeValues = getAttributeValues(vo);
attributeValues.add(0, order7.toString());
order7++;
data.add(attributeValues);
}
addMergeTable(document, data7);
addContent(document,"严重及以上缺陷未消除情况说明:");
if (workReportDetailVO.getSeriousDefectUneliminatedTextList().isEmpty()) {
addContent(document, "");
} else {
for (String content : workReportDetailVO.getRunSituationTextList()) {
addContent(document, content);
}
}
// 这里是动态标题和内容
for (OtherDetailVO otherDetailVO : workReportDetailVO.getOtherDetailInfoList()) {
addParagraph(document, otherDetailVO.getTitle());
for (String content : otherDetailVO.getContents()) {
addContent(document, content);
}
}
// 设置响应头信息
response.setHeader("Content-Disposition", "attachment; filename=" + title + ".docx");
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
// 将文档写入输出流
document.write(response.getOutputStream());
document.close();
}
/**
* @author: gch
* @Description: 添加基础文本内容
* @Date: 2023/8/19 12:12
* @Param:
* @return:
*/
private void addContent(XWPFDocument document, String content) {
document.createParagraph().createRun().setText(content);
}
/**
* @author: gch
* @Description: 添加段落
* @Date: 2023/8/19 12:11
* @Param:
* @return:
*/
private void addParagraph(XWPFDocument document, String s) {
XWPFParagraph paragraph1 = document.createParagraph();
paragraph1.setAlignment(ParagraphAlignment.LEFT);
XWPFRun run1 = paragraph1.createRun();
run1.setBold(true);
run1.setFontSize(16); // 设置标题字体大小
run1.setText(s);
}
/**
* @author: gch
* @Description: 添加段落 居中
* @Date: 2023/8/19 12:11
* @Param:
* @return:
*/
private void addParagraphCenter(XWPFDocument document, String s) {
XWPFParagraph paragraph1 = document.createParagraph();
paragraph1.setAlignment(ParagraphAlignment.CENTER);
XWPFRun run1 = paragraph1.createRun();
run1.setBold(true);
run1.setFontSize(16); // 设置标题字体大小
run1.setText(s);
}
/**
* @author: gch
* @Description: 添加动态表格
* @Date: 2023/8/19 12:11
* @Param:
* @return:
*/
private void addTable(XWPFDocument document, List<String> headers, List<List<String>> data) {
Integer rowNum = 2;
if (!Objects.isNull(data) && !data.isEmpty()) {
rowNum = data.size() + 1;
}
// 添加表格
XWPFTable table = document.createTable(rowNum, headers.size()); // 创建一个3行3列的表格
// 创建表格后给每个单元格设置样式
for (int row = 0; row < rowNum; row++) {
for (int col = 0; col < headers.size(); col++) {
XWPFTableCell cell = table.getRow(row).getCell(col);
cell.setWidth("1000");
addCellCenterStyle(cell);
}
}
// 设置表头
for (int col = 0; col < headers.size(); col++) {
XWPFTableCell cell = table.getRow(0).getCell(col);
cell.setText(headers.get(col));
}
// 设置示例数据
for (int row = 0; row < data.size(); row++) {
for (int col = 0; col < headers.size(); col++) {
XWPFTableCell cell = table.getRow(row + 1).getCell(col);
cell.setText(data.get(row).get(col));
}
}
}
/**
* @author: gch
* @Description: 添加动态表格
* @Date: 2023/8/19 12:11
* @Param:
* @return:
*/
private void addMergeTable(XWPFDocument document, List<List<String>> data) {
Integer rowNum = 4;
if (!Objects.isNull(data) && !data.isEmpty()) {
rowNum = data.size() + 3;
}
// 添加表格
XWPFTable table = document.createTable(rowNum, 10);
// 创建表格后给每个单元格设置样式
for (int row = 0; row < rowNum; row++) {
for (int col = 0; col < 10; col++) {
XWPFTableCell cell = table.getRow(row).getCell(col);
cell.setWidth("1000");
addCellCenterStyle(cell);
}
}
mergeCellsHorizontal(table, 0, 1, 6);
mergeCellsHorizontal(table, 0, 7, 9);
mergeCellsHorizontal(table, 1, 1, 2);
mergeCellsHorizontal(table, 1, 3, 4);
mergeCellsHorizontal(table, 1, 5, 6);
mergeCellsVertically(table, 0, 0, 2);
mergeCellsVertically(table, 7, 1, 2);
mergeCellsVertically(table, 8, 1, 2);
mergeCellsVertically(table, 9, 1, 2);
//手动设置表头
addTableContext(table, 0, 0, "项目部");
addTableContext(table, 0, 1, "本周发现及处理情况");
addTableContext(table, 0, 7, "累计未消除缺陷");
addTableContext(table, 1, 1, "危急缺陷");
addTableContext(table, 1, 3, "重大缺陷");
addTableContext(table, 1, 5, "一般缺陷");
addTableContext(table, 1, 7, "危急缺陷");
addTableContext(table, 1, 8, "重大缺陷");
addTableContext(table, 1, 9, "一般缺陷");
addTableContext(table, 2, 1, "发现");
addTableContext(table, 2, 2, "消除");
addTableContext(table, 2, 3, "发现");
addTableContext(table, 2, 4, "消除");
addTableContext(table, 2, 5, "发现");
addTableContext(table, 2, 6, "消除");
// 设置示例数据
for (int row = 0; row < data.size(); row++) {
for (int col = 0; col < 10; col++) {
XWPFTableCell cell = table.getRow(row + 3).getCell(col);
cell.setText(data.get(row).get(col));
}
}
}
private static void addTableContext(XWPFTable table, int row, int col, String text) {
XWPFTableCell cell = table.getRow(row).getCell(col);
cell.setText(text);
}
/**
* @author: gch
* @Description: 添加水平居中韩国样式
* @Date: 2023/8/19 12:11
* @Param:
* @return:
*/
private void addCellCenterStyle(XWPFTableCell cell) {
CTTc ctTc = cell.getCTTc();
//获取 CTP
CTP ctP = (ctTc.sizeOfPArray() == 0) ?
ctTc.addNewP() : ctTc.getPArray(0);
//获取段落
XWPFParagraph par = cell.getParagraph(ctP);
//设置水平居中
par.setAlignment(ParagraphAlignment.CENTER);
// 垂直居中
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
}
/**
* @Description: 跨列合并
* table要合并单元格的表格
* row要合并哪一行的单元格
* fromCell开始合并的单元格
* toCell合并到哪一个单元格
*/
public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {
for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
if ( cellIndex == fromCell ) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
}
}
}
/**
* @Description: 跨行合并
* table要合并单元格的表格
* col要合并哪一列的单元格
* fromRow从哪一行开始合并单元格
* toRow合并到哪一个行
*/
public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
if ( rowIndex == fromRow ) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
}
}
}
/**
* @Description: 获取对象属性值并转换成字符串列表
* @Author: gch
* @Date: 2023/8/23 10:54
*/
public static List<String> getAttributeValues(Object obj) {
Class<?> objClass = obj.getClass();
List<String> valuesList = new ArrayList<>();
// 获取对象定义的所有属性
Field[] fields = objClass.getDeclaredFields();
// 遍历属性并获取属性值
for (Field field : fields) {
field.setAccessible(true); // 设置私有属性可访问
try {
Object value = field.get(obj);
String valueStr = (value != null) ? value.toString() : "";
valuesList.add(valueStr);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return valuesList;
}
}
运行结果如下: