Java 导出PDF 1、内容可以插入自定义表格 2、内容插入图片

Java PDF导出工具:自定义表格与图片插入

下面我将实现一个Java PDF导出工具,支持插入自定义表格和图片的功能。这个解决方案使用iText 7库,提供了一个直观的用户界面,可以预览生成的PDF内容。

java 复制代码
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;

public class PDFExporter extends JFrame {

    private JTable table;
    private DefaultTableModel tableModel;
    private JTextArea previewArea;
    private List<String> imagePaths = new ArrayList<>();
    private PdfFont font;
    private PdfFont titleFont;

    public PDFExporter() {
        super("PDF导出工具 - 支持自定义表格与图片插入");
        setSize(900, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        initFonts();
        initUI();
    }

    private void initFonts() {
        try {
            // 创建字体(实际应用中应使用支持中文的字体文件)
            font = PdfFontFactory.createFont();
            titleFont = PdfFontFactory.createFont(PdfFontFactory.HELVETICA_BOLD);
        } catch (Exception e) {
            e.printStackTrace();
            font = PdfFontFactory.createFont(PdfFontFactory.COURIER);
            titleFont = PdfFontFactory.createFont(PdfFontFactory.COURIER_BOLD);
        }
    }

    private void initUI() {
        // 创建主面板
        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

        // 创建顶部面板
        JPanel topPanel = new JPanel(new BorderLayout(10, 10));
        
        // 表格模型
        String[] columns = {"书名", "作者", "价格 (¥)", "出版年份", "评分"};
        tableModel = new DefaultTableModel(columns, 0);
        table = new JTable(tableModel);
        table.setRowHeight(30);
        table.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        
        // 添加示例数据
        addSampleData();
        
        JScrollPane tableScroll = new JScrollPane(table);
        tableScroll.setBorder(BorderFactory.createTitledBorder("自定义表格数据"));
        topPanel.add(tableScroll, BorderLayout.CENTER);
        
        // 表格操作按钮
        JPanel tableButtonPanel = new JPanel(new GridLayout(5, 1, 5, 5));
        JButton addRowBtn = new JButton("添加行");
        JButton deleteRowBtn = new JButton("删除行");
        JButton addImageBtn = new JButton("添加图片");
        JButton previewBtn = new JButton("预览PDF");
        JButton exportBtn = new JButton("导出PDF");
        
        addRowBtn.addActionListener(e -> tableModel.addRow(new Object[]{"", "", "", "", ""}));
        deleteRowBtn.addActionListener(e -> {
            int row = table.getSelectedRow();
            if (row != -1) {
                tableModel.removeRow(row);
            }
        });
        addImageBtn.addActionListener(e -> addImage());
        previewBtn.addActionListener(e -> previewPDF());
        exportBtn.addActionListener(e -> exportPDF());
        
        tableButtonPanel.add(addRowBtn);
        tableButtonPanel.add(deleteRowBtn);
        tableButtonPanel.add(addImageBtn);
        tableButtonPanel.add(previewBtn);
        tableButtonPanel.add(exportBtn);
        topPanel.add(tableButtonPanel, BorderLayout.EAST);
        
        // 预览区域
        previewArea = new JTextArea();
        previewArea.setFont(new Font("等线", Font.PLAIN, 14));
        previewArea.setEditable(false);
        previewArea.setBackground(new Color(240, 240, 240));
        previewArea.setBorder(BorderFactory.createTitledBorder("PDF预览内容"));
        
        JScrollPane previewScroll = new JScrollPane(previewArea);
        previewScroll.setPreferredSize(new Dimension(0, 200));
        
        // 添加组件到主面板
        mainPanel.add(topPanel, BorderLayout.CENTER);
        mainPanel.add(previewScroll, BorderLayout.SOUTH);
        
        add(mainPanel);
        
        // 状态栏
        JLabel statusBar = new JLabel("就绪 | 添加表格数据并插入图片,然后导出PDF");
        statusBar.setBorder(BorderFactory.createEtchedBorder());
        add(statusBar, BorderLayout.SOUTH);
        
        updatePreview();
    }
    
    private void addSampleData() {
        Object[][] data = {
            {"Java核心技术", "Cay S. Horstmann", "128.50", "2022", "4.8"},
            {"Effective Java", "Joshua Bloch", "99.80", "2018", "4.9"},
            {"深入理解Java虚拟机", "周志明", "119.00", "2019", "4.7"},
            {"Spring实战", "Craig Walls", "89.90", "2020", "4.6"},
            {"Python编程:从入门到实践", "Eric Matthes", "75.00", "2021", "4.7"}
        };
        
        for (Object[] row : data) {
            tableModel.addRow(row);
        }
    }
    
    private void addImage() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("选择要插入的图片");
        fileChooser.setMultiSelectionEnabled(true);
        
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            for (File file : fileChooser.getSelectedFiles()) {
                imagePaths.add(file.getAbsolutePath());
            }
            updatePreview();
            JOptionPane.showMessageDialog(this, "已添加 " + fileChooser.getSelectedFiles().length + " 张图片", "添加图片", JOptionPane.INFORMATION_MESSAGE);
        }
    }
    
    private void updatePreview() {
        StringBuilder sb = new StringBuilder();
        sb.append("PDF 内容预览:\n");
        sb.append("----------------------------------------\n");
        sb.append("标题: 图书清单报告\n\n");
        
        sb.append("表格数据 (").append(tableModel.getRowCount()).append(" 行):\n");
        for (int col = 0; col < tableModel.getColumnCount(); col++) {
            sb.append(String.format("%-20s", tableModel.getColumnName(col)));
        }
        sb.append("\n");
        
        for (int row = 0; row < tableModel.getRowCount(); row++) {
            for (int col = 0; col < tableModel.getColumnCount(); col++) {
                Object value = tableModel.getValueAt(row, col);
                sb.append(String.format("%-20s", value != null ? value.toString() : ""));
            }
            sb.append("\n");
        }
        
        sb.append("\n图片列表 (").append(imagePaths.size()).append(" 张):\n");
        for (String path : imagePaths) {
            sb.append("• ").append(new File(path).getName()).append("\n");
        }
        
        previewArea.setText(sb.toString());
    }
    
    private void previewPDF() {
        try {
            File tempFile = File.createTempFile("pdf_preview", ".pdf");
            createPDF(tempFile.getAbsolutePath());
            
            if (Desktop.isDesktopSupported()) {
                Desktop.getDesktop().open(tempFile);
            } else {
                JOptionPane.showMessageDialog(this, 
                    "PDF预览已生成: " + tempFile.getAbsolutePath(), 
                    "预览生成成功", 
                    JOptionPane.INFORMATION_MESSAGE);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, 
                "生成预览时出错: " + ex.getMessage(), 
                "错误", 
                JOptionPane.ERROR_MESSAGE);
        }
    }
    
    private void exportPDF() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("保存PDF文件");
        fileChooser.setSelectedFile(new File("图书清单报告.pdf"));
        
        int result = fileChooser.showSaveDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();
            String filePath = file.getAbsolutePath();
            
            if (!filePath.toLowerCase().endsWith(".pdf")) {
                filePath += ".pdf";
            }
            
            try {
                createPDF(filePath);
                JOptionPane.showMessageDialog(this, 
                    "PDF导出成功: " + filePath, 
                    "导出成功", 
                    JOptionPane.INFORMATION_MESSAGE);
                
                if (Desktop.isDesktopSupported()) {
                    Desktop.getDesktop().open(new File(filePath));
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(this, 
                    "导出PDF时出错: " + ex.getMessage(), 
                    "错误", 
                    JOptionPane.ERROR_MESSAGE);
            }
        }
    }
    
    private void createPDF(String filePath) throws Exception {
        try (PdfWriter writer = new PdfWriter(filePath);
             PdfDocument pdf = new PdfDocument(writer);
             Document document = new Document(pdf)) {
            
            // 设置文档属性
            document.setMargins(50, 50, 50, 50);
            
            // 添加标题
            Paragraph title = new Paragraph("图书清单报告")
                .setFont(titleFont)
                .setFontSize(24)
                .setTextAlignment(TextAlignment.CENTER)
                .setFontColor(ColorConstants.DARK_GRAY)
                .setMarginBottom(20);
            document.add(title);
            
            // 添加副标题
            Paragraph subtitle = new Paragraph("自定义表格与图片展示")
                .setFont(font)
                .setFontSize(16)
                .setTextAlignment(TextAlignment.CENTER)
                .setFontColor(ColorConstants.GRAY)
                .setMarginBottom(30);
            document.add(subtitle);
            
            // 添加表格
            addTableToDocument(document);
            
            // 添加图片
            addImagesToDocument(document);
            
            // 添加页脚
            Paragraph footer = new Paragraph("生成时间: " + new java.util.Date())
                .setFont(font)
                .setFontSize(10)
                .setTextAlignment(TextAlignment.CENTER)
                .setFontColor(ColorConstants.LIGHT_GRAY)
                .setMarginTop(30);
            document.add(footer);
        }
    }
    
    private void addTableToDocument(Document document) {
        // 创建表格
        float[] columnWidths = {3, 2, 1, 1, 1};
        Table pdfTable = new Table(UnitValue.createPercentArray(columnWidths));
        pdfTable.setWidth(UnitValue.createPercentValue(100));
        pdfTable.setMarginBottom(30);
        
        // 添加表头
        for (int col = 0; col < tableModel.getColumnCount(); col++) {
            Cell headerCell = new Cell()
                .add(new Paragraph(tableModel.getColumnName(col))
                .setFont(titleFont)
                .setFontSize(12)
                .setBackgroundColor(new com.itextpdf.kernel.color.Color(230, 230, 230))
                .setTextAlignment(TextAlignment.CENTER);
            pdfTable.addHeaderCell(headerCell);
        }
        
        // 添加表格数据
        for (int row = 0; row < tableModel.getRowCount(); row++) {
            for (int col = 0; col < tableModel.getColumnCount(); col++) {
                Object value = tableModel.getValueAt(row, col);
                String text = value != null ? value.toString() : "";
                
                Cell dataCell = new Cell()
                    .add(new Paragraph(text))
                    .setFont(font)
                    .setFontSize(11);
                
                // 设置特殊列的样式
                if (col == 2) { // 价格列
                    dataCell.setTextAlignment(TextAlignment.RIGHT);
                } else if (col == 4) { // 评分列
                    try {
                        double rating = Double.parseDouble(text);
                        if (rating >= 4.5) {
                            dataCell.setFontColor(ColorConstants.GREEN);
                        } else if (rating >= 4.0) {
                            dataCell.setFontColor(ColorConstants.BLUE);
                        } else {
                            dataCell.setFontColor(ColorConstants.ORANGE);
                        }
                    } catch (NumberFormatException e) {
                        // 忽略格式错误
                    }
                    dataCell.setTextAlignment(TextAlignment.CENTER);
                } else {
                    dataCell.setTextAlignment(TextAlignment.LEFT);
                }
                
                pdfTable.addCell(dataCell);
            }
        }
        
        document.add(pdfTable);
    }
    
    private void addImagesToDocument(Document document) throws Exception {
        if (imagePaths.isEmpty()) return;
        
        // 添加图片标题
        Paragraph imageTitle = new Paragraph("图书封面")
            .setFont(titleFont)
            .setFontSize(16)
            .setMarginBottom(15);
        document.add(imageTitle);
        
        // 添加图片
        for (String path : imagePaths) {
            if (!Files.exists(Paths.get(path))) continue;
            
            try {
                ImageData imageData = ImageDataFactory.create(path);
                Image pdfImage = new Image(imageData);
                
                // 调整图片大小(最大宽度400px,保持宽高比)
                float width = pdfImage.getImageWidth();
                float height = pdfImage.getImageHeight();
                float maxWidth = 400;
                
                if (width > maxWidth) {
                    float ratio = maxWidth / width;
                    pdfImage.scale(ratio, ratio);
                }
                
                // 居中显示
                pdfImage.setHorizontalAlignment(com.itextpdf.layout.property.HorizontalAlignment.CENTER);
                pdfImage.setMarginBottom(20);
                
                document.add(pdfImage);
            } catch (Exception e) {
                System.err.println("无法加载图片: " + path);
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            PDFExporter exporter = new PDFExporter();
            exporter.setVisible(true);
        });
    }
}

