From 6b797e8adc5ce402ef1261e73b48501c6e7e7754 Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Fri, 17 May 2024 13:22:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(X-Pack):=20=E5=AE=9A=E6=97=B6=E6=8A=A5?= =?UTF-8?q?=E5=91=8A-=E5=AF=BC=E5=87=BAexcel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../visualization/bo/ExcelSheetModel.java | 21 +++ .../manage/CoreVisualizationExportManage.java | 146 ++++++++++++++++++ .../template/FilterBuildTemplate.java | 23 +++ .../utils/VisualizationExcelUtils.java | 100 ++++++++++++ 4 files changed, 290 insertions(+) create mode 100644 core/core-backend/src/main/java/io/dataease/visualization/bo/ExcelSheetModel.java create mode 100644 core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationExportManage.java create mode 100644 core/core-backend/src/main/java/io/dataease/visualization/template/FilterBuildTemplate.java create mode 100644 core/core-backend/src/main/java/io/dataease/visualization/utils/VisualizationExcelUtils.java diff --git a/core/core-backend/src/main/java/io/dataease/visualization/bo/ExcelSheetModel.java b/core/core-backend/src/main/java/io/dataease/visualization/bo/ExcelSheetModel.java new file mode 100644 index 0000000000..d1b83898fd --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/visualization/bo/ExcelSheetModel.java @@ -0,0 +1,21 @@ +package io.dataease.visualization.bo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +public class ExcelSheetModel implements Serializable { + @Serial + private static final long serialVersionUID = 1122095875367371623L; + + private String sheetName; + + private List heads; + + private List> data; + + private List filedTypes; +} diff --git a/core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationExportManage.java b/core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationExportManage.java new file mode 100644 index 0000000000..4f53fb57a0 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationExportManage.java @@ -0,0 +1,146 @@ +package io.dataease.visualization.manage; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.dataease.api.chart.dto.ChartExtFilterDTO; +import io.dataease.api.chart.dto.ChartViewDTO; +import io.dataease.api.chart.dto.ChartViewFieldDTO; +import io.dataease.api.chart.request.ChartExtRequest; +import io.dataease.api.visualization.vo.DataVisualizationVO; +import io.dataease.chart.manage.ChartDataManage; +import io.dataease.chart.manage.ChartViewManege; +import io.dataease.constant.CommonConstants; +import io.dataease.exception.DEException; +import io.dataease.utils.AuthUtils; +import io.dataease.utils.JsonUtil; +import io.dataease.visualization.bo.ExcelSheetModel; +import io.dataease.visualization.dao.ext.mapper.ExtDataVisualizationMapper; +import io.dataease.visualization.template.FilterBuildTemplate; +import io.dataease.visualization.utils.VisualizationExcelUtils; +import jakarta.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +@Component +public class CoreVisualizationExportManage { + @Resource + private ExtDataVisualizationMapper extDataVisualizationMapper; + + @Resource + private ChartViewManege chartViewManege; + + @Resource + private ChartDataManage chartDataManage; + + @Resource + private VisualizationTemplateExtendDataManage extendDataManage; + + public File exportExcel(Long dvId, String busiFlag, List viewIdList, boolean onlyDisplay) throws Exception { + DataVisualizationVO visualization = extDataVisualizationMapper.findDvInfo(dvId, busiFlag); + if (ObjectUtils.isEmpty(visualization)) DEException.throwException("资源不存在或已经被删除..."); + List chartViewDTOS = chartViewManege.listBySceneId(dvId); + + if (CollectionUtils.isNotEmpty(viewIdList)) { + chartViewDTOS = chartViewDTOS.stream().filter(item -> viewIdList.contains(item.getId())).collect(Collectors.toList()); + } + if (CollectionUtils.isEmpty(chartViewDTOS)) return null; + Map chartExtRequestMap = buildViewRequest(visualization, onlyDisplay); + List sheets = chartViewDTOS.stream().map(view -> { + ChartExtRequest extRequest = chartExtRequestMap.get(view.getId().toString()); + if (ObjectUtils.isNotEmpty(extRequest)) { + view.setChartExtRequest(extRequest); + } + view.getChartExtRequest().setUser(AuthUtils.getUser().getUserId()); + return exportViewData(view); + }).toList(); + return VisualizationExcelUtils.exportExcel(sheets, visualization.getName(), visualization.getId().toString()); + } + + private ExcelSheetModel exportViewData(ChartViewDTO request) { + ExcelSheetModel result = new ExcelSheetModel(); + ChartViewDTO chartViewDTO = null; + if (CommonConstants.VIEW_DATA_FROM.TEMPLATE.equalsIgnoreCase(request.getDataFrom())) { + chartViewDTO = extendDataManage.getChartDataInfo(request.getId(), request); + } else { + try { + chartViewDTO = chartDataManage.calcData(request); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + String title = chartViewDTO.getTitle(); + Map chart = chartViewDTO.getData(); + + Object objectFields = chart.get("fields"); + List fields = (List) objectFields; + List heads = new ArrayList<>(); + List headKeys = new ArrayList<>(); + List fieldTypes = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(fields)) { + fields.forEach(field -> { + Object name = field.getName(); + Object dataeaseName = field.getDataeaseName(); + Object deType = field.getDeType(); + if (ObjectUtils.isNotEmpty(name) && ObjectUtils.isNotEmpty(dataeaseName)) { + heads.add(name.toString()); + headKeys.add(dataeaseName.toString()); + fieldTypes.add((int) deType); + } + }); + } + Object objectTableRow = chart.get("tableRow"); + List> tableRow = (List>) objectTableRow; + + List> details = tableRow.stream().map(row -> headKeys.stream().map(key -> { + Object val = row.get(key); + if (ObjectUtils.isEmpty(val)) + return StringUtils.EMPTY; + return filterInvalidDecimal(val.toString()); + }).collect(Collectors.toList())).collect(Collectors.toList()); + result.setHeads(heads); + result.setData(details); + result.setFiledTypes(fieldTypes); + result.setSheetName(title); + return result; + } + + private String filterInvalidDecimal(String sourceNumberStr) { + if (StringUtils.isNotBlank(sourceNumberStr) && StringUtils.contains(sourceNumberStr, ".")) { + sourceNumberStr = sourceNumberStr.replaceAll("0+?$", ""); + sourceNumberStr = sourceNumberStr.replaceAll("[.]$", ""); + } + return sourceNumberStr; + } + + private final TypeReference>> tokenType = new TypeReference>>() { + }; + + + private Map buildViewRequest(DataVisualizationVO panelDto, Boolean justView) { + String componentsJson = panelDto.getComponentData(); + List> components = JsonUtil.parseList(componentsJson, tokenType); + Map result = new HashMap<>(); + Map> panelFilters = FilterBuildTemplate.buildEmpty(components); + // List tableInfoViewIds = findTableInfoViewIds(components); + for (Map.Entry> entry : panelFilters.entrySet()) { + List chartExtFilterRequests = entry.getValue(); + ChartExtRequest chartExtRequest = new ChartExtRequest(); + chartExtRequest.setQueryFrom("panel"); + chartExtRequest.setFilter(chartExtFilterRequests); + chartExtRequest.setResultCount((int) 1000); + chartExtRequest.setResultMode("all"); + result.put(entry.getKey(), chartExtRequest); + } + return result; + } + +} diff --git a/core/core-backend/src/main/java/io/dataease/visualization/template/FilterBuildTemplate.java b/core/core-backend/src/main/java/io/dataease/visualization/template/FilterBuildTemplate.java new file mode 100644 index 0000000000..013e8f2808 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/visualization/template/FilterBuildTemplate.java @@ -0,0 +1,23 @@ +package io.dataease.visualization.template; + +import io.dataease.api.chart.dto.ChartExtFilterDTO; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FilterBuildTemplate { + + public static Map> buildEmpty(List> components) { + Map> result = new HashMap<>(); + components.forEach(element -> { + if (StringUtils.equals(element.get("component").toString(), "UserView")) { + String viewId = element.get("id").toString(); + result.put(viewId, new ArrayList<>()); + } + }); + return result; + } +} diff --git a/core/core-backend/src/main/java/io/dataease/visualization/utils/VisualizationExcelUtils.java b/core/core-backend/src/main/java/io/dataease/visualization/utils/VisualizationExcelUtils.java new file mode 100644 index 0000000000..bd608ec876 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/visualization/utils/VisualizationExcelUtils.java @@ -0,0 +1,100 @@ +package io.dataease.visualization.utils; + +import io.dataease.engine.constant.DeTypeConstants; +import io.dataease.utils.FileUtils; +import io.dataease.utils.LogUtil; +import io.dataease.visualization.bo.ExcelSheetModel; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class VisualizationExcelUtils { + + private static final String suffix = ".xlsx"; + private static final String BASE_ROOT = "/opt/dataease2.0/data/report/"; + + public static File exportExcel(List sheets, String fileName, String folderId) throws Exception { + AtomicReference realFileName = new AtomicReference<>(fileName); + Workbook wb = new SXSSFWorkbook(); + + sheets.forEach(sheet -> { + + List> details = sheet.getData(); + List fieldTypes = sheet.getFiledTypes(); + details.add(0, sheet.getHeads()); + String sheetName = sheet.getSheetName(); + Pattern pattern = Pattern.compile("[\\s\\\\/:\\*\\?\\\"<>\\|]"); + Matcher matcher = pattern.matcher(sheetName); + sheetName = matcher.replaceAll("-"); + Sheet curSheet = wb.createSheet(sheetName); + if (StringUtils.isBlank(fileName)) { + String cName = sheetName + suffix; + realFileName.set(cName); + } + + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + font.setFontHeightInPoints((short) 12); + font.setBold(true); + cellStyle.setFont(font); + cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + if (CollectionUtils.isNotEmpty(details)) { + for (int i = 0; i < details.size(); i++) { + Row row = curSheet.createRow(i); + List rowData = details.get(i); + if (rowData != null) { + for (int j = 0; j < rowData.size(); j++) { + Cell cell = row.createCell(j); + // with DataType + if (i > 0 && (fieldTypes.get(j).equals(DeTypeConstants.DE_INT) || fieldTypes.get(j).equals(DeTypeConstants.DE_FLOAT)) && StringUtils.isNotEmpty(rowData.get(j))) { + cell.setCellValue(Double.valueOf(rowData.get(j))); + } else { + cell.setCellValue(rowData.get(j)); + } + if (i == 0) {// 头部 + cell.setCellStyle(cellStyle); + // 设置列的宽度 + curSheet.setColumnWidth(j, 255 * 20); + } + } + } + } + } + }); + if (!StringUtils.endsWith(fileName, suffix)) { + realFileName.set(realFileName.get() + suffix); + } + String folderPath = BASE_ROOT; + if (StringUtils.isNotBlank(folderId)) { + folderPath = BASE_ROOT + folderId + "/"; + } + + folderPath += Thread.currentThread().getId() + "/"; + FileUtils.validateExist(folderPath); + File result = new File(folderPath + realFileName.get()); + FileOutputStream fos = new FileOutputStream(result); + BufferedOutputStream outputStream = new BufferedOutputStream(fos); + try { + wb.write(outputStream); + } catch (Exception e) { + LogUtil.error(e.getMessage(), new Throwable(e)); + throw e; + } finally { + wb.close(); + outputStream.flush(); + outputStream.close(); + } + return result; + } +}