最近遇到一个项目,其中需要对Excel进行读取、写入、创建等操作,于是在网上查了资料使用了poi包来解析Excel,在此总结一下poi包的一些简单用法,以备以后使用,如有不对之处,欢迎各位指正。
这里提供一下使用poi所需要的jar包,有需要的朋友可以进行下载:poi-4.0.1所需jar包
public class ReadExcelTool {
//总行数
private int totalRows = 0;
//总列数
private int totalCells = 0;
//错误信息
private String errorInfo;
//判断文件是否存在或是否是Excel格式
public boolean validateExcel(String filePath){
if (filePath == null || !(WDWUtil.isExcel2003(filePath) || WDWUtil.isExcel2007(filePath))){
errorInfo = "文件不是Excel格式";
return false;
}
File file = new File(filePath);
if (file == null || !file.exists()){
errorInfo = "文件不存在";
return false;
}
return true;
}
//读取Excel文件
public List readXls(String filePath) throws Exception{
List dataList = new ArrayList();
InputStream is = null;
try{
//验证文件是否合法
if (!validateExcel(filePath)){
System.out.println(errorInfo);
return null;
}
//判断文件的类型
//public static boolean isExcel2003(String filePath){
return filePath.matches("^.+\\.(?i)(xls)$");
}
//public static boolean isExcel2007(String filePath){
return filePath.matches("^.+\\.(?i)(xlsx)$");
}
boolean isExcel2003 = true;
if (WDWUtil.isExcel2007(filePath)){
isExcel2003 = false;
}
//调用方法读取Excel
File file = new File(filePath);
is = new FileInputStream(file);
dataList = read(is,isExcel2003);
is.close();
}catch (Exception e){
e.printStackTrace();
}finally{
if (is != null){
try{
is.close();
} catch (Exception ex){
is = null;
ex.printStackTrace();
}
}
}
return dataList;
}
//根据不同版本读取Excel文件
public List read(InputStream inputStream,boolean isExcel2003){
List dataList = null;
try{
//根据Excel文件版本创建Workbook的方式
Workbook wb = null;
if (isExcel2003){
//文件后缀xls
wb = new HSSFWorkbook(inputStream);
}else{
//文件后缀xlsx
wb = new XSSFWorkbook(inputStream);
}
dataList = read(wb);
}catch (IOException e){
e.printStackTrace();
}
return dataList;
}
//解析Excel表格
private List read(Workbook wb){
List dataList = new ArrayList<>();
//得到第一个sheet
Sheet sheet = wb.getSheetAt(0);
//得到Excel的行数
this.totalRows = sheet.getPhysicalNumberOfRows();
//得到Excel的列数
if (this.totalRows >= 1 && sheet.getRow(0) != null){
this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
}
//循环Excel的行
for(int r=1;r
值得注意的是,在取单元格的值时,Excel单元格中不同格式的数据是对应不同的方法的,因为poi会检测数据的类型。如此处获取文本信息则使用getStringCellValue(),如果读取其他格式的数据则需要不同的方法:
1.数值类型使用getNumericCellValue()
2.布尔类型使用getBooleanCellValue()
3.公式使用getCellFormula()
此外还有一些其他的类型如空值、错误等。
如果我们需要生成的是一个有规律的Excel,那么使用poi来生成就非常方便;而如果是一个没有规律的Excel(某些地方需要合并单元格,某些地方需要加边框),那么建议使用第三种操作(写入Excel),越是复杂的Excel生成起来越麻烦。
//根据提供的Excel文件模板生成一个excel
public static HSSFWorkbook BuildExcel(){
//一个workbook对应一个excel,此处创建的是2003版本
HSSFWorkbook wb = new HSSFWorkbook();
//生成excel中可能用到的单元格样式
//字体样式
HSSFFont font1 = wb.createFont(); //仿宋_GB2312,14号字
font1.setFontName("仿宋_GB2312"); //字体名称
font1.setFontHeightInPoints((short)14); //字体大小
HSSFFont font2 = wb.createFont(); //宋体,18号字
font2.setFontName("宋体");
font2.setFontHeightInPoints((short)18);
HSSFFont font3 = wb.createFont(); //方正仿宋,14号字
font3.setFontName("方正仿宋");
font3.setFontHeightInPoints((short)14);
//单元格样式
HSSFCellStyle style1 = wb.createCellStyle(); //垂直居中、水平左对齐,字体样式1
style1.setFont(font1); //注入字体
style1.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中
style1.setAlignment(HorizontalAlignment.LEFT); //水平左对齐
HSSFCellStyle style2 = wb.createCellStyle(); //水平和垂直居中,字体样式2
style2.setFont(font2);
style2.setAlignment(HorizontalAlignment.CENTER); //水平居中
style2.setVerticalAlignment(VerticalAlignment.CENTER);
HSSFCellStyle style9 = wb.createCellStyle(); //垂直顶端对齐、水平左对齐,字体样式3,带四周边框,自动换行
style9.setFont(font3);
style9.setVerticalAlignment(VerticalAlignment.TOP);
style9.setAlignment(HorizontalAlignment.LEFT);
style9.setBorderBottom(BorderStyle.THIN); //边框宽度为1
style9.setBorderTop(BorderStyle.THIN);
style9.setBorderLeft(BorderStyle.THIN);
style9.setBorderRight(BorderStyle.THIN);
style9.setWrapText(true); //自动换行
//生成一个sheet,对应excel中的sheet,参数为excel中sheet显示的名字
HSSFSheet sheet = wb.createSheet("Sheet1");
//设置每列的宽度,共有15列
sheet.setColumnWidth(0,(int)(10.75*256*1.1));
sheet.setColumnWidth(1,(int)(18.88*256*1.1));
sheet.setColumnWidth(2,(int)(7.25*256*1.1));
sheet.setColumnWidth(3,(int)(12.38*256*1.1));
sheet.setColumnWidth(4,(int)(12.38*256*1.1));
sheet.setColumnWidth(5,(int)(12.38*256*1.1));
sheet.setColumnWidth(6,(int)(16.75*256*1.1));
sheet.setColumnWidth(7,(int)(22.13*256*1.1));
sheet.setColumnWidth(8,(int)(29.63*256*1.1));
sheet.setColumnWidth(9,(int)(4.75*256*1.1));
sheet.setColumnWidth(10,(int)(24.88*256*1.1));
sheet.setColumnWidth(11,(int)(5.75*256*1.1));
sheet.setColumnWidth(12,(int)(14.88*256*1.1));
sheet.setColumnWidth(13,(int)(24.75*256*1.1));
sheet.setColumnWidth(14,(int)(8*256*1.1));
//单独设置每一行
//第一行
HSSFRow row1 = sheet.createRow(0);
row1.setHeight((short)(20*29.25)); //设定行高
//创建每一行的每个单元格
HSSFCell cell = row1.createCell(0);
cell.setCellStyle(style1);
cell.setCellValue("附1");
//第二行
HSSFRow row2 = sheet.createRow(1);
row2.setHeight((short)(20*13.5));
//第三行
HSSFRow row3 = sheet.createRow(2);
row3.setHeight((short)(20*31.5));
sheet.addMergedRegion(new CellRangeAddress(2,2,0,14)); //单元格合并,参数(起始行、结束行、起始列、结束列)
cell = row3.createCell(0);
cell.setCellStyle(style2);
return wb;
}
从代码中可以看出,要创建一个Excel,首先要创建一个workbook,在workbook上创建sheet,在sheet中创建每一个单元格,并且设置其样式。
因为我使用的是WPS打开Excel,所以我的列宽显示的单位是字符,行高显示的单位是磅。假如给了一个模板,按照其来创建Excel,那么设定列宽的时候值就取col*256*1.1,col是模板中列的列宽,这样得到的结果会比原有宽度稍大;在设定行高的时候,值就取20*row,row是模板中行的行高,这样得到的结果与原有行高相同。
另外,在给合并单元格设置样式和填值得时候,只需要在这个合并单元格的左上角单元格设置即可,给个例子。
此处我合并了第4行至第7行,第3列至第5列的单元格,那么针对第四行第三列这个单元格设置样式和填值即可。但是这里有一个比较坑的地方,那就是如果想给这个合并单元格添加边框的话,就不能只针对这一个单元格,而是要将这个合并单元格外围的所有子单元格都设置好样式(带边框)。
其实写入Excel相当于前两种用法的结合,先读取Excel获得一个workbook,再对这个workbook进行各种操作。
public static HSSFWorkbook addCompanyMessageToExcel(HSSFWorkbook wb, Result re){
Sheet sheet = wb.getSheet("Sheet1");
Cell cell = sheet.getRow(4).getCell(2);
cell.setCellValue(re.getBEI().getENTNAME());
//循环对单元格进行调整
for(int i=0;i
读取Excel获得workbook可以参见文章开头第一种用法。
如后续有更多poi的用法,将会持续更新,也欢迎各位进行指正和讨论。