JXLS导出数据到Excel表格

本文详细介绍了如何利用Jxls库在Java项目中实现Excel数据导出功能,包括项目构建、实体类定义、数据访问层实现、Servlet处理及模版设计等步骤。

直接贴代码了,就不讲概念了。。。。

先列出项目工程结构:

1.先创建一个web项目,这里我使用maven构建

    pom.xml文件需要导入的jar包

<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls</artifactId>
    <version>2.4.6</version>
</dependency>
<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls-poi</artifactId>
    <version>1.0.15</version>
</dependency>
<dependency>
    <groupId>org.jxls</groupId>
    <artifactId>jxls-jexcel</artifactId>
    <version>1.0.7</version>
</dependency>

2.创建实体类,这里创建Employee类

        private Integer id;
	private String empName;
	private Integer age;
	private String address;
	
	public Employee(){}
	
	public Employee(Integer id, String empName, Integer age, String address) {
		this.id = id;
		this.empName = empName;
		this.age = age;
		this.address = address;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getEmpName() {
		return empName;
	}
	public void setEmpName(String empName) {
		this.empName = empName;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}

3.创建数据访问层类,这里就不连接数据库了,直接初始化数据。(创建EmpDao类)

public List<Employee> getEmployee(){
        List<Employee> empList = new ArrayList<Employee>();
        Employee emp1 = new Employee(1,"张三",16,"xxx区");
	Employee emp2 = new Employee(2,"李四",20,"xxxx家湾");
	Employee emp3 = new Employee(3,"王五",36,"xxx区");
	Employee emp4 = new Employee(4,"赵柳",39,"xxx北");
	Employee emp5 = new Employee(5,"田七",21,"xxx区");
	Employee emp6 = new Employee(6,"王八",42,"xx科技园");
		
	empList.add(emp1);
	empList.add(emp2);
	empList.add(emp3);
	empList.add(emp4);
	empList.add(emp5);
	empList.add(emp6);
		
	return empList;
}

4.创建Servlet类,处理数据导入

package com.kys.controller;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;

import com.kys.dao.EmpDao;

public class EmployeeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private EmpDao empDao = new EmpDao();

	public void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		/**
		 * InputStream is = EmployeeServlet.class.getResourceAsStream("/report/emp.xlsx")
		 * 这行代码主要是读取excel模块(excel模版下面在介绍),模版我放在根路径下 : /report/
		 */
		/**
		 * OutputStream os = new FileOutputStream("target/emp.xlsx")
		 * 主要导出的路径、路径存在maven工程下target文件下
		 */
		/**
		 *  context.putVar("emps",empDao.getEmployee());
		 *  把获取到的数据保存到作用域中
		 */
		/**
		 * JxlsHelper.getInstance().processTemplate(is, os, context);
		 * 生成到excel表格中
		 */
		try(InputStream is = EmployeeServlet.class.getResourceAsStream("/report/emp.xlsx")) {
	        try (OutputStream os = new FileOutputStream("target/emp.xlsx")) {
	            Context context = new Context();
	            context.putVar("emps",empDao.getEmployee());
	            JxlsHelper.getInstance().processTemplate(is, os, context);
	        }
	    }
	}
}

5.页面层index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Employee</title>
</head>
<body>
	<!-- Servlet的访问地址:empSer -->
	<a href="empSer">导出</a>
</body>
</html>

6.Excel模版我保存到src/main/resources/report目录下

下面介绍excel表格需要怎么写:

先看一下官网的解释:

    

简单的解释就是:

    在excel表格中,比如name,birthDate,Payment,Bonus的数据区域为A1:D4

   如何标明数据区域?

        在A1单元格中点击鼠标右键,插入批注:写入    jx:area(lastCell="D4") 意思就是从插入批注的单元格到lastCell=D4都是属于数据区域

 

        接着在A1单元格中循环保存到作用域的集合对象,写入 jx:each(items="emps" var="emp" lastCell="D4") 

    查看完整的批注:

            

那么 jx:area 和  jx:each分别是使用的是Apache JEXL表达式,和jsp中jstl表达式一样

excel表格使用${}获取bean对象的值,和jsp页面的差不多一样

 

 

最后运行项目,点击页面的导出将会得到如下数据:

导出的表格下载在maven项目下的target目录中:双击打开得到如下数据

 

以上将是所有步骤,只是一个简单的例子,需要其他功能还需要继续美化,加强

 

 

还有这是我第一次写的博客,大家有什么问题可以提出来,写的不是很好,不要见怪。以后会慢慢提升的大笑

 

 

 

    

 

            

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<think>我们正在处理用户的问题:在Java中导出数据Excel并实现小计功能。 根据用户需求,我们需要生成一个结构清晰的回答,并确保回答真实可靠。 我们将使用Apache POI库,因为它是最常用的Java库之一,用于处理Microsoft Office格式文件,包括Excel。 小计功能通常意味着在数据分组后,对每个组进行汇总(如求和、平均值等),并在每个组的末尾添加一行显示汇总结果。 步骤: 1. 创建Workbook和Sheet。 2. 创建数据行,并确保数据按某个字段分组(例如,部门、类别等)。 3. 在每组数据之后插入一行小计行,使用公式或直接计算值。 4. 在最后添加总计行。 注意:我们也可以使用POI的Sheet.addSubtotal方法(在XSSFSheet中)来添加小计,但这里我们将展示手动添加小计的方法,以便更灵活。 然而,Apache POI确实提供了一种内置的方法来创建小计:`sheet.groupRow`和`sheet.setRowGroupCollapsed`,以及使用`addSubtotalRow`(在较新版本中)。但为了清晰,我们将展示一个基本的手动实现。 由于用户没有指定分组字段和汇总字段,我们假设: - 数据按第一列(索引0)分组。 - 对第二列(索引1)和第三列(索引2)进行求和。 我们将创建一个示例: - 数据行:包括部门、销售额、成本等。 - 按部门分组,然后对销售额和成本进行小计,最后总计。 但是,请注意:如果数据量很大,我们可能需要先对数据进行排序(按分组字段),然后再添加小计行。 我们将按以下步骤编写代码: 1. 准备数据(这里我们使用一个二维数组模拟数据,实际中可能从数据库获取)。 2. 对数据按分组列进行排序(这里按第一列)。 3. 遍历数据,当分组列的值变化时,插入小计行。 4. 在最后插入总计行。 另外,我们也可以使用POI的`XSSFSheet`的`addSubtotal`方法,但该方法需要设置分组。我们将展示两种方式: 方式一:手动计算并插入小计行(更灵活,适用于各种需求) 方式二:使用POI内置的小计功能(更简单,但可能不够灵活) 由于用户要求小计功能,我们将重点放在手动方式上,因为这样更可控。 代码示例: 我们将使用: - Workbook: XSSFWorkbook (对应.xlsx格式) - 数据:假设有三列:部门、销售额、成本 步骤: 1. 创建Workbook和Sheet。 2. 创建标题行。 3. 准备数据列表(已按部门排序)。 4. 遍历数据,同时记录当前部门,当部门改变时,插入小计行(在上一个部门的最后一行后面)。 5. 在最后插入总计行。 注意:插入行时,需要将后面的行下移,因此我们可以先记录每个小计的位置,最后再插入。但更简单的方法是,我们可以在内存中构建好带有小计行的数据,然后一次性写入,这样避免在遍历时移动行。 因此,我们可以: - 先对原始数据进行分组,计算每个组的小计。 - 然后构建一个新的数据列表,包括原始数据行和插入的小计行。 - 最后将这个新的数据列表写入Excel。 这样避免在写入过程中移动行,更简单。 示例代码: 假设数据结构为: class DataRow { String department; double sales; double cost; } 我们使用一个List<DataRow>存储数据,然后按部门排序。 然后,我们构建一个新的列表(List<Object>),其中Object可以是原始数据行,也可以是一个小计行(用特殊对象表示,或者用字符串标识)。但为了简单,我们可以创建一个新的列表,元素类型为Object,然后遍历原始数据,当部门改变时,添加一个小计行(用字符串"Subtotal"标识,然后记录小计值)。 但是,在写入Excel时,我们需要知道每一行的具体值。因此,我们可以这样: 构建一个List<List<Object>>,每个元素是一行的数据(包括原始数据行和小计行)。 步骤: 1. 初始化一个空列表(newRows)用于存放最终要写入的所有行(包括小计行)。 2. 初始化当前部门变量为null,以及一个临时列表(currentGroup)存放当前组的行。 3. 遍历排序后的原始数据: - 如果当前部门为空,设置当前部门为第一个数据的部门。 - 如果当前数据的部门与当前部门相同,则将该行数据加入当前组(currentGroup),并继续。 - 否则,说明部门改变: a. 将当前组的所有行添加到newRows中。 b. 为当前组添加一个小计行(计算当前组的sales和cost总和),并添加到newRows。 c. 重置当前组,将当前数据加入作为新组的第一个数据,并更新当前部门。 4. 遍历结束后,将最后一个组的数据添加到newRows,并添加小计行。 5. 最后,添加总计行(计算所有小计行的总和,或者直接计算所有原始数据)。 然后,我们将newRows写入到Excel中。 这样,我们就有了一个包含小计行的数据列表。 接下来,我们编写代码。 注意:在写入小计行时,我们希望小计行在视觉上突出显示(例如,加粗,背景色等),所以我们将设置单元格样式。 另外,小计行通常放在每个分组的最后一行,并且小计行的分组字段列显示为“部门 Subtotal”或直接写“小计”。 我们开始写代码: 由于代码较长,我们将分步展示。</think>### Java中导出数据Excel并实现小计功能 在Java中实现Excel数据导出和小计功能,推荐使用 **Apache POI** 库(处理.xlsx格式)或 **JExcelAPI**(处理.xls格式)。以下是分步实现方案: #### 1. 添加依赖 ```xml <!-- Maven 依赖 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency> ``` #### 2. 完整代码示例 ```java import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileOutputStream; import java.util.*; public class ExcelExporter { public static void main(String[] args) throws Exception { // 1. 模拟数据(部门, 销售额, 成本) List<Object[]> data = Arrays.asList( new Object[]{"市场部", 15000, 5000}, new Object[]{"市场部", 20000, 7000}, new Object[]{"技术部", 30000, 10000}, new Object[]{"技术部", 25000, 8000} ); // 2. 创建工作簿和Sheet try (Workbook workbook = new XSSFWorkbook()) { Sheet sheet = workbook.createSheet("销售报告"); // 3. 创建标题行 Row headerRow = sheet.createRow(0); String[] headers = {"部门", "销售额", "成本", "利润"}; for (int i = 0; i < headers.length; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(headers[i]); } // 4. 填充数据并计算利润 int rowNum = 1; Map<String, Double> subtotals = new LinkedHashMap<>(); // 存储小计 for (Object[] rowData : data) { Row row = sheet.createRow(rowNum++); String dept = (String) rowData[0]; double sales = (double) rowData[1]; double cost = (double) rowData[2]; double profit = sales - cost; // 写入数据 row.createCell(0).setCellValue(dept); row.createCell(1).setCellValue(sales); row.createCell(2).setCellValue(cost); row.createCell(3).setCellValue(profit); // 累加小计 subtotals.put(dept, subtotals.getOrDefault(dept, 0.0) + profit); } // 5. 添加小计行 CellStyle subtotalStyle = workbook.createCellStyle(); subtotalStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); subtotalStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); Font font = workbook.createFont(); font.setBold(true); subtotalStyle.setFont(font); for (Map.Entry<String, Double> entry : subtotals.entrySet()) { Row subtotalRow = sheet.createRow(rowNum++); Cell cell = subtotalRow.createCell(0); cell.setCellValue(entry.getKey() + " 小计"); cell.setCellStyle(subtotalStyle); subtotalRow.createCell(3).setCellValue(entry.getValue()); } // 6. 自动调整列宽 for (int i = 0; i < headers.length; i++) { sheet.autoSizeColumn(i); } // 7. 保存文件 try (FileOutputStream fos = new FileOutputStream("销售报告.xlsx")) { workbook.write(fos); } } System.out.println("Excel文件生成成功!"); } } ``` #### 关键功能说明 1. **数据分组小计**: - 使用 `Map<String, Double>` 按部门累计利润值 - 遍历Map在小计行显示汇总值 2. **样式设置**: - 小计行使用灰色背景和加粗字体 - `autoSizeColumn()` 自动调整列宽 3. **公式扩展**(如需): ```java // 添加公式计算(例如在总计行) Row totalRow = sheet.createRow(rowNum); totalRow.createCell(0).setCellValue("总计"); totalRow.createCell(3).setCellFormula("SUM(D2:D" + (rowNum-1) + ")"); ``` #### 高级优化建议 1. **大数据量处理**: - 使用 `SXSSFWorkbook` 替代 `XSSFWorkbook` 处理百万级数据 - 启用流式导出避免内存溢出: ```java SXSSFWorkbook workbook = new SXSSFWorkbook(100); // 保留100行在内存 ``` 2. **模板引擎集成**: - 使用 `JXLS` 库基于Excel模板生成报告 - 支持复杂格式和公式预定义 3. **异步导出**: ```java CompletableFuture.runAsync(() -> { // 导出逻辑 }); ``` #### 注意事项 1. 数据排序:确保源数据按分组字段(如部门)排序 2. 类型安全:使用POI的 `DataFormatter` 正确处理数据类型 3. 内存管理:导出完成后调用 `workbook.dispose()`(SXSSF) > 此方案适用于业务报表、财务汇总等场景,实际应用中可结合Spring Boot实现RESTful导出接口[^1]。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值