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

2023-12-27 06:19:17

前言

在原本的项目中见到导出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();
		}
	}
}

输出如下:

在这里插入图片描述

输出的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();
    }
}

具体可以自身的解耦合,或者通过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;
	}
}

创建一个专门导出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();
		}
	}
}

以下代码中涉及的知识点可看我之前的知识: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);

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

文章来源:https://blog.csdn.net/weixin_47872288/article/details/135209106
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。