Merge pull request #9703 from dataease/pr@dev-v2@feat_report_excel

fix(X-Pack): 定时报告-导出excel
This commit is contained in:
fit2cloud-chenyw 2024-05-17 13:23:28 +08:00 committed by GitHub
commit 6dcbb71bd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 290 additions and 0 deletions

View File

@ -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<String> heads;
private List<List<String>> data;
private List<Integer> filedTypes;
}

View File

@ -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<Long> viewIdList, boolean onlyDisplay) throws Exception {
DataVisualizationVO visualization = extDataVisualizationMapper.findDvInfo(dvId, busiFlag);
if (ObjectUtils.isEmpty(visualization)) DEException.throwException("资源不存在或已经被删除...");
List<ChartViewDTO> 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<String, ChartExtRequest> chartExtRequestMap = buildViewRequest(visualization, onlyDisplay);
List<ExcelSheetModel> 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<String, Object> chart = chartViewDTO.getData();
Object objectFields = chart.get("fields");
List<ChartViewFieldDTO> fields = (List<ChartViewFieldDTO>) objectFields;
List<String> heads = new ArrayList<>();
List<String> headKeys = new ArrayList<>();
List<Integer> 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<Map<String, Object>> tableRow = (List<Map<String, Object>>) objectTableRow;
List<List<String>> 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<List<Map<String, Object>>> tokenType = new TypeReference<List<Map<String, Object>>>() {
};
private Map<String, ChartExtRequest> buildViewRequest(DataVisualizationVO panelDto, Boolean justView) {
String componentsJson = panelDto.getComponentData();
List<Map<String, Object>> components = JsonUtil.parseList(componentsJson, tokenType);
Map<String, ChartExtRequest> result = new HashMap<>();
Map<String, List<ChartExtFilterDTO>> panelFilters = FilterBuildTemplate.buildEmpty(components);
// List<String> tableInfoViewIds = findTableInfoViewIds(components);
for (Map.Entry<String, List<ChartExtFilterDTO>> entry : panelFilters.entrySet()) {
List<ChartExtFilterDTO> 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;
}
}

View File

@ -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<String, List<ChartExtFilterDTO>> buildEmpty(List<Map<String, Object>> components) {
Map<String, List<ChartExtFilterDTO>> 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;
}
}

View File

@ -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<ExcelSheetModel> sheets, String fileName, String folderId) throws Exception {
AtomicReference<String> realFileName = new AtomicReference<>(fileName);
Workbook wb = new SXSSFWorkbook();
sheets.forEach(sheet -> {
List<List<String>> details = sheet.getData();
List<Integer> 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<String> 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;
}
}