Java案例如何实现报表?

wen python案例 1

本文目录导读:

Java案例如何实现报表?

  1. 使用Apache POI生成Excel报表(最常用)
  2. 使用JasperReports生成复杂报表(专业级)
  3. 使用EasyExcel(阿里巴巴优化版本)
  4. 使用iText生成PDF报表
  5. 使用DynamicReports(JasperReports的简化版)
  6. 技术选型建议
  7. 最佳实践建议

在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全面

最佳实践建议

  1. 项目初期:使用EasyExcel快速实现简单的Excel导出
  2. 复杂报表需求:采用JasperReports + 可视化设计器
  3. 大数据量场景:使用分页导出 + EasyExcel的流式写入
  4. PDF报表:考虑iText或JasperReports
  5. Web报表:可以引入ECharts等前端图表库实现可视化

选择方案时需考虑:数据量大小、报表复杂度、团队技术栈、维护成本等因素。

抱歉,评论功能暂时关闭!