diff --git a/report-core/pom.xml b/report-core/pom.xml index 4fc498d3..ad74fd59 100644 --- a/report-core/pom.xml +++ b/report-core/pom.xml @@ -166,6 +166,18 @@ 3.0.9 + + org.xhtmlrenderer + core-renderer + R8 + + + + com.itextpdf.tool + xmlworker + 5.5.13 + + diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CellStyleDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CellStyleDto.java new file mode 100644 index 00000000..364a839d --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CellStyleDto.java @@ -0,0 +1,16 @@ +package com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto; + +import lombok.Data; + +@Data +public class CellStyleDto { + /** + * 格式名称 + */ + private String fa; + + /** + * 格式类型 + */ + private String t; +} \ No newline at end of file diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CommentDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CommentDto.java new file mode 100644 index 00000000..95d45e5e --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CommentDto.java @@ -0,0 +1,38 @@ +package com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto; + + +import lombok.Data; + +@Data +public class CommentDto { + /** + * 批注框左边距 + */ + private int left; + + /** + * 批注框上边距 + */ + private int top; + + /** + * 批注框宽度 + */ + private int width; + + /** + * 批注框高度 + */ + private int height; + + /** + * 批注内容 + */ + private String value; + + /** + * 批注框是否显示 + */ + private boolean isshow; +} + diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java index df92b09f..739563f0 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java @@ -5,6 +5,7 @@ import com.anji.plus.gaea.curd.dto.GaeaBaseDTO; import lombok.Data; import java.io.Serializable; +import java.util.List; /** @@ -58,4 +59,9 @@ public class ReportExcelDto extends GaeaBaseDTO implements Serializable { */ private String exportType; + /** + * 报表总体数据 + */ + private String rowDatas; + } diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelStyleDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelStyleDto.java new file mode 100644 index 00000000..dc8d41f9 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelStyleDto.java @@ -0,0 +1,97 @@ + +package com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto; + +import com.anji.plus.gaea.curd.dto.GaeaBaseDTO; +import lombok.Data; + +import java.io.Serializable; + + +/** + * @author chenxg + * @date 2023/8/1 10:37 + */ +@Data +public class ReportExcelStyleDto extends GaeaBaseDTO implements Serializable { + /** + * 单元格值格式 + */ + private CellStyleDto ct; + + /** + * 内容的原始值 + */ + private String v; + + /** + * 内容的显示值 + */ + private String m; + + /** + * 背景颜色 + */ + private String bg; + + /** + * 字体编号 + */ + private String ff; + + /** + * 字体颜色 + */ + private String fc; + + /** + * 是否加粗 + */ + private boolean bl; + + /** + * 是否斜体 + */ + private boolean it; + + /** + * 字体大小 + */ + private int fs; + + /** + * 是否删除线 + */ + private boolean cl; + + /** + * 水平对齐方式 + */ + private int ht; + + /** + * 垂直对齐方式 + */ + private int vt; + + /** + * 文字旋转角度 + */ + private int tr; + + /** + * 是否自动换行 + */ + private int tb; + + /** + * 批注信息 + */ + private CommentDto ps; + + /** + * 单元格公式 + */ + private String f; + + +} \ No newline at end of file diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java index fd17950a..60a37fa9 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java @@ -19,29 +19,40 @@ import com.anjiplus.template.gaea.business.modules.file.service.GaeaFileService; import com.anjiplus.template.gaea.business.modules.report.dao.ReportMapper; import com.anjiplus.template.gaea.business.modules.report.dao.entity.Report; import com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto.ReportExcelDto; +import com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto.ReportExcelStyleDto; import com.anjiplus.template.gaea.business.modules.reportexcel.dao.ReportExcelMapper; import com.anjiplus.template.gaea.business.modules.reportexcel.dao.entity.ReportExcel; import com.anjiplus.template.gaea.business.modules.reportexcel.service.ReportExcelService; import com.anjiplus.template.gaea.business.modules.reportexcel.util.CellType; import com.anjiplus.template.gaea.business.modules.reportexcel.util.XlsUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.itextpdf.text.*; +import com.itextpdf.text.Font; +import com.itextpdf.text.pdf.BaseFont; +import com.itextpdf.text.pdf.PdfPCell; +import com.itextpdf.text.pdf.PdfPTable; +import com.itextpdf.text.pdf.PdfWriter; +import com.itextpdf.tool.xml.XMLWorkerHelper; +import com.lowagie.text.DocumentException; +import io.swagger.models.auth.In; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.xhtmlrenderer.pdf.ITextRenderer; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.*; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * TODO @@ -136,43 +147,212 @@ public class ReportExcelServiceImpl implements ReportExcelService { @Override public Boolean exportExcel(ReportExcelDto reportExcelDto) { + logger.error("导出..."); + exportExcelCore(reportExcelDto); + return true; + } + /** + * 抽取导出Excel核心逻辑 + */ + public void exportExcelCore(ReportExcelDto reportExcelDto) + { String reportCode = reportExcelDto.getReportCode(); String exportType = reportExcelDto.getExportType(); - logger.error("导出..."); - if (exportType.equals(ExportTypeEnum.GAEA_TEMPLATE_EXCEL.getCodeValue())) { - ReportExcelDto report = detailByReportCode(reportCode); - reportExcelDto.setJsonStr(report.getJsonStr()); - String jsonStr = analysisReportData(reportExcelDto); - List lists=(List ) JSON.parse(jsonStr); - OutputStream out = null; - File file = null; - try { - String fileName = report.getReportCode(); - File dir = new File(dictPath + ZIP_PATH); - if (!dir.exists()){ - dir.mkdirs(); - } - String filePath = dir.getAbsolutePath() + File.separator + fileName + ".xlsx"; - file = new File(filePath); - out = Files.newOutputStream(Paths.get(filePath)); - XlsUtil.exportXlsFile(out, true, lists); + List> reportExcelStyleList = new ArrayList<>(); + JSONObject rowData= JSON.parseObject(reportExcelDto.getRowDatas()); + // 将JSONObject对象转换为列表 + List dataNumList = rowData.keySet().stream().map(Integer::parseInt).sorted().collect(Collectors.toList()); + for (Integer i : dataNumList) { + JSONArray jsonArray = rowData.getJSONArray(i.toString()); + List reportExcelStyleDtos = jsonArray.toJavaList(ReportExcelStyleDto.class); + reportExcelStyleList.add(reportExcelStyleDtos); + } + ReportExcelDto report = detailByReportCode(reportCode); + reportExcelDto.setJsonStr(report.getJsonStr()); + String jsonStr = analysisReportData(reportExcelDto); + List lists=(List ) JSON.parse(jsonStr); + OutputStream out = null; + File file = null; + File pdfFile = null; + try { + String fileName = report.getReportCode(); + File dir = new File(dictPath + ZIP_PATH); + if (!dir.exists()){ + dir.mkdirs(); + } + String filePath = dir.getAbsolutePath() + File.separator + fileName + ".xlsx"; + file = new File(filePath); + out = Files.newOutputStream(Paths.get(filePath)); + XlsUtil.exportXlsFile(out, true, lists); + if (exportType.equals(ExportTypeEnum.GAEA_TEMPLATE_EXCEL.getCodeValue())) { gaeaFileService.upload(file); + } + else if(exportType.equals(ExportTypeEnum.GAEA_TEMPLATE_PDF.getCodeValue())) + { + // 将Excel文件转换为PDF + String pdfFileName = fileName + ".pdf"; + String pdfFilePath = dir.getAbsolutePath() + File.separator + pdfFileName; + pdfFile = convertExcelToPdf(filePath, pdfFilePath,reportExcelStyleList); + gaeaFileService.upload(pdfFile); + } + } catch (IOException e) { + logger.error("导出失败", e); + }finally { + try { + out.close(); + file.delete(); + if(!Objects.isNull(pdfFile)) + { + pdfFile.delete(); + } } catch (IOException e) { - logger.error("导出失败", e); - }finally { - try { - out.close(); - file.delete(); - } catch (IOException e) { - throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + } + + } + } + // 将Excel文件转换为PDF + public File convertExcelToPdf(String excelFilePath, String pdfFilePath, List> reportExcelStyleList) { + try { + // 读取Excel文件 + Workbook workbook = new XSSFWorkbook(excelFilePath); + Sheet sheet = workbook.getSheetAt(0); + + // 创建PDF文档 + Document document = new Document(PageSize.A4); + PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath)); + document.open(); + + // 创建PDF表格 + PdfPTable table = new PdfPTable(sheet.getRow(0).getLastCellNum()); + table.setWidthPercentage(100); + + // 设置中文字体 + BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + Font font = new Font(baseFont, 10, Font.NORMAL); + + // 设置表头 + Row headerRow = sheet.getRow(0); + for (int i = 0; i < headerRow.getLastCellNum(); i++) { + Cell headerCell = headerRow.getCell(i); + + // 获取单元格样式 + PdfPCell tableCell = new PdfPCell(); + tableCell.setPhrase(new Phrase(getStringValue(headerCell), font)); + ReportExcelStyleDto reportExcelStyleDto = reportExcelStyleList.get(0).get(i); + if(!Objects.isNull(reportExcelStyleDto)) + { + processCellStyle(reportExcelStyleDto,tableCell); } + table.addCell(tableCell); + } + // 遍历Excel表格的行和列 + for (int i = 1; i <= sheet.getLastRowNum(); i++) { + Row row = sheet.getRow(i); + if (row == null) { + // 如果行为空,创建一个空的行并添加到PDF表格中 + row = sheet.createRow(i); + } + for (int j = 0; j < headerRow.getLastCellNum(); j++) { + Cell cell = row.getCell(j, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); + if (cell.getCellType() == org.apache.poi.ss.usermodel.CellType.BLANK) { + cell.setCellValue(" "); + } + PdfPCell tableCell = new PdfPCell(); + tableCell.setPhrase(new Phrase(getStringValue(cell), font)); + ReportExcelStyleDto reportExcelStyleDto = reportExcelStyleList.get(i).get(j); + if(!Objects.isNull(reportExcelStyleDto)) + { + processCellStyle(reportExcelStyleDto,tableCell); + } + table.addCell(tableCell); + } } + + // 将表格添加到PDF文档中 + document.add(table); + + document.close(); + workbook.close(); + + System.out.println("Excel转换为PDF成功!"); + + return new File(pdfFilePath); + } catch (IOException e) { + e.printStackTrace(); + } catch (com.itextpdf.text.DocumentException e) { + e.printStackTrace(); } - return true; + + return null; } + /** + * 处理导出pdf文件样式 + * @param tableCell + */ + public void processCellStyle(ReportExcelStyleDto reportExcelStyleDto,PdfPCell tableCell) + { + //处理单元格背景颜色 + String bg = reportExcelStyleDto.getBg(); + java.awt.Color color = null; + if(!Objects.isNull(bg)) + { + color = java.awt.Color.decode(bg); + tableCell.setBackgroundColor(new BaseColor(color.getRed(), color.getGreen(), color.getBlue())); + } + //处理字体 + String fc = reportExcelStyleDto.getFc(); + Integer fs = reportExcelStyleDto.getFs(); + String ff = reportExcelStyleDto.getFf(); + Boolean bl = reportExcelStyleDto.isBl(); + Boolean it = reportExcelStyleDto.isIt(); + Font font = new Font(); + // 设置字体颜色 + if(!Objects.isNull(fc)) + { + color = java.awt.Color.decode(fc); + font.setColor(new BaseColor(color.getRed(), color.getGreen(), color.getBlue())); + } + // 设置字体 + if(!Objects.isNull(ff) && !Objects.equals("0",ff)) + { + font.setFamily(ff.toString()); + } + // 设置字体大小 + if(!Objects.isNull(fs) && !Objects.equals(0,fs)) + { + font.setSize(fs); + } + // 设置字体加粗 + if(Objects.equals(Boolean.TRUE,bl)) + { + font.setStyle(Font.BOLD); + } + // 设置字体斜体 + if(Objects.equals(Boolean.TRUE,it)) + { + font.setStyle(Font.ITALIC); + } + // 设置字体加粗且斜体 + if(Objects.equals(Boolean.TRUE,bl) && Objects.equals(Boolean.TRUE,it)) + { + font.setStyle(Font.BOLDITALIC); + } + Phrase phrase = tableCell.getPhrase(); + tableCell.setPhrase(new Paragraph(phrase.getContent(), font)); + //处理字体 + tableCell.setBorderColor(BaseColor.BLACK); + } + + private String getStringValue(Cell cell) { + if (cell == null) + return ""; + else + return cell.toString(); + } /** * 解析报表数据,动态插入列表数据和对象数据 */ diff --git a/report-ui/src/views/excelreport/viewer/index.vue b/report-ui/src/views/excelreport/viewer/index.vue index b94dd9a9..ac5fa404 100644 --- a/report-ui/src/views/excelreport/viewer/index.vue +++ b/report-ui/src/views/excelreport/viewer/index.vue @@ -108,16 +108,17 @@ export default { this.createSheet(); }, async download(val) { - if (val == "gaea_template_pdf") { - this.$message("暂不支持pdf"); - return; - } + // if (val == "gaea_template_pdf") { + // this.$message("暂不支持pdf"); + // return; + // } const result = {}; result["reportCode"] = this.reportCode; result["setParam"] = JSON.stringify(this.params.setParam); if (val != "") { result["exportType"] = val; } + this.getCellStyleData(result); const { code, message } = await exportExcel(result); if (code != 200) return; this.$message.success(message); @@ -192,7 +193,22 @@ export default { $(function() { luckysheet.create(options); }); - } + }, + getCellStyleData(result) { + const sheetData = luckysheet.getluckysheetfile(); // 获取整个表格的数据 + const rowDatas = {}; + + for (let sheetIndex in sheetData) { + const sheet = sheetData[sheetIndex]; + if (sheet && sheet.data) { + for (let rowIndex in sheet.data) { + const row = sheet.data[rowIndex]; + rowDatas[rowIndex]=row; + } + } + } + result["rowDatas"] = JSON.stringify(rowDatas);; + }, } };