maven的依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
基础版的截图 三级表头,每天对应一大列
实战复杂的截图 三级表头,每天对应一大列
表格分为横向排列和纵向排列,比较复杂,
还涉及多个表头,编写代码太复杂,历时4天完成。
基础版实现代码
public static void main(String[] args) {
String base = "温度,湿度,气压";
String identifyStr = "日期,设备" + "," + base;
String head = base + "," + "时间段";
String[] identifyArray = Func.toStrArray(",", identifyStr);
String[] headArray = Func.toStrArray(",", head);
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("设备属性数据表 ");
// 数据
Map<String, List<Map<String, Object>>> dailyData = getDailyData(identifyArray, 3);
String header0 = "";
int i = 0;
for (Map.Entry<String, List<Map<String, Object>>> entry : dailyData.entrySet()) {
String day = entry.getKey();
List<Map<String, Object>> dataList = entry.getValue();
// 合并单元格
int lastCellNum = identifyArray.length;
int cellst = i * (lastCellNum + 3); // 0-5 7-12 14-19 21-26
int cellend = i * (lastCellNum + 3) + lastCellNum;
i++;
sheet.addMergedRegion(new CellRangeAddress(0, 0, cellst, cellend)); // 合并表头一的单元格
sheet.addMergedRegion(new CellRangeAddress(1, 1, cellst, cellend)); // 合并表头二的单元格 导出时间
sheet.addMergedRegion(new CellRangeAddress(2, 2, cellst, cellend)); // 合并表头三的单元格 汇总数据
Row headerRow1 = sheet.getRow(0);
if (headerRow1 == null) {
headerRow1 = sheet.createRow(0);
}
// 设置边框样式
CellStyle borderStyle = workbook.createCellStyle();
borderStyle.setBorderBottom(BorderStyle.THIN);
borderStyle.setBorderTop(BorderStyle.THIN);
borderStyle.setBorderLeft(BorderStyle.THIN);
borderStyle.setBorderRight(BorderStyle.THIN);
borderStyle.setAlignment(HorizontalAlignment.CENTER);
borderStyle.setVerticalAlignment(VerticalAlignment.CENTER);
header0 = StringUtil.format("至{}设备数据导出", "设备名66");
headerRow1.createCell(cellst).setCellValue(header0);
Row dateRow = sheet.getRow(1);
if (dateRow == null) {
dateRow = sheet.createRow(1);
}
dateRow.createCell(cellst).setCellValue("导出时间:" + DateUtil.formatDateTime(DateUtil.now()));
Row dateRow2 = sheet.getRow(2);
if (dateRow2 == null) {
dateRow2 = sheet.createRow(2);
}
dateRow2.createCell(cellst).setCellValue("汇总数据");
Row dateRow3 = sheet.getRow(3);
if (dateRow3 == null) {
dateRow3 = sheet.createRow(3);
}
dateRow3.createCell(cellst).setCellValue("统计类型");
Row dateRow4 = sheet.getRow(4);
if (dateRow4 == null) {
dateRow4 = sheet.createRow(4);
}
dateRow4.createCell(cellst).setCellValue("合计");
Row dateRow5 = sheet.getRow(5);
if (dateRow5 == null) {
dateRow5 = sheet.createRow(5);
}
dateRow5.createCell(cellst + 0).setCellValue("平均值");
Row dateRow6 = sheet.getRow(6);
if (dateRow6 == null) {
dateRow6 = sheet.createRow(6);
}
dateRow6.createCell(cellst + 0).setCellValue("最大值");
Row dateRow7 = sheet.getRow(7);
if (dateRow7 == null) {
dateRow7 = sheet.createRow(7);
}
dateRow7.createCell(cellst + 0).setCellValue("最小值");
Row dateRow8 = sheet.getRow(8);
if (dateRow8 == null) {
dateRow8 = sheet.createRow(8);
}
dateRow8.createCell(cellst + 0).setCellValue("异常波动情况");
Row dateRow9 = sheet.getRow(9);
if (dateRow9 == null) {
dateRow9 = sheet.createRow(9);
}
dateRow9.createCell(cellst + 0).setCellValue("报警情况");
Row dateRow10 = sheet.getRow(10);
if (dateRow10 == null) {
dateRow10 = sheet.createRow(10);
}
dateRow10.createCell(cellst).setCellValue("预警情况");
for (int cells = 1; cells <= headArray.length; cells++) {
dateRow3.createCell(cellst + cells).setCellValue(headArray[cells - 1]); // 统计类型 表头
dateRow4.createCell(cellst + cells).setCellValue("4_" + cells);
dateRow5.createCell(cellst + cells).setCellValue("5_" + cells);
dateRow6.createCell(cellst + cells).setCellValue("6_" + cells);
dateRow7.createCell(cellst + cells).setCellValue("7_" + cells);
dateRow8.createCell(cellst + cells).setCellValue("8_" + cells);
dateRow9.createCell(cellst + cells).setCellValue("9_" + cells);
dateRow10.createCell(cellst + cells).setCellValue("10_" + cells);
}
// 写入数据
int rowNum = 15;
int arrayLength = 0;
for (Map<String, Object> data : dataList) {
// 创建表头三
Row headerRow = sheet.getRow(14);
if (headerRow == null) {
headerRow = sheet.createRow(14);
}
Row row = sheet.getRow(rowNum);
if (row == null) {
row = sheet.createRow(rowNum);
}
for (int c = 0; c < identifyArray.length; c++) {
Cell headerCell2 = headerRow.createCell(cellst + c);
headerCell2.setCellValue(identifyArray[c]);
row.createCell(cellst + c).setCellValue(data.get(identifyArray[c]).toString());
}
rowNum++;
arrayLength++;
}
}
// 写入到文件
try (FileOutputStream fileOut = new FileOutputStream("C:\\Users\\xu\\Desktop\\表格\\daily_data.xlsx")) {
workbook.write(fileOut);
} catch (IOException e) {
e.printStackTrace();
}
// 关闭工作簿
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 模拟数据
private static Map<String, List<Map<String, Object>>> getDailyData(String[] array, int timeDay) {
Map<String, List<Map<String, Object>>> data = new HashMap<>();
for (int i = 0; i < timeDay; i++) {
List<Map<String, Object>> day1Data = new ArrayList<>();
for (int c = 0; c < 5; c++) {
Map<String, Object> day1Row1 = new HashMap<>();
for (String str : array) {
day1Row1.put(str, 1 + i);
}
day1Data.add(day1Row1);
}
data.put("Day" + i, day1Data);
}
return data;
}
实战复杂案例代码
里面有模拟的数据,可以直接运行,无需编写代码即可导出
package com.bluebird.iot.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bluebird.common.enums.iot.AlarmRuleTypeEnum;
import com.bluebird.common.model.TimeSplit;
import com.bluebird.core.log.exception.ServiceException;
import com.bluebird.core.tool.utils.DateUtil;
import com.bluebird.core.tool.utils.Func;
import com.bluebird.core.tool.utils.StringUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Pattern;
public class ExcelExporter {
// 报警情况
private static final Integer ALARM_ANALYSIS = 5;
// 预警情况
private static final Integer WARNING_ANALYSIS = 6;
// 异常波动情况
private static final Integer ABNORMAL_ANALYSIS = 7;
// 计算大小值
private static final Integer MIN_NUM = 2147483647;
//计算最大值
private static final Integer MAX_NUM = -2147483648;
@Data
public static class ModelItem {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "中文名称 ")
private String name;
@ApiModelProperty(value = "属性标识符")
private String identifier;
@ApiModelProperty(value = "单位")
private String unit;
}
@Data
public static class Value {
private static final long serialVersionUID = 1L;
private String identify;
private String value;
}
@Data
public static class AlarmData {
private static final long serialVersionUID = 1L;
private int ruleType;
private long time;
private List<Value> value;
}
// 处理表头模拟数据
private static List<ModelItem> getModelItemList( ) {
// 雷(L) 风(F) 气 水 雨(Y) 电
List<ModelItem> modelItemList = new ArrayList<>();
ModelItem feng = new ModelItem();
feng.setName("风");
feng.setIdentifier("feng");
feng.setUnit("F");
ModelItem yu = new ModelItem();
yu.setName("雨");
yu.setIdentifier("yu");
yu.setUnit("Y");
ModelItem lei = new ModelItem();
lei.setName("雷");
lei.setIdentifier("lei");
lei.setUnit("L");
ModelItem dian = new ModelItem();
dian.setName("电");
dian.setIdentifier("dian");
dian.setUnit("D");
ModelItem qi = new ModelItem();
qi.setName("气");
qi.setIdentifier("qi");
qi.setUnit("Q");
ModelItem shui = new ModelItem();
shui.setName("水");
shui.setIdentifier("shui");
shui.setUnit("L");
modelItemList.add( feng );
modelItemList.add( yu );
modelItemList.add( lei );
modelItemList.add( qi );
modelItemList.add( shui );
return modelItemList;
}
// 模拟表头二 报警信息
private static List<AlarmData> getAlarmDataList( ){
List<AlarmData> alarmDataList = new ArrayList<>();
AlarmData alarmData1 = new AlarmData();
alarmData1.setTime(1718359244437L);
alarmData1.setRuleType(1);
List<Value> value_1 = new ArrayList<>();
Value value1 = new Value();
value1.setValue("30");
value1.setIdentify("qi");
Value value2 = new Value();
value2.setValue("70");
value2.setIdentify("shui");
Value value3 = new Value();
value3.setValue("88");
value3.setIdentify("feng");
value_1.add( value1 );
value_1.add( value2 );
value_1.add( value3 );
alarmData1.setValue( value_1 );
AlarmData alarmData3 = new AlarmData();
alarmData3.setTime(1718359244437L);
alarmData3.setRuleType(2);
List<Value> value_3 = new ArrayList<>();
Value value7 = new Value();
value7.setValue("30");
value7.setIdentify("qi");
Value value8 = new Value();
value8.setValue("70");
value8.setIdentify("shui");
Value value9 = new Value();
value9.setValue("88");
value9.setIdentify("feng");
value_3.add( value7 );
value_3.add( value8 );
value_3.add( value9 );
alarmData3.setValue( value_3 );
AlarmData alarmData = new AlarmData();
alarmData.setTime(1718359244437L);
alarmData.setRuleType(2);
List<Value> value_2 = new ArrayList<>();
Value value4 = new Value();
value4.setValue("30");
value4.setIdentify("qi");
Value value5 = new Value();
value5.setValue("70");
value5.setIdentify("shui");
Value value6 = new Value();
value6.setValue("88");
value6.setIdentify("feng");
value_2.add( value4 );
value_2.add( value5 );
value_2.add( value6 );
alarmData.setValue( value_2 );
alarmDataList.add( alarmData );
alarmDataList.add( alarmData1 );
alarmDataList.add( alarmData3 );
return alarmDataList;
}
// 处理模拟表头三 的刘表
// {"identifies":["lei","feng","qi","shui","yu","dian"],"values":["50","60","40","70","10","15"],"_id":1718359477276,"time":1718359477276,"deviceSn":"wsd01"}
private static List<JSONObject> getList(){
List<JSONObject> aggregatedList = new ArrayList<>();
JSONObject jsonObject = new JSONObject();
String[] identifies = {"lei","feng","qi","shui","yu","dian"};
jsonObject.put("identifies", identifies);
String[] values = {"50","60","40","70","10","15"};
jsonObject.put("values", values);
jsonObject.put("time", "1718359477276");
jsonObject.put("deviceSn", "wsd01");
aggregatedList.add( jsonObject );
return aggregatedList;
}
public static Date strToDate(String dateStr) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = sdf.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
public static void main(String[] args) {
toExportUtils( );
}
public static String dateToString(Object date ) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
public static List<TimeSplit> getStartAndEndTimesForEachDay(Date startDate, Date endDate) {
List<TimeSplit> timeSplits = new ArrayList<>();
// 将开始日期转为LocalDate
ZonedDateTime startZonedDateTime = startDate.toInstant().atZone(ZoneId.systemDefault());
LocalDate startLocalDate = startZonedDateTime.toLocalDate();
// 将结束日期转为LocalDate
ZonedDateTime endZonedDateTime = endDate.toInstant().atZone(ZoneId.systemDefault());
LocalDate endLocalDate = endZonedDateTime.toLocalDate();
// 检查开始日期和结束日期是否在同一天
if (startLocalDate.isEqual(endLocalDate)) {
timeSplits.add(new TimeSplit(startDate, endDate));
return timeSplits;
}
// 将确切的startDateTime添加第一天
ZonedDateTime endOfFirstDay = startLocalDate.atTime(LocalTime.MAX).atZone(ZoneId.systemDefault());
timeSplits.add(new TimeSplit(startDate, Date.from(endOfFirstDay.toInstant())));
// 迭代剩余的天数,直到endLocalDate的前一天
LocalDate current = startLocalDate.plusDays(1);
while (current.isBefore(endLocalDate)) {
ZonedDateTime startOfDay = current.atStartOfDay(ZoneId.systemDefault());
ZonedDateTime endOfDay = current.atTime(LocalTime.MAX).atZone(ZoneId.systemDefault());
// Add the current day's start and end times to the list
timeSplits.add(new TimeSplit(Date.from(startOfDay.toInstant()), Date.from(endOfDay.toInstant())));
// Move to the next day
current = current.plusDays(1);
}
// Handle the last day separately to include the exact endDateTime
ZonedDateTime startOfLastDay = endLocalDate.atStartOfDay(ZoneId.systemDefault());
if (startOfLastDay.isBefore(endZonedDateTime)) {
timeSplits.add(new TimeSplit(Date.from(startOfLastDay.toInstant()), endDate));
}
return timeSplits;
}
public static void toExportUtils( ) {
long startExecutionTime = System.currentTimeMillis();
Date startTime = strToDate("2024-06-16 01:00:00 ") ;
Date endTime = strToDate("2024-06-18 01:00:00") ;
String[] identifys = Func.toStrArray(",", "feng,yu,lei,qi,shui");
// 获取用户选择的统计类型
String statisticsTypesStr = "7,6,5,2,1,3,4";
List<Integer> statisticsTypes = Func.toIntList(",", statisticsTypesStr);
// 处理 这4个表头 合计:1,平均值:2,最大值:3,最小值:4 由于有顺序或者是否查询此表头 需要特殊处理下
List<Integer> topFourList = new ArrayList<>();
Map<Integer, String> integerStringMap = toMap();
for (Integer statisticsType : statisticsTypes) {
if (statisticsType < 5) {
topFourList.add(statisticsType);
}
}
List<TimeSplit> timeSplitList = getStartAndEndTimesForEachDay(startTime, endTime);
if (timeSplitList != null && timeSplitList.size() > 7) {
throw new ServiceException("导出时间不能超过7天,请修改时间后再导出!");
}
List<ModelItem> modelItemList = getModelItemList();
if (modelItemList == null || modelItemList.size() == 0) {
throw new ServiceException("物模型不存在");
}
String base = "";
String identifyKeyStr = "日期,设备" + ",";
Map<String, String> mapHead = new HashMap<>();
Map<String, String> mapSum = new HashMap<>();
String sumKey = "";
Map<String, ModelItem> modelItemMap = new HashMap<>();
if (identifys != null && identifys.length > 0) {
for (int i = 0; i < identifys.length; i++) {
String identify = identifys[i];
ModelItem item = new ModelItem();
for (ModelItem modelItem : modelItemList) {
if (identify.equals(modelItem.getIdentifier())) {
item = modelItem;
break;
}
}
identifyKeyStr = identifyKeyStr + item.getIdentifier() + ",";
sumKey = sumKey + item.getIdentifier() + ",";
if (StringUtil.isNotBlank(item.getUnit())) {
base = base + item.getName() + "(" + item.getUnit() + ")" + ",";
mapHead.put(item.getIdentifier(), item.getName() + "(" + item.getUnit() + ")");
mapSum.put(item.getIdentifier(), item.getName() + "(" + item.getUnit() + ")");
} else {
base = base + item.getName() + ",";
mapHead.put(item.getIdentifier(), item.getName());
mapSum.put(item.getIdentifier(), item.getName());
}
modelItemMap.put(item.getIdentifier(), item);
}
mapHead.put("日期", "日期");
mapHead.put("设备", "设备");
}
String identifyStr = "日期,设备" + "," + base;
String head = base + "时间段";
String[] identifyKey = Func.toStrArray(",", identifyKeyStr);
// 列表数据 使用的 带 日期,设备 的字段
String[] identifyArray = Func.toStrArray(",", identifyStr);
// 统计使用的 带 时间段 的字段
String[] headArray = Func.toStrArray(",", head);
// 前端传过来的物属性
String[] sumArray = Func.toStrArray(",", sumKey);
// 处理总数据
Map<String, List<Map<String, Object>>> dailyData = new LinkedHashMap<>();
// 处理统计告警等信息
Map<String, List<AlarmData>> alarmMapData = new LinkedHashMap<>();
// 将计算的 告警、统计等综合记录下,便于下个集合遍历使用
Map<String, Integer> excelMapCount = new LinkedHashMap<>();
// 查询每天的总数据量 由于表头、合计、最值、告警等会占用一定的行数 所以这里最多按照 excelCount 计算 如果超过 excelCount 就返回提示
for (int i = 0; i < timeSplitList.size(); i++) {
TimeSplit timeSplit = timeSplitList.get(i);
// 自定义设备名称 例如: ....设备_2024-06-14至2024-06-18
String keyMap = "";
// 计算小时数
LocalDateTime startDateTime = LocalDateTime.ofInstant(startTime.toInstant(), ZoneId.systemDefault());
LocalDateTime endDateTime = LocalDateTime.ofInstant(endTime.toInstant(), ZoneId.systemDefault());
long hours = ChronoUnit.HOURS.between(startDateTime, endDateTime);
if (hours <= 24) {
keyMap = StringUtil.format("{}_{}小时", "设备名称", hours);
} else {
keyMap = StringUtil.format("{}_{}至{}",
"设备名称", DateUtil.formatDate(timeSplit.getStartDateTime()), DateUtil.formatDate(timeSplit.getEndDateTime()));
}
List<AlarmData> alarmDataProjectionList = null;
//查询报警、预警、异常等数据
if (statisticsTypes.contains(ALARM_ANALYSIS) || statisticsTypes.contains(WARNING_ANALYSIS) || statisticsTypes.contains(ABNORMAL_ANALYSIS)) {
alarmDataProjectionList = getAlarmDataList(); // getAlarmData(statisticsTypes, identifys, serviceId, productKey, deviceSn, timeSplit);
alarmMapData.put(keyMap, alarmDataProjectionList);
}
// 查询数据总量 我这 用200模拟下
long deviceDayCount = 200L ;
System.out.println( "================== 第 "+dateToString(timeSplit.getStartDateTime())+" 天的消息总数量为:"+deviceDayCount+ " 条" );
// 表格总行数 65535 - 表头和统计以及空格 按照 12计算 = 65523
int excelCount = 65523;
if (alarmDataProjectionList != null) {
excelCount = excelCount - alarmDataProjectionList.size();
}
if (deviceDayCount > excelCount) {
throw new ServiceException(dateToString(timeSplit.getStartDateTime()) + " 当天总数量超过 65535 的最大限制了,不能导出!");
}
excelMapCount.put(keyMap, Integer.parseInt(String.valueOf(deviceDayCount)));
}
// 根据时间天 查询数据
for (int i = 0; i < timeSplitList.size(); i++) {
TimeSplit timeSplit = timeSplitList.get(i);
// 自定义设备名称 例如: 演示能耗设备_2024-05-30至2024-05-30
String keyMap = "";
// 计算小时数
LocalDateTime startDateTime = LocalDateTime.ofInstant(startTime.toInstant(), ZoneId.systemDefault());
LocalDateTime endDateTime = LocalDateTime.ofInstant(endTime.toInstant(), ZoneId.systemDefault());
long hours = ChronoUnit.HOURS.between(startDateTime, endDateTime);
if (hours <= 24) {
keyMap = StringUtil.format("{}_{}小时", "设备名称", hours);
} else {
keyMap = StringUtil.format("{}_{}至{}", "设备名称", DateUtil.formatDate(timeSplit.getStartDateTime()), DateUtil.formatDate(timeSplit.getEndDateTime()));
}
// 拿到最大值
int maxRow = excelMapCount.get(keyMap);
// 每次查询的数据量
int offset = 0;
int batchSize = 10;
//计算遍历次数
int divisionResult = maxRow / batchSize;
//计算最后一次 取余
int remainder = maxRow % batchSize;
List<Map<String, Object>> dayData = new ArrayList<>();
if (maxRow > 0) {
for (int max = 0; max <= divisionResult; max++) {
// 计算最后一次的偏移量
if (max == divisionResult && remainder != 0) {
batchSize = remainder;
}
// 查询表头三列表数据 TODO
List<JSONObject> aggregatedList = getList();// getDeviceParseLog(identifys, serviceId, productKey, deviceSn, timeSplit, offset, batchSize, endTime);
for (JSONObject jsonObject : aggregatedList) {
Map<String, Object> dayRow = new HashMap<>();
dayRow.put("日期", dateToString(new Date()));
dayRow.put("设备", jsonObject.get("deviceSn"));
Object identifies = jsonObject.get("identifies");
Object values = jsonObject.get("values");
List<String> identifiesList = JSONArray.parseArray(JSON.toJSONString(identifies), String.class);
List<String> objectList = JSONArray.parseArray(JSON.toJSONString(values), String.class);
for (int j = 0; j < identifiesList.size(); j++) {
String str = identifiesList.get(j);
int val = 0;
if (isNumber(objectList.get(j))) {
val = Integer.parseInt(objectList.get(j));
} else {
val = 0;
}
dayRow.put(str, val);
}
dayData.add(dayRow);
}
offset += batchSize;
}
}
dailyData.put(keyMap, dayData);
}
String header0 = "";
int i = 0;
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("设备属性数据表 ");
// 遍历天
for (Map.Entry<String, List<Map<String, Object>>> entry : dailyData.entrySet()) {
String nameTime = entry.getKey();
List<AlarmData> alarmDataProjectionList = alarmMapData.get(nameTime);
// 处理统计信息
Map<String, List<Object>> listMap = new HashMap<>();
List<String> stringList = Arrays.asList(sumArray);
for (String keyPY : stringList) {
int sum = 0;
int count = 0;
int max = MAX_NUM;
BigDecimal avg = null;
int min = MIN_NUM;
// 处理最大值和最小值、总和
for (Map<String, Object> stringObjectMap : entry.getValue()) {
for (Map.Entry<String, Object> stringObjectEntry : stringObjectMap.entrySet()) {
if (keyPY.equals(stringObjectEntry.getKey())) {
int value = Integer.parseInt(stringObjectEntry.getValue().toString());
sum += value;
count++;
if (max < value) {
max = value;
}
if (min > value) {
min = value;
}
}
}
}
if (count != 0) {
BigDecimal num = new BigDecimal(sum);
BigDecimal denom = new BigDecimal(count);
avg = num.divide(denom, 2, RoundingMode.HALF_UP);
}
List<Object> list = new ArrayList<>();
// 时间段
List<Object> listTime = new ArrayList<>();
for (int top = 0; top < topFourList.size(); top++) {
int topNum = topFourList.get(top);
// 合计:1,平均值:2,最大值:3,最小值:4
String headName = integerStringMap.get(topNum);
if ("合计".equals(headName)) {
list.add(sum);
} else if ("平均值".equals(headName)) {
list.add(avg);
} else if ("最大值".equals(headName)) {
list.add(max);
} else if ("最小值".equals(headName)) {
list.add(min);
}
listTime.add(0);
}
// 处理 统计的数据 时间和其他物模型
if (alarmDataProjectionList != null && alarmDataProjectionList.size() > 0) {
for (int j = 0; j < alarmDataProjectionList.size(); j++) {
AlarmData alarmDataProjection = alarmDataProjectionList.get(j);
String time = dateToString(alarmDataProjection.getTime());
if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.ONE.getValue()) {
listTime.add(time); // 报警情况
} else if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.TWO.getValue()) {
listTime.add(time); // 预警情况
} else if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.THREE.getValue()) {
listTime.add(time); // 异常情况
}
List<Value> valueList = alarmDataProjection.getValue();
if (valueList != null && valueList.size() > 0) {
int value = 0;
for (Value identifyValue : valueList) {
if (keyPY.equals(identifyValue.getIdentify())) {
value = Integer.parseInt(identifyValue.getValue());
}
}
list.add(value);
}
}
}
String keyName = mapSum.get(keyPY);
listMap.put(keyName, list);
listMap.put("时间段", listTime);
}
// 每天的数据
List<Map<String, Object>> dataList = entry.getValue();
// 合并单元格
int lastCellNum = identifyArray.length;
int cellst = i * (lastCellNum + 3);
int cellend = i * (lastCellNum + 3) + lastCellNum;
i++;
// 设置边框样式
CellStyle borderStyle = workbook.createCellStyle();
borderStyle.setBorderBottom(BorderStyle.THIN); // 下边框加粗
borderStyle.setBorderTop(BorderStyle.THIN); // 上边框加粗
borderStyle.setBorderLeft(BorderStyle.THIN); // 左边框加粗
borderStyle.setBorderRight(BorderStyle.THIN); // 右边框加粗
borderStyle.setAlignment(HorizontalAlignment.CENTER); // 水平对齐方式为居中
borderStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直对齐方式为居中
sheet.addMergedRegion(new CellRangeAddress(0, 0, cellst, cellend)); // 合并表头一的单元格
sheet.addMergedRegion(new CellRangeAddress(1, 1, cellst, cellend)); // 合并表头二的单元格 导出时间
sheet.addMergedRegion(new CellRangeAddress(2, 2, cellst, cellend)); // 合并表头三的单元格 汇总数据
sheet.addMergedRegion(new CellRangeAddress(3, 3, cellst, cellst + 1)); // 合并表头四的单元格 统计类型
Row headerRow0 = sheet.getRow(0);
if (headerRow0 == null) {
headerRow0 = sheet.createRow(0);
}
header0 = StringUtil.format("{}设备数据导出", nameTime);
headerRow0.createCell(cellst).setCellValue(header0);
Row dateRow1 = sheet.getRow(1);
if (dateRow1 == null) {
dateRow1 = sheet.createRow(1);
}
dateRow1.createCell(cellst).setCellValue("导出时间:" + DateUtil.formatDateTime(DateUtil.now()));
Row dateRow2 = sheet.getRow(2);
if (dateRow2 == null) {
dateRow2 = sheet.createRow(2);
}
Cell cell2 = dateRow2.createCell(cellst);
cell2.setCellValue("汇总数据");
int cellCount = 2 + headArray.length;
// 对 汇总数据合并的后边的行处理样式 边框加粗
for (int j = 0; j < cellCount; j++) {
Cell cell_j = dateRow2.createCell(cellst + j );
cell_j.setCellStyle(borderStyle);
}
Row dateRow3 = sheet.getRow(3);
if (dateRow3 == null) {
dateRow3 = sheet.createRow(3);
}
Cell cell3 = dateRow3.createCell(cellst);
cell3.setCellValue("统计类型");
cell3.setCellStyle(borderStyle);
// 对 统计类型合并的后边一行处理样式 边框加粗
Cell cell_1 = dateRow3.createCell(cellst + 1 );
cell_1.setCellStyle(borderStyle);
List<Row> rowList = new ArrayList<>();
for (int top = 0; top < topFourList.size(); top++) {
int topNum = topFourList.get(top);
// 合计:1,平均值:2,最大值:3,最小值:4
String headName = integerStringMap.get(topNum);
Row dateRowHead = sheet.getRow(top + 4);
if (dateRowHead == null) {
dateRowHead = sheet.createRow(top + 4);
}
Cell cellHead = dateRowHead.createCell(cellst);
cellHead.setCellValue(headName);
cellHead.setCellStyle(borderStyle);
// 对 合计、平均值、最大值、最小值 合并的后边一行处理样式 边框加粗
Cell cellHead_1 = dateRowHead.createCell(cellst + 1 );
cellHead_1.setCellStyle(borderStyle);
rowList.add(dateRowHead);
sheet.addMergedRegion(new CellRangeAddress(4 + top , 4 + top, cellst, cellst + 1)); // 合并表头 6的单元格 平均值
}
// 设置红色背景样式 异常波动情况
CellStyle abnormalBackgroundStyle = workbook.createCellStyle();
abnormalBackgroundStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
abnormalBackgroundStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
abnormalBackgroundStyle.setAlignment(HorizontalAlignment.CENTER);
abnormalBackgroundStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置蓝色背景样式 报警情况
CellStyle alarmBackgroundStyle = workbook.createCellStyle();
alarmBackgroundStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
alarmBackgroundStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
alarmBackgroundStyle.setAlignment(HorizontalAlignment.CENTER);
alarmBackgroundStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置黄色背景样式 预警情况
CellStyle warningBackgroundStyle = workbook.createCellStyle();
warningBackgroundStyle.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
warningBackgroundStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
warningBackgroundStyle.setAlignment(HorizontalAlignment.CENTER);
warningBackgroundStyle.setVerticalAlignment(VerticalAlignment.CENTER);
int size = topFourList.size();
// 合计 动态处理 异常情况、报警情况、预警情况 的表格
if (alarmDataProjectionList != null && alarmDataProjectionList.size() > 0) {
for (int j = 0; j < alarmDataProjectionList.size(); j++) {
AlarmData alarmDataProjection = alarmDataProjectionList.get(j);
Row dateRowJ = sheet.getRow(4 + size + j);
if (dateRowJ == null) {
dateRowJ = sheet.createRow(4 + size + j);
}
Cell cellJ = dateRowJ.createCell(cellst);
if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.ONE.getValue()) {
sheet.addMergedRegion(new CellRangeAddress(4 + size + j, 4 + size + j, cellst, cellst + 1)); // 合并表头 10的单元格 报警情况
cellJ.setCellValue("报警情况");
cellJ.setCellStyle(alarmBackgroundStyle);
} else if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.TWO.getValue()) {
sheet.addMergedRegion(new CellRangeAddress(4 + size + j, 4 + size + j, cellst, cellst + 1)); // 合并表头 11的单元格 预警情况
cellJ.setCellValue("预警情况");
cellJ.setCellStyle(warningBackgroundStyle);
} else if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.THREE.getValue()) {
sheet.addMergedRegion(new CellRangeAddress(4 + size + j, 4 + size + j, cellst, cellst + 1)); // 合并表头 9的单元格 异常波动情况
cellJ.setCellValue("异常波动情况");
cellJ.setCellStyle(abnormalBackgroundStyle);
}
}
}
// 表头二 统计类型、属性、时间段等
for (int cells = 0; cells < headArray.length; cells++) {
List<Object> objects = listMap.get(headArray[cells]);
Cell cell_3 = dateRow3.createCell(cellst + cells + 2); // 统计类型 表头
if ( "时间段".equals( headArray[cells] )) {
sheet.setColumnWidth(cellst + cells + 2, 20 * 256); // 时间段 加宽
}
cell_3.setCellValue(headArray[cells]);
cell_3.setCellStyle(borderStyle);
// 处理统计的数据
for (int row = 0; row < rowList.size(); row++) {
int topNum = topFourList.get(row);
// 合计:1,平均值:2,最大值:3,最小值:4
String headName = integerStringMap.get(topNum);
Row cellsDate = rowList.get(row);
Cell cell_Dat = cellsDate.createCell(cellst + cells + 2);
if ("平均值".equals(headName)) {
cell_Dat.setCellValue(toDateStr(objects.get(row), 1)); // 平均值
} else {
cell_Dat.setCellValue(toDateStr(objects.get(row), 0)); // 合计、最大值、最小值
}
cell_Dat.setCellStyle(borderStyle);
}
// 动态处理 异常情况、报警情况、预警情况
if (alarmDataProjectionList != null && alarmDataProjectionList.size() > 0) {
for (int j = 0; j < alarmDataProjectionList.size(); j++) {
AlarmData alarmDataProjection = alarmDataProjectionList.get(j);
Row dateRowJ = sheet.getRow(4 + size + j);
if (dateRowJ == null) {
dateRowJ = sheet.createRow(4 + size + j);
}
Cell cell_J = dateRowJ.createCell(cellst + cells + 2);
if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.ONE.getValue()) {
cell_J.setCellValue(toDateStr(objects.get(size + j), 0)); // 报警情况
cell_J.setCellStyle(alarmBackgroundStyle);
} else if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.TWO.getValue()) {
cell_J.setCellValue(toDateStr(objects.get(size + j), 0)); // 预警情况
cell_J.setCellStyle(warningBackgroundStyle);
} else if (alarmDataProjection.getRuleType() == AlarmRuleTypeEnum.THREE.getValue()) {
cell_J.setCellValue(toDateStr(objects.get(size + j), 0)); // 异常波动情况
cell_J.setCellStyle(abnormalBackgroundStyle);
}
}
}
}
int addNum = alarmDataProjectionList == null ? 0 : alarmDataProjectionList.size();
// 写入数据
int rowNum = 8 + size + addNum;
if (dataList == null || dataList.size() == 0) {
// 创建表头三
Row headerRow = sheet.getRow(7 + size + addNum);
if (headerRow == null) {
headerRow = sheet.createRow(7 + size + addNum);
}
Row row = sheet.getRow(rowNum);
if (row == null) {
row = sheet.createRow(rowNum);
}
for (int c = 0; c < identifyKey.length; c++) {
String headName = identifyKey[c];
Cell headerCell2 = headerRow.createCell(cellst + c);
String cellValue = mapHead.get(headName);
headerCell2.setCellValue(cellValue);
// 设置列宽度为默认值的两倍
if ("日期".equals(headName) || "设备".equals(headName)) {
sheet.setColumnWidth(cellst + c, 20 * 256);
}
}
} else {
for (Map<String, Object> data : dataList) {
// 创建表头三
Row headerRow = sheet.getRow(7 + size + addNum);
if (headerRow == null) {
headerRow = sheet.createRow(7 + size + addNum);
}
Row row = sheet.getRow(rowNum);
if (row == null) {
row = sheet.createRow(rowNum);
}
for (int c = 0; c < identifyKey.length; c++) {
String headName = identifyKey[c];
Cell headerCell2 = headerRow.createCell(cellst + c);
String cellValue = mapHead.get(headName);
headerCell2.setCellValue(cellValue);
row.createCell(cellst + c).setCellValue(data.get(headName) == null ? "0" : data.get(headName).toString());
// 设置列宽度为默认值的两倍
if ("日期".equals(headName) || "设备".equals(headName)) {
sheet.setColumnWidth(cellst + c, 20 * 256);
}
}
rowNum++;
}
}
}
// 写入到文件
try (FileOutputStream fileOut = new FileOutputStream("C:\\Users\\xu\\Desktop\\表格\\daily_data333333.xlsx")) {
workbook.write(fileOut);
} catch (IOException e) {
e.printStackTrace();
}
// 关闭工作簿
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
// 记录结束执行此方法的时间
long endExecutionTime = System.currentTimeMillis();
double executionTime = (endExecutionTime - startExecutionTime) / 1000.0;
System.out.println("================= 共执行了 " + executionTime +" 秒============");
}
// 处理统计和前端传值的对应 前端写死的
public static Map<Integer,String> toMap(){
Map<Integer,String> map = new HashMap<>();
map.put( 1, "合计");
map.put( 2, "平均值");
map.put( 3, "最大值");
map.put( 4, "最小值");
return map;
}
// 判断字符串是否是整数或浮点数
private static boolean isNumber(String str) {
if (str == null || str.isEmpty()) {
return false;
}
// 正则表达式匹配整数或浮点数
String numberRegex = "^-?\\d+(\\.\\d+)?$";
return Pattern.matches(numberRegex, str);
}
private static String toDateStr(Object dateStr, int type) {
if (dateStr instanceof Integer) {
if (dateStr == null || MIN_NUM == Integer.parseInt(dateStr.toString()) || MAX_NUM == Integer.parseInt(dateStr.toString()) || 0 == Integer.parseInt(dateStr.toString())) {
return "/";
}
} else if (dateStr instanceof Double) {
if (dateStr == null || dateStr == "" || 0 == Double.valueOf(dateStr.toString())) {
return "/";
}
} else {
if (dateStr == null || dateStr == "") {
return "/";
}
}
return String.valueOf(dateStr);
}
}