|
|
|
@ -12,24 +12,31 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceProductionDa
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceProductionDailyReportRespVO;
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceProductionDailyReportRespVO;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.devicewarinningrecord.DeviceWarinningRecordDO;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.devicecontactmodel.DeviceContactModelMapper;
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.devicecontactmodel.DeviceContactModelMapper;
|
|
|
|
import cn.iocoder.yudao.module.mes.api.workteam.WorkTeamApi;
|
|
|
|
import cn.iocoder.yudao.module.mes.api.workteam.WorkTeamApi;
|
|
|
|
import cn.iocoder.yudao.module.mes.api.workteam.dto.WorkTeamRespDTO;
|
|
|
|
import cn.iocoder.yudao.module.mes.api.workteam.dto.WorkTeamRespDTO;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
|
|
|
|
|
|
|
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
import lombok.SneakyThrows;
|
|
|
|
import lombok.SneakyThrows;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
import org.apache.poi.ss.usermodel.Cell;
|
|
|
|
import org.apache.poi.ss.usermodel.Cell;
|
|
|
|
|
|
|
|
import org.apache.poi.ss.usermodel.CellStyle;
|
|
|
|
|
|
|
|
import org.apache.poi.ss.usermodel.CellType;
|
|
|
|
import org.apache.poi.ss.usermodel.Row;
|
|
|
|
import org.apache.poi.ss.usermodel.Row;
|
|
|
|
import org.apache.poi.ss.usermodel.Sheet;
|
|
|
|
import org.apache.poi.ss.usermodel.Sheet;
|
|
|
|
import org.apache.poi.ss.usermodel.Workbook;
|
|
|
|
import org.apache.poi.ss.usermodel.Workbook;
|
|
|
|
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
|
|
|
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
|
|
|
|
|
|
|
import org.apache.poi.ss.util.CellRangeAddress;
|
|
|
|
import org.springframework.core.io.ClassPathResource;
|
|
|
|
import org.springframework.core.io.ClassPathResource;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
@ -57,8 +64,10 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
|
|
|
|
|
|
|
|
private static final String TEMPLATE_PATH = "excel/templates/fully-automatic-molding-production-daily-report-template.xlsx";
|
|
|
|
private static final String TEMPLATE_PATH = "excel/templates/fully-automatic-molding-production-daily-report-template.xlsx";
|
|
|
|
private static final String REPORT_PATH_PREFIX = "iot/device/production-daily-report";
|
|
|
|
private static final String REPORT_PATH_PREFIX = "iot/device/production-daily-report";
|
|
|
|
|
|
|
|
private static final String ALARM_LEVEL_DICT_TYPE = "alarm_registration";
|
|
|
|
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
|
|
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
|
|
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
|
|
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
|
|
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
@Resource
|
|
|
|
private DeviceMapper deviceMapper;
|
|
|
|
private DeviceMapper deviceMapper;
|
|
|
|
@ -69,6 +78,8 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
@Resource
|
|
|
|
@Resource
|
|
|
|
private WorkTeamApi workTeamApi;
|
|
|
|
private WorkTeamApi workTeamApi;
|
|
|
|
@Resource
|
|
|
|
@Resource
|
|
|
|
|
|
|
|
private DictDataApi dictDataApi;
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
private FileService fileService;
|
|
|
|
private FileService fileService;
|
|
|
|
@Resource
|
|
|
|
@Resource
|
|
|
|
private FileMapper fileMapper;
|
|
|
|
private FileMapper fileMapper;
|
|
|
|
@ -96,15 +107,19 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
if (!endTime.isAfter(startTime)) {
|
|
|
|
if (!endTime.isAfter(startTime)) {
|
|
|
|
endTime = endTime.plusDays(1);
|
|
|
|
endTime = endTime.plusDays(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.info("[production-daily-report] generate request: reportDate={}, workTeamId={}, workTeamName={}, startTime={}, endTime={}, deviceIds={}",
|
|
|
|
|
|
|
|
reqVO.getReportDate(), reqVO.getWorkTeamId(), workTeam.getTeamName(), startTime, endTime, deviceIds);
|
|
|
|
|
|
|
|
|
|
|
|
List<DeviceProductionDailyReportRespVO.DeviceCapacityItem> items = buildCapacityItems(deviceIds, deviceMap, startTime, endTime);
|
|
|
|
List<DeviceProductionDailyReportRespVO.DeviceCapacityItem> items = buildCapacityItems(deviceIds, deviceMap, startTime, endTime);
|
|
|
|
byte[] excelContent = buildExcel(reqVO, workTeam, startTime, endTime, items);
|
|
|
|
byte[] excelContent = buildExcel(reqVO, workTeam, startTime, endTime, items, deviceIds);
|
|
|
|
|
|
|
|
|
|
|
|
String fileName = String.format("全自动成型机生产日报表_%s_%s_%s.xlsx",
|
|
|
|
String fileName = String.format("全自动成型机生产日报表_%s_%s_%s.xlsx",
|
|
|
|
reqVO.getReportDate().format(DateTimeFormatter.BASIC_ISO_DATE), reqVO.getWorkTeamId(), System.currentTimeMillis());
|
|
|
|
reqVO.getReportDate().format(DateTimeFormatter.BASIC_ISO_DATE), reqVO.getWorkTeamId(), System.currentTimeMillis());
|
|
|
|
String filePath = String.format("%s/date=%s/workTeamId=%s/deviceIds=%s/deviceTags=%s/%s",
|
|
|
|
String filePath = String.format("%s/date=%s/workTeamId=%s/deviceIds=%s/deviceTags=%s/%s",
|
|
|
|
REPORT_PATH_PREFIX, reqVO.getReportDate(), reqVO.getWorkTeamId(), joinDeviceIds(deviceIds), buildDeviceTags(deviceIds), fileName);
|
|
|
|
REPORT_PATH_PREFIX, reqVO.getReportDate(), reqVO.getWorkTeamId(), joinDeviceIds(deviceIds), buildDeviceTags(deviceIds), fileName);
|
|
|
|
Map<String, String> file = fileService.createFile(fileName, filePath, excelContent);
|
|
|
|
Map<String, String> file = fileService.createFile(fileName, filePath, excelContent);
|
|
|
|
|
|
|
|
log.info("[production-daily-report] file created: fileName={}, filePath={}, fileUrl={}, contentLength={}",
|
|
|
|
|
|
|
|
file.get("fileName"), filePath, file.get("fileUrl"), excelContent.length);
|
|
|
|
|
|
|
|
|
|
|
|
DeviceProductionDailyReportRespVO respVO = buildBaseResp(reqVO.getReportDate(), workTeam, startTime, endTime, deviceIds);
|
|
|
|
DeviceProductionDailyReportRespVO respVO = buildBaseResp(reqVO.getReportDate(), workTeam, startTime, endTime, deviceIds);
|
|
|
|
respVO.setFileName(file.get("fileName"));
|
|
|
|
respVO.setFileName(file.get("fileName"));
|
|
|
|
@ -141,7 +156,7 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
Map<Long, DeviceDO> deviceMap,
|
|
|
|
Map<Long, DeviceDO> deviceMap,
|
|
|
|
LocalDateTime startTime,
|
|
|
|
LocalDateTime startTime,
|
|
|
|
LocalDateTime endTime) {
|
|
|
|
LocalDateTime endTime) {
|
|
|
|
Map<Long, List<DeviceContactModelDO>> capacityPointMap = queryCapacityPoints(deviceIds);
|
|
|
|
Map<Long, DeviceContactModelDO> capacityPointMap = queryCapacityPoints(deviceIds);
|
|
|
|
Map<Long, Map<String, Object>> firstRows = tDengineService.queryDevicesEarliestRow(deviceIds,
|
|
|
|
Map<Long, Map<String, Object>> firstRows = tDengineService.queryDevicesEarliestRow(deviceIds,
|
|
|
|
startTime.format(DATE_TIME_FORMATTER), endTime.format(DATE_TIME_FORMATTER));
|
|
|
|
startTime.format(DATE_TIME_FORMATTER), endTime.format(DATE_TIME_FORMATTER));
|
|
|
|
Map<Long, Map<String, Object>> lastRows = tDengineService.queryDevicesLatestRow(deviceIds,
|
|
|
|
Map<Long, Map<String, Object>> lastRows = tDengineService.queryDevicesLatestRow(deviceIds,
|
|
|
|
@ -150,31 +165,28 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
List<DeviceProductionDailyReportRespVO.DeviceCapacityItem> items = new ArrayList<>();
|
|
|
|
List<DeviceProductionDailyReportRespVO.DeviceCapacityItem> items = new ArrayList<>();
|
|
|
|
for (Long deviceId : deviceIds) {
|
|
|
|
for (Long deviceId : deviceIds) {
|
|
|
|
DeviceDO device = deviceMap.get(deviceId);
|
|
|
|
DeviceDO device = deviceMap.get(deviceId);
|
|
|
|
List<DeviceContactModelDO> points = capacityPointMap.getOrDefault(deviceId, Collections.emptyList());
|
|
|
|
DeviceContactModelDO point = capacityPointMap.get(deviceId);
|
|
|
|
if (CollUtil.isEmpty(points)) {
|
|
|
|
if (point == null) {
|
|
|
|
items.add(buildEmptyCapacityItem(device));
|
|
|
|
items.add(buildEmptyCapacityItem(device));
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Map<String, Object> firstRow = firstRows.get(deviceId);
|
|
|
|
Map<String, Object> firstRow = firstRows.get(deviceId);
|
|
|
|
Map<String, Object> lastRow = lastRows.get(deviceId);
|
|
|
|
Map<String, Object> lastRow = lastRows.get(deviceId);
|
|
|
|
for (DeviceContactModelDO point : points) {
|
|
|
|
items.add(buildCapacityItem(device, point, firstRow, lastRow));
|
|
|
|
items.add(buildCapacityItem(device, point, firstRow, lastRow));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return items;
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Map<Long, List<DeviceContactModelDO>> queryCapacityPoints(List<Long> deviceIds) {
|
|
|
|
private Map<Long, DeviceContactModelDO> queryCapacityPoints(List<Long> deviceIds) {
|
|
|
|
List<DeviceContactModelDO> points = deviceContactModelMapper.selectList(
|
|
|
|
List<DeviceContactModelDO> points = deviceContactModelMapper.selectList(
|
|
|
|
Wrappers.<DeviceContactModelDO>lambdaQuery()
|
|
|
|
Wrappers.<DeviceContactModelDO>lambdaQuery()
|
|
|
|
.in(DeviceContactModelDO::getDeviceId, deviceIds)
|
|
|
|
.in(DeviceContactModelDO::getDeviceId, deviceIds)
|
|
|
|
.and(wrapper -> wrapper.like(DeviceContactModelDO::getTypeName, "产能")
|
|
|
|
.eq(DeviceContactModelDO::getTypeName, "产能")
|
|
|
|
.or().like(DeviceContactModelDO::getAttributeType, "产能")
|
|
|
|
|
|
|
|
.or().like(DeviceContactModelDO::getAttributeName, "产能"))
|
|
|
|
|
|
|
|
.orderByAsc(DeviceContactModelDO::getDeviceId)
|
|
|
|
.orderByAsc(DeviceContactModelDO::getDeviceId)
|
|
|
|
.orderByAsc(DeviceContactModelDO::getSort)
|
|
|
|
.orderByDesc(DeviceContactModelDO::getCreateTime)
|
|
|
|
.orderByAsc(DeviceContactModelDO::getId));
|
|
|
|
.orderByDesc(DeviceContactModelDO::getId));
|
|
|
|
return points.stream().collect(Collectors.groupingBy(DeviceContactModelDO::getDeviceId, LinkedHashMap::new, Collectors.toList()));
|
|
|
|
return points.stream().collect(Collectors.toMap(DeviceContactModelDO::getDeviceId, item -> item, (first, second) -> first,
|
|
|
|
|
|
|
|
LinkedHashMap::new));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private DeviceProductionDailyReportRespVO.DeviceCapacityItem buildEmptyCapacityItem(DeviceDO device) {
|
|
|
|
private DeviceProductionDailyReportRespVO.DeviceCapacityItem buildEmptyCapacityItem(DeviceDO device) {
|
|
|
|
@ -212,36 +224,238 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
@SneakyThrows
|
|
|
|
@SneakyThrows
|
|
|
|
private byte[] buildExcel(DeviceProductionDailyReportGenerateReqVO reqVO, WorkTeamRespDTO workTeam,
|
|
|
|
private byte[] buildExcel(DeviceProductionDailyReportGenerateReqVO reqVO, WorkTeamRespDTO workTeam,
|
|
|
|
LocalDateTime startTime, LocalDateTime endTime,
|
|
|
|
LocalDateTime startTime, LocalDateTime endTime,
|
|
|
|
List<DeviceProductionDailyReportRespVO.DeviceCapacityItem> items) {
|
|
|
|
List<DeviceProductionDailyReportRespVO.DeviceCapacityItem> items, List<Long> deviceIds) {
|
|
|
|
try (InputStream inputStream = new ClassPathResource(TEMPLATE_PATH).getInputStream();
|
|
|
|
try (InputStream inputStream = new ClassPathResource(TEMPLATE_PATH).getInputStream();
|
|
|
|
Workbook workbook = WorkbookFactory.create(inputStream);
|
|
|
|
Workbook workbook = WorkbookFactory.create(inputStream);
|
|
|
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
|
|
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
|
|
|
Sheet sheet = workbook.getSheetAt(0);
|
|
|
|
Sheet sheet = workbook.getSheetAt(0);
|
|
|
|
setCellValue(sheet, 2, 0, "日期:" + LocalDate.now().format(DATE_FORMATTER));
|
|
|
|
setReportColumnWidths(sheet);
|
|
|
|
setCellValue(sheet, 2, 4, "班次:" + StrUtil.blankToDefault(workTeam.getTeamName(), ""));
|
|
|
|
log.info("[production-daily-report] template loaded: path={}, sheetName={}, mergedRegions={}",
|
|
|
|
setCellValue(sheet, 19, 9, "审核:");
|
|
|
|
TEMPLATE_PATH, sheet.getSheetName(), sheet.getMergedRegions());
|
|
|
|
|
|
|
|
String dateText = "日期:" + reqVO.getReportDate().format(DATE_FORMATTER);
|
|
|
|
int rowIndex = 5;
|
|
|
|
String shiftText = "班次:" + StrUtil.blankToDefault(workTeam.getTeamName(), "");
|
|
|
|
|
|
|
|
setHeaderValue(sheet, "日期:", dateText, 2, 0);
|
|
|
|
|
|
|
|
setHeaderValue(sheet, "班次:", shiftText, 2, 4);
|
|
|
|
|
|
|
|
log.info("[production-daily-report] header cells after write: A3={}, C3={}, E3={}",
|
|
|
|
|
|
|
|
getCellValue(sheet, 2, 0), getCellValue(sheet, 2, 2), getCellValue(sheet, 2, 4));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int rowIndex = 4;
|
|
|
|
|
|
|
|
int exceptionStartRowIndex = 5;
|
|
|
|
|
|
|
|
Row templateRow = sheet.getRow(rowIndex);
|
|
|
|
|
|
|
|
if (items.size() > 1) {
|
|
|
|
|
|
|
|
sheet.shiftRows(exceptionStartRowIndex, sheet.getLastRowNum(), items.size() - 1, true, false);
|
|
|
|
|
|
|
|
}
|
|
|
|
for (int index = 0; index < items.size(); index++) {
|
|
|
|
for (int index = 0; index < items.size(); index++) {
|
|
|
|
if (rowIndex + index > 9) {
|
|
|
|
|
|
|
|
sheet.shiftRows(10, sheet.getLastRowNum(), 1, true, false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Row row = sheet.getRow(rowIndex + index);
|
|
|
|
Row row = sheet.getRow(rowIndex + index);
|
|
|
|
if (row == null) {
|
|
|
|
if (row == null) {
|
|
|
|
row = sheet.createRow(rowIndex + index);
|
|
|
|
row = sheet.createRow(rowIndex + index);
|
|
|
|
|
|
|
|
copyRowStyle(templateRow, row, 5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DeviceProductionDailyReportRespVO.DeviceCapacityItem item = items.get(index);
|
|
|
|
DeviceProductionDailyReportRespVO.DeviceCapacityItem item = items.get(index);
|
|
|
|
setCellValue(row, 0, index + 1);
|
|
|
|
setCellValue(row, 0, index + 1);
|
|
|
|
setCellValue(row, 1, StrUtil.blankToDefault(item.getDeviceCode(), item.getDeviceName()));
|
|
|
|
setCellValue(row, 1, buildDeviceText(item.getDeviceName(), item.getDeviceCode()));
|
|
|
|
setCellValue(row, 4, item.getCapacityName());
|
|
|
|
setCellValue(row, 2, buildCapacityPointText(item));
|
|
|
|
setCellValue(row, 20, item.getCapacityDiff());
|
|
|
|
setCellValue(row, 3, item.getCapacityDiff());
|
|
|
|
setCellValue(row, 21, toHour(startTime, endTime));
|
|
|
|
setCellValue(row, 4, startTime.toLocalTime() + "-" + endTime.toLocalTime());
|
|
|
|
setCellValue(row, 22, startTime.toLocalTime() + "-" + endTime.toLocalTime());
|
|
|
|
|
|
|
|
setCellValue(row, 24, workTeam.getTeamName());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fillWarningDescription(sheet, rowIndex + items.size() + 2, deviceIds, startTime, endTime);
|
|
|
|
workbook.write(outputStream);
|
|
|
|
workbook.write(outputStream);
|
|
|
|
return outputStream.toByteArray();
|
|
|
|
byte[] bytes = outputStream.toByteArray();
|
|
|
|
|
|
|
|
logGeneratedHeader(bytes);
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void fillWarningDescription(Sheet sheet, int warningRowIndex, List<Long> deviceIds,
|
|
|
|
|
|
|
|
LocalDateTime startTime, LocalDateTime endTime) {
|
|
|
|
|
|
|
|
List<DeviceWarinningRecordDO> warningRecords = tDengineService.selectDeviceWarningList(deviceIds, startTime, endTime);
|
|
|
|
|
|
|
|
Map<Long, List<DeviceWarinningRecordDO>> warningMap = warningRecords.stream()
|
|
|
|
|
|
|
|
.collect(Collectors.groupingBy(DeviceWarinningRecordDO::getDeviceId, LinkedHashMap::new, Collectors.toList()));
|
|
|
|
|
|
|
|
Map<String, String> alarmLevelLabelMap = buildAlarmLevelLabelMap();
|
|
|
|
|
|
|
|
Row templateRow = sheet.getRow(warningRowIndex);
|
|
|
|
|
|
|
|
for (int index = 0; index < deviceIds.size(); index++) {
|
|
|
|
|
|
|
|
Row row = sheet.getRow(warningRowIndex + index);
|
|
|
|
|
|
|
|
if (row == null) {
|
|
|
|
|
|
|
|
row = sheet.createRow(warningRowIndex + index);
|
|
|
|
|
|
|
|
copyRowStyle(templateRow, row, 5);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
mergeCellsIfAbsent(sheet, warningRowIndex + index, 2, 4);
|
|
|
|
|
|
|
|
Long deviceId = deviceIds.get(index);
|
|
|
|
|
|
|
|
setCellValue(row, 0, index + 1);
|
|
|
|
|
|
|
|
setCellValue(row, 1, getDeviceText(deviceId));
|
|
|
|
|
|
|
|
String warningDescription = buildWarningDescription(warningMap.getOrDefault(deviceId, Collections.emptyList()), alarmLevelLabelMap);
|
|
|
|
|
|
|
|
setCellValue(row, 2, warningDescription);
|
|
|
|
|
|
|
|
setWrapText(row, 2);
|
|
|
|
|
|
|
|
row.setHeightInPoints(Math.max(row.getHeightInPoints(), 18F * Math.max(1, warningDescription.split("\n", -1).length)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
removeRowsFromEnd(sheet, warningRowIndex + deviceIds.size());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setReportColumnWidths(Sheet sheet) {
|
|
|
|
|
|
|
|
sheet.setColumnWidth(0, 8 * 256);
|
|
|
|
|
|
|
|
sheet.setColumnWidth(1, 32 * 256);
|
|
|
|
|
|
|
|
sheet.setColumnWidth(2, 52 * 256);
|
|
|
|
|
|
|
|
sheet.setColumnWidth(3, 14 * 256);
|
|
|
|
|
|
|
|
sheet.setColumnWidth(4, 22 * 256);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildCapacityPointText(DeviceProductionDailyReportRespVO.DeviceCapacityItem item) {
|
|
|
|
|
|
|
|
String capacityName = item.getCapacityName();
|
|
|
|
|
|
|
|
String capacityCode = item.getCapacityCode();
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(capacityName)) {
|
|
|
|
|
|
|
|
return StrUtil.blankToDefault(capacityCode, "");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(capacityCode) || StringUtils.equals(capacityName, capacityCode)) {
|
|
|
|
|
|
|
|
return capacityName;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return capacityName + "(" + capacityCode + ")";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getDeviceText(Long deviceId) {
|
|
|
|
|
|
|
|
DeviceDO device = deviceMapper.selectById(deviceId);
|
|
|
|
|
|
|
|
if (device == null) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return buildDeviceText(device.getDeviceName(), device.getDeviceCode());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildDeviceText(String deviceName, String deviceCode) {
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(deviceName)) {
|
|
|
|
|
|
|
|
return StrUtil.blankToDefault(deviceCode, "");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(deviceCode)) {
|
|
|
|
|
|
|
|
return deviceName;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return deviceName + "(" + deviceCode + ")";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildWarningDescription(List<DeviceWarinningRecordDO> warningRecords, Map<String, String> alarmLevelLabelMap) {
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(warningRecords)) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return warningRecords.stream()
|
|
|
|
|
|
|
|
.collect(Collectors.groupingBy(this::getWarningPointName, LinkedHashMap::new, Collectors.toList()))
|
|
|
|
|
|
|
|
.entrySet().stream()
|
|
|
|
|
|
|
|
.map(entry -> entry.getKey() + ":" + buildWarningPointSummary(entry.getValue(), alarmLevelLabelMap))
|
|
|
|
|
|
|
|
.collect(Collectors.joining("\n"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildWarningPointSummary(List<DeviceWarinningRecordDO> warningRecords, Map<String, String> alarmLevelLabelMap) {
|
|
|
|
|
|
|
|
return warningRecords.stream()
|
|
|
|
|
|
|
|
.collect(Collectors.groupingBy(this::getWarningRuleKey, LinkedHashMap::new, Collectors.toList()))
|
|
|
|
|
|
|
|
.values().stream()
|
|
|
|
|
|
|
|
.map(records -> buildWarningRuleSummary(records, alarmLevelLabelMap))
|
|
|
|
|
|
|
|
.collect(Collectors.joining(";"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getWarningRuleKey(DeviceWarinningRecordDO record) {
|
|
|
|
|
|
|
|
return getWarningName(record) + "|" + StrUtil.blankToDefault(record.getAlarmLevel(), "");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildWarningRuleSummary(List<DeviceWarinningRecordDO> warningRecords, Map<String, String> alarmLevelLabelMap) {
|
|
|
|
|
|
|
|
DeviceWarinningRecordDO firstRecord = warningRecords.get(0);
|
|
|
|
|
|
|
|
String levelText = buildAlarmLevelText(firstRecord.getAlarmLevel(), alarmLevelLabelMap);
|
|
|
|
|
|
|
|
return getWarningName(firstRecord) + warningRecords.size() + "次"
|
|
|
|
|
|
|
|
+ buildWarningValueRangeText(warningRecords) + levelText + buildWarningTimeRangeText(warningRecords);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildAlarmLevelText(String alarmLevel, Map<String, String> alarmLevelLabelMap) {
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(alarmLevel)) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
String alarmLevelLabel = alarmLevelLabelMap.get(normalizeAlarmLevel(alarmLevel));
|
|
|
|
|
|
|
|
return ",等级=" + StrUtil.blankToDefault(alarmLevelLabel, alarmLevel);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Map<String, String> buildAlarmLevelLabelMap() {
|
|
|
|
|
|
|
|
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList(ALARM_LEVEL_DICT_TYPE);
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(dictDataList)) {
|
|
|
|
|
|
|
|
return Collections.emptyMap();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Map<String, String> alarmLevelLabelMap = new LinkedHashMap<>();
|
|
|
|
|
|
|
|
for (DictDataRespDTO dictData : dictDataList) {
|
|
|
|
|
|
|
|
if (dictData == null || StringUtils.isBlank(dictData.getValue())) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
alarmLevelLabelMap.put(normalizeAlarmLevel(dictData.getValue()), dictData.getLabel());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return alarmLevelLabelMap;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String normalizeAlarmLevel(String alarmLevel) {
|
|
|
|
|
|
|
|
String value = StringUtils.trimToEmpty(alarmLevel);
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(value)) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
return BigDecimal.valueOf(Double.parseDouble(value)).stripTrailingZeros().toPlainString();
|
|
|
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getWarningPointName(DeviceWarinningRecordDO record) {
|
|
|
|
|
|
|
|
return StrUtil.blankToDefault(record.getModelName(),
|
|
|
|
|
|
|
|
StrUtil.blankToDefault(record.getRuleName(), StrUtil.blankToDefault(record.getRule(), "未知点位")));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getWarningName(DeviceWarinningRecordDO record) {
|
|
|
|
|
|
|
|
return StrUtil.blankToDefault(record.getRuleName(), StrUtil.blankToDefault(record.getRule(), "告警"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildWarningValueRangeText(List<DeviceWarinningRecordDO> warningRecords) {
|
|
|
|
|
|
|
|
List<Double> values = warningRecords.stream()
|
|
|
|
|
|
|
|
.map(this::parseWarningValue)
|
|
|
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(values)) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
double minValue = values.stream().min(Double::compareTo).orElse(0D);
|
|
|
|
|
|
|
|
double maxValue = values.stream().max(Double::compareTo).orElse(0D);
|
|
|
|
|
|
|
|
if (BigDecimal.valueOf(minValue).compareTo(BigDecimal.valueOf(maxValue)) == 0) {
|
|
|
|
|
|
|
|
return ",值=" + formatNumber(minValue);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ",值=" + formatNumber(minValue) + "~" + formatNumber(maxValue);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Double parseWarningValue(DeviceWarinningRecordDO record) {
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(record.getAddressValue())) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
return Double.valueOf(record.getAddressValue());
|
|
|
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String buildWarningTimeRangeText(List<DeviceWarinningRecordDO> warningRecords) {
|
|
|
|
|
|
|
|
List<LocalDateTime> times = warningRecords.stream()
|
|
|
|
|
|
|
|
.map(DeviceWarinningRecordDO::getCreateTime)
|
|
|
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
|
|
|
.sorted()
|
|
|
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(times)) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalDateTime startTime = times.get(0);
|
|
|
|
|
|
|
|
LocalDateTime endTime = times.get(times.size() - 1);
|
|
|
|
|
|
|
|
if (Objects.equals(startTime, endTime)) {
|
|
|
|
|
|
|
|
return ",时间=" + formatWarningTime(startTime, startTime);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ",时间=" + formatWarningTime(startTime, endTime) + "~" + formatWarningTime(endTime, startTime);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String formatWarningTime(LocalDateTime time, LocalDateTime compareTime) {
|
|
|
|
|
|
|
|
if (Objects.equals(time.toLocalDate(), compareTime.toLocalDate())) {
|
|
|
|
|
|
|
|
return time.format(TIME_FORMATTER);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return time.format(DATE_TIME_FORMATTER);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String formatNumber(Double value) {
|
|
|
|
|
|
|
|
return BigDecimal.valueOf(value).stripTrailingZeros().toPlainString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private DeviceProductionDailyReportRespVO convertFileToReport(FileDO file) {
|
|
|
|
private DeviceProductionDailyReportRespVO convertFileToReport(FileDO file) {
|
|
|
|
@ -343,6 +557,11 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void setCellValue(Sheet sheet, int rowIndex, int columnIndex, Object value) {
|
|
|
|
private void setCellValue(Sheet sheet, int rowIndex, int columnIndex, Object value) {
|
|
|
|
|
|
|
|
CellRangeAddress mergedRegion = getMergedRegion(sheet, rowIndex, columnIndex);
|
|
|
|
|
|
|
|
if (mergedRegion != null) {
|
|
|
|
|
|
|
|
rowIndex = mergedRegion.getFirstRow();
|
|
|
|
|
|
|
|
columnIndex = mergedRegion.getFirstColumn();
|
|
|
|
|
|
|
|
}
|
|
|
|
Row row = sheet.getRow(rowIndex);
|
|
|
|
Row row = sheet.getRow(rowIndex);
|
|
|
|
if (row == null) {
|
|
|
|
if (row == null) {
|
|
|
|
row = sheet.createRow(rowIndex);
|
|
|
|
row = sheet.createRow(rowIndex);
|
|
|
|
@ -361,5 +580,167 @@ public class DeviceProductionDailyReportServiceImpl implements DeviceProductionD
|
|
|
|
cell.setCellValue(value == null ? "" : value.toString());
|
|
|
|
cell.setCellValue(value == null ? "" : value.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setWrapText(Row row, int columnIndex) {
|
|
|
|
|
|
|
|
Cell cell = row.getCell(columnIndex);
|
|
|
|
|
|
|
|
if (cell == null) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CellStyle cellStyle = row.getSheet().getWorkbook().createCellStyle();
|
|
|
|
|
|
|
|
cellStyle.cloneStyleFrom(cell.getCellStyle());
|
|
|
|
|
|
|
|
cellStyle.setWrapText(true);
|
|
|
|
|
|
|
|
cell.setCellStyle(cellStyle);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void copyRowStyle(Row sourceRow, Row targetRow, int columnCount) {
|
|
|
|
|
|
|
|
if (sourceRow == null || targetRow == null) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
targetRow.setHeight(sourceRow.getHeight());
|
|
|
|
|
|
|
|
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
|
|
|
|
|
|
Cell sourceCell = sourceRow.getCell(columnIndex);
|
|
|
|
|
|
|
|
if (sourceCell == null) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Cell targetCell = targetRow.getCell(columnIndex);
|
|
|
|
|
|
|
|
if (targetCell == null) {
|
|
|
|
|
|
|
|
targetCell = targetRow.createCell(columnIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
targetCell.setCellStyle(sourceCell.getCellStyle());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void mergeCellsIfAbsent(Sheet sheet, int rowIndex, int firstColumn, int lastColumn) {
|
|
|
|
|
|
|
|
CellRangeAddress newRegion = new CellRangeAddress(rowIndex, rowIndex, firstColumn, lastColumn);
|
|
|
|
|
|
|
|
for (CellRangeAddress mergedRegion : sheet.getMergedRegions()) {
|
|
|
|
|
|
|
|
if (mergedRegion.intersects(newRegion)) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sheet.addMergedRegion(newRegion);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void removeRowsFromEnd(Sheet sheet, int startRowIndex) {
|
|
|
|
|
|
|
|
int lastRowIndex = sheet.getLastRowNum();
|
|
|
|
|
|
|
|
if (startRowIndex > lastRowIndex) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = sheet.getNumMergedRegions() - 1; index >= 0; index--) {
|
|
|
|
|
|
|
|
CellRangeAddress mergedRegion = sheet.getMergedRegion(index);
|
|
|
|
|
|
|
|
if (mergedRegion.getFirstRow() >= startRowIndex) {
|
|
|
|
|
|
|
|
sheet.removeMergedRegion(index);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int rowIndex = lastRowIndex; rowIndex >= startRowIndex; rowIndex--) {
|
|
|
|
|
|
|
|
Row row = sheet.getRow(rowIndex);
|
|
|
|
|
|
|
|
if (row != null) {
|
|
|
|
|
|
|
|
sheet.removeRow(row);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setHeaderValue(Sheet sheet, String label, String value, int fallbackRowIndex, int fallbackColumnIndex) {
|
|
|
|
|
|
|
|
Cell labelCell = findCellByPrefix(sheet, label);
|
|
|
|
|
|
|
|
if (labelCell != null) {
|
|
|
|
|
|
|
|
CellRangeAddress mergedRegion = getMergedRegion(sheet, labelCell.getRowIndex(), labelCell.getColumnIndex());
|
|
|
|
|
|
|
|
log.info("[production-daily-report] set header by label: label={}, foundCell={}, rowIndex={}, columnIndex={}, mergedRegion={}, value={}",
|
|
|
|
|
|
|
|
label, labelCell.getAddress().formatAsString(), labelCell.getRowIndex(), labelCell.getColumnIndex(), mergedRegion, value);
|
|
|
|
|
|
|
|
setStringCellValueForce(sheet, labelCell.getRowIndex(), labelCell.getColumnIndex(), value);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CellRangeAddress mergedRegion = getMergedRegion(sheet, fallbackRowIndex, fallbackColumnIndex);
|
|
|
|
|
|
|
|
log.info("[production-daily-report] set header by fallback: label={}, fallbackRowIndex={}, fallbackColumnIndex={}, mergedRegion={}, value={}",
|
|
|
|
|
|
|
|
label, fallbackRowIndex, fallbackColumnIndex, mergedRegion, value);
|
|
|
|
|
|
|
|
setStringCellValueForce(sheet, fallbackRowIndex, fallbackColumnIndex, value);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setStringCellValueForce(Sheet sheet, int rowIndex, int columnIndex, String value) {
|
|
|
|
|
|
|
|
CellRangeAddress mergedRegion = getMergedRegion(sheet, rowIndex, columnIndex);
|
|
|
|
|
|
|
|
int firstRowIndex = mergedRegion != null ? mergedRegion.getFirstRow() : rowIndex;
|
|
|
|
|
|
|
|
int firstColumnIndex = mergedRegion != null ? mergedRegion.getFirstColumn() : columnIndex;
|
|
|
|
|
|
|
|
Row row = sheet.getRow(firstRowIndex);
|
|
|
|
|
|
|
|
if (row == null) {
|
|
|
|
|
|
|
|
row = sheet.createRow(firstRowIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cell oldCell = row.getCell(firstColumnIndex);
|
|
|
|
|
|
|
|
org.apache.poi.ss.usermodel.CellStyle cellStyle = oldCell != null ? oldCell.getCellStyle() : null;
|
|
|
|
|
|
|
|
if (oldCell != null) {
|
|
|
|
|
|
|
|
row.removeCell(oldCell);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Cell newCell = row.createCell(firstColumnIndex, CellType.STRING);
|
|
|
|
|
|
|
|
if (cellStyle != null) {
|
|
|
|
|
|
|
|
newCell.setCellStyle(cellStyle);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
newCell.setCellValue(value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mergedRegion != null) {
|
|
|
|
|
|
|
|
for (int column = mergedRegion.getFirstColumn() + 1; column <= mergedRegion.getLastColumn(); column++) {
|
|
|
|
|
|
|
|
Cell mergedCell = row.getCell(column);
|
|
|
|
|
|
|
|
if (mergedCell != null) {
|
|
|
|
|
|
|
|
mergedCell.setCellValue("");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
log.info("[production-daily-report] force set header cell: targetRowIndex={}, targetColumnIndex={}, mergedRegion={}, value={}, actualValue={}",
|
|
|
|
|
|
|
|
firstRowIndex, firstColumnIndex, mergedRegion, value, getCellValue(sheet, firstRowIndex, firstColumnIndex));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@SneakyThrows
|
|
|
|
|
|
|
|
private void logGeneratedHeader(byte[] bytes) {
|
|
|
|
|
|
|
|
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(bytes))) {
|
|
|
|
|
|
|
|
Sheet sheet = workbook.getSheetAt(0);
|
|
|
|
|
|
|
|
log.info("[production-daily-report] generated bytes header check: A3={}, C3={}, E3={}, mergedRegions={}",
|
|
|
|
|
|
|
|
getCellValue(sheet, 2, 0), getCellValue(sheet, 2, 2), getCellValue(sheet, 2, 4), sheet.getMergedRegions());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getCellValue(Sheet sheet, int rowIndex, int columnIndex) {
|
|
|
|
|
|
|
|
Row row = sheet.getRow(rowIndex);
|
|
|
|
|
|
|
|
Cell cell = row != null ? row.getCell(columnIndex) : null;
|
|
|
|
|
|
|
|
if (cell == null) {
|
|
|
|
|
|
|
|
CellRangeAddress mergedRegion = getMergedRegion(sheet, rowIndex, columnIndex);
|
|
|
|
|
|
|
|
if (mergedRegion != null) {
|
|
|
|
|
|
|
|
row = sheet.getRow(mergedRegion.getFirstRow());
|
|
|
|
|
|
|
|
cell = row != null ? row.getCell(mergedRegion.getFirstColumn()) : null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (row == null) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cell == null) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cell.getCellType() == CellType.STRING) {
|
|
|
|
|
|
|
|
return cell.getStringCellValue();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cell.getCellType() == CellType.NUMERIC) {
|
|
|
|
|
|
|
|
return String.valueOf(cell.getNumericCellValue());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cell.getCellType() == CellType.BOOLEAN) {
|
|
|
|
|
|
|
|
return String.valueOf(cell.getBooleanCellValue());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return cell.toString();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Cell findCellByPrefix(Sheet sheet, String label) {
|
|
|
|
|
|
|
|
for (Row row : sheet) {
|
|
|
|
|
|
|
|
for (Cell cell : row) {
|
|
|
|
|
|
|
|
if (cell.getCellType() == CellType.STRING && StringUtils.startsWith(cell.getStringCellValue(), label)) {
|
|
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private CellRangeAddress getMergedRegion(Sheet sheet, int rowIndex, int columnIndex) {
|
|
|
|
|
|
|
|
for (CellRangeAddress mergedRegion : sheet.getMergedRegions()) {
|
|
|
|
|
|
|
|
if (mergedRegion.isInRange(rowIndex, columnIndex)) {
|
|
|
|
|
|
|
|
return mergedRegion;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|