移除 统计分析导出Excel相关代码;

This commit is contained in:
yu 2025-01-22 16:08:23 +08:00
parent db9e6efc68
commit 35ce87cfb0
3 changed files with 0 additions and 892 deletions

View File

@ -1,55 +0,0 @@
package com.das.modules.page.controller;
import com.das.modules.page.domian.dto.TrendAnalyseDto;
import com.das.modules.page.domian.dto.TrendContrastDto;
import com.das.modules.page.service.StatisticalAnalysisService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RequestMapping("/api/page/statistical")
@RestController
public class StatisticalAnalysisController {
@Autowired
private StatisticalAnalysisService statisticalAnalysisService;
/**
* 趋势分析 (单机分析)Excel导出
* @param param 查询条件
*/
@PostMapping("/trendAnalyseExport")
public void trendAnalyseExport(@RequestBody List<TrendAnalyseDto> param ,HttpServletRequest request, HttpServletResponse response) {
statisticalAnalysisService.trendAnalyseExport(param, request, response);
}
/**
* 功率曲线Excel导出
* @param param 查询条件
*/
@PostMapping("/powerCurveExport")
public void powerCurveExport(@RequestBody TrendAnalyseDto param ,HttpServletRequest request, HttpServletResponse response) {
statisticalAnalysisService.powerCurveExport(param, request, response);
}
/**
* 趋势对比(多机对比) Excel导出
* @param param 查询条件
*/
@PostMapping("/trendContrastExport")
public void trendContrastExport(@RequestBody TrendContrastDto param , HttpServletRequest request, HttpServletResponse response) {
statisticalAnalysisService.trendContrastExport(param, request, response);
}
}

View File

@ -1,30 +0,0 @@
package com.das.modules.page.service;
import com.das.modules.page.domian.dto.TrendAnalyseDto;
import com.das.modules.page.domian.dto.TrendContrastDto;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
public interface StatisticalAnalysisService {
/**
* 趋势分析Excel导出
* @param param 查询条件
*/
void trendAnalyseExport(List<TrendAnalyseDto> param, HttpServletRequest request, HttpServletResponse response);
/**
* 功率曲线Excel导出
* @param param 查询条件
*/
void powerCurveExport(TrendAnalyseDto param, HttpServletRequest request, HttpServletResponse response);
/**
* 趋势对比Excel导出
* @param param 查询条件
*/
void trendContrastExport(TrendContrastDto param, HttpServletRequest request, HttpServletResponse response);
}

View File

@ -1,807 +0,0 @@
package com.das.modules.page.service.impl;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.das.common.constant.StatisticalAnalysisConstant;
import com.das.common.constant.StatisticalAnalysisFunctionConstant;
import com.das.common.exceptions.ServiceException;
import com.das.common.utils.BeanCopyUtils;
import com.das.modules.curve.domain.entity.CurveItemEntity;
import com.das.modules.curve.service.TheoreticalPowerCurveService;
import com.das.modules.data.domain.SnapshotValueQueryParam;
import com.das.modules.data.domain.TSValueQueryParam;
import com.das.modules.data.domain.WindowValueQueryParam;
import com.das.modules.data.service.DataService;
import com.das.modules.equipment.entity.SysIotModelField;
import com.das.modules.equipment.mapper.SysIotModelFieldMapper;
import com.das.modules.page.domian.dto.TrendAnalyseDto;
import com.das.modules.page.domian.dto.TrendContrastDto;
import com.das.modules.page.service.StatisticalAnalysisService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Slf4j
@Service
public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisService {
@Autowired
DataService dataService;
@Autowired
private TheoreticalPowerCurveService theoreticalPowerCurveService;
@Autowired
private SysIotModelFieldMapper sysIotModelFieldMapper;
private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
/**
* 趋势分析Excel导出
*
* @param param 查询条件
*/
@Override
public void trendAnalyseExport(List<TrendAnalyseDto> param, HttpServletRequest request, HttpServletResponse response) {
//根据条件获取历史数据
List<Map<String, Map<String, Map<String, Object>>>> mapsList = new ArrayList<>();
for (TrendAnalyseDto trendAnalyseDto : param) {
//瞬时值
if (trendAnalyseDto.getCalFunction().equals(StatisticalAnalysisFunctionConstant.INTERPOLATION)){
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
BeanCopyUtils.copy(trendAnalyseDto,tsValueQueryParam);
Map<String, Map<String, Map<String, Object>>> resultMap = dataService.queryTimeSeriesValues(tsValueQueryParam);
mapsList.add(resultMap);
}else {
//其他
WindowValueQueryParam windowValueQueryParam = new WindowValueQueryParam();
BeanCopyUtils.copy(trendAnalyseDto,windowValueQueryParam);
Map<String, Map<String, Map<String, Object>>> stringMapMap = dataService.queryWindowsValues(windowValueQueryParam);
mapsList.add(stringMapMap);
}
}
//获取Excel的列
LinkedHashMap<String, String> map = getTrendColumnName(param);
List<Map<String, Object>> dataList = new ArrayList<>();
// 遍历数据填充Excel数据集
setTrendAnalyseExcelValue(mapsList, dataList);
ExcelWriter writer = ExcelUtil.getWriter(RandomUtil.randomInt(100, 1000) + "statistics" + ".xlsx");
//设置Excel样式
setExcelStyle(writer, map, dataList);
//下载Excel
downloadExcel(response, writer,StatisticalAnalysisConstant.TREND_ANALYSE);
}
/**
* 功率曲线Excel导出
*
* @param param 查询条件
*/
@Override
public void powerCurveExport(TrendAnalyseDto param, HttpServletRequest request, HttpServletResponse response) {
//获取理论数据
List<CurveItemEntity> curveItemEntitieList = theoreticalPowerCurveService.
queryCurveItemByParent(param.getMadeinfactory(), param.getModel());
//根据条件获取历史数据
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
BeanCopyUtils.copy(param,tsValueQueryParam);
Map<String, Map<String, Map<String, Object>>> resultMap = dataService.queryTimeSeriesValues(tsValueQueryParam);
//显示曲线,需要计算功率的平均值
if (param.getDisplayCurve()==1){
try {
List<Double> windSpeedList = new ArrayList<>();
List<Double> powerList = new ArrayList<>();
getPowerCurveValueList(resultMap, powerList, windSpeedList);
List<Map<String, List<Double>>> maps = calculateAverages(windSpeedList, powerList);
setPowerCurveValueList(resultMap, maps);
} catch (Exception e) {
log.error("计算功率曲线平均值失败:"+e.getMessage());
}
}
List<Map<String, Object>> dataList = new ArrayList<>();
//填充功率曲线,Excel的数据集
setPowerCurveExcelValue(resultMap, dataList, curveItemEntitieList);
//获取功率曲线的列
LinkedHashMap<String, String> map = getPowerCurveColumnName(param);
ExcelWriter writer = ExcelUtil.getWriter(RandomUtil.randomInt(100, 1000) + "statistics" + ".xlsx");
//设置Excel样式
setExcelStyle(writer, map, dataList);
//下载Excel
downloadExcel(response, writer,StatisticalAnalysisConstant.POWER_CURVE);
}
/**
* 趋势对比Excel导出
* @param param 查询条件
* @return TD数据库数据
*/
@Override
public void trendContrastExport(TrendContrastDto param, HttpServletRequest request, HttpServletResponse response) {
Map<String, Map<String, Map<String, Object>>> maps = null;
//瞬时值,历史区间数据查询
if (param.getCalFunction().equals(StatisticalAnalysisFunctionConstant.INTERPOLATION)){
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
BeanCopyUtils.copy(param,tsValueQueryParam);
maps = dataService.queryTimeSeriesValues(tsValueQueryParam);
}else {
WindowValueQueryParam windowparam = new WindowValueQueryParam();
BeanCopyUtils.copy(param,windowparam);
maps = dataService.queryWindowsValues(windowparam);
}
//自定义别名 别名的key和实体类中的名称要对应上
LinkedHashMap<String, String> map = gettrendContrastColumnName(param);
List<Map<String, Object>> dataList = new ArrayList<>();
// 遍历数据将数据添加到dataList中
setTrendContrastExcelValue(maps, dataList);
ExcelWriter writer = ExcelUtil.getWriter(RandomUtil.randomInt(100, 1000) + "statistics" + ".xlsx");
//设置Excel样式
setExcelStyle(writer, map, dataList);
//下载Excel
downloadExcel(response, writer,StatisticalAnalysisConstant.TREND_CONTRAST);
}
/**
* 设置Excel样式
*
* @param writer ExcelWriter
* @param map 表格的列
* @param dataList Excel数据集
*/
private void setExcelStyle(ExcelWriter writer, LinkedHashMap<String, String> map, List<Map<String, Object>> dataList) {
//自定义别名 别名的key和实体类中的名称要对应上
writer.setHeaderAlias(map);
//水平居中对齐垂直中间对齐
writer.getStyleSet().setAlign(HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
//所有单元格宽25个字符
writer.setColumnWidth(-1, 25);
// 一次性写出内容使用默认样式强制输出标题
writer.write(dataList, true);
}
/**
* 趋势分析-遍历数据填充Excel和图表数据集
* @param mapsList 测点历史数据
* @param dataList Excel数据集
*/
private void setTrendAnalyseExcelValue(List<Map<String, Map<String, Map<String, Object>>>> mapsList,
List<Map<String, Object>> dataList) {
for (int i = 0; i < mapsList.size(); i++) {
List<String> timesListstr = new ArrayList<>();
List<Double> valuesList = new ArrayList<>();
int num = i + 1;
String pointName = null;
Map<String, Map<String, Map<String, Object>>> stringMapMap = mapsList.get(i);
for (Map.Entry<String, Map<String, Map<String, Object>>> stringMapEntry : stringMapMap.entrySet()) {
for (Map.Entry<String, Map<String, Object>> mapEntry : stringMapEntry.getValue().entrySet()) {
pointName = mapEntry.getKey();
for (Map.Entry<String, Object> stringObjectEntry : mapEntry.getValue().entrySet()) {
String key1 = stringObjectEntry.getKey();
if (key1.equals("times")) {
List<Long> times = (List<Long>) stringObjectEntry.getValue();
List<String> liststr = times.stream()
.map(timestamp -> new Date(timestamp))
.map(date -> sdf.format(date))
.toList();
timesListstr.addAll(liststr);
}
if (key1.equals("values")) {
List<Double> values = (List<Double>) stringObjectEntry.getValue();
valuesList.addAll(values);
}
}
}
}
String pointNameKey = pointName + num;
String timeKey = "time" + num;
if (i == 0) {
for (int j = 0; j < timesListstr.size(); j++) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put(timeKey, timesListstr.get(j));
dataMap.put(pointNameKey, valuesList.get(j));
dataList.add(dataMap);
}
} else {
if (dataList.size()< timesListstr.size()){
for (int j = dataList.size(); j < timesListstr.size(); j++) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put(timeKey, timesListstr.get(j));
dataMap.put(pointNameKey, valuesList.get(j));
dataList.add(dataMap);
}
}
for (int j = 0; j < timesListstr.size(); j++) {
Map<String, Object> stringObjectMap = dataList.get(j);
stringObjectMap.put(timeKey, timesListstr.get(j));
stringObjectMap.put(pointNameKey, valuesList.get(j));
}
}
}
}
/**
* 趋势对比填充Excel数据集
*
* @param dataList Excel数据集
* @param maps 测点数据
*/
private void setTrendContrastExcelValue(Map<String, Map<String, Map<String, Object>>> maps,
List<Map<String, Object>> dataList) {
Map<String,Integer> mapKey = new HashMap<>();
int num =1;
int flagNum = 0;
for (Map.Entry<String, Map<String, Map<String, Object>>> stringMapEntry : maps.entrySet()) {
for (Map.Entry<String, Map<String, Object>> mapEntry : stringMapEntry.getValue().entrySet()) {
List<String> timesListstr = new ArrayList<>();
List<Double> valuesList = new ArrayList<>();
String key = mapEntry.getKey();
if (mapKey.containsKey(key)){
num++;
String str = key + num;
mapKey.put(str, num );
key=str;
}else {
mapKey.put(key, num);
}
for (Map.Entry<String, Object> stringObjectEntry : mapEntry.getValue().entrySet()) {
String key1 = stringObjectEntry.getKey();
if (key1.equals("times")) {
List<Long> times = (List<Long>) stringObjectEntry.getValue();
List<String> liststr = times.stream()
.map(timestamp -> new Date(timestamp))
.map(date -> sdf.format(date))
.toList();
timesListstr.addAll(liststr);
}
if (key1.equals("values")) {
List<Double> values = (List<Double>) stringObjectEntry.getValue();
valuesList.addAll(values);
}
}
if (flagNum == 0) {
for (int j = 0; j < timesListstr.size(); j++) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("time", timesListstr.get(j));
dataMap.put(key, valuesList.get(j));
dataList.add(dataMap);
}
} else {
for (int j = 0; j < timesListstr.size(); j++) {
Map<String, Object> stringObjectMap = dataList.get(j);
stringObjectMap.put(key, valuesList.get(j));
}
}
flagNum++;
}
}
}
/**
* 趋势-获取表格的列
* @param param 查询条件
* @return 表格的列
*/
private LinkedHashMap<String, String> getTrendColumnName(List<TrendAnalyseDto> param) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
for (int i = 0; i < param.size(); i++) {
TrendAnalyseDto trendAnalyseDto = param.get(i);
String timeName = trendAnalyseDto.getTimeName();
int num = i + 1;
map.put("time" + num, "时间" + num);
for (SnapshotValueQueryParam device : trendAnalyseDto.getDevices()) {
//获取属性名称
for (String attribute : device.getAttributes()) {
map.put(attribute + num, timeName);
}
}
}
return map;
}
/**
* 趋势对比-获取表格的列
*
* @param param 查询条件
* @return 表格的列
*/
private LinkedHashMap<String, String> gettrendContrastColumnName(TrendContrastDto param) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("time", "时间");
List<String> strList = new ArrayList<>();
for (SnapshotValueQueryParam device : param.getDevices()) {
strList.addAll(device.getAttributes());
}
int num =1;
for (String code : strList) {
QueryWrapper<SysIotModelField> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("attribute_code", code);
List<SysIotModelField> sysIotModelFields = sysIotModelFieldMapper.selectVoList(queryWrapper);
for (SysIotModelField sysIotModelField : sysIotModelFields) {
if (map.containsKey(sysIotModelField.getAttributeCode())){
num++;
map.put(sysIotModelField.getAttributeCode()+num, sysIotModelField.getAttributeName()+num );
}else {
map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getAttributeName());
}
}
}
return map;
}
/**
* 获取功率曲线的列
* @return Excel的列
*/
private LinkedHashMap<String, String> getPowerCurveColumnName(TrendAnalyseDto param) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("time", "时间");
if (param.getWindSource().equals("原始风速")){
map.put("AvgWindSpeed_10min", "原始风速");
}else {
map.put("AvgWindSpeedCal_10min", "处理后风速");
}
map.put("AvgActivePower_10min", "功率");
map.put("theoryIWindSpeed", "理论风速");
map.put("theoryIGenPower", "理论功率");
return map;
}
/**
* 功率曲线-遍历数据填充Excel数据集
*
* @param maps 测点历史数据
* @param dataList Excel数据集
* @param curveItemEntitieList 理论数据
*/
private void setPowerCurveExcelValue(Map<String, Map<String, Map<String, Object>>> maps,
List<Map<String, Object>> dataList, List<CurveItemEntity> curveItemEntitieList) {
for (Map.Entry<String, Map<String, Map<String, Object>>> stringMapEntry : maps.entrySet()) {
int flagNum = 0;
for (Map.Entry<String, Map<String, Object>> mapEntry : stringMapEntry.getValue().entrySet()) {
List<String> timesListstr = new ArrayList<>();
List<Double> valuesList = new ArrayList<>();
String key = mapEntry.getKey();
for (Map.Entry<String, Object> stringObjectEntry : mapEntry.getValue().entrySet()) {
String key1 = stringObjectEntry.getKey();
if (key1.equals("times")) {
List<Long> times = (List<Long>) stringObjectEntry.getValue();
List<String> liststr = times.stream()
.map(timestamp -> new Date(timestamp))
.map(date -> sdf.format(date))
.toList();
timesListstr.addAll(liststr);
}
if (key1.equals("values")) {
List<Double> values = (List<Double>) stringObjectEntry.getValue();
valuesList.addAll(values);
}
}
if (flagNum == 0) {
for (int j = 0; j < timesListstr.size(); j++) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("time", timesListstr.get(j));
dataMap.put(key, valuesList.get(j));
dataList.add(dataMap);
}
} else {
for (int j = 0; j < timesListstr.size(); j++) {
Map<String, Object> stringObjectMap = dataList.get(j);
stringObjectMap.put(key, valuesList.get(j));
}
}
flagNum++;
}
}
//转换为map
List<Map<String, Object>> listMap = curveItemEntitieList.stream()
.map(entity -> {
Map<String, Object> map = new HashMap<>();
map.put("theoryIWindSpeed", entity.getPower());
map.put("theoryIGenPower", entity.getSpeed());
return map;
})
.collect(Collectors.toList());
if (listMap.size() > dataList.size()) {
for (int i = 0; i < listMap.size(); i++) {
Map<String, Object> stringObjectMap1 = listMap.get(i);
if (dataList.size() > i) {
Map<String, Object> stringObjectMap = dataList.get(i);
stringObjectMap.put("theoryIWindSpeed", stringObjectMap1.get("theoryIWindSpeed"));
stringObjectMap.put("theoryIGenPower", stringObjectMap1.get("theoryIGenPower"));
}else {
HashMap<String, Object> theoryMaps = new HashMap<>();
theoryMaps.put("theoryIWindSpeed", stringObjectMap1.get("theoryIWindSpeed"));
theoryMaps.put("theoryIGenPower", stringObjectMap1.get("theoryIGenPower"));
dataList.add(theoryMaps);
}
}
} else {
for (int i = 0; i < dataList.size(); i++) {
Map<String, Object> dataMap = dataList.get(i);
if (listMap.size() > i) {
Map<String, Object> stringObjectMap1 = listMap.get(i);
dataMap.put("theoryIWindSpeed", stringObjectMap1.get("theoryIWindSpeed"));
dataMap.put("theoryIGenPower", stringObjectMap1.get("theoryIGenPower"));
}
}
}
}
/**
* 下载Excel
*
* @param response 响应对象
* @param writer Excel对象
* @param title 标题
*/
private void downloadExcel(HttpServletResponse response, ExcelWriter writer,String title) {
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType("application/vnd.ms-excel");
// 清除缓存
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
try {
// 设置请求头属性
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(title+"-"+System.currentTimeMillis()+".xls", StandardCharsets.UTF_8));
ServletOutputStream out = response.getOutputStream();
// 写出到文件
writer.flush(out, true);
// 关闭writer释放内存
writer.close();
// 此处记得关闭输出Servlet流
IoUtil.close(out);
} catch (Exception e) {
throw new ServiceException("文件下载失败==" + e);
}
}
/**
* 获取图表类别集
* @param map Excel的列
* @return 图表类别集
*/
private List<String> getCharKey(LinkedHashMap<String, String> map) {
//获取图表类别集
List<String> chartKey = new ArrayList<>();
for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
String value = stringStringEntry.getValue();
if (!value.contains("时间")){
chartKey.add(value);
}
}
return chartKey;
}
/**
* 生成折线图,并插入到Excel中
* @param writer Sheet对象
* @param data 测点数据集合
* @param titleText 标题
* @param chartKey 类别数据集
*/
private static void addChartToExcel(ExcelWriter writer, List<Map<String, Object>> data,
String titleText,List<String> chartKey) {
try {
if (CollectionUtils.isEmpty(data)){
return;
}
// 获取Sheet对象
XSSFSheet sheet = (XSSFSheet) writer.getSheet();
// 创建绘图区域
XSSFDrawing drawing = sheet.createDrawingPatriarch();
int columnCount = sheet.getRow(0).getPhysicalNumberOfCells() + 1;
//图表位置,插入到最后一列+1
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, columnCount, 0, 15, 15);
// 创建图表
XSSFChart xssfChart = drawing.createChart(anchor);
// 设置图表标题
xssfChart.setTitleText(titleText);
// 创建数据系列
XDDFChartLegend legend = xssfChart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
XDDFCategoryAxis bottomAxis = xssfChart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = xssfChart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
XDDFLineChartData chartData = (XDDFLineChartData) xssfChart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
// 遍历每个系列并添加数据
setChartData(data, titleText, chartKey, chartData, sheet);
xssfChart.plot(chartData);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 生成散点图,并插入到 Excel
* @param writer Sheet 对象
* @param data 测点数据集合
* @param titleText 标题
* @param chartKey 类别数据集
*/
private static void addScattersChartToExcel(ExcelWriter writer, List<Map<String, Object>> data,
String titleText, List<String> chartKey) {
try {
if (CollectionUtils.isEmpty(data)) {
return;
}
// 获取 Sheet 对象
XSSFSheet sheet = (XSSFSheet) writer.getSheet();
// 创建绘图区域
XSSFDrawing drawing = sheet.createDrawingPatriarch();
int columnCount = sheet.getRow(0).getPhysicalNumberOfCells() + 1;
// 图表位置,插入到最后一列+1
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, columnCount, 0, 15, 15);
// 创建图表
XSSFChart xssfChart = drawing.createChart(anchor);
// 设置图表标题
xssfChart.setTitleText(titleText);
// 创建数据系列
XDDFChartLegend legend = xssfChart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
XDDFValueAxis bottomAxis = xssfChart.createValueAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = xssfChart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
// 创建散点图数据
XDDFScatterChartData chartData = (XDDFScatterChartData) xssfChart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
// 遍历每个系列并添加数据
setChartDataForScatter(data, titleText, chartKey, chartData, sheet);
// 确保散点图数据点之间不连线
for (XDDFChartData.Series series : chartData.getSeries()) {
if (series instanceof XDDFScatterChartData.Series) {
XDDFScatterChartData.Series scatterSeries = (XDDFScatterChartData.Series) series;
scatterSeries.setSmooth(false);
scatterSeries.setMarkerStyle(MarkerStyle.CIRCLE);
}
}
xssfChart.plot(chartData);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 为散点图设置数据系列
* @param data 测点数据集合
* @param titleText 标题
* @param chartKey 类别数据集
* @param chartData 散点图数据对象
* @param sheet Excel Sheet 对象
*/
private static void setChartDataForScatter(List<Map<String, Object>> data, String titleText, List<String> chartKey,
XDDFScatterChartData chartData, XSSFSheet sheet) {
for (String key : chartKey) {
XDDFDataSource<Double> xAxisData = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
new CellRangeAddress(1, data.size(), 0, 0));
XDDFNumericalDataSource<Double> yAxisData = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
new CellRangeAddress(1, data.size(), chartKey.indexOf(key) + 1, chartKey.indexOf(key) + 1));
XDDFScatterChartData.Series series = (XDDFScatterChartData.Series) chartData.addSeries(xAxisData, yAxisData);
series.setTitle(key, null);
}
}
/**
* 给每个类别,添加数据
* @param data 测点数据
* @param titleText 标题
* @param chartKey 类别key
* @param chartData 图表数据
* @param sheet sheet对象
*/
private static void setChartData(List<Map<String, Object>> data, String titleText, List<String> chartKey, XDDFLineChartData chartData, XSSFSheet sheet) {
if (titleText.equals(StatisticalAnalysisConstant.TREND_ANALYSE)) {
int strStartRow = 0;
int strEndCol = 0;
int numStartRow = 1;
int numEndCol = 1;
for (int i = 0; i < chartKey.size(); i++) {
XDDFLineChartData.Series series = (XDDFLineChartData.Series) chartData.addSeries(
createStringDataReference(sheet, 1, data.size(), strStartRow, strEndCol), // 类别X轴
createNumericDataReference(sheet, 1, data.size(), numStartRow, numEndCol) // Y轴
);
series.setTitle(chartKey.get(i), null);
strStartRow += 2;
strEndCol += 2;
numStartRow += 2;
numEndCol += 2;
}
} else {
for (int i = 0; i < chartKey.size(); i++) {
XDDFLineChartData.Series series = (XDDFLineChartData.Series) chartData.addSeries(
createStringDataReference(sheet, 1, data.size(), 0, 0), // 类别X轴
createNumericDataReference(sheet, 1, data.size(), i + 1, i + 1) // Y轴
);
series.setTitle(chartKey.get(i), null);
}
}
}
/**
* 创建字符串数据引用
* @return XDDFDataSource<String>
*/
private static XDDFDataSource<String> createStringDataReference(XSSFSheet sheet, int startRow, int endRow, int startCol, int endCol) {
CellRangeAddress ref = new CellRangeAddress(startRow, endRow, startCol, endCol);
return XDDFDataSourcesFactory.fromStringCellRange(sheet, ref);
}
/**
* 创建值数据引用
* @return XDDFNumericalDataSource<Double>
*/
private static XDDFNumericalDataSource<Double> createNumericDataReference(XSSFSheet sheet, int startRow, int endRow, int startCol, int endCol) {
CellRangeAddress ref = new CellRangeAddress(startRow, endRow, startCol, endCol);
return XDDFDataSourcesFactory.fromNumericCellRange(sheet, ref);
}
/**
* 计算平均功率
*/
public static List<Map<String,List<Double>>> calculateAverages(List<Double> windSpeeds, List<Double> powers) {
// 找出最大的风速
double maxWindSpeed = Double.MIN_VALUE;
for (double windSpeed : windSpeeds) {
if (windSpeed > maxWindSpeed) {
maxWindSpeed = windSpeed;
}
}
double interval = 0.5;
List<Map<String,List<Double>>> result = new ArrayList<>();
Map<String,List<Double>> dataMap = new HashMap<>();
List<Double> windSpeedList = new ArrayList<>();
List<Double> powerList = new ArrayList<>();
// 0 开始 interval 为步长遍历风速
for (double windSpeed = 0; windSpeed <= maxWindSpeed; windSpeed += interval) {
double sumPower = 0;
int count = 0;
// 遍历输入列表计算满足风速范围的功率总和和计数
for (int i = 0; i < windSpeeds.size(); i++) {
double currentWindSpeed = windSpeeds.get(i);
double currentPower = powers.get(i);
if (currentWindSpeed >= windSpeed && currentWindSpeed < windSpeed + interval) {
sumPower += currentPower;
count++;
}
}
// 如果计数大于 0计算平均值并添加到结果列表
if (count > 0) {
double averagePower = sumPower / count;
windSpeedList.add(windSpeed + interval);
powerList.add(averagePower);
}
}
dataMap.put("windSpeed", windSpeedList);
dataMap.put("power", powerList);
result.add(dataMap);
return result;
}
/**
* 根据size删除List<String> value1的值
*/
@NotNull
private static List<String> delTimes(Map.Entry<String, Object> stringObjectEntry, List<Map<String, List<Double>>> maps) {
int powerSize = maps.get(0).get("power").size();
List<String> value1 = (List<String>) stringObjectEntry.getValue();
List<String> collect = IntStream.range(0, value1.size())
.filter(i -> i < powerSize)
.mapToObj(value1::get)
.collect(Collectors.toList());
return collect;
}
private static void getPowerCurveValueList(Map<String, Map<String, Map<String, Object>>> resultMap,
List<Double> powerList, List<Double> windSpeedList) {
for (Map.Entry<String, Map<String, Map<String, Object>>> stringMapEntry : resultMap.entrySet()) {
for (Map.Entry<String, Map<String, Object>> mapEntry : stringMapEntry.getValue().entrySet()) {
String key = mapEntry.getKey();
Map<String, Object> value = mapEntry.getValue();
//功率
if (key.equals("AvgActivePower_10min")) {
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
if (stringObjectEntry.getKey().equals("values")) {
List<Float> values = (List<Float>) stringObjectEntry.getValue();
List<Double> doubleList = values.stream()
.map(Float::doubleValue)
.collect(Collectors.toList());
powerList.addAll(doubleList);
}
}
}
if (key.equals("AvgWindSpeed_10min") || key.equals("AvgWindSpeedCal_10min")){
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
if (stringObjectEntry.getKey().equals("values")){
List<Float> values = (List<Float>) stringObjectEntry.getValue();
List<Double> doubleList = values.stream()
.map(Float::doubleValue)
.collect(Collectors.toList());
windSpeedList.addAll(doubleList);
}
}
}
}
}
}
private static void setPowerCurveValueList(Map<String, Map<String, Map<String, Object>>> resultMap,
List<Map<String, List<Double>>> maps) {
if (CollectionUtils.isEmpty(maps)){
return;
}
for (Map.Entry<String, Map<String, Map<String, Object>>> stringMapEntry : resultMap.entrySet()) {
for (Map.Entry<String, Map<String, Object>> mapEntry : stringMapEntry.getValue().entrySet()) {
String key = mapEntry.getKey();
Map<String, Object> value = mapEntry.getValue();
//功率
if (key.equals("AvgActivePower_10min")) {
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
if (stringObjectEntry.getKey().equals("values")) {
stringObjectEntry.setValue(maps.get(0).get("power"));
}
if (stringObjectEntry.getKey().equals("times")){
List<String> collect = delTimes(stringObjectEntry, maps);
stringObjectEntry.setValue(collect);
}
}
}
if (key.equals("AvgWindSpeed_10min") || key.equals("AvgWindSpeedCal_10min")){
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
if (stringObjectEntry.getKey().equals("values")){
stringObjectEntry.setValue(maps.get(0).get("windSpeed"));
}
if (stringObjectEntry.getKey().equals("times")){
List<String> collect = delTimes(stringObjectEntry, maps);
stringObjectEntry.setValue(collect);
}
}
}
}
}
}
}