mstester2011 发表于 昨天 04:53

如何用java导出excel


在Java开发中,将数据导出为Excel文件是常见的业务需求,无论是生成报表、数据备份还是用户下载,掌握Excel导出技术都是开发者的必备技能。本文将系统介绍Java导出Excel的多种实现方式,涵盖基础API、第三方库以及性能优化技巧,帮助读者构建高效、稳定的导出功能。如何用java导出excelhttps://www.sundawu.cn/post-46806.html相关问题,欢迎点击进入网站链接!


一、Java原生方式:Apache POI基础
Apache POI是Apache基金会提供的开源库,支持对Microsoft Office格式文件的读写操作。其核心模块包括HSSF(Excel 97-2003)和XSSF(Excel 2007+),分别对应.xls和.xlsx格式。

1.1 环境准备
在Maven项目中引入依赖:



    org.apache.poi
    poi
    5.2.3


    org.apache.poi
    poi-ooxml
    5.2.3

1.2 基础导出实现
以下是一个简单的HSSF示例,生成包含标题和数据的Excel文件:


import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;

import java.io.FileOutputStream;
import java.io.IOException;

public class BasicExcelExporter {
    public static void exportToXls(String filePath) throws IOException {
      // 创建工作簿
      HSSFWorkbook workbook = new HSSFWorkbook();
      // 创建工作表
      HSSFSheet sheet = workbook.createSheet("员工数据");
      
      // 创建标题行
      HSSFRow headerRow = sheet.createRow(0);
      String[] headers = {"ID", "姓名", "部门", "薪资"};
      for (int i = 0; i
1.3 XSSF高级特性
XSSF支持Excel 2007+的.xlsx格式,提供更大的数据容量(104万行)和更丰富的功能:


import org.apache.poi.xssf.usermodel.*;

public class AdvancedExcelExporter {
    public static void exportToXlsx(String filePath) throws IOException {
      XSSFWorkbook workbook = new XSSFWorkbook();
      XSSFSheet sheet = workbook.createSheet("销售数据");
      
      // 创建日期格式
      XSSFCellStyle dateStyle = workbook.createCellStyle();
      CreationHelper createHelper = workbook.getCreationHelper();
      dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd"));
      
      // 填充数据(包含日期)
      Object[][] data = {
            {"A001", "笔记本电脑", 5999, new Date()},
            {"B002", "智能手机", 3999, new Date()}
      };
      
      for (int i = 0; i
二、第三方库对比与选择
除了POI,还有多个优秀的第三方库可供选择,各有特点:

2.1 EasyExcel:阿里开源的高性能库
EasyExcel采用基于SAX的读取模式,内存消耗仅为POI的1/6,特别适合大数据量导出。


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;

import java.util.ArrayList;
import java.util.List;

public class Employee {
    @ExcelProperty("员工ID")
    private Integer id;
    @ExcelProperty("姓名")
    private String name;
    @ExcelProperty("部门")
    private String department;
    @ExcelProperty("薪资")
    private Double salary;
    // 构造方法、getter/setter省略
}

public class EasyExcelDemo {
    public static void exportWithEasyExcel(String filePath) {
      List employees = new ArrayList();
      employees.add(new Employee(1, "张三", "技术部", 8500.0));
      employees.add(new Employee(2, "李四", "市场部", 7800.0));
      
      EasyExcel.write(filePath, Employee.class)
                .sheet("员工信息")
                .doWrite(employees);
    }
}
2.2 JExcelAPI:轻量级替代方案
JExcelAPI(jxl)是较早的Java Excel处理库,仅支持.xls格式,但API简单易用:


import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class JExcelDemo {
    public static void exportWithJExcel(String filePath) throws Exception {
      WritableWorkbook workbook = Workbook.createWorkbook(new File(filePath));
      WritableSheet sheet = workbook.createSheet("产品列表", 0);
      
      sheet.addCell(new Label(0, 0, "产品ID"));
      sheet.addCell(new Label(1, 0, "产品名称"));
      sheet.addCell(new Label(2, 0, "价格"));
      
      sheet.addCell(new Label(0, 1, "P001"));
      sheet.addCell(new Label(1, 1, "无线鼠标"));
      sheet.addCell(new jxl.write.Number(2, 1, 129.9));
      
      workbook.write();
      workbook.close();
    }
}
2.3 库选择建议

POI:功能全面,适合复杂需求,但大数据量时内存消耗大
EasyExcel:大数据量导出首选,阿里生态支持
JExcelAPI:仅需基础功能且项目限制使用旧版Excel时
三、性能优化与最佳实践
导出Excel时,性能优化尤为重要,特别是处理上万行数据时。

3.1 内存管理技巧
使用SXSSF(POI的流式API)处理大数据量:


import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFCell;

public class SXSSFDemo {
    public static void exportLargeData(String filePath) throws IOException {
      // 设置行访问窗口为100(内存中保留的行数)
      SXSSFWorkbook workbook = new SXSSFWorkbook(100);
      SXSSFSheet sheet = workbook.createSheet("订单数据");
      
      // 模拟10万行数据
      for (int i = 0; i
3.2 异步导出实现
结合Spring Boot实现异步导出,避免阻塞主线程:


import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class ExcelExportService {
   
    @Async
    public void asyncExport(String filePath) {
      // 这里使用前面介绍的任意导出方法
      try {
            BasicExcelExporter.exportToXls(filePath);
      } catch (IOException e) {
            // 异常处理
      }
    }
}

// 控制器调用
@RestController
@RequestMapping("/api/export")
public class ExportController {
   
    @Autowired
    private ExcelExportService exportService;
   
    @GetMapping("/start")
    public ResponseEntity startExport() {
      exportService.asyncExport("export/data.xls");
      return ResponseEntity.ok("导出任务已启动");
    }
}
3.3 模板导出技术
使用模板可以分离业务逻辑和格式设计,提高可维护性:


import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;

public class TemplateExporter {
    public static void exportWithTemplate(String templatePath, String outputPath, Map data) throws Exception {
      try (FileInputStream fis = new FileInputStream(templatePath);
             Workbook workbook = new XSSFWorkbook(fis)) {
            
            Sheet sheet = workbook.getSheetAt(0);
            
            // 替换模板中的占位符(如${name})
            for (Row row : sheet) {
                for (Cell cell : row) {
                  if (cell.getCellType() == CellType.STRING) {
                        String value = cell.getStringCellValue();
                        for (Map.Entry entry : data.entrySet()) {
                            if (value.contains("${" + entry.getKey() + "}")) {
                              value = value.replace("${" + entry.getKey() + "}", entry.getValue().toString());
                              cell.setCellValue(value);
                            }
                        }
                  }
                }
            }
            
            try (FileOutputStream fos = new FileOutputStream(outputPath)) {
                workbook.write(fos);
            }
      }
    }
   
    public static void main(String[] args) {
      Map data = new HashMap();
      data.put("title", "2023年度销售报告");
      data.put("date", "2023-12-31");
      data.put("totalSales", 1250000);
      
      try {
            exportWithTemplate("template.xlsx", "report.xlsx", data);
      } catch (Exception e) {
            e.printStackTrace();
      }
    }
}
四、常见问题与解决方案

4.1 中文乱码问题
确保文件编码正确,并在响应头中设置:


@GetMapping("/download")
public void downloadExcel(HttpServletResponse response) throws IOException {
    response.setContentType("application/vnd.ms-excel");
    response.setCharacterEncoding("UTF-8");
    response.setHeader("Content-Disposition", "attachment;filename=data.xlsx");
   
    // 使用OutputStream直接写入响应
    try (OutputStream os = response.getOutputStream();
         XSSFWorkbook workbook = new XSSFWorkbook()) {
      // 创建工作表和数据...
      workbook.write(os);
    }
}
4.2 大数据量导出超时
解决方案:

分页查询数据,分批写入Excel
使用SXSSF的流式API
增加JVM内存(-Xmx参数)
实现异步导出+下载通知机制
4.3 复杂格式处理
对于合并单元格、条件格式等复杂需求,POI提供丰富API:


// 合并单元格示例
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3)); // 合并A1:D1

// 条件格式示例
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule(
    ComparisonOperator.GT, "5000"); // 薪资>5000
FontFormatting fontFmt = new FontFormatting();
fontFmt.setFontColorIndex(IndexedColors.RED.index);
rule.setFontFormatting(fontFmt);

CellRangeAddress[] regions = {new CellRangeAddress(1, 100, 2, 2)}; // C2:C101
sheetCF.addConditionalFormatting(regions, rule);
五、完整项目示例
结合Spring Boot实现完整的导出功能:

5.1 实体类定义

public class Product {
    private Long id;
    private String name;
    private String category;
    private BigDecimal price;
    private LocalDate createTime;
    // 构造方法、getter/setter省略
}
5.2 服务层实现

@Service
public class ProductExportService {
   
    @Autowired
    private ProductRepository productRepository;
   
    public byte[] exportProducts() {
      try (XSSFWorkbook workbook = new XSSFWorkbook()) {
            XSSFSheet sheet = workbook.createSheet("产品列表");
            
            // 创建标题行
            XSSFRow headerRow = sheet.createRow(0);
            String[] headers = {"ID", "产品名称", "分类", "价格", "创建日期"};
            for (int i = 0; ipage = productRepository.findAll(PageRequest.of(0, 1000));
            List products = page.getContent();
            
            // 填充数据
            for (int i = 0; i
5.3 控制器实现

@RestController
@RequestMapping("/api/products")
public class ProductExportController {
   
    @Autowired
    private ProductExportService exportService;
   
    @GetMapping("/export")
    public ResponseEntity exportProducts() {
      byte[] excelBytes = exportService.exportProducts();
      
      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
      headers.setContentDispositionFormData("attachment", "products.xlsx");
      
      return new ResponseEntity(excelBytes, headers, HttpStatus.OK);
    }
}
六、总结与展望
Java导出Excel技术已经非常成熟,开发者可以根据项目需求选择合适的方案:

小型项目:POI或EasyExcel
大数据量:SXSSF或EasyExcel
复杂格式:POI高级特性
快速开发:模板导出+EasyExcel
未来发展趋势包括:

更高效的流式处理
与前端框架的深度集成
云存储直接导出
AI辅助的报表生成
关键词:Java导出Excel、Apache POI、EasyExcel、JExcelAPI、SXSSF、异步导出、模板导出、性能优化

简介:本文全面介绍了Java导出Excel的多种实现方式,包括Apache POI基础用法、EasyExcel高性能方案、JExcelAPI轻量级替代,以及SXSSF流式处理大数据量。详细讲解了内存管理、异步导出、模板技术等优化手段,并提供完整的Spring Boot项目示例,涵盖从环境配置到高级特性的所有关键知识点。
页: [1]
查看完整版本: 如何用java导出excel