天天看点

基于POI实现新老版本的Excel文件导入/导出

目前我已知的针对Excel表格的导入导出的方法,在poi的基础上,有三种

POI有三种API:

POI-HSSF

POI-XSSF

SXSSF

官方文档的说法:

HSSF是POI项目的Excel '97(-2007)文件格式的纯Java实现。XSSF是POI Project的Excel 2007 OOXML(.xlsx)文件格式的纯Java实现。

自3.8-beta3以来,POI提供了基于XSSF构建的低内存占用SXSSF API。

SXSSF是XSSF的API兼容流式扩展,用于在必须生成非常大的电子表格时使用,并且堆空间有限。SXSSF通过限制对滑动窗口内行的访问来实现其低内存占用,而XSSF允许访问文档中的所有行。不再在窗口中的旧行变得不可访问,因为它们被写入磁盘。

简单的说,HSSF对应旧的xls格式,XSSF对应新的xlsx格式,SXSSF是在XSSF的基础上,支持导出大批量的excel数据。

————————————————

版权声明:本文以上内容参考CSDN博主「南城柳旧时人」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/SudaDays/article/details/90669237

如果对这三种方法不熟悉的小伙伴可以点进去看看。

接下来就直接是干货了,首先上的是基于XSSF对应新的xlsx格式

首先是添加代码所需要的依赖:

<!-- poi 2003 -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.15</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.15</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.15</version>
		</dependency>
		<!--文件上传组件 -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.5</version>
		</dependency>
		<!-- 因为我用的是SpringBoot框架做的测试其他依赖就不添加了 -->
           

定义一个接受的对象并加上get、set方法:

public class Indicator {
	private String id;
	private String ip;
	private String port;
	private String log;
	private String statue;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getIp() {
		return ip;
	}
	public void setIp(String ip) {
		this.ip = ip;
	}
	public String getPort() {
		return port;
	}
	public void setPort(String port) {
		this.port = port;
	}
	public String getLog() {
		return log;
	}
	public void setLog(String log) {
		this.log = log;
	}
	public String getStatue() {
		return statue;
	}
	public void setStatue(String statue) {
		this.statue = statue;
	}
	@Override
	public String toString() {
		return "Indicator [id=" + id + ", ip=" + ip + ", port=" + port + ", log=" + log + ", statue=" + statue + "]";
	}
	
}

           

导入本地Excel文件的方法代码:

/*
	 * 根据本地地址获取Excel文件并解析
	 */
	@Test
	public void testAddExcel() throws Exception{
		String url = "D:\\myword\\test-excel\\设备信息.xls";
		//获取系统文档
		InputStream is = new FileInputStream(url);
		//反序列化恢复对象
		List<Indicator> list = read2007Xlsx(is);
		System.out.println(list.size());
	}
	/**  解析序列化的Excel文件 */
	private List<Indicator> read2007Xlsx(InputStream is) throws Exception{
		List<Indicator> list = new ArrayList<Indicator>();

		XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is);
		//读取表
		XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
		//读取行
		for (int rowNum = 0; rowNum < xssfSheet.getLastRowNum()+1; rowNum++) {
			XSSFRow xssfRow = xssfSheet.getRow(rowNum);
			if(xssfRow != null) {
				//新建Indicator对象,用来保存每一行的数据
				Indicator indicator = new Indicator();
				//索引这一行的单元格,我用来测试的Excel表格只有5行元素,所以就不多写了
				xssfRow.getCell(0).setCellType(CellType.STRING);
				xssfRow.getCell(1).setCellType(CellType.STRING);
				xssfRow.getCell(2).setCellType(CellType.STRING);
				xssfRow.getCell(3).setCellType(CellType.STRING);
				xssfRow.getCell(4).setCellType(CellType.STRING);

				indicator.setId(xssfRow.getCell(0).getStringCellValue());
				indicator.setIp(xssfRow.getCell(1).getStringCellValue());
				indicator.setLog(xssfRow.getCell(2).getStringCellValue());
				indicator.setPort(xssfRow.getCell(3).getStringCellValue());
				indicator.setStatue(xssfRow.getCell(4).getStringCellValue());
				System.out.println(indicator.toString());
				list.add(indicator);
			}
		}

		xssfWorkbook.close();
		return list;
	}

           

以下是运行结果

Indicator [id=设备编号, ip=IP地址, port=通道数量, log=端口, statue=状态]
Indicator [id=00000196, ip=192.168.8.246, port=8, log=10001, statue=启用]
Indicator [id=50100008, ip=192.168.8.58, port=8, log=10001, statue=启用]
3
           

关于POI-XSSF的导出方法可以参考POI-HSSF的导出,具体的在下面有呈现;

那么,接下来就是POI-HSSF的导入代码块了;

/*
	 * 根据本地地址获取Excel文件并解析
	 */
	@Test
	public void testAddExce2() throws Exception{
		String url = "D:\\testexcel\\test1.xls";
		//获取系统文档
		InputStream is = new FileInputStream(url);
		//反序列化恢复对象
		List<Indicator> list = read2003Xlsx(is);
		System.out.println(list.size());
	}
	/**  解析序列化的Excel文件 */
	private List<Indicator> read2003Xlsx(InputStream is) throws Exception {
		List<Indicator> list = new ArrayList<Indicator>();

		HSSFWorkbook hssfWorkbook = new HSSFWorkbook(is);
		//读取表
		HSSFSheet sheetAt = hssfWorkbook.getSheetAt(0);
		//读取行
		for (int rowNum = 0; rowNum < sheetAt.getLastRowNum()+1; rowNum++) {
			HSSFRow hssfRow = sheetAt.getRow(rowNum);
			if(hssfRow != null) {
				//新建Indicator对象,用来保存每一行的数据
				Indicator indicator = new Indicator();
				//索引这一行的单元格
				hssfRow.getCell(0).setCellType(CellType.STRING);
				hssfRow.getCell(1).setCellType(CellType.STRING);
				hssfRow.getCell(2).setCellType(CellType.STRING);
				hssfRow.getCell(3).setCellType(CellType.STRING);
				hssfRow.getCell(4).setCellType(CellType.STRING);

				indicator.setId(hssfRow.getCell(0).getStringCellValue());
				indicator.setIp(hssfRow.getCell(1).getStringCellValue());
				indicator.setLog(hssfRow.getCell(2).getStringCellValue());
				indicator.setPort(hssfRow.getCell(3).getStringCellValue());
				indicator.setStatue(hssfRow.getCell(4).getStringCellValue());
				System.out.println(indicator.toString());
				list.add(indicator);
			}
		}

		hssfWorkbook.close();
		return list;
	}
           

输出结果:

Indicator [id=id, ip=名字, port=年龄, log=性别, statue=t]
Indicator [id=1, ip=小明, port=19, log=女, statue=1]
Indicator [id=2, ip=小白, port=18, log=男, statue=2]
Indicator [id=3, ip=小红, port=35, log=男, statue=3]
4

           

那么,接下来就是POI-HSSF的导出代码块了;(POI-XSSF的导出参考这一块,不过我们在写导出时一般只需要写一种就可以了,不推荐使用哪一种【ps:留一个小想法,让用户来选择新版本还是旧版本其实更好吧!!!】)

@Test
	public void testPOI() {
		//创建HSSFWorkbook对象  
		HSSFWorkbook wb = new HSSFWorkbook();  
		//创建HSSFSheet对象  
		HSSFSheet sheet = wb.createSheet("sheet0");  
		//创建HSSFRow对象  
		HSSFRow row = sheet.createRow(0);  
		//创建HSSFCell对象  
		HSSFCell cell=row.createCell(0);  
		//设置单元格的值  
		cell.setCellValue("test1");  
		//输出Excel文件  
		try {
			FileOutputStream output=new FileOutputStream("D:\\testexcel\\test.xls");  
			wb.write(output);
			output.flush();  
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
	}
           

是不是觉得这种导出太简陋了?其实POI很齐全的,在这里我就不过多介绍了,直接上链接!

福利:

直接可用的导出,自己根据下边的讲解自行修改,不修改直接用也可以!

————————————————

版权声明:以下链接中的内容为CSDN博主「w893932747」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/w893932747/article/details/89354979

关于导出的这位朋友讲的可以说非常详细了。所以我就偷个懒做搬运工啦!

----------------这是分割线--------------------

关于SXSSF的我就不多讲了,推荐参考官方文档。

----------------这是分割线--------------------

接下来就是重头戏了,在导入的时候,我们往往是不知道用户上传的到底是哪个版本?但是用后缀名判断一定是很愚蠢的行为。

因此我在参考了CSDN博主「yuanlijiefengjuan」的文章,遵循 CC 4.0 BY-SA 版权协议,转载附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/yuanlijiefengjuan/article/details/86689953

直接上代码!

@SuppressWarnings("deprecation")
	@Test
	public void testAddExce3() throws Exception{
		String url = "D:\\myword\\test-excel\\2019年01月23日环流日报.xls";
		//获取系统文档的序列化对象
		InputStream is = new FileInputStream(url);
		//判断是哪个版本的Excel
		boolean isExcel2003 = false;
		if(!is.markSupported()) {
			is = new PushbackInputStream(is, 8);
		}
		if(POIFSFileSystem.hasPOIFSHeader(is)) {
			isExcel2003 = true;
			System.out.println("2003及以下");
		}
		if(POIXMLDocument.hasOOXMLHeader(is)) {
			isExcel2003 = false;
			System.out.println("2007及以上");
		}
		if(isExcel2003) {
			//反序列化恢复对象
		List<Indicator> list = read2003Xlsx(is);
		System.out.println(list.size());
		}
		if(!isExcel2003) {
			//反序列化恢复对象
			List<Indicator> list = read2007Xlsx(is);
			System.out.println(list.size());
		}
	}
	/**  所调用的两个反序列化的方法就在前面代码块中,我就不重复了 */
           

直接上结果:

2007及以上
Indicator [id=序号, ip=线路名称, port=A相最小值, log=接地环流位置, statue=A相最大值]
Indicator [id=1, ip=测试线路2, port=0.00, log=40120335, statue=31.51]
Indicator [id=2, ip=测试线路2, port=27.26, log=40120337, statue=32.89]
Indicator [id=3, ip=测试线路2, port=0.00, log=40120340, statue=0.00]
Indicator [id=4, ip=测试线路2, port=0.00, log=40120341, statue=0.00]
Indicator [id=5, ip=测试线路2, port=0.00, log=40120343, statue=0.01]
Indicator [id=6, ip=测试线路2, port=0.00, log=40120344, statue=0.00]
Indicator [id=7, ip=测试线路2, port=0.00, log=40120348, statue=0.01]
Indicator [id=8, ip=测试线路2, port=0.00, log=40120350, statue=0.00]
Indicator [id=9, ip=测试线路2, port=0.00, log=40120351, statue=0.00]
Indicator [id=10, ip=测试线路2, port=0.00, log=40120352, statue=0.00]
Indicator [id=11, ip=测试线路2, port=0.00, log=40120354, statue=0.00]
Indicator [id=12, ip=测试线路2, port=0.00, log=40120356, statue=30.19]
Indicator [id=13, ip=测试线路2, port=0.00, log=40120357, statue=0.00]
Indicator [id=14, ip=测试线路2, port=0.00, log=40120358, statue=0.00]
Indicator [id=15, ip=测试线路2, port=0.00, log=40120362, statue=0.01]
Indicator [id=16, ip=测试线路2, port=0.00, log=40120363, statue=30.46]
17

           

以上,就是我对POI导入导出的全部想法啦!新人第一次发帖~有什么问题,大家可以指出来哦!

下面是WorkbookFactory的导入代码,就不放结果了…加班ing

/**
     *  @Description: 导入Excel文件
     *  @author: zjh
     *  @Date 2019-09-20
     */
    public static List<Map<Integer,String>> readExcel(MultipartFile file){
        List<Map<Integer,String>> list = new LinkedList<>();
        try {
            String fileName = file.getOriginalFilename();
            /* 正则验证文件格式 */
            Matcher matcher = COMPOLE.matcher(fileName);
            if(!matcher.matches()){
                throw new Exception("文件格式不正确");
            }
            Workbook wb = WorkbookFactory.create(file.getInputStream());
            /* 获取Excel表格第一页 */
            Sheet sheet = wb.getSheetAt(0);
            for (int i = 0; i < sheet.getLastRowNum()+1; i++) {
                /* 新建Map对象,用来保存每一行的数据 */
                Map<Integer, String> map = new HashMap<>(5);
                /* 索引这一行的单元格 */
                Row row = sheet.getRow(i);
                if(row != null){
                    /* 索引这一行的单元格 */
                    row.getCell(0).setCellType(CellType.STRING);
                    row.getCell(1).setCellType(CellType.STRING);
                    row.getCell(2).setCellType(CellType.STRING);
                    row.getCell(3).setCellType(CellType.STRING);
                    row.getCell(4).setCellType(CellType.STRING);

                    map.put(0, row.getCell(0).getStringCellValue());
                    map.put(1, row.getCell(1).getStringCellValue());
                    map.put(2, row.getCell(2).getStringCellValue());
                    map.put(3, row.getCell(3).getStringCellValue());
                    map.put(4, row.getCell(4).getStringCellValue());
                    /* 存入集合 */
                    list.add(map);
                }
            }
            wb.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }