本文目录导读:

- 使用Apache POI生成Excel报表(最常用)
- 使用JasperReports生成复杂报表(专业级)
- 使用EasyExcel(阿里巴巴优化版本)
- 使用iText生成PDF报表
- 使用DynamicReports(JasperReports的简化版)
- 技术选型建议
- 最佳实践建议
在Java中实现报表有多种方式,从简单的CSV导出到复杂的企业级BI报表平台,以下是几种主流的实现方案和具体案例:
使用Apache POI生成Excel报表(最常用)
依赖配置 (Maven)
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
案例:生成销售报表
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.time.LocalDate;
import java.util.List;
public class SalesReportGenerator {
public void generateSalesReport(List<SalesData> salesDataList, String filePath) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("销售报表");
// 1. 创建样式
CellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerStyle.setFont(createBoldFont(workbook));
// 2. 创建标题行
Row headerRow = sheet.createRow(0);
String[] headers = {"日期", "产品名称", "数量", "单价", "总金额"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerStyle);
}
// 3. 填充数据
int rowNum = 1;
for (SalesData data : salesDataList) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(data.getDate().toString());
row.createCell(1).setCellValue(data.getProductName());
row.createCell(2).setCellValue(data.getQuantity());
row.createCell(3).setCellValue(data.getUnitPrice());
row.createCell(4).setCellValue(data.getAmount());
}
// 4. 设置列宽
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i);
}
// 5. 写入文件
try (FileOutputStream fos = new FileOutputStream(filePath)) {
workbook.write(fos);
} catch (Exception e) {
e.printStackTrace();
}
// 6. 关闭工作簿
try {
workbook.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private Font createBoldFont(Workbook workbook) {
Font font = workbook.createFont();
font.setBold(true);
font.setFontHeightInPoints((short) 14);
return font;
}
}
// 数据模型
class SalesData {
private LocalDate date;
private String productName;
private int quantity;
private double unitPrice;
private double amount;
// getters and setters
}
使用JasperReports生成复杂报表(专业级)
依赖配置
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.21.0</version>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-fonts</artifactId>
<version>6.21.0</version>
</dependency>
案例:生成PDF报表
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
public class JasperReportExample {
public void generateReport(List<Employee> employees, String reportPath) {
try {
// 1. 编译jrxml文件(需先设计报表模板)
JasperReport jasperReport = JasperCompileManager
.compileReport("reports/employee_report.jrxml");
// 2. 准备数据源
JRBeanCollectionDataSource dataSource =
new JRBeanCollectionDataSource(employees);
// 3. 设置参数(可选)
JRParameter param = new JRParameter();
Map<String, Object> parameters = new HashMap<>();
parameters.put("TITLE", "员工信息报表");
parameters.put("COMPANY", "某科技有限公司");
// 4. 填充报表
JasperPrint jasperPrint = JasperFillManager
.fillReport(jasperReport, parameters, dataSource);
// 5. 导出为PDF
JasperExportManager.exportReportToPdfFile(jasperPrint, reportPath);
// 或导出为HTML
// JasperExportManager.exportReportToHtmlFile(jasperPrint, reportPath);
System.out.println("报表生成成功!");
} catch (JRException e) {
e.printStackTrace();
}
}
}
// 数据模型
class Employee {
private int id;
private String name;
private String department;
private double salary;
private LocalDate hireDate;
// getters and setters
}
报表模板设计 (employee_report.jrxml)
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports"
name="employee_report" pageWidth="595" pageHeight="842">
<parameter name="TITLE" class="java.lang.String"/>
<parameter name="COMPANY" class="java.lang.String"/>
<queryString>
<![CDATA[]]>
</queryString>
<field name="id" class="java.lang.Integer"/>
<field name="name" class="java.lang.String"/>
<field name="department" class="java.lang.String"/>
<field name="salary" class="java.lang.Double"/>
<band height="50">
<textField>
<reportElement x="0" y="0" width="515" height="30"/>
<textElement textAlignment="Center">
<font size="18" isBold="true"/>
</textElement>
<textFieldExpression>
<![CDATA[$P{TITLE}]]>
</textFieldExpression>
</textField>
</band>
</title>
<columnHeader>
<band height="20">
<staticText>
<reportElement x="0" y="0" width="100" height="20"/>
<text>ID</text>
</staticText>
<staticText>
<reportElement x="100" y="0" width="150" height="20"/>
<text>姓名</text>
</staticText>
<staticText>
<reportElement x="250" y="0" width="150" height="20"/>
<text>部门</text>
</staticText>
<staticText>
<reportElement x="400" y="0" width="115" height="20"/>
<text>薪资</text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="20">
<textField>
<reportElement x="0" y="0" width="100" height="20"/>
<textFieldExpression>
<![CDATA[$F{id}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="150" height="20"/>
<textFieldExpression>
<![CDATA[$F{name}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="250" y="0" width="150" height="20"/>
<textFieldExpression>
<![CDATA[$F{department}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="400" y="0" width="115" height="20"/>
<textFieldExpression>
<![CDATA[$F{salary}]]>
</textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
使用EasyExcel(阿里巴巴优化版本)
依赖配置
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.4</version>
</dependency>
案例:大数据量导出
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
public class EasyExcelExample {
// 1. 定义导出模型
@Data
public static class OrderData {
@ExcelProperty("订单编号")
private String orderId;
@ExcelProperty("客户名称")
private String customerName;
@ExcelProperty("订单金额")
private BigDecimal amount;
@ExcelProperty("订单日期")
private Date orderDate;
@ExcelProperty("状态")
private String status;
}
// 2. 简单导出
public void simpleExport(List<OrderData> dataList, String fileName) {
EasyExcel.write(fileName, OrderData.class)
.sheet("订单列表")
.doWrite(dataList);
}
// 3. 复杂样式导出
public void styledExport(List<OrderData> dataList, String fileName) {
// 自定义样式
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
// 设置策略
WriteHandler writeHandler = new AbstractVerticalWriteHandler() {
// 自定义处理逻辑
};
EasyExcel.write(fileName, OrderData.class)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自适应列宽
.sheet("报表")
.doWrite(dataList);
}
// 4. Web下载
public void exportToWeb(HttpServletResponse response, List<OrderData> dataList) {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition",
"attachment;filename=" + URLEncoder.encode("订单报表.xlsx", "UTF-8"));
try {
EasyExcel.write(response.getOutputStream(), OrderData.class)
.sheet("报表")
.doWrite(dataList);
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用iText生成PDF报表
依赖配置
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.5</version>
</dependency>
案例:生成发票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.element.Table;
import com.itextpdf.layout.property.UnitValue;
public class PDFInvoiceExample {
public void generateInvoice(Invoice invoice, String filePath) {
try {
PdfWriter writer = new PdfWriter(filePath);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
// 添加标题
document.add(new Paragraph("发票")
.setFontSize(20)
.setBold()
.setTextAlignment(TextAlignment.CENTER));
// 添加客户信息
document.add(new Paragraph("客户名称: " + invoice.getCustomerName()));
document.add(new Paragraph("发票日期: " + invoice.getDate()));
document.add(new Paragraph("发票编号: " + invoice.getInvoiceNo()));
// 创建表格
float[] columnWidths = {2, 1, 1, 1};
Table table = new Table(UnitValue.createPercentArray(columnWidths));
// 添加表头
table.addHeaderCell("商品名称");
table.addHeaderCell("数量");
table.addHeaderCell("单价");
table.addHeaderCell("金额");
// 添加数据行
for (InvoiceItem item : invoice.getItems()) {
table.addCell(item.getProductName());
table.addCell(String.valueOf(item.getQuantity()));
table.addCell(String.valueOf(item.getUnitPrice()));
table.addCell(String.valueOf(item.getAmount()));
}
document.add(table);
// 添加总计
document.add(new Paragraph("总计金额: " + invoice.getTotalAmount())
.setBold()
.setTextAlignment(TextAlignment.RIGHT));
document.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用DynamicReports(JasperReports的简化版)
依赖配置
<dependency>
<groupId>net.sourceforge.dynamicreports</groupId>
<artifactId>dynamicreports-core</artifactId>
<version>6.12.1</version>
</dependency>
案例:简洁报表生成
import static net.sf.dynamicreports.report.builder.DynamicReports.*;
public class DynamicReportsExample {
public void generateDynamicReport() {
try {
// 创建报表
JasperReportBuilder report = report()
.title(cmp.text("员工报表").setStyle(stl.style().bold()))
.columns(
col.column("ID", "id", type.integerType()),
col.column("姓名", "name", type.stringType()),
col.column("部门", "department", type.stringType()),
col.column("薪资", "salary", type.bigDecimalType())
)
.title(cmp.text("公司信息").setStyle(stl.style().bold()))
.pageFooter(cmp.pageXofY());
// 填充数据
List<Employee> employees = getEmployeeData();
report.setDataSource(employees);
// 导出为PDF
report.toPdf(new FileOutputStream("dynamic_report.pdf"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
技术选型建议
| 技术方案 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| Apache POI | 简单Excel导出 | 轻量级,灵活 | 代码量较大 |
| JasperReports | 复杂专业报表 | 功能强大,支持多种格式 | 学习曲线陡峭 |
| EasyExcel | 大数据量导出 | 内存优化好,API简洁 | 功能相对有限 |
| iText | PDF生成 | 专业的PDF处理 | 学习成本较高 |
| DynamicReports | 快速开发 | API简洁,易上手 | 功能不如JasperReports全面 |
最佳实践建议
- 项目初期:使用EasyExcel快速实现简单的Excel导出
- 复杂报表需求:采用JasperReports + 可视化设计器
- 大数据量场景:使用分页导出 + EasyExcel的流式写入
- PDF报表:考虑iText或JasperReports
- Web报表:可以引入ECharts等前端图表库实现可视化
选择方案时需考虑:数据量大小、报表复杂度、团队技术栈、维护成本等因素。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播