mirror of
https://github.com/dataease/dataease.git
synced 2026-06-13 01:01:20 +08:00
fix: 【图表】下钻后导出格式错位
This commit is contained in:
@@ -140,6 +140,7 @@ public class ChartDataServer implements ChartDataApi {
|
||||
request.setHeader(dsHeader);
|
||||
request.setExcelTypes(dsTypes);
|
||||
}
|
||||
viewDTO.setData(chartViewInfo.getData());
|
||||
request.setDetails(tableRow);
|
||||
request.setData(chartViewInfo.getData());
|
||||
} catch (Exception e) {
|
||||
@@ -386,19 +387,12 @@ public class ChartDataServer implements ChartDataApi {
|
||||
|
||||
public static void setExcelData(Sheet detailsSheet, CellStyle cellStyle, Object[] header, List<Object[]> details, ViewDetailField[] detailFields, Integer[] excelTypes, Comment comment, ChartViewDTO viewInfo, Workbook wb) {
|
||||
List<CellStyle> styles = new ArrayList<>();
|
||||
List<ChartViewFieldDTO> xAxis = new ArrayList<>();
|
||||
|
||||
xAxis.addAll(viewInfo.getXAxis());
|
||||
xAxis.addAll(viewInfo.getYAxis());
|
||||
xAxis.addAll(viewInfo.getXAxisExt());
|
||||
xAxis.addAll(viewInfo.getYAxisExt());
|
||||
xAxis.addAll(viewInfo.getExtStack());
|
||||
xAxis.addAll(viewInfo.getDrillFields());
|
||||
List<ChartViewFieldDTO> exportFields = resolveExportFields(viewInfo, header);
|
||||
TableHeader tableHeader = null;
|
||||
Integer totalDepth = 0;
|
||||
List<CellRangeAddress> mergeConfig = new ArrayList<>();
|
||||
if (StringUtils.equalsAnyIgnoreCase(viewInfo.getType(), "table-normal", "table-info")) {
|
||||
for (ChartViewFieldDTO tmpAxis : xAxis) {
|
||||
for (ChartViewFieldDTO tmpAxis : exportFields) {
|
||||
if (tmpAxis.isHide()) {
|
||||
continue;
|
||||
}
|
||||
@@ -415,10 +409,7 @@ public class ChartDataServer implements ChartDataApi {
|
||||
if (tableHeaderMap.get("headerGroup") != null && Boolean.parseBoolean(tableHeaderMap.get("headerGroup").toString())) {
|
||||
var tmpHeader = JsonUtil.parseObject((String) JsonUtil.toJSONString(customAttr.get("tableHeader")), TableHeader.class);
|
||||
// 校验字段数量和顺序
|
||||
var allAxis = new ArrayList<>(viewInfo.getXAxis().stream().filter(x -> !x.isHide()).toList());
|
||||
if (StringUtils.equalsIgnoreCase(viewInfo.getType(), "table-normal")) {
|
||||
allAxis.addAll(viewInfo.getYAxis().stream().filter(x -> !x.isHide()).toList());
|
||||
}
|
||||
var allAxis = new ArrayList<>(exportFields.stream().filter(x -> !x.isHide()).toList());
|
||||
if (validateHeaderGroup(tmpHeader, allAxis)) {
|
||||
tableHeader = tmpHeader;
|
||||
for (TableHeader.ColumnInfo column : tableHeader.getHeaderGroupConfig().getColumns()) {
|
||||
@@ -430,7 +421,6 @@ public class ChartDataServer implements ChartDataApi {
|
||||
}
|
||||
}
|
||||
if ("table-info".equalsIgnoreCase(viewInfo.getType()) && !"dataset".equalsIgnoreCase(viewInfo.getDownloadType())) {
|
||||
xAxis = xAxis.stream().filter(x -> !x.isHide()).toList();
|
||||
Map<String, Object> tableCell = (Map<String, Object>) viewInfo.getCustomAttr().get("tableCell");
|
||||
Boolean mergeCells = (Boolean) tableCell.get("mergeCells");
|
||||
if (mergeCells != null && mergeCells) {
|
||||
@@ -506,7 +496,7 @@ public class ChartDataServer implements ChartDataApi {
|
||||
int width = 0;
|
||||
Integer depth = 0;
|
||||
for (TableHeader.ColumnInfo column : tableHeader.getHeaderGroupConfig().getColumns()) {
|
||||
createCell(tableHeader, column, width, depth, detailsSheet, cellStyle, totalDepth, rowMap, xAxis);
|
||||
createCell(tableHeader, column, width, depth, detailsSheet, cellStyle, totalDepth, rowMap, exportFields);
|
||||
width = width + column.getWidth();
|
||||
}
|
||||
}
|
||||
@@ -556,9 +546,11 @@ public class ChartDataServer implements ChartDataApi {
|
||||
detailsSheet.setColumnWidth(j, 255 * 20);
|
||||
} else if (cellValObj != null) {
|
||||
try {
|
||||
if (StringUtils.equalsAnyIgnoreCase(viewInfo.getType(), "table-info", "table-normal") && Arrays.asList(DeTypeConstants.DE_INT,DeTypeConstants.DE_FLOAT).contains(xAxis.get(j).getDeType())) {
|
||||
if (StringUtils.equalsAnyIgnoreCase(viewInfo.getType(), "table-info", "table-normal")
|
||||
&& j < exportFields.size()
|
||||
&& Arrays.asList(DeTypeConstants.DE_INT, DeTypeConstants.DE_FLOAT).contains(exportFields.get(j).getDeType())) {
|
||||
try {
|
||||
FormatterCfgDTO formatterCfgDTO = xAxis.get(j).getFormatterCfg() == null ? new FormatterCfgDTO().setUnitLanguage(Lang.isChinese() ? "ch" : "en") : xAxis.get(j).getFormatterCfg();
|
||||
FormatterCfgDTO formatterCfgDTO = exportFields.get(j).getFormatterCfg() == null ? new FormatterCfgDTO().setUnitLanguage(Lang.isChinese() ? "ch" : "en") : exportFields.get(j).getFormatterCfg();
|
||||
row.getCell(j).setCellStyle(styles.get(j));
|
||||
row.getCell(j).setCellValue(Double.valueOf(cellValue(formatterCfgDTO, new BigDecimal(cellValObj.toString()))));
|
||||
} catch (Exception e) {
|
||||
@@ -581,7 +573,7 @@ public class ChartDataServer implements ChartDataApi {
|
||||
ChartSeniorFunctionCfgDTO functionCfgDTO = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("functionCfg")), ChartSeniorFunctionCfgDTO.class);
|
||||
if (functionCfgDTO != null && StringUtils.isNotEmpty(functionCfgDTO.getEmptyDataStrategy()) && functionCfgDTO.getEmptyDataStrategy().equalsIgnoreCase("setZero")) {
|
||||
if ((viewInfo.getType().equalsIgnoreCase("table-normal") || viewInfo.getType().equalsIgnoreCase("table-info"))) {
|
||||
if (functionCfgDTO.getEmptyDataFieldCtrl().contains(xAxis.get(j).getDataeaseName())) {
|
||||
if (j < exportFields.size() && functionCfgDTO.getEmptyDataFieldCtrl().contains(exportFields.get(j).getDataeaseName())) {
|
||||
cell.setCellValue(0);
|
||||
}
|
||||
} else {
|
||||
@@ -599,6 +591,53 @@ public class ChartDataServer implements ChartDataApi {
|
||||
}
|
||||
}
|
||||
|
||||
static List<ChartViewFieldDTO> resolveExportFields(ChartViewDTO viewInfo, Object[] header) {
|
||||
List<ChartViewFieldDTO> fields = new ArrayList<>();
|
||||
if (viewInfo != null && viewInfo.getData() != null && viewInfo.getData().get("fields") != null) {
|
||||
Object fieldsObj = viewInfo.getData().get("fields");
|
||||
if (fieldsObj instanceof List<?> fieldList && !fieldList.isEmpty() && fieldList.getFirst() instanceof ChartViewFieldDTO) {
|
||||
fields.addAll(fieldList.stream().map(ChartViewFieldDTO.class::cast).toList());
|
||||
} else {
|
||||
fields.addAll(JsonUtil.parseList(JsonUtil.toJSONString(fieldsObj).toString(), new TypeReference<List<ChartViewFieldDTO>>() {
|
||||
}));
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(fields)) {
|
||||
appendFields(fields, viewInfo == null ? null : viewInfo.getXAxis());
|
||||
appendFields(fields, viewInfo == null ? null : viewInfo.getYAxis());
|
||||
appendFields(fields, viewInfo == null ? null : viewInfo.getXAxisExt());
|
||||
appendFields(fields, viewInfo == null ? null : viewInfo.getYAxisExt());
|
||||
appendFields(fields, viewInfo == null ? null : viewInfo.getExtStack());
|
||||
appendFields(fields, viewInfo == null ? null : viewInfo.getDrillFields());
|
||||
}
|
||||
if (ArrayUtils.isEmpty(header) || CollectionUtils.isEmpty(fields)) {
|
||||
return fields;
|
||||
}
|
||||
Map<String, Deque<ChartViewFieldDTO>> fieldMap = new HashMap<>();
|
||||
fields.forEach(field -> fieldMap.computeIfAbsent(getExportFieldName(field), key -> new ArrayDeque<>()).add(field));
|
||||
List<ChartViewFieldDTO> orderedFields = new ArrayList<>();
|
||||
for (Object headerItem : header) {
|
||||
if (headerItem == null) {
|
||||
continue;
|
||||
}
|
||||
Deque<ChartViewFieldDTO> matchedFields = fieldMap.get(headerItem.toString());
|
||||
if (matchedFields != null && !matchedFields.isEmpty()) {
|
||||
orderedFields.add(matchedFields.removeFirst());
|
||||
}
|
||||
}
|
||||
return CollectionUtils.isNotEmpty(orderedFields) ? orderedFields : fields;
|
||||
}
|
||||
|
||||
private static void appendFields(List<ChartViewFieldDTO> target, List<ChartViewFieldDTO> source) {
|
||||
if (CollectionUtils.isNotEmpty(source)) {
|
||||
target.addAll(source);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getExportFieldName(ChartViewFieldDTO field) {
|
||||
return StringUtils.isNotBlank(field.getChartShowName()) ? field.getChartShowName() : field.getName();
|
||||
}
|
||||
|
||||
private static List<CellRangeAddress> getMergeConfig(List<Object[]> data, int colIndex, int offsetHeight) {
|
||||
var result = new ArrayList<CellRangeAddress>();
|
||||
var preRange = new ArrayList<Integer[]>();
|
||||
|
||||
@@ -3,17 +3,27 @@ package io.dataease.chart.server;
|
||||
import io.dataease.api.chart.request.ChartExcelRequest;
|
||||
import io.dataease.chart.constant.ChartConstants;
|
||||
import io.dataease.chart.manage.ChartDataManage;
|
||||
import io.dataease.constant.DeTypeConstants;
|
||||
import io.dataease.exportCenter.manage.ExportCenterLimitManage;
|
||||
import io.dataease.exportCenter.util.ExportCenterUtils;
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.extensions.view.dto.FormatterCfgDTO;
|
||||
import org.junit.Test;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -63,12 +73,75 @@ public class ChartDataServerTest {
|
||||
assertEquals(100_000, resultCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findExcelDataStoresCalculatedFieldsOnViewInfo() throws Exception {
|
||||
ChartDataServer chartDataServer = chartDataServerWithExportLimits(1_000_000L, 1_000_000L);
|
||||
|
||||
ChartViewDTO view = new ChartViewDTO();
|
||||
view.setResultMode(ChartConstants.VIEW_RESULT_MODE.ALL);
|
||||
|
||||
ChartExcelRequest request = new ChartExcelRequest();
|
||||
request.setDownloadType("view");
|
||||
request.setViewInfo(view);
|
||||
|
||||
chartDataServer.findExcelData(request);
|
||||
|
||||
assertNotNull(view.getData());
|
||||
assertEquals(1, ((List<?>) view.getData().get("fields")).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setExcelDataUsesCurrentDrillFieldOrderForNumericFormats() {
|
||||
ChartViewFieldDTO province = field("province", "省份", DeTypeConstants.DE_STRING);
|
||||
ChartViewFieldDTO city = field("city", "城市", DeTypeConstants.DE_STRING);
|
||||
ChartViewFieldDTO amount = field("amount", "销售额", DeTypeConstants.DE_FLOAT);
|
||||
amount.setFormatterCfg(new FormatterCfgDTO().setType("value").setDecimalCount(2));
|
||||
|
||||
ChartViewDTO view = new ChartViewDTO();
|
||||
view.setType("table-info");
|
||||
view.setXAxis(new ArrayList<>(Arrays.asList(province, amount)));
|
||||
view.setDrillFields(new ArrayList<>(List.of(city)));
|
||||
Map<String, Object> customAttr = new HashMap<>();
|
||||
customAttr.put("tableHeader", new HashMap<String, Object>());
|
||||
customAttr.put("tableCell", new HashMap<>(Map.of("mergeCells", false)));
|
||||
view.setCustomAttr(customAttr);
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("fields", new ArrayList<>(Arrays.asList(province, city, amount)));
|
||||
view.setData(data);
|
||||
|
||||
try (Workbook workbook = new XSSFWorkbook()) {
|
||||
Sheet sheet = workbook.createSheet("data");
|
||||
CellStyle headStyle = workbook.createCellStyle();
|
||||
List<Object[]> details = new ArrayList<>();
|
||||
details.add(new Object[]{"省份", "城市", "销售额"});
|
||||
details.add(new Object[]{"浙江", "杭州", "1234.5"});
|
||||
|
||||
ChartDataServer.setExcelData(
|
||||
sheet,
|
||||
headStyle,
|
||||
new Object[]{"省份", "城市", "销售额"},
|
||||
details,
|
||||
null,
|
||||
new Integer[]{DeTypeConstants.DE_STRING, DeTypeConstants.DE_STRING, DeTypeConstants.DE_FLOAT},
|
||||
view,
|
||||
workbook
|
||||
);
|
||||
|
||||
assertEquals("General", sheet.getRow(1).getCell(1).getCellStyle().getDataFormatString());
|
||||
assertEquals("0.00", sheet.getRow(1).getCell(2).getCellStyle().getDataFormatString());
|
||||
assertEquals(1234.5D, sheet.getRow(1).getCell(2).getNumericCellValue(), 0.0001D);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private ChartDataServer chartDataServerWithExportLimits(Long viewLimit, Long datasetLimit) throws Exception {
|
||||
ChartDataManage chartDataManage = mock(ChartDataManage.class);
|
||||
when(chartDataManage.calcData(any(ChartViewDTO.class))).thenAnswer(invocation -> {
|
||||
ChartViewDTO result = new ChartViewDTO();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("sourceData", new ArrayList<Object[]>());
|
||||
data.put("fields", List.of(field("name", "名称", DeTypeConstants.DE_STRING)));
|
||||
result.setData(data);
|
||||
return result;
|
||||
});
|
||||
@@ -82,4 +155,12 @@ public class ChartDataServerTest {
|
||||
ReflectionTestUtils.setField(chartDataServer, "chartDataManage", chartDataManage);
|
||||
return chartDataServer;
|
||||
}
|
||||
|
||||
private static ChartViewFieldDTO field(String dataeaseName, String name, Integer deType) {
|
||||
ChartViewFieldDTO field = new ChartViewFieldDTO();
|
||||
field.setDataeaseName(dataeaseName);
|
||||
field.setName(name);
|
||||
field.setDeType(deType);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user