From b7f23d885a722df10f404381e5fb55d0dbc33379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=A1=D0=B0=D0=B2=D0=B5=D0=BB=D1=8C=D0=B5=D0=B2?= <100-90@rtsk.loc> Date: Fri, 21 Nov 2025 04:38:52 +0300 Subject: [PATCH] add export grid service --- .../service/ExportGridV2Service.java | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 backend/src/main/java/ru/micord/ervu_dashboard/service/ExportGridV2Service.java diff --git a/backend/src/main/java/ru/micord/ervu_dashboard/service/ExportGridV2Service.java b/backend/src/main/java/ru/micord/ervu_dashboard/service/ExportGridV2Service.java new file mode 100644 index 00000000..d9378ef3 --- /dev/null +++ b/backend/src/main/java/ru/micord/ervu_dashboard/service/ExportGridV2Service.java @@ -0,0 +1,171 @@ +package ru.micord.ervu_dashboard.service; + +import model.FileModel; +import model.grid.GridColumnAggregationValues; +import model.grid.GridDataExportFormat; +import model.grid.GridRow; +import model.grid.GridRows; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import property.grid.GridColumn; +import service.GridV2ServiceImpl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Base64; +import java.util.Date; +import java.util.List; + +public class ExportGridV2Service extends GridV2ServiceImpl { + + protected FileModel getFileModelWithContent(String[] columnIdsToExport, + GridDataExportFormat exportFormat, GridRows gridRows) { + FileModel fileModel = new FileModel(); + fileModel.setFileId(this.getObjectId()); + + switch (exportFormat) { + case XLS: + fileModel.setFileExtension(".xls"); + fileModel.setFileContent(getXlsContent(columnIdsToExport, gridRows)); + break; + case XLSX: + fileModel.setFileExtension(".xlsx"); + fileModel.setFileContent(getXlsxContent(columnIdsToExport, gridRows)); + break; + default: + throw new IllegalArgumentException("Unknown export format = " + exportFormat); + } + fileModel.setFileName( + LocalDate.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy")) + + fileModel.fileExtension); + fileModel.setIsImage(false); + + return fileModel; + } + + + private String getXlsxContent(String[] columnIdsToExport, GridRows gridRows) { + return getExcelContent(columnIdsToExport, gridRows, new SXSSFWorkbook()); + } + + private String getXlsContent(String[] columnIdsToExport, GridRows gridRows) { + return getExcelContent(columnIdsToExport, gridRows, new HSSFWorkbook()); + } + + private String getExcelContent(String[] columnIdsToExport, GridRows gridRows, + Workbook workbook) { + List orderedColumns = getOrderedColumns(columnIdsToExport); + Sheet sheet = workbook.createSheet(); + writeHeaderLine(workbook, sheet, orderedColumns, gridRows.getAggregationValues() != null); + writeDataLines(workbook, sheet, orderedColumns, gridRows); + + try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + workbook.write(bos); + return Base64.getEncoder().encodeToString(bos.toByteArray()); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void autosizeByHeader(Sheet sheet, int columnIndex, String header, int minChars, int padding) { + int length = header != null ? header.length() : 0; + + // Берём максимум из (минимальная ширина, длина заголовка + отступ) + int finalWidth = Math.max(minChars, length + padding); + + sheet.setColumnWidth(columnIndex, finalWidth * 256); + } + + private void writeHeaderLine(Workbook workbook, Sheet sheet, + List orderedColumns, boolean hasAggregationValues) { + Row row = sheet.createRow(0); + CellStyle style = createBoldStyle(workbook); + int minWidth = 20; + int padding = 5; + + int colIndex = hasAggregationValues ? 1 : 0; + for (GridColumn column : orderedColumns) { + createCell(row, colIndex, column.displayName, style); + autosizeByHeader(sheet, colIndex, column.displayName, minWidth, padding); + colIndex++; + } + } + + private void createCell(Row row, int columnCount, Object value, CellStyle style) { + Cell cell = row.createCell(columnCount); + + if (value == null) { + cell.setBlank(); + } + else if (value instanceof Number) { + cell.setCellValue(((Number) value).doubleValue()); + } + else if (value instanceof Boolean) { + cell.setCellValue((Boolean) value); + } + else if (value instanceof Date) { + cell.setCellValue((Date) value); + } + else if (value instanceof LocalDate) { + cell.setCellValue((LocalDate) value); + } + else if (value instanceof LocalDateTime) { + cell.setCellValue((LocalDateTime) value); + } + else { + cell.setCellValue(value.toString()); + } + cell.setCellStyle(style); + } + + private void writeDataLines(Workbook workbook, Sheet sheet, + List orderedColumns, GridRows gridRows) { + int rowCount = 1; + + CellStyle style = workbook.createCellStyle(); + style.setWrapText(true); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + GridColumnAggregationValues aggregationValues = gridRows.getAggregationValues(); + + for (GridRow gridRow : gridRows.getRows()) { + int columnCount = aggregationValues != null ? 1 : 0; + Row row = sheet.createRow(rowCount++); + row.setHeight((short) -1); + for (GridColumn gridColumn : orderedColumns) { + createCell(row, columnCount, + gridRow.get(getClientColumnId(gridColumn)), style + ); + columnCount++; + } + } + + if (aggregationValues != null) { + Row aggregationRow = sheet.createRow(rowCount); + CellStyle boldStyle = createBoldStyle(workbook); + createCell(aggregationRow, 0, aggregationHeaderForExport, boldStyle); + + int columnCount = 1; + for (GridColumn gridColumn : orderedColumns) { + createCell(aggregationRow, columnCount, + aggregationValues.get(getClientColumnId(gridColumn)), boldStyle + ); + columnCount++; + } + } + } + + private CellStyle createBoldStyle(Workbook workbook) { + CellStyle boldStyle = workbook.createCellStyle(); + Font font = workbook.createFont(); + font.setBold(true); + boldStyle.setFont(font); + boldStyle.setAlignment(HorizontalAlignment.CENTER); + return boldStyle; + } +}