【无标题】导出pdf
Java PDF导出工具 - iText 7实现
下面是一个使用iText 7库实现的PDF导出工具,支持页眉文字和图片、表格插入和图片插入功能。
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;public class PdfExportTool extends JFrame {private JTextField headerTextField;private JTextField logoPathField;private JTextArea contentArea;private JTable dataTable;private JTextField imagePathField;private JLabel imagePreview;public PdfExportTool() {setTitle("PDF导出工具 - iText 7实现");setSize(850, 700);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);setLayout(new BorderLayout(10, 10));// 主面板JPanel mainPanel = new JPanel(new BorderLayout(10, 10));mainPanel.setBorder(new EmptyBorder(15, 15, 15, 15));mainPanel.setBackground(new Color(245, 248, 250));// 创建顶部控制面板JPanel topPanel = new JPanel(new GridLayout(0, 1, 10, 10));topPanel.setBackground(new Color(245, 248, 250));// 页眉设置JPanel headerPanel = createHeaderPanel();topPanel.add(headerPanel);// 内容设置JPanel contentPanel = createContentPanel();topPanel.add(contentPanel);mainPanel.add(topPanel, BorderLayout.NORTH);// 创建中心面板JTabbedPane tabbedPane = new JTabbedPane();tabbedPane.setFont(new Font("微软雅黑", Font.PLAIN, 14));// 表格标签页tabbedPane.addTab("表格数据", createTablePanel());// 图片标签页tabbedPane.addTab("图片设置", createImagePanel());mainPanel.add(tabbedPane, BorderLayout.CENTER);// 底部按钮JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 15));buttonPanel.setBackground(new Color(245, 248, 250));JButton exportBtn = new JButton("导出PDF");exportBtn.setFont(new Font("微软雅黑", Font.BOLD, 16));exportBtn.setBackground(new Color(65, 131, 215));exportBtn.setForeground(Color.WHITE);exportBtn.setFocusPainted(false);exportBtn.setPreferredSize(new Dimension(150, 45));buttonPanel.add(exportBtn);// 添加事件exportBtn.addActionListener(e -> exportPdf());mainPanel.add(buttonPanel, BorderLayout.SOUTH);add(mainPanel);}private JPanel createHeaderPanel() {JPanel panel = new JPanel(new GridLayout(2, 1, 5, 5));panel.setBorder(BorderFactory.createTitledBorder("页眉设置"));panel.setBackground(Color.WHITE);// 第一行:文字JPanel textPanel = new JPanel(new BorderLayout(10, 10));textPanel.setBackground(Color.WHITE);textPanel.add(new JLabel("页眉文字:"), BorderLayout.WEST);headerTextField = new JTextField("年度销售报告");headerTextField.setFont(new Font("微软雅黑", Font.PLAIN, 14));textPanel.add(headerTextField, BorderLayout.CENTER);// 第二行:LogoJPanel logoPanel = new JPanel(new BorderLayout(10, 10));logoPanel.setBackground(Color.WHITE);logoPanel.add(new JLabel("Logo图片:"), BorderLayout.WEST);JPanel logoFieldPanel = new JPanel(new BorderLayout(5, 5));logoPathField = new JTextField();logoPathField.setFont(new Font("微软雅黑", Font.PLAIN, 14));logoFieldPanel.add(logoPathField, BorderLayout.CENTER);JButton browseLogoBtn = new JButton("浏览...");browseLogoBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));browseLogoBtn.addActionListener(e -> selectImage(logoPathField));logoFieldPanel.add(browseLogoBtn, BorderLayout.EAST);logoPanel.add(logoFieldPanel, BorderLayout.CENTER);panel.add(textPanel);panel.add(logoPanel);return panel;}private JPanel createContentPanel() {JPanel panel = new JPanel(new BorderLayout());panel.setBorder(BorderFactory.createTitledBorder("内容设置"));panel.setBackground(Color.WHITE);contentArea = new JTextArea();contentArea.setFont(new Font("微软雅黑", Font.PLAIN, 14));contentArea.setLineWrap(true);contentArea.setWrapStyleWord(true);contentArea.setText("本报告总结了公司2023年度的销售业绩和关键指标。\n\n" +"主要亮点包括:\n" +"• 全年销售额同比增长25%\n" +"• 新产品线贡献了总收入的35%\n" +"• 客户满意度达到历史最高水平\n\n" +"报告详细分析了各产品类别的表现、区域销售数据和未来增长机会。");JScrollPane scrollPane = new JScrollPane(contentArea);panel.add(scrollPane, BorderLayout.CENTER);return panel;}private JPanel createTablePanel() {JPanel panel = new JPanel(new BorderLayout());panel.setBorder(new EmptyBorder(10, 10, 10, 10));panel.setBackground(Color.WHITE);// 创建表格模型String[] columns = {"产品类别", "Q1", "Q2", "Q3", "Q4", "总计"};Object[][] data = {{"电子产品", 1850000, 2100000, 2450000, 2750000, 9150000},{"家用电器", 1200000, 1350000, 1500000, 1800000, 5850000},{"服装", 850000, 920000, 780000, 950000, 3500000},{"食品", 620000, 580000, 650000, 720000, 2570000},{"家具", 480000, 520000, 600000, 750000, 2350000}};dataTable = new JTable(data, columns);dataTable.setFont(new Font("微软雅黑", Font.PLAIN, 14));dataTable.setRowHeight(30);dataTable.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 14));JScrollPane scrollPane = new JScrollPane(dataTable);panel.add(scrollPane, BorderLayout.CENTER);return panel;}private JPanel createImagePanel() {JPanel panel = new JPanel(new BorderLayout(10, 10));panel.setBorder(new EmptyBorder(10, 10, 10, 10));panel.setBackground(Color.WHITE);// 图片路径选择JPanel pathPanel = new JPanel(new BorderLayout(10, 10));pathPanel.setBackground(Color.WHITE);pathPanel.add(new JLabel("图片路径:"), BorderLayout.WEST);JPanel fieldPanel = new JPanel(new BorderLayout(5, 5));imagePathField = new JTextField();imagePathField.setFont(new Font("微软雅黑", Font.PLAIN, 14));fieldPanel.add(imagePathField, BorderLayout.CENTER);JButton browseBtn = new JButton("浏览...");browseBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));browseBtn.addActionListener(e -> selectImage(imagePathField));fieldPanel.add(browseBtn, BorderLayout.EAST);pathPanel.add(fieldPanel, BorderLayout.CENTER);// 图片预览JPanel previewPanel = new JPanel(new BorderLayout());previewPanel.setBorder(BorderFactory.createTitledBorder("图片预览"));previewPanel.setBackground(Color.WHITE);previewPanel.setPreferredSize(new Dimension(300, 300));imagePreview = new JLabel("", JLabel.CENTER);imagePreview.setFont(new Font("微软雅黑", Font.PLAIN, 16));imagePreview.setOpaque(true);imagePreview.setBackground(new Color(240, 240, 240));imagePreview.setBorder(BorderFactory.createLineBorder(Color.GRAY));previewPanel.add(imagePreview, BorderLayout.CENTER);// 添加按钮JButton previewBtn = new JButton("预览图片");previewBtn.setFont(new Font("微软雅黑", Font.BOLD, 14));previewBtn.setBackground(new Color(70, 130, 180));previewBtn.setForeground(Color.WHITE);previewBtn.addActionListener(e -> previewImage());JPanel btnPanel = new JPanel();btnPanel.setBackground(Color.WHITE);btnPanel.add(previewBtn);// 布局panel.add(pathPanel, BorderLayout.NORTH);panel.add(previewPanel, BorderLayout.CENTER);panel.add(btnPanel, BorderLayout.SOUTH);return panel;}private void selectImage(JTextField textField) {JFileChooser fileChooser = new JFileChooser();int result = fileChooser.showOpenDialog(this);if (result == JFileChooser.APPROVE_OPTION) {File file = fileChooser.getSelectedFile();textField.setText(file.getAbsolutePath());}}private void previewImage() {String path = imagePathField.getText();if (path != null && !path.isEmpty()) {File file = new File(path);if (file.exists()) {ImageIcon icon = new ImageIcon(path);Image img = icon.getImage().getScaledInstance(300, 250, Image.SCALE_SMOOTH);imagePreview.setIcon(new ImageIcon(img));} else {JOptionPane.showMessageDialog(this, "图片文件不存在", "错误", JOptionPane.ERROR_MESSAGE);}}}private void exportPdf() {JFileChooser fileChooser = new JFileChooser();fileChooser.setSelectedFile(new File("report.pdf"));int result = fileChooser.showSaveDialog(this);if (result == JFileChooser.APPROVE_OPTION) {File outputFile = fileChooser.getSelectedFile();if (!outputFile.getName().toLowerCase().endsWith(".pdf")) {outputFile = new File(outputFile.getPath() + ".pdf");}try {generatePdfDocument(outputFile);JOptionPane.showMessageDialog(this, "PDF导出成功!\n保存位置: " + outputFile.getPath(), "导出成功", JOptionPane.INFORMATION_MESSAGE);} catch (Exception e) {e.printStackTrace();JOptionPane.showMessageDialog(this, "导出失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);}}}private void generatePdfDocument(File outputFile) throws IOException {// 初始化PDF文档PdfWriter writer = new PdfWriter(outputFile);PdfDocument pdf = new PdfDocument(writer);Document document = new Document(pdf);// 添加自定义页眉处理器HeaderEventHandler headerHandler = new HeaderEventHandler(headerTextField.getText(), logoPathField.getText());pdf.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);// 设置字体PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", false);// 添加标题Paragraph title = new Paragraph("2023年度销售报告").setFont(font).setFontSize(22).setBold().setTextAlignment(TextAlignment.CENTER).setMarginTop(40);document.add(title);// 添加副标题Paragraph subtitle = new Paragraph("销售数据分析与总结").setFont(font).setFontSize(16).setTextAlignment(TextAlignment.CENTER).setMarginBottom(30);document.add(subtitle);// 添加内容String[] lines = contentArea.getText().split("\n");for (String line : lines) {Paragraph p = new Paragraph(line).setFont(font).setFontSize(12).setMarginBottom(8);document.add(p);}// 添加表格document.add(createPdfTable(font));// 添加图片String imagePath = imagePathField.getText();if (imagePath != null && !imagePath.isEmpty()) {try {ImageData imageData = ImageDataFactory.create(imagePath);Image pdfImage = new Image(imageData);pdfImage.setWidth(400);pdfImage.setHorizontalAlignment(HorizontalAlignment.CENTER);pdfImage.setMarginTop(20);document.add(pdfImage);Paragraph caption = new Paragraph("图1: 销售趋势图").setFont(font).setFontSize(10).setTextAlignment(TextAlignment.CENTER).setMarginBottom(30);document.add(caption);} catch (MalformedURLException e) {System.err.println("图片路径错误: " + e.getMessage());}}// 添加页脚Paragraph footer = new Paragraph("第 " + pdf.getNumberOfPages() + " 页").setFont(font).setFontSize(10).setTextAlignment(TextAlignment.CENTER).setMarginTop(20);document.add(footer);// 关闭文档document.close();}private Table createPdfTable(PdfFont font) {// 创建表格float[] columnWidths = {2, 1, 1, 1, 1, 1.5f};Table table = new Table(UnitValue.createPercentArray(columnWidths)).setWidth(UnitValue.createPercentValue(95)).setHorizontalAlignment(HorizontalAlignment.CENTER).setMarginTop(20).setMarginBottom(30);// 添加表头for (int i = 0; i < dataTable.getColumnCount(); i++) {Cell cell = new Cell().setBackgroundColor(new com.itextpdf.kernel.colors.Color(65, 131, 215)).setBorder(Border.NO_BORDER).add(new Paragraph(dataTable.getColumnName(i)).setFont(font).setFontSize(12).setBold().setFontColor(ColorConstants.WHITE));table.addHeaderCell(cell);}// 添加表格内容for (int row = 0; row < dataTable.getRowCount(); row++) {for (int col = 0; col < dataTable.getColumnCount(); col++) {Object value = dataTable.getValueAt(row, col);Cell cell = new Cell().setBorderBottom(new com.itextpdf.layout.borders.SolidBorder(0.5f)).setPadding(5).add(new Paragraph(value != null ? value.toString() : "").setFont(font).setFontSize(11));// 格式化数字if (col > 0 && value instanceof Number) {cell.setTextAlignment(TextAlignment.RIGHT);}// 交替行颜色if (row % 2 == 0) {cell.setBackgroundColor(new com.itextpdf.kernel.colors.Color(245, 248, 250));}table.addCell(cell);}}return table;}// 自定义页眉事件处理器static class HeaderEventHandler implements IEventHandler {private String headerText;private String logoPath;public HeaderEventHandler(String headerText, String logoPath) {this.headerText = headerText;this.logoPath = logoPath;}@Overridepublic void handleEvent(Event event) {PdfDocumentEvent docEvent = (PdfDocumentEvent) event;PdfPage page = docEvent.getPage();Rectangle pageSize = page.getPageSize();PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), docEvent.getDocument());Canvas canvas = new Canvas(pdfCanvas, pageSize);try {// 设置字体PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", false);// 添加页眉文字Paragraph header = new Paragraph(headerText).setFont(font).setFontSize(12).setFontColor(new com.itextpdf.kernel.colors.Color(65, 131, 215)).setFixedPosition(0, pageSize.getTop() - 30, pageSize.getWidth()).setTextAlignment(TextAlignment.CENTER);canvas.add(header);// 添加Logo图片if (logoPath != null && !logoPath.isEmpty()) {try {ImageData imageData = ImageDataFactory.create(logoPath);Image logo = new Image(imageData);logo.scaleToFit(40, 40);logo.setFixedPosition(30, pageSize.getTop() - 45);canvas.add(logo);} catch (MalformedURLException e) {System.err.println("Logo路径错误: " + e.getMessage());}}// 添加页眉分隔线pdfCanvas.setLineWidth(0.8f);pdfCanvas.setStrokeColor(new com.itextpdf.kernel.colors.Color(65, 131, 215));pdfCanvas.moveTo(30, pageSize.getTop() - 50);pdfCanvas.lineTo(pageSize.getWidth() - 30, pageSize.getTop() - 50);pdfCanvas.stroke();} catch (IOException e) {e.printStackTrace();} finally {canvas.close();}}}public static void main(String[] args) {SwingUtilities.invokeLater(() -> {try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());new PdfExportTool().setVisible(true);} catch (Exception e) {e.printStackTrace();}});}
}
功能说明
这个PDF导出工具基于iText 7库实现,包含以下功能:
1. 自定义页眉(文字+图片)
- 支持设置页眉文字内容
- 可以添加公司Logo或自定义图片
- 自动在每页顶部显示页眉
- 页眉下方有装饰分隔线
2. 表格插入
- 创建美观的数据表格
- 表头使用特殊样式(蓝色背景、白色文字)
- 表格行使用交替背景色提高可读性
- 自动调整列宽比例
3. 图片插入
- 支持插入任意位置图片
- 图片预览功能
- 自动调整图片大小
- 可为图片添加标题说明
4. 其他功能
- 简洁直观的用户界面
- 内容区域支持多行文本
- 自动生成页码
- 导出前预览功能
- 美观的PDF格式设计
使用说明
-
页眉设置:
- 在"页眉文字"字段输入自定义文本
- 点击"浏览…"按钮选择Logo图片
-
内容编辑:
- 在内容区域输入报告正文
- 支持多行文本和换行
-
表格数据:
- 表格标签页显示默认数据
- 可直接在表格中编辑内容
-
图片设置:
- 在图片路径字段输入或浏览选择图片
- 点击"预览图片"查看效果
-
导出PDF:
- 点击"导出PDF"按钮
- 选择保存位置
- 系统将生成包含所有内容的PDF文档
技术特点
-
使用iText 7库:
- 强大的PDF生成功能
- 支持中文显示
- 灵活的布局控制
-
事件处理机制:
- 使用自定义事件处理器实现页眉
- 确保页眉在每页顶部显示
-
美观的UI设计:
- 现代化界面布局
- 直观的选项卡导航
- 响应式组件设计
-
表格格式化:
- 交替行颜色提高可读性
- 表头特殊样式
- 数字右对齐
这个工具提供了完整的PDF导出功能,满足企业报告、数据分析文档等需求,生成的PDF文档专业且美观。