package com.goafanti.common.utils.pdf; import com.goafanti.RD.bo.OutWordRdDetails; import com.goafanti.common.constant.AFTConstants; import com.goafanti.common.utils.DateUtils; import com.goafanti.common.utils.excel.FileUtils; import com.goafanti.expenseAccount.bo.MainExpenseAccount; import com.itextpdf.text.Document; import com.itextpdf.text.Font; import com.itextpdf.text.*; 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 org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xwpf.usermodel.*; import org.springframework.http.MediaType; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.Date; public class PDFUtils { /** * 删除临时目录及其内容 * * @param dir 临时目录 */ private static void deleteTempDirectory(File dir) { if (dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isDirectory()) { deleteTempDirectory(file); } else { file.delete(); } } } dir.delete(); } } /** * 将Word文档转换为PDF文件 * * @param wordFilePath Word文件路径 * @param pdfFilePath 生成的PDF文件路径 * @throws IOException * @throws DocumentException */ public static void convertWordToPDF(String wordFilePath, String pdfFilePath) throws IOException, DocumentException { Document document = new Document(PageSize.A4); try (InputStream in = new FileInputStream(wordFilePath)) { // 创建PDF写入器 FileOutputStream outputStream = new FileOutputStream(pdfFilePath); PdfWriter.getInstance(document, outputStream); document.open(); // 处理Word文档内容 processWordDocument(wordFilePath, document); document.close(); outputStream.close(); } } /** * 将XLSX文件转换为PDF文件 * * @param xlsxFilePath XLSX文件路径 * @param pdfFilePath 生成的PDF文件路径 * @throws IOException * @throws DocumentException */ public static void convertXlsxToPDF(String xlsxFilePath, String pdfFilePath) throws IOException, DocumentException { Document document = new Document(PageSize.A4.rotate()); // 使用横向页面以适应更多列 try (InputStream in = new FileInputStream(xlsxFilePath)) { Workbook workbook = new XSSFWorkbook(in); // 创建PDF写入器 FileOutputStream outputStream = new FileOutputStream(pdfFilePath); PdfWriter.getInstance(document, outputStream); document.open(); // 处理Excel工作簿内容 processExcelWorkbook(workbook, document); document.close(); outputStream.close(); workbook.close(); } } /** * 将Word文档转换为PDF并提供下载 * * @param wordFilePath Word文件路径 * @param response HttpServletResponse对象 * @param pdfFileName 生成的PDF文件名 * @param uploadPath 上传路径 * @throws IOException * @throws DocumentException */ public static void convertWordToPDFForDownload(String wordFilePath, HttpServletResponse response, String pdfFileName, String uploadPath) throws IOException, DocumentException { String realFileName = uploadPath + "/tmp/" + System.currentTimeMillis() + ".pdf"; Document document = new Document(PageSize.A4); try (InputStream in = new FileInputStream(wordFilePath)) { // 设置响应头,用于文件下载 FileUtils.setAttachmentResponseHeader(response, pdfFileName, pdfFileName + ".pdf"); // 创建PDF写入器 FileOutputStream outputStream = new FileOutputStream(realFileName); PdfWriter.getInstance(document, outputStream); document.open(); // 处理Word文档内容 processWordDocument(wordFilePath, document); document.close(); outputStream.close(); // 提供文件下载 FileUtils.writeBytes(realFileName, response.getOutputStream()); FileUtils.deleteFile(realFileName); } } /** * 处理Word文档并将其内容添加到PDF文档中 * * @param wordFilePath Word文件路径 * @param document PDF文档对象 * @throws IOException * @throws DocumentException */ private static void processWordDocument(String wordFilePath, Document document) throws IOException, DocumentException { try (InputStream in = new FileInputStream(wordFilePath)) { XWPFDocument xwpfDocument = new XWPFDocument(in); // 获取文档中的所有段落 java.util.List paragraphs = xwpfDocument.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { // 创建PDF段落 Paragraph pdfParagraph = new Paragraph(); paragraph.getRuns().forEach(run -> { System.out.println(run.getPictureText()); System.out.println(run.getFontSize()); }); // 设置段落对齐方式 switch (paragraph.getAlignment()) { case CENTER: pdfParagraph.setAlignment(Element.ALIGN_CENTER); break; case RIGHT: pdfParagraph.setAlignment(Element.ALIGN_RIGHT); break; case LEFT: case BOTH: default: pdfParagraph.setAlignment(Element.ALIGN_LEFT); break; } // 处理段落中的所有文本块(XWPFRun) for (XWPFRun run : paragraph.getRuns()) { String text = run.getText(0); if (text != null) { // 创建带样式的PDF字体 Font pdfFont = createPDFFontFromRun(run); Chunk chunk = new Chunk(text, pdfFont); pdfParagraph.add(chunk); } } // 只有当段落有内容时才添加到文档中 if (pdfParagraph.size() > 0 && !pdfParagraph.getContent().toString().trim().isEmpty()) { document.add(pdfParagraph); } } // 处理表格(如果有) java.util.List tables = xwpfDocument.getTables(); for (XWPFTable table : tables) { // 处理表格中的每一行 java.util.List rows = table.getRows(); for (XWPFTableRow row : rows) { StringBuilder rowText = new StringBuilder(); java.util.List cells = row.getTableCells(); for (XWPFTableCell cell : cells) { String cellText = cell.getText(); rowText.append(cellText).append(" | "); } if (rowText.length() > 0) { document.add(new Paragraph(rowText.toString())); } } } } } /** * 处理Excel工作簿并将其内容添加到PDF文档中 * * @param workbook Excel工作簿对象 * @param document PDF文档对象 * @throws DocumentException */ private static void processExcelWorkbook(Workbook workbook, Document document) throws DocumentException { // 添加文档标题(文件名) document.add(new Paragraph("Excel文档转换", PDFUtils.getTitleFont())); document.add(Chunk.NEWLINE); // 处理每个工作表 for (int i = 0; i < workbook.getNumberOfSheets(); i++) { Sheet sheet = workbook.getSheetAt(i); // 添加工作表名称 Paragraph sheetTitle = new Paragraph("工作表: " + sheet.getSheetName(), PDFUtils.getBigFont()); document.add(sheetTitle); document.add(Chunk.NEWLINE); // 计算需要的列数 int columnCount = 0; for (Row row : sheet) { int lastCellNum = row.getLastCellNum(); if (lastCellNum > columnCount) { columnCount = lastCellNum; } } if (columnCount > 0) { // 创建表格 PdfPTable table = new PdfPTable(columnCount); table.setWidthPercentage(100); float[] columnWidths = new float[columnCount]; for (int j = 0; j < columnCount; j++) { columnWidths[j] = 1f; } table.setWidths(columnWidths); // 处理行数据 int rowCount = 0; for (Row row : sheet) { // 处理每行的单元格 for (int colIndex = 0; colIndex < columnCount; colIndex++) { Cell cell = row.getCell(colIndex); String cellValue = getCellValue(cell); PdfPCell pdfCell = new PdfPCell(new Phrase(cellValue, PDFUtils.getFont())); pdfCell.setPadding(3); // 设置表头样式 if (rowCount == 0) { pdfCell.setBackgroundColor(BaseColor.LIGHT_GRAY); pdfCell.setHorizontalAlignment(Element.ALIGN_CENTER); } table.addCell(pdfCell); } rowCount++; // 限制处理的行数,避免内容过多 if (rowCount > 100) { PdfPCell pdfCell = new PdfPCell(new Phrase("... (内容过多,省略剩余部分)", PDFUtils.getFont())); pdfCell.setColspan(columnCount); pdfCell.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(pdfCell); break; } } document.add(table); } document.add(Chunk.NEWLINE); } } /** * 获取单元格的值 * * @param cell Excel单元格 * @return 单元格内容字符串 */ private static String getCellValue(Cell cell) { if (cell == null) { return ""; } switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: return cell.getStringCellValue(); case Cell.CELL_TYPE_NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { return cell.getDateCellValue().toString(); } else { // 避免科学计数法显示数字 return String.valueOf(cell.getNumericCellValue()); } case Cell.CELL_TYPE_BOOLEAN: return String.valueOf(cell.getBooleanCellValue()); case Cell.CELL_TYPE_FORMULA: return cell.getCellFormula(); default: return ""; } } /** * 根据Word文档中的Run样式创建PDF字体 * * @param run Word文档中的文本块 * @return PDF字体 */ private static Font createPDFFontFromRun(XWPFRun run) { // 获取字体大小,默认为12 int fontSize = 12; if (run.getFontSize() != -1) { fontSize = run.getFontSize(); } // 设置字体样式 int fontStyle = Font.NORMAL; if (run.isBold() && run.isItalic()) { fontStyle = Font.BOLDITALIC; } else if (run.isBold()) { fontStyle = Font.BOLD; } else if (run.isItalic()) { fontStyle = Font.ITALIC; } // 创建字体 Font font = PDFUtils.getFont(fontSize); font.setStyle(fontStyle); // 处理字体颜色 if (run.getColor() != null) { // 注意:Word中的颜色格式与PDF中的颜色格式可能不同 // 这里简化处理,实际应用中可能需要转换颜色格式 } return font; } public void pushRd(OutWordRdDetails data, HttpServletResponse response,String uploadPath) { String attName = data.getRdName()+new Date().getTime() + ".pdf"; String realFileName = uploadPath+"/tmp/"+new Date().getTime() + ".pdf"; response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); Document document=new Document(); try { FileUtils.setAttachmentResponseHeader(response, data.getRdName(),attName); FileOutputStream outputStream = new FileOutputStream(realFileName); PdfWriter.getInstance(document, outputStream); document.open(); Paragraph paragraph = new Paragraph(data.getRdName(), getTitleFont()); paragraph.setAlignment(1); document.add(paragraph); addPDFDocument(document,"项目起止时间: ",data.getStartEndTime()); addPDFDocument(document,"公司名称: ",data.getUserName()); addPDFDocument(document,"项目负责人: ",data.getConsultantName()); addPDFDocument(document,"技术领域: ",data.getTechnicalField()); addPDFDocument(document,"技术来源: ",data.getTechnologySource()); addPDFDocument(document,"研发费用总预计: ",data.getTotalAmount().toEngineeringString()+" 万元"); addPDFDocument(document,"研发目的/立项目的/实施方式",null); addPDFContent(document," "+data.getRdObjective()); addPDFDocument(document,"核心技术/创新点",null); addPDFContent(document," "+data.getCoreTechnology()); addPDFDocument(document,"成果",null); addPDFContent(document," "+data.getAchieveResults()); document.close(); outputStream.close(); FileUtils.writeBytes(realFileName, response.getOutputStream()); FileUtils.deleteFile(realFileName); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void addPDFDocument(Document document, String key, String value) throws DocumentException { if(key!=null) { document.add(new Chunk(key, getBigFont())); } Phrase phrase = new Phrase(value, getFont()); phrase.setLeading(40); if(value!=null)document.add(phrase); document.add(Chunk.NEWLINE); } private static void addPDFDocument(Document document, String value) throws DocumentException { Phrase phrase = new Phrase(value, getFont()); phrase.setLeading(40); if(value!=null)document.add(phrase); document.add(Chunk.NEWLINE); } private void addPDFContent(Document document, String value) throws DocumentException { Phrase phrase = new Phrase(value, getFont()); phrase.setLeading(25); if(value!=null)document.add(phrase); document.add(Chunk.NEWLINE); document.add(Chunk.NEWLINE); } public static Font getTitleFont(){ return setFont(24,Font.NORMAL); } public static Font getBigFont(){ return setFont(16,Font.NORMAL); } public static Font getFont(){ Font font =setFont(12,Font.NORMAL); return font; } public static Font getFont(int size){ Font font =setFont(size,Font.NORMAL); return font; } /** * * @param size 大小 * @return */ public static Font setFont(Integer size,Integer style){ BaseFont baseFont = null; Font font=null; try { baseFont=BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); font=new Font(baseFont,size,style); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return font; } private static String CHECKNO="报销编号:"; private static String APPLYDEP="申请部门:"; private static String ANAME="报销人:"; private static String CREATETIME="报销日期:"; private static String REMARKS="报销事由:"; private static String BANK_ACCOUNT="收款方式:"; private static String BLANK=" "; public static void pushExpenseTitle(Document document, MainExpenseAccount mainExpenseAccount) throws DocumentException { StringBuilder builder = new StringBuilder(); builder.append(CHECKNO).append(mainExpenseAccount.getCheckNo()).append(BLANK) .append(APPLYDEP).append(mainExpenseAccount.getApplyDepName()).append(BLANK).append(BLANK).append(BLANK) .append(ANAME).append(mainExpenseAccount.getAname()); Paragraph tile1=new Paragraph(builder.toString(),getFont(8)); document.add(tile1); String creactTime= DateUtils.formatDate(mainExpenseAccount.getCreateTime(), AFTConstants.YYYYMMDD); int x2 = CREATETIME.length() + creactTime.length()/2 + REMARKS.length() + mainExpenseAccount.getRemarks().length() + BANK_ACCOUNT.length() + mainExpenseAccount.getBank().length() + mainExpenseAccount.getAccounts().length()/2 + mainExpenseAccount.getName().length(); builder.setLength(0); if (x2>55){ builder.append(CREATETIME).append(creactTime).append(BLANK) .append(REMARKS).append(mainExpenseAccount.getRemarks()).append(BLANK) .append(BANK_ACCOUNT).append(mainExpenseAccount.getBank()).append(BLANK) .append(mainExpenseAccount.getAccounts()).append(BLANK) .append(mainExpenseAccount.getName()); }else { int y =(60-x2)*2; StringBuilder blank= new StringBuilder(); for (int i = 0; i < y; i++) { blank.append(" "); } builder.append(CREATETIME).append(creactTime).append(blank) .append(REMARKS).append(mainExpenseAccount.getRemarks()).append(blank) .append(BANK_ACCOUNT).append(mainExpenseAccount.getBank()).append(BLANK) .append(mainExpenseAccount.getAccounts()).append(BLANK) .append(mainExpenseAccount.getName()); } Paragraph tile2=new Paragraph(builder.toString(),getFont(8)); document.add(tile2); } }