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);
// 第二行:Logo
JPanel 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;
}
@Override
public 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文档专业且美观。