|
|
@@ -5,20 +5,394 @@ 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.docx4j.Docx4J;
|
|
|
+import org.docx4j.openpackaging.exceptions.Docx4JException;
|
|
|
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
|
|
import org.springframework.http.MediaType;
|
|
|
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
-import java.io.FileNotFoundException;
|
|
|
-import java.io.FileOutputStream;
|
|
|
-import java.io.IOException;
|
|
|
+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<XWPFParagraph> 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<XWPFTable> tables = xwpfDocument.getTables();
|
|
|
+ for (XWPFTable table : tables) {
|
|
|
+ // 处理表格中的每一行
|
|
|
+ java.util.List<XWPFTableRow> rows = table.getRows();
|
|
|
+ for (XWPFTableRow row : rows) {
|
|
|
+ StringBuilder rowText = new StringBuilder();
|
|
|
+ java.util.List<XWPFTableCell> 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(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++) {
|
|
|
+ if (j==1||j==0){
|
|
|
+ columnWidths[j] = 30f;
|
|
|
+ }else {
|
|
|
+ columnWidths[j] = 10f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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);
|
|
|
+ Font font = PDFUtils.getFont(10);
|
|
|
+ PdfPCell pdfCell = new PdfPCell(new Phrase(cellValue, font));
|
|
|
+ pdfCell.setPadding(1);
|
|
|
+
|
|
|
+ // 设置表头样式
|
|
|
+ if (rowCount == 0) {
|
|
|
+ pdfCell.setBackgroundColor(BaseColor.LIGHT_GRAY);
|
|
|
+ pdfCell.setHorizontalAlignment(Element.ALIGN_CENTER);
|
|
|
+ //第一行合并
|
|
|
+ pdfCell.setColspan(columnCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 static void newConvertWordToPDF(String s, String s1) {
|
|
|
+ try (FileOutputStream fos = new FileOutputStream(s1)) {
|
|
|
+ WordprocessingMLPackage wordMLPackage = Docx4J.load(new File(s));
|
|
|
+ Docx4J.toPDF(wordMLPackage, fos);
|
|
|
+ } catch (Docx4JException e) {
|
|
|
+ throw new RuntimeException("转换Word文档到PDF失败: " + s, e);
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ throw new RuntimeException("找不到文件: " + s + " 或 " + s1, e);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("写入PDF文件时发生IO错误: " + s1, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
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";
|
|
|
@@ -68,6 +442,13 @@ public class PDFUtils {
|
|
|
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);
|
|
|
@@ -162,5 +543,4 @@ public class PDFUtils {
|
|
|
Paragraph tile2=new Paragraph(builder.toString(),getFont(8));
|
|
|
document.add(tile2);
|
|
|
}
|
|
|
-
|
|
|
}
|