因为最近的项目需要对Excel进行读写操作,看了朋友使用的阿里的easyExcel发现仍然需要依赖poi而且使用起来也并不是那么容易。github的文档也只有一份,使用起来不够灵活,easyExcel内存占用非常少的优点对我来讲也可有可无,实际上poi的占用也不高。最后,我对poi进行了简单易用的二次封装,并投入项目使用。
语言:java
jdk版本要求:满足poi4.1.0的jdk版本要求即可,亲测jdk1.8和jdk11,更低版本的没测试过。
需要的jar包:
1、gson直接使用maven导入,也可自行下载,版本没有限制
<!--++++++++++++++GSON依赖++++++++++++++++++++++++++++++++++-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
2、poi包集合,poi包在使用时添加maven依赖总是会报org.apache.poi.hssf.usermodel.HSSFWorkbook;找不到,搞得我头大。所以我从网上扒了几天,提供了离线的poi包完整依赖集合,传送门:
poi4.1.0 jar包集合
如果使用maven打包离线jar文件到项目中,需要在pom的builder标签中添加配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<target>11</target>
<source>11</source>
<compilerArguments>
<extdirs>./libs</extdirs><!-- libs 为pom文件同级目录-->
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
项目中测试写Excel效果:
读效果:
poi封装代码,包导入后直接复制粘贴即可:
import com.google.gson.Gson;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
/**
*Excel工具
*@author:http://www.gaozhi.online
*/
public class Excel {
/**
* Excel格式-枚举用于区分版本时使用
*/
public static enum VERSION{
XLS, XLSX
};
/**
* 方位-表的Cell的上下左右四个边界
*/
public static enum POSITION{
LEFT,BOTTOM,RIGHT,TOP,ALL
}
/**
* 读取Excel的工具
*/
public static class Reader{
private Gson gson=new Gson();
private File file;
private Workbook workbook;
private FileInputStream inputStream;
//起始列
private int startColumn=0;
//结束列
private int endColumn=1;
private ReaderListener readerListener;
/**
*
* @param path 要读取的文件路径+文件名
* @param version 文件版本
* @throws FileNotFoundException 文件不存在则抛出异常
*/
public Reader(String path,VERSION version)throws FileNotFoundException{
file=new File(path);
if(!file.exists()){
throw new FileNotFoundException("文件"+path+"不存在!");
}
inputStream = new FileInputStream(file);
// 1.读取工作簿
try {
workbook = version==VERSION.XLS ? new HSSFWorkbook(inputStream) : new XSSFWorkbook(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取读取列数起点
* @return
*/
public int getStartColumn() {
return startColumn;
}
/**
* 设置读取列数起点
* @param startColumn
*/
public void setStartColumn(int startColumn) {
this.startColumn = startColumn;
}
/**
* 获取读取列数终点
* @return
*/
public int getEndColumn() {
return endColumn;
}
/**
* 设置读取列数终点
* @param endColumn
*/
public void setEndColumn(int endColumn) {
this.endColumn = endColumn;
}
/**
* 获取表格数量
* @return
*/
public int getSheetNum(){
return workbook.getNumberOfSheets();
}
/**
* 根据序号获取表格
* @param i
* @return
*/
public Sheet getSheetByID(int i){
return workbook.getSheetAt(i);
}
/**
* 根据表名获取表
* @param name
* @return
*/
public Sheet getSheetByName(String name){
for(int i=0;i<getSheetNum();i++){
if(StringUtil.equals(getSheetByID(i).getSheetName(),name))
return getSheetByID(i);
}
return null;
}
/**
* 获取表格行数
* @param sheet
* @return
*/
public int getSheetRowNum(Sheet sheet){
return sheet.getPhysicalNumberOfRows();
}
/**
* 获取表格全部数据
* @param sheet 表格
* @return
*/
public List<String> read(Sheet sheet){
return read(sheet,0,getSheetRowNum(sheet)-1);
}
/**
* 获取表格的从start 到最后一行
* @param sheet 表格
* @param start 起点
* @return
*/
public List<String> read(Sheet sheet,int start){
return read(sheet,start,getSheetRowNum(sheet));
}
/**
* 获取表格的 start 到 end 行
* @param sheet
* @param start
* @param end
* @return
*/
public List<String> read(Sheet sheet,int start,int end){
List<String> listTotal=new LinkedList<>();
for(int i=start;i<end;i++){//读
Row row=sheet.getRow(i);
List<String> listRow=new LinkedList<>();
for(int j=startColumn;j<endColumn;j++){
Cell cell=row.getCell(j);
if (cell == null) {
listRow.add("");
if(readerListener!=null){
readerListener.reader(sheet,i,j,"");
}
} else {
listRow.add(cell.getStringCellValue());
if(readerListener!=null){
readerListener.reader(sheet,i,j,cell.getStringCellValue());
}
}
}
listTotal.add(gson.toJson(listRow));
if(readerListener!=null){
readerListener.reader(sheet,i,gson.toJson(listRow));
}
}
return listTotal;
}
/**
* 设置读监听器
* @param readerListener
*/
public void setReaderListener(ReaderListener readerListener) {
this.readerListener = readerListener;
}
public void close(){
try {
inputStream.close();
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读表监听器
*/
public interface ReaderListener{
void reader(Sheet sheet,int row,String json);
void reader(Sheet sheet,int row,int column,String content);
}
}
/**
* 写Excel
*/
public static class Writer{
private Workbook workbook;
private Sheet sheet;
private String path;
private FileOutputStream out;
/**
*
* @param path excel文件路径+文件名
* @param sheetName excel 表名称
* @param version excel版本
*/
public Writer(String path,String sheetName,VERSION version) throws IOException {
File file=new File(path);
if(file.exists()){
file.createNewFile();
}
out= new FileOutputStream(path);
workbook = version==VERSION.XLS ? new HSSFWorkbook():new XSSFWorkbook();
//创建工作表
sheet = workbook.createSheet(sheetName);
}
/**
* 创建合并单元格
* @param firstRow 起始行
* @param lastRow 结束行
* @param firstCol 起始列
* @param lastCol 结束列
*/
public CellRangeAddress createMergedRegion(int firstRow, int lastRow, int firstCol, int lastCol){
//创建合并单元格对象
CellRangeAddress cellRangeAddress = new CellRangeAddress(firstRow,lastRow,firstCol,lastCol);
sheet.addMergedRegion(cellRangeAddress);
return cellRangeAddress;
}
/**
* 设置合并单元格样式
* @param region
*/
public void setRegionBorderStyle(CellRangeAddress region,BorderStyle style,int color,POSITION position){
// 合并单元格左边框样式
if(position==POSITION.LEFT||position==POSITION.ALL){
RegionUtil.setBorderLeft(style, region, sheet);
RegionUtil.setLeftBorderColor(color, region, sheet);
}
// 合并单元格上边框样式
if(position==POSITION.TOP||position==POSITION.ALL){
RegionUtil.setBorderTop(style, region, sheet);
RegionUtil.setTopBorderColor(color, region, sheet);
}
// 合并单元格右边框样式
if(position==POSITION.RIGHT||position==POSITION.ALL){
RegionUtil.setBorderRight(style, region, sheet);
RegionUtil.setRightBorderColor(color, region, sheet);
}
// 合并单元格下边框样式
if(position==POSITION.BOTTOM||position==POSITION.ALL){
RegionUtil.setBorderBottom(style, region, sheet);
RegionUtil.setBottomBorderColor(color, region, sheet);
}
}
/**
* 设置默认列宽
* @param columnWidth
*/
public void setDefaultColumnWidth(int columnWidth){
sheet.setDefaultColumnWidth(columnWidth);
}
/**
* 设置默认行高
* @param height
*/
public void setDefaultRowHeight(short height){
sheet.setDefaultRowHeight(height);
}
/**
* 设置列宽
* @param i
* @param width
*/
public void setColumnWidth(int i,int width){
sheet.setColumnWidth(i,width);
}
/**
* 获取表格行数
* @return
*/
public int getSheetRowNum(){
return sheet.getPhysicalNumberOfRows();
}
/**
* 创建style
* @return
*/
public CellStyle createStyle(){
return workbook.createCellStyle();
}
/**
* 创建字体
* @return
*/
public Font createFont(){
return workbook.createFont();
}
/**
* 向sheet中写入一行数据
* @param rowData 行数据
* @param cellStyle 样式
* @return 返回表的行数
*/
public int writeRow(List<String> rowData, CellStyle cellStyle){
Row row=sheet.createRow(getSheetRowNum());
int i=0;
for(String e:rowData){
Cell cell=row.createCell(i);
cell.setCellStyle(cellStyle);
cell.setCellValue(e);
i++;
}
return getSheetRowNum();
}
/**
* 将缓冲区数据写入磁盘
*/
public void flush(){
try {
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 关闭writer,
*/
public void close(){
try {
workbook.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Excel写监听器
*/
public interface WriterListener{
void writer(Sheet sheet,int row,String json);
void writer(Sheet sheet,int row,int column,String content);
}
}
}
封装方法中给出了函数的简单注解,这里给出具体的使用例子:
使用方法:
读方法很简单,就不赘述了。
写方法如下:
**方法一:**直接使用,查看Excel.Writer的API注释即可快速上手。
**方法二:**定制表模板,需要生成的表大多拥有固定的结构和样式。所以我推荐这种方法。下面给出的示例代码解析:1、继承Excel.Writer。2、定制表的样式,根据具体需求。要特别注意的一点是合并单元格 不仅需要设置CellStyle,还需要单独的Border设置,如下:
设置合并单元格区域的边框样式:
setRegionBorderStyle(createMergedRegion(0,0,0,title.size()-1),BorderStyle.THIN,IndexedColors.WHITE.getIndex(), Excel.POSITION.ALL);。
package gaozhi.online.excel;
import gaozhi.online.application.Application;
import gaozhi.online.util.Excel;
import org.apache.poi.ss.usermodel.*;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
/**
* 收费单生成
*/
public class ChargeExcelWriter extends Excel.Writer {
//表头样式
private CellStyle sheetHeaderStyle=createStyle();
//表列头样式
private CellStyle sheetColumnHeaderStyle=createStyle();
//表格内容样式
private CellStyle sheetContentStyle=createStyle();
//表尾样式
private CellStyle sheetTailStyle=createStyle();
/**
* @param path excel文件路径+文件名
* @param sheetName excel 表名称
* @param version excel版本
*/
public ChargeExcelWriter(String path, String sheetName, Excel.VERSION version) throws IOException {
super(path, sheetName, version);
setDefaultColumnWidth(6);
setDefaultRowHeight((short) 10);
generalStyle(sheetHeaderStyle,(short)16);
generalStyle(sheetColumnHeaderStyle,(short)8);
generalStyle(sheetContentStyle,(short)11);
generalStyle(sheetTailStyle,(short)13);
}
/**
* @param style 要设置的样式
* @param fontSize 字体大小
*/
private void generalStyle(CellStyle style,short fontSize){
style.setAlignment(HorizontalAlignment.CENTER);//水平居中
style.setVerticalAlignment(VerticalAlignment.CENTER );//垂直居中
// 创建字体
Font font =createFont();
//font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontHeightInPoints(fontSize);
style.setFont(font);
//设置边框
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
}
/**
* 画收费表的表头
* @param header
* @param title
*/
public void writeHeader(String header, List<String>title){
List<String>headerList=new LinkedList<>();
headerList.add(header);
writeRow(headerList,sheetHeaderStyle);
setRegionBorderStyle(createMergedRegion(0,0,0,title.size()-1),BorderStyle.THIN,IndexedColors.WHITE.getIndex(), Excel.POSITION.ALL);
writeRow(title,sheetColumnHeaderStyle);
}
/**
* 写收费表的内容
* @param rowData
*/
public void writeRow(List<String>rowData){
writeRow(rowData,sheetContentStyle);
}
/**
* 写底部信息
* @param tail
*/
public void writeTail(String tail){
List<String>tailList=new LinkedList<>();
tailList.add(tail);
writeRow(tailList,sheetContentStyle);
setRegionBorderStyle(createMergedRegion(getSheetRowNum()-1,getSheetRowNum()-1,0, Application.charge_sheet_title.length-1),BorderStyle.THIN,IndexedColors.WHITE.getIndex(), Excel.POSITION.ALL);
}
}
上手demo
写完不要忘了将缓冲区内容写入磁盘并关闭流:
package gaozhi.online.excel;
import gaozhi.online.util.Excel;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class Test {
public static void main(String[]args) throws IOException {
//写xlsx版本的excel 如果不存在则创建,第一个参数为路径加名称,后缀名需要匹配版本,第二个参数为表格名,第三个参数为excel版本
ChargeExcelWriter chargeExcelWriter=new ChargeExcelWriter("text.xlsx","我是表格1", Excel.VERSION.XLSX);
String[]title_str=new String[]{"第一列","第二列","第三列","第四列"};
List<String> title= Arrays.asList(title_str);
chargeExcelWriter.writeHeader("xxx收费表",title);
for(int i=0;i<10;i++)
chargeExcelWriter.writeRow(title);
//记得将缓冲区数据写入磁盘
chargeExcelWriter.flush();
//使用完记得关闭解除资源占用
chargeExcelWriter.close();
}
}
demo代码效果:
创作不易,跪求点赞收藏,转发请注明出处