mirror of
https://github.com/dataease/dataease.git
synced 2026-06-13 09:04:38 +08:00
fix(图表): 修复明细表开启总计导出excel时,总计没有导出。 #18114
This commit is contained in:
@@ -154,6 +154,10 @@ public class DefaultChartHandler extends AbstractChartPlugin {
|
||||
if (view.getIsExcelExport()) {
|
||||
Map<String, Object> sourceInfo = ChartDataBuild.transTableNormal(xAxis, yAxis, view, calcResult.getOriginData(), extStack, desensitizationList);
|
||||
sourceInfo.put("sourceData", calcResult.getOriginData());
|
||||
// 将汇总计算结果传递到导出数据中
|
||||
if (calcResult.getData() != null && calcResult.getData().get("customSumResult") != null) {
|
||||
sourceInfo.put("customSumResult", calcResult.getData().get("customSumResult"));
|
||||
}
|
||||
view.setData(sourceInfo);
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -264,13 +264,38 @@ public class ChartDataServer implements ChartDataApi {
|
||||
List<Object[]> details = new ArrayList<>();
|
||||
Sheet detailsSheet;
|
||||
Integer sheetIndex = 1;
|
||||
|
||||
boolean summaryEnabled = !"dataset".equals(request.getDownloadType()) && isSummaryEnabled(request.getViewInfo());
|
||||
SummaryConfig summaryConfig = null;
|
||||
SummaryAccumulator summaryAcc = null;
|
||||
List<ChartViewFieldDTO> allExportColumns = null;
|
||||
Map<String, BigDecimal> customSumResult = null;
|
||||
if (summaryEnabled) {
|
||||
summaryConfig = parseSummaryConfig(request.getViewInfo());
|
||||
summaryAcc = new SummaryAccumulator();
|
||||
allExportColumns = getAllExportColumns(request.getViewInfo());
|
||||
}
|
||||
|
||||
request.getViewInfo().getChartExtRequest().setPageSize(Long.valueOf(extractPageSize));
|
||||
ChartViewDTO chartViewDTO = findExcelData(request);
|
||||
for (long i = 1; i < chartViewDTO.getTotalPage() + 1; i++) {
|
||||
request.getViewInfo().getChartExtRequest().setGoPage(i);
|
||||
findExcelData(request);
|
||||
ChartViewDTO pageDto = findExcelData(request);
|
||||
details.addAll(request.getDetails());
|
||||
|
||||
if (summaryEnabled) {
|
||||
accumulatePageStats(summaryAcc, request.getDetails(), allExportColumns, summaryConfig);
|
||||
if (i == chartViewDTO.getTotalPage() && pageDto.getData() != null && pageDto.getData().get("customSumResult") != null) {
|
||||
customSumResult = (Map<String, BigDecimal>) pageDto.getData().get("customSumResult");
|
||||
}
|
||||
}
|
||||
|
||||
if ((details.size() + extractPageSize) > sheetLimit || i == chartViewDTO.getTotalPage()) {
|
||||
if (i == chartViewDTO.getTotalPage() && summaryEnabled && summaryAcc.totalCount > 0) {
|
||||
Object[] totalRow = buildSummaryRow(allExportColumns, summaryConfig, summaryAcc, customSumResult);
|
||||
details.add(totalRow);
|
||||
}
|
||||
|
||||
detailsSheet = wb.createSheet("数据" + sheetIndex);
|
||||
Integer[] excelTypes = request.getExcelTypes();
|
||||
List<ChartViewFieldDTO> xAxis = new ArrayList<>();
|
||||
@@ -865,5 +890,182 @@ public class ChartDataServer implements ChartDataApi {
|
||||
public void exportScreenViewLog(Long id) {
|
||||
}
|
||||
|
||||
public static boolean isSummaryEnabled(ChartViewDTO viewInfo) {
|
||||
if (viewInfo == null || viewInfo.getCustomAttr() == null) return false;
|
||||
String type = viewInfo.getType();
|
||||
if (!StringUtils.equalsAnyIgnoreCase(type, "table-info", "table-normal")) return false;
|
||||
Map<String, Object> basicStyle = (Map<String, Object>) viewInfo.getCustomAttr().get("basicStyle");
|
||||
if (basicStyle == null) return false;
|
||||
return basicStyle.get("showSummary") != null && (Boolean) basicStyle.get("showSummary");
|
||||
}
|
||||
|
||||
public static SummaryConfig parseSummaryConfig(ChartViewDTO viewInfo) {
|
||||
SummaryConfig config = new SummaryConfig();
|
||||
Map<String, Object> basicStyle = (Map<String, Object>) viewInfo.getCustomAttr().get("basicStyle");
|
||||
config.summaryLabel = (basicStyle.get("summaryLabel") != null && StringUtils.isNotBlank(basicStyle.get("summaryLabel").toString()))
|
||||
? basicStyle.get("summaryLabel").toString()
|
||||
: (Lang.isChinese() ? "总计" : "Total");
|
||||
|
||||
List<Map<String, Object>> seriesSummary = basicStyle.get("seriesSummary") != null
|
||||
? (List<Map<String, Object>>) basicStyle.get("seriesSummary") : null;
|
||||
|
||||
List<ChartViewFieldDTO> summaryFields;
|
||||
if (viewInfo.getType().equalsIgnoreCase("table-info")) {
|
||||
summaryFields = viewInfo.getXAxis();
|
||||
} else {
|
||||
summaryFields = new ArrayList<>();
|
||||
summaryFields.addAll(viewInfo.getXAxis());
|
||||
summaryFields.addAll(viewInfo.getYAxis());
|
||||
}
|
||||
|
||||
for (ChartViewFieldDTO field : summaryFields) {
|
||||
String fName = field.getDataeaseName();
|
||||
String sType = "sum";
|
||||
boolean sShow = true;
|
||||
if (seriesSummary != null) {
|
||||
for (Map<String, Object> s : seriesSummary) {
|
||||
if (fName.equals(s.get("field"))) {
|
||||
sType = s.get("summary") == null ? "sum" : s.get("summary").toString();
|
||||
sShow = s.get("show") == null || (Boolean) s.get("show");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
config.summaryTypeMap.put(fName, sType);
|
||||
config.summaryShowMap.put(fName, sShow);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
public static void accumulatePageStats(SummaryAccumulator acc, List<Object[]> pageDetails,
|
||||
List<ChartViewFieldDTO> allColumns, SummaryConfig config) {
|
||||
if (pageDetails == null) return;
|
||||
for (Object[] row : pageDetails) {
|
||||
acc.totalCount++;
|
||||
for (int j = 0; j < allColumns.size() && j < row.length; j++) {
|
||||
ChartViewFieldDTO field = allColumns.get(j);
|
||||
String fName = field.getDataeaseName();
|
||||
if (!config.summaryShowMap.containsKey(fName) || !config.summaryShowMap.get(fName)) continue;
|
||||
String sType = config.summaryTypeMap.get(fName);
|
||||
if (sType == null || "custom".equals(sType)) continue;
|
||||
Object valObj = row[j];
|
||||
if (valObj == null || StringUtils.isBlank(valObj.toString())) continue;
|
||||
try {
|
||||
BigDecimal val = new BigDecimal(valObj.toString());
|
||||
switch (sType) {
|
||||
case "max":
|
||||
BigDecimal curMax = acc.maxMap.get(fName);
|
||||
if (curMax == null || val.compareTo(curMax) > 0) acc.maxMap.put(fName, val);
|
||||
break;
|
||||
case "min":
|
||||
BigDecimal curMin = acc.minMap.get(fName);
|
||||
if (curMin == null || val.compareTo(curMin) < 0) acc.minMap.put(fName, val);
|
||||
break;
|
||||
default:
|
||||
acc.sumMap.merge(fName, val, BigDecimal::add);
|
||||
acc.countMap.merge(fName, 1L, Long::sum);
|
||||
if ("var_pop".equals(sType) || "stddev_pop".equals(sType)) {
|
||||
acc.sumOfSquaresMap.merge(fName, val.multiply(val), BigDecimal::add);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object[] buildSummaryRow(List<ChartViewFieldDTO> allColumns, SummaryConfig config,
|
||||
SummaryAccumulator acc, Map<String, BigDecimal> customSumResult) {
|
||||
Object[] totalRow = new Object[allColumns.size()];
|
||||
boolean labelSet = false;
|
||||
for (int j = 0; j < allColumns.size(); j++) {
|
||||
ChartViewFieldDTO field = allColumns.get(j);
|
||||
String fName = field.getDataeaseName();
|
||||
if (config.summaryShowMap.containsKey(fName) && config.summaryShowMap.get(fName)) {
|
||||
String sType = config.summaryTypeMap.get(fName);
|
||||
switch (sType) {
|
||||
case "custom":
|
||||
totalRow[j] = customSumResult != null && customSumResult.get(fName) != null
|
||||
? customSumResult.get(fName).toPlainString() : null;
|
||||
break;
|
||||
case "max":
|
||||
totalRow[j] = acc.maxMap.get(fName) != null ? acc.maxMap.get(fName).toPlainString() : null;
|
||||
break;
|
||||
case "min":
|
||||
totalRow[j] = acc.minMap.get(fName) != null ? acc.minMap.get(fName).toPlainString() : null;
|
||||
break;
|
||||
case "avg":
|
||||
BigDecimal sum = acc.sumMap.get(fName);
|
||||
Long cnt = acc.countMap.get(fName);
|
||||
if (sum != null && cnt != null && cnt > 0) {
|
||||
totalRow[j] = sum.divide(BigDecimal.valueOf(cnt), 8, java.math.RoundingMode.HALF_UP).toPlainString();
|
||||
}
|
||||
break;
|
||||
case "sum":
|
||||
totalRow[j] = acc.sumMap.get(fName) != null ? acc.sumMap.get(fName).toPlainString() : null;
|
||||
break;
|
||||
case "var_pop":
|
||||
totalRow[j] = calcVariance(acc, fName, false);
|
||||
break;
|
||||
case "stddev_pop":
|
||||
totalRow[j] = calcVariance(acc, fName, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (!labelSet) {
|
||||
totalRow[j] = config.summaryLabel;
|
||||
labelSet = true;
|
||||
}
|
||||
}
|
||||
if (!labelSet && totalRow.length > 0) {
|
||||
totalRow[0] = config.summaryLabel;
|
||||
}
|
||||
return totalRow;
|
||||
}
|
||||
|
||||
private static String calcVariance(SummaryAccumulator acc, String fName, boolean isSqrt) {
|
||||
Long cnt = acc.countMap.get(fName);
|
||||
BigDecimal sum = acc.sumMap.get(fName);
|
||||
BigDecimal sumSq = acc.sumOfSquaresMap.get(fName);
|
||||
if (cnt == null || cnt < 2 || sum == null || sumSq == null) return null;
|
||||
BigDecimal mean = sum.divide(BigDecimal.valueOf(cnt), 16, java.math.RoundingMode.HALF_UP);
|
||||
BigDecimal variance = sumSq.divide(BigDecimal.valueOf(cnt), 16, java.math.RoundingMode.HALF_UP)
|
||||
.subtract(mean.multiply(mean));
|
||||
BigDecimal sampleVariance = variance.multiply(BigDecimal.valueOf(cnt))
|
||||
.divide(BigDecimal.valueOf(cnt - 1), 8, java.math.RoundingMode.HALF_UP);
|
||||
if (isSqrt) {
|
||||
return BigDecimal.valueOf(Math.sqrt(sampleVariance.doubleValue()))
|
||||
.setScale(8, java.math.RoundingMode.HALF_UP).toPlainString();
|
||||
}
|
||||
return sampleVariance.toPlainString();
|
||||
}
|
||||
|
||||
public static List<ChartViewFieldDTO> getAllExportColumns(ChartViewDTO viewInfo) {
|
||||
List<ChartViewFieldDTO> allColumns = new ArrayList<>();
|
||||
allColumns.addAll(viewInfo.getXAxis());
|
||||
allColumns.addAll(viewInfo.getYAxis());
|
||||
allColumns.addAll(viewInfo.getXAxisExt());
|
||||
allColumns.addAll(viewInfo.getYAxisExt());
|
||||
allColumns.addAll(viewInfo.getExtStack());
|
||||
return allColumns;
|
||||
}
|
||||
|
||||
public static class SummaryConfig {
|
||||
public String summaryLabel;
|
||||
public Map<String, String> summaryTypeMap = new HashMap<>();
|
||||
public Map<String, Boolean> summaryShowMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public static class SummaryAccumulator {
|
||||
public long totalCount = 0;
|
||||
public Map<String, BigDecimal> sumMap = new HashMap<>();
|
||||
public Map<String, BigDecimal> maxMap = new HashMap<>();
|
||||
public Map<String, BigDecimal> minMap = new HashMap<>();
|
||||
public Map<String, Long> countMap = new HashMap<>();
|
||||
public Map<String, BigDecimal> sumOfSquaresMap = new HashMap<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -484,14 +484,38 @@ public class ExportCenterDownLoadManage {
|
||||
Sheet detailsSheet;
|
||||
Integer sheetIndex = 1;
|
||||
if ("dataset".equals(request.getDownloadType()) || request.getViewInfo().getType().equalsIgnoreCase("table-info") || request.getViewInfo().getType().equalsIgnoreCase("table-normal")) {
|
||||
boolean summaryEnabled = !"dataset".equals(request.getDownloadType()) && ChartDataServer.isSummaryEnabled(request.getViewInfo());
|
||||
ChartDataServer.SummaryConfig summaryConfig = null;
|
||||
ChartDataServer.SummaryAccumulator summaryAcc = null;
|
||||
List<ChartViewFieldDTO> allExportColumns = null;
|
||||
Map<String, java.math.BigDecimal> customSumResult = null;
|
||||
if (summaryEnabled) {
|
||||
summaryConfig = ChartDataServer.parseSummaryConfig(request.getViewInfo());
|
||||
summaryAcc = new ChartDataServer.SummaryAccumulator();
|
||||
allExportColumns = ChartDataServer.getAllExportColumns(request.getViewInfo());
|
||||
}
|
||||
|
||||
request.getViewInfo().getChartExtRequest().setPageSize(Long.valueOf(extractPageSize));
|
||||
ChartViewDTO chartViewDTO = chartDataServer.findExcelData(request);
|
||||
for (long i = 1; i < chartViewDTO.getTotalPage() + 1; i++) {
|
||||
request.getViewInfo().getChartExtRequest().setGoPage(i);
|
||||
request.getViewInfo().setExtStack(request.getViewInfo().getExtStack().stream().filter(ele -> !ele.isHide()).collect(Collectors.toList()));
|
||||
chartDataServer.findExcelData(request);
|
||||
ChartViewDTO pageDto = chartDataServer.findExcelData(request);
|
||||
details.addAll(request.getDetails());
|
||||
|
||||
if (summaryEnabled) {
|
||||
ChartDataServer.accumulatePageStats(summaryAcc, request.getDetails(), allExportColumns, summaryConfig);
|
||||
if (i == chartViewDTO.getTotalPage() && pageDto.getData() != null && pageDto.getData().get("customSumResult") != null) {
|
||||
customSumResult = (Map<String, java.math.BigDecimal>) pageDto.getData().get("customSumResult");
|
||||
}
|
||||
}
|
||||
|
||||
if (((details.size() + extractPageSize) > sheetLimit) || i == chartViewDTO.getTotalPage()) {
|
||||
if (i == chartViewDTO.getTotalPage() && summaryEnabled && summaryAcc.totalCount > 0) {
|
||||
Object[] totalRow = ChartDataServer.buildSummaryRow(allExportColumns, summaryConfig, summaryAcc, customSumResult);
|
||||
details.add(totalRow);
|
||||
}
|
||||
|
||||
detailsSheet = wb.createSheet("数据" + sheetIndex);
|
||||
Integer[] excelTypes = request.getExcelTypes();
|
||||
ViewDetailField[] detailFields = request.getDetailFields();
|
||||
|
||||
@@ -10,6 +10,7 @@ import io.dataease.constant.DeTypeConstants;
|
||||
import io.dataease.dataset.server.DatasetFieldServer;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.exportCenter.util.ExportCenterUtils;
|
||||
import io.dataease.chart.server.ChartDataServer;
|
||||
import io.dataease.extensions.view.dto.ChartExtFilterDTO;
|
||||
import io.dataease.extensions.view.dto.ChartExtRequest;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
@@ -27,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -174,6 +176,7 @@ public class CoreVisualizationExportManage {
|
||||
boolean rightExist = ObjectUtils.isNotEmpty(chart.get("right"));
|
||||
if (!leftExist && !rightExist) {
|
||||
ExcelSheetModel sheetModel = exportSingleData(chart, title);
|
||||
appendSummaryToSheet(sheetModel, chartViewDTO, chart);
|
||||
resultList.add(sheetModel);
|
||||
return resultList;
|
||||
}
|
||||
@@ -196,6 +199,75 @@ public class CoreVisualizationExportManage {
|
||||
return sourceNumberStr;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void appendSummaryToSheet(ExcelSheetModel sheetModel, ChartViewDTO chartViewDTO, Map<String, Object> chart) {
|
||||
if (!ChartDataServer.isSummaryEnabled(chartViewDTO)) return;
|
||||
ChartDataServer.SummaryConfig config = ChartDataServer.parseSummaryConfig(chartViewDTO);
|
||||
List<ChartViewFieldDTO> allColumns = ChartDataServer.getAllExportColumns(chartViewDTO);
|
||||
ChartDataServer.SummaryAccumulator acc = new ChartDataServer.SummaryAccumulator();
|
||||
|
||||
Object objectTableRow = chart.get("tableRow");
|
||||
if (objectTableRow == null) objectTableRow = chart.get("sourceData");
|
||||
if (objectTableRow == null) return;
|
||||
|
||||
List<Map<String, Object>> tableRow = (List<Map<String, Object>>) objectTableRow;
|
||||
for (Map<String, Object> row : tableRow) {
|
||||
acc.totalCount++;
|
||||
for (int j = 0; j < allColumns.size(); j++) {
|
||||
ChartViewFieldDTO field = allColumns.get(j);
|
||||
String fName = field.getDataeaseName();
|
||||
if (!config.summaryShowMap.containsKey(fName) || !config.summaryShowMap.get(fName)) continue;
|
||||
String sType = config.summaryTypeMap.get(fName);
|
||||
if (sType == null || "custom".equals(sType)) continue;
|
||||
Object valObj = row.get(fName);
|
||||
if (valObj == null || StringUtils.isBlank(valObj.toString())) continue;
|
||||
try {
|
||||
BigDecimal val = new BigDecimal(valObj.toString());
|
||||
switch (sType) {
|
||||
case "max":
|
||||
BigDecimal curMax = acc.maxMap.get(fName);
|
||||
if (curMax == null || val.compareTo(curMax) > 0) acc.maxMap.put(fName, val);
|
||||
break;
|
||||
case "min":
|
||||
BigDecimal curMin = acc.minMap.get(fName);
|
||||
if (curMin == null || val.compareTo(curMin) < 0) acc.minMap.put(fName, val);
|
||||
break;
|
||||
default:
|
||||
acc.sumMap.merge(fName, val, BigDecimal::add);
|
||||
acc.countMap.merge(fName, 1L, Long::sum);
|
||||
if ("var_pop".equals(sType) || "stddev_pop".equals(sType)) {
|
||||
acc.sumOfSquaresMap.merge(fName, val.multiply(val), BigDecimal::add);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (acc.totalCount == 0) return;
|
||||
|
||||
Map<String, BigDecimal> customSumResult = chart.get("customSumResult") != null
|
||||
? (Map<String, BigDecimal>) chart.get("customSumResult") : null;
|
||||
|
||||
Object[] totalRowArr = ChartDataServer.buildSummaryRow(allColumns, config, acc, customSumResult);
|
||||
|
||||
List<String> headKeys = new ArrayList<>();
|
||||
for (ChartViewFieldDTO field : allColumns) {
|
||||
headKeys.add(field.getDataeaseName());
|
||||
}
|
||||
|
||||
List<String> summaryRow = new ArrayList<>();
|
||||
for (int i = 0; i < headKeys.size(); i++) {
|
||||
if (i < totalRowArr.length && totalRowArr[i] != null) {
|
||||
summaryRow.add(totalRowArr[i].toString());
|
||||
} else {
|
||||
summaryRow.add(StringUtils.EMPTY);
|
||||
}
|
||||
}
|
||||
sheetModel.getData().add(summaryRow);
|
||||
}
|
||||
|
||||
private final TypeReference<List<Map<String, Object>>> tokenType = new TypeReference<List<Map<String, Object>>>() {
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user