使用说明

要运行此程序,您需要以下依赖项:

  1. iText 7 Core库 (用于PDF生成)
  2. Java Swing (用于GUI)

Maven依赖配置

xml 复制代码
<dependencies>
    <!-- iText 7 Core -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext7-core</artifactId>
        <version>7.2.5</version>
        <type>pom</type>
    </dependency>
    
    <!-- 其他必要的依赖项 -->
</dependencies>

程序功能

  1. 表格自定义

    • 添加/删除表格行
    • 编辑表格内容
    • 支持多列数据
  2. 图片插入

    • 添加多张图片
    • 自动调整图片大小
    • 保持图片宽高比
  3. PDF操作

    • 预览生成的PDF
    • 导出PDF文件
    • 自动打开生成的PDF
  4. 用户界面

    • 表格数据编辑区
    • PDF内容预览区
    • 操作按钮面板

使用步骤

  1. 在表格中编辑或添加图书数据
  2. 点击"添加图片"按钮插入图书封面
  3. 使用"预览PDF"查看效果
  4. 满意后点击"导出PDF"保存文件

程序会自动为表格添加样式,并根据评分值显示不同颜色,使生成的PDF更具可读性。

注意:实际使用中,您可能需要添加中文字体支持以正确显示中文内容。

相关推荐
编程大师哥3 分钟前
vxe-table 透视表分组汇总及排序基础配置
java
8***848217 分钟前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
9***J62819 分钟前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
M***Z21030 分钟前
SQL 建表语句详解
java·数据库·sql
v***79430 分钟前
Spring Boot 热部署
java·spring boot·后端
执笔论英雄31 分钟前
【RL】python协程
java·网络·人工智能·python·设计模式
galaxyffang42 分钟前
认证、会话管理、授权的区别
java
未名编程1 小时前
Windows 下如何部署 Nacos 并导入配置文件
java·windows
boonya1 小时前
Java中Plugin设计模式的规范应用
java·spring·设计模式·插件模式
杰克尼1 小时前
3. 分巧克力
java·数据结构·算法