目前我已知的针对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;
}