首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

详细讲解Java使用HSSFWorkbook函数导出Excel表(附实战)

  • 25-03-03 14:23
  • 3327
  • 7338
blog.csdn.net

目录

  • 前言
  • 1. 概念
  • 2. demo
  • 3. 实战

前言

在原本的项目中见到导出Excel的功能,好奇是什么原函数以及如何使用
此博文主要偏向实际的应用开发,不会讲太多的底层代码知识(不过代码已增加注释)

1. 概念

Apache POI库提供了HSSFWorkbook类来处理旧的Excel文件格式(.xls)。

下面是对HSSFWorkbook的一些基本概念和用法的解释:

HSSFWorkbook 概念:

  • 工作簿 (Workbook): HSSFWorkbook代表一个Excel工作簿,它是Excel文件的顶层容器。工作簿可以包含多个工作表(Sheet)。

  • 工作表 (Sheet): 工作表是工作簿中的一个单独的表。一个HSSFWorkbook可以包含多个HSSFSheet,每个工作表都包含行和列。

  • 行 (Row): 行是工作表中的一行,你可以在行中创建单元格并添加数据。

  • 单元格 (Cell): 单元格是工作表中的一个单元,可以包含文本、数字、日期等数据。

2. demo

类似的函数还有XSSFWorkbook函数(适用于.xlsx格式的Excel文件)

为了方便讲解,以下使用HSSFWorkbook函数(该函数支持旧的(.xls)版本),两者其实差不多,给出以下demo例子:

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

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

public class test2 {

	public static void main(String[] args) {
		// 创建工作簿,如果想更换为HSSFWorkbook,则替换即可
		try (Workbook workbook = new HSSFWorkbook()) {
			// 创建工作表
			Sheet sheet = workbook.createSheet("码农研究僧的博客");

			// 创建标题行
			Row headerRow = sheet.createRow(0);
			// 创建第0列,其赋值为Cell类
			Cell headerCell1 = headerRow.createCell(0);
			// 通过该类赋值其含义,此为第0列的属性
			headerCell1.setCellValue("Name");
			// 此为第1列的属性
			Cell headerCell2 = headerRow.createCell(1);
			headerCell2.setCellValue("Age");

			// 添加第一行的数据行
			Row dataRow1 = sheet.createRow(1);
			Cell dataCell1 = dataRow1.createCell(0);
			dataCell1.setCellValue("码农");
			Cell dataCell2 = dataRow1.createCell(1);
			dataCell2.setCellValue(25);

			// 添加第二行的数据行
			Row dataRow2 = sheet.createRow(2);
			Cell dataCell3 = dataRow2.createCell(0);
			dataCell3.setCellValue("研究僧");
			Cell dataCell4 = dataRow2.createCell(1);
			dataCell4.setCellValue(50);

			// 保存文件
			try (FileOutputStream fileOut = new FileOutputStream("workbook.xlsx")) {
				workbook.write(fileOut);
				System.out.println("Excel文件导出成功!");
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

输出如下:

在这里插入图片描述

输出的excel为项目的路径,具体内容如下:

在这里插入图片描述

类似复杂一点,创建多个表

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

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

public class ExcelExportUtil {

    public static void exportManySheetExcel() {
        try (Workbook workbook = new XSSFWorkbook()) {
            // 创建第一个工作表
            Sheet sheet1 = workbook.createSheet("Sheet1");
            createSheetContent(sheet1);

            // 创建第二个工作表
            Sheet sheet2 = workbook.createSheet("Sheet2");
            createSheetContent(sheet2);

            // 创建第三个工作表
            Sheet sheet3 = workbook.createSheet("Sheet3");
            createSheetContent(sheet3);

            // 保存文件
            try (FileOutputStream fileOut = new FileOutputStream("workbook_multiple_sheets.xlsx")) {
                workbook.write(fileOut);
                System.out.println("Excel文件导出成功!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void createSheetContent(Sheet sheet) {
     	// 创建标题行
		Row headerRow = sheet.createRow(0);
		// 创建第0列,其赋值为Cell类
		Cell headerCell1 = headerRow.createCell(0);
		// 通过该类赋值其含义,此为第0列的属性
		headerCell1.setCellValue("Name");
		// 此为第1列的属性
		Cell headerCell2 = headerRow.createCell(1);
		headerCell2.setCellValue("Age");

		// 添加第一行的数据行
		Row dataRow1 = sheet.createRow(1);
		Cell dataCell1 = dataRow1.createCell(0);
		dataCell1.setCellValue("码农");
		Cell dataCell2 = dataRow1.createCell(1);
		dataCell2.setCellValue(25);
	
		// 添加第二行的数据行
		Row dataRow2 = sheet.createRow(2);
		Cell dataCell3 = dataRow2.createCell(0);
		dataCell3.setCellValue("研究僧");
		Cell dataCell4 = dataRow2.createCell(1);
		dataCell4.setCellValue(50);
    }

    public static void main(String[] args) {
        exportManySheetExcel();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

具体可以自身的解耦合,或者通过list列表进行判定!

3. 实战

对于多个表格,我们需要设置一个entity类,专门存放各个sheet名称、标题以及数据集等:

package org.manongyanjiuseng.equipment.entity;

import java.util.List;

public class ExcelExp {

	// sheet的名称
	private String fileName;
	// sheet里的标题
	private String[] handers;
	// sheet里的数据集
	private List<String[]> dataset;
	
	private String tableName;

	public ExcelExp(String fileName, String[] handers, List<String[]> dataset, String tableName) {
		this.fileName = fileName;
		this.handers = handers;
		this.dataset = dataset;
		this.tableName = tableName;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String[] getHanders() {
		return handers;
	}

	public void setHanders(String[] handers) {
		this.handers = handers;
	}

	public List<String[]> getDataset() {
		return dataset;
	}

	public void setDataset(List<String[]> dataset) {
		this.dataset = dataset;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

创建一个专门导出Excel的功能函数:

package org.manongyanjiuseng.equipment.excel;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.manongyanjiuseng.equipment.controller.ResumeBaseParametersController;
import org.manongyanjiuseng.equipment.entity.ExcelExp;
import org.springframework.http.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


public final class ExcelExportUtil {
	
	// 这一行是为了中间logger 打印日志测试而已!
	private static final Logger logger = LoggerFactory.getLogger(ExcelExportUtil.class);
	private ExcelExportUtil (){}
	private static ExcelExportUtil excelExportUtil = null;
	static{
		/** 类加载时创建,只会创建一个对象 */
		if(excelExportUtil == null) excelExportUtil = new ExcelExportUtil ();
	}


	public static Workbook exportManySheetExcel(List<ExcelExp> mysheets) {
		
		// 创建工作薄
		HSSFWorkbook wb = new HSSFWorkbook();
		// 创建sheets中传输进来的数据量
		List<ExcelExp> sheets = mysheets;

		// 设置表头样式表头样式
		HSSFCellStyle style = wb.createCellStyle();
		// 创建一个居中格式
		style.setAlignment(HorizontalAlignment.CENTER); 
		
		// 字体样式
		HSSFFont fontStyle = wb.createFont();
		fontStyle.setFontName("微软雅黑");
		fontStyle.setFontHeightInPoints((short) 12);
		// fontStyle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		style.setFont(fontStyle);
		for (ExcelExp excel : sheets) {
			
			// 新建一个sheet,获取该sheet名称
			HSSFSheet sheet = wb.createSheet(excel.getFileName());
			// 获取sheet的标题名
			String[] handers = excel.getHanders();
			
			HSSFRow tableName = sheet.createRow(0);
			HSSFCell cellName = tableName.createCell(0);
			sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 9));
			HSSFCellStyle titleStyle = wb.createCellStyle();
			
			// 设置单元格样式,设置标题字体
			HSSFFont titleFont = wb.createFont(); 
			// 字号
			titleFont.setFontHeightInPoints((short) 16); 
			titleStyle.setFont(titleFont);
			titleStyle.setAlignment(HorizontalAlignment.CENTER);

			cellName.setCellStyle(titleStyle);
			// 设置单元格内容
			cellName.setCellValue(excel.getTableName());
			
			HSSFRow rowFirst = sheet.createRow(1);// 第一个sheet的第一行为标题
			// 写标题
			for (int i = 0; i < handers.length; i++) {
				// 获取第一行的每个单元格
				HSSFCell cell = rowFirst.createCell(i);
				// 往单元格里写数据
				cell.setCellValue(handers[i]);
				// 加样式
				cell.setCellStyle(style); 
				// 设置每列的列宽
				sheet.setColumnWidth(i, 4000); 
			}

			// 写数据集
			List<String[]> dataset = excel.getDataset();
			for (int i = 0; i < dataset.size(); i++) {
				// 获取该对象
				String[] data = dataset.get(i);

				// 创建数据行
				HSSFRow row = sheet.createRow(i + 2);

				for (int j = 0; j < data.length; j++) {
					// 设置对应单元格的值
					row.createCell(j).setCellValue(data[j]);
				}
			}
		}
		return wb;
	}




	// 处理数据流的时候
	public static void outputXls(Workbook workbook, String fileName, HttpServletResponse response,
								 HttpServletRequest request) {
		ByteArrayOutputStream os = new ByteArrayOutputStream();

		try {
			workbook.write(os);
			byte[] content = os.toByteArray();
			InputStream is = new ByteArrayInputStream(content);
			// 设置response参数,可以打开下载页面
			response.reset();
			response.setHeader("Content-Type","application/msexcel");
			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			response.setHeader("Content-Disposition",
				"attachment;filename=" + URLEncoder.encode(fileName+".xls","utf-8"));
			ServletOutputStream out = response.getOutputStream();
			BufferedInputStream bis = null;
			BufferedOutputStream bos = null;
			try {
				bis = new BufferedInputStream(is);
				bos = new BufferedOutputStream(out);
				byte[] buff = new byte[2048];
				int bytesRead;
				// Simple read/write loop.
				while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
					bos.write(buff, 0, bytesRead);
					bos.flush();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (bis != null)
					bis.close();
				if (bos != null)
					bos.close();
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150

以下代码中涉及的知识点可看我之前的知识:Mybatis-plus动态条件查询QueryWrapper的函数用法

其controller函数中主要处理前端传输的数据,以及数据库封装好的数据进行预处理即可:(只给相关核心部分,具体看个人所需)

关键信息使用xx代替,但不是同个xx

	@PostMapping("/xx")
	@ApiOperationSupport(order = 0)
	@ApiOperation(value = "导出码农研究僧的粉丝",notes = "xx")
	public void exportfan(@RequestBody Map<String,Object> parameters) throws IllegalAccessException {
	
	//处理前端传输进来的数据
	String xx= parameters.get("xx").toString();
	String yy= parameters.get("yy").toString();
	Integer zz= Integer.parseInt(parameters.get("zz").toString());
	
	//主要性能及参数
	manongVO baseParametersVO = new manongVO();

	baseParametersVO.setxx(xx);
	// 此函数主要通过Mabatis-plus中的QueryWrapper函数,可看我上面的一个链接
	List<xx> baseParametersList = xx.list(Condition.getQueryWrapper(xx));

	//封装成excel数据
	List<String[]> dataAllList = new ArrayList<>();
	for (xx data : baseParametersList){
		Field[] fields = data.getClass().getDeclaredFields();
		String[] dataArray = new String[fields.length];
		for (int i = 0;i < fields.length;i++){
			Field field = fields[i];
			//设置允许通过反射访问私有变量
			field.setAccessible(true);
			//获取字段的值
			String value = field.get(data) == null ? null : field.get(data).toString();
			//获取字段属性名称
			String name = field.getName();
			dataArray[i] = value;
		}
		dataAllList.add(dataArray);
	}
	// 创建excellist的数据
	ArrayList<ExcelExp> excelList = new ArrayList<>();
	
	// 创建表头一一存储!
	String[] headArr = new String[]{"id","xx","yyy"};

	ExcelExp excelExp1 = new ExcelExp("码农研究僧", headArr, dataAllList, xx+"yanjiuseng");

	excelList.add(excelExp1);
	



	//。。。。 一直这样封装多个excel的数据
	// 预处理数据
	// 存储数据封装
	// 创建表头一一存储!
	String[] headArr = new String[]{"id","xx","yyy"};

	ExcelExp excelExp2 = new ExcelExp("码农研究僧", headArr, dataAllList, xx+"yanjiuseng");

	excelList.add(excelExp2);




	// 处理最后的数据
	Workbook workbook = ExcelExportUtil.exportManySheetExcel(excelList);
	
	HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
	
	HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
	
	ExcelExportUtil.outputXls(workbook,xx+"excel的标题",response,request);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

上述代码中有些过于累赘的话,可自行删减,此处提供一个id思路!

文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览145194 人正在系统学习中
码农研究僧
微信公众号
1.框架等前沿技术 2.日常生活 3.技术交流
注:本文转载自blog.csdn.net的码农研究僧的文章"https://blog.csdn.net/weixin_47872288/article/details/135209106"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top