在Java项目开发中,将学生成绩单导出为PDF格式是教务类系统的常见功能需求,需要保证导出的报表布局清晰、数据准确,同时支持中文、数字、特殊符号等各类内容的正常显示。实现该功能通常会选择iText这类成熟的PDF操作库,它提供了丰富的API用于构建PDF文档结构、绘制表格、设置字体样式。

一、环境准备与依赖引入
首先需要引入iText相关的依赖,这里以iText 7为例,在Maven项目的pom.xml中添加如下依赖:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.5</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>font-asian</artifactId>
<version>7.2.5</version>
</dependency>
第二个依赖是用于支持中文字体的亚洲字体包,避免后续出现中文无法显示的问题。
二、成绩单PDF报表生成核心步骤
1. 创建PDF文档基础结构
首先需要初始化PDF文档对象,设置页面大小、边距等基础属性,代码如下:
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import java.io.File;
import java.io.FileNotFoundException;
public class ScoreExportUtil {
public static void createScorePdf(String outputPath) throws FileNotFoundException {
// 初始化PdfWriter,指定输出路径
PdfWriter writer = new PdfWriter(new File(outputPath));
// 创建PdfDocument对象
PdfDocument pdf = new PdfDocument(writer);
// 创建Document对象,用于操作PDF内容
Document document = new Document(pdf);
// 设置页面边距,上、右、下、左分别为20、20、20、20
document.setMargins(20, 20, 20, 20);
// 添加成绩单标题
Paragraph title = new Paragraph("学生成绩单");
title.setTextAlignment(TextAlignment.CENTER);
title.setFontSize(18);
document.add(title);
// 后续添加表格等内容
// 关闭文档,释放资源
document.close();
}
}
2. 构建成绩单表格
成绩单通常包含学生基本信息、各科成绩、总分、排名等内容,使用表格布局最为合适,iText提供了<Table>类用于创建表格,示例代码如下:
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.kernel.colors.ColorConstants;
public static void addScoreTable(Document document) {
// 创建4列的表格,列宽比例为2:1:1:1
float[] columnWidths = {2f, 1f, 1f, 1f};
Table table = new Table(columnWidths);
// 设置表格宽度为页面宽度的100%
table.setWidth(100);
// 添加表头
String[] headers = {"科目", "分数", "班级排名", "年级排名"};
for (String header : headers) {
Cell cell = new Cell();
cell.add(new Paragraph(header));
cell.setBackgroundColor(ColorConstants.LIGHT_GRAY);
cell.setTextAlignment(TextAlignment.CENTER);
table.addCell(cell);
}
// 添加示例成绩数据
String[][] scoreData = {
{"语文", "92", "5", "12"},
{"数学", "88", "8", "20"},
{"英语", "95", "3", "8"},
{"物理", "85", "10", "25"},
{"总分", "360", "6", "15"}
};
for (String[] row : scoreData) {
for (String cellContent : row) {
Cell cell = new Cell();
cell.add(new Paragraph(cellContent));
cell.setTextAlignment(TextAlignment.CENTER);
table.addCell(cell);
}
}
document.add(table);
}
三、字体支持细节配置
很多开发者在使用iText导出PDF时会遇到中文无法显示的问题,这是因为默认字体不支持中文,需要手动配置中文字体,具体有两种常用方式。
1. 使用内置亚洲字体
iText的font-asian包内置了支持中文的字体,可直接调用,示例代码如下:
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.io.font.PdfEncodings;
import java.io.IOException;
public static PdfFont getChineseFont() throws IOException {
// 使用内置的宋体字体,支持中文
PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true);
return font;
}
创建字体后,将其设置到对应的文本元素上即可:
Paragraph title = new Paragraph("学生成绩单");
title.setFont(getChineseFont());
title.setFontSize(18);
title.setTextAlignment(TextAlignment.CENTER);
document.add(title);
2. 加载自定义字体文件
如果需要使用项目内的自定义字体文件,比如微软雅黑,可将字体文件放到resources目录下,通过路径加载:
import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
public static PdfFont getCustomFont() throws IOException {
// 加载resources目录下的微软雅黑字体文件
FontProgram fontProgram = FontProgramFactory.createFont("msyh.ttf");
PdfFont font = PdfFontFactory.createFont(fontProgram, PdfEncodings.IDENTITY_H, true);
return font;
}
四、完整导出示例与注意事项
将上述步骤整合后,完整的成绩单导出代码如下:
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.io.font.PdfEncodings;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ScoreExportUtil {
public static void exportScorePdf(String outputPath) throws FileNotFoundException, IOException {
PdfWriter writer = new PdfWriter(new File(outputPath));
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
document.setMargins(20, 20, 20, 20);
// 设置中文字体
PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true);
// 添加标题
Paragraph title = new Paragraph("学生成绩单");
title.setFont(chineseFont);
title.setFontSize(18);
title.setTextAlignment(com.itextpdf.layout.property.TextAlignment.CENTER);
document.add(title);
// 添加学生基本信息
Paragraph info = new Paragraph("姓名:张三 学号:20230101 班级:三年级一班");
info.setFont(chineseFont);
info.setFontSize(12);
document.add(info);
// 添加成绩表格
float[] columnWidths = {2f, 1f, 1f, 1f};
Table table = new Table(columnWidths);
table.setWidth(100);
String[] headers = {"科目", "分数", "班级排名", "年级排名"};
for (String header : headers) {
Cell cell = new Cell();
cell.add(new Paragraph(header).setFont(chineseFont));
cell.setBackgroundColor(ColorConstants.LIGHT_GRAY);
cell.setTextAlignment(com.itextpdf.layout.property.TextAlignment.CENTER);
table.addCell(cell);
}
String[][] scoreData = {
{"语文", "92", "5", "12"},
{"数学", "88", "8", "20"},
{"英语", "95", "3", "8"},
{"物理", "85", "10", "25"},
{"总分", "360", "6", "15"}
};
for (String[] row : scoreData) {
for (String cellContent : row) {
Cell cell = new Cell();
cell.add(new Paragraph(cellContent).setFont(chineseFont));
cell.setTextAlignment(com.itextpdf.layout.property.TextAlignment.CENTER);
table.addCell(cell);
}
}
document.add(table);
// 关闭文档
document.close();
}
public static void main(String[] args) {
try {
exportScorePdf("D:/score.pdf");
System.out.println("成绩单导出成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
需要注意,导出路径需要保证目录存在,否则会抛出文件找不到的异常,可在导出前添加目录校验逻辑。另外如果导出的内容包含特殊符号,也需要确认字体是否支持对应的字符集,避免出现乱码情况。