本人目前还在学习阶段,部分代码写的不够完善,也有参考网上的代码片段,只是结合自己的想法,希望对poi导入导出做个适合于自己使用的封装,尽量把常用的工具能封装成自己的jar,便于以后工作学习中的使用。
工作学习中难免需要将数据导入导出到excel表中,java 也有许多jar包支持这部分操作,我使用的就是poi包进行excel的导入导出。新建项目就就免了,我用的是mvn构建的,主要的poi依赖:
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-ooxmlartifactId>
<version>3.10-FINALversion>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
<version>3.10-FINALversion>
dependency>
前期工作准备完成,开始代码部分:
/**
* 通过传入对象list集合写入excel表
* @param contentList 需写入的list集合对象
* @param outpath excel输出路径,包含excel文件名
* @param
* @throws IOException
*/
public static void writeExcel(List contentList , String outpath) throws IOException{
if(contentList !=null && outpath !=null){
//创建工作簿,若包含".xlsx"则认为是10版本,否则用03版
Workbook wb=new HSSFWorkbook();
if(outpath.contains(".xlsx")){
wb=new XSSFWorkbook();
}
CreationHelper helper=wb.getCreationHelper();
//
Sheet sheet=wb.createSheet("sheet1");
//利用反射获取传入对象第一个元素的所有属性
Field[] fields=contentList.get(0).getClass().getDeclaredFields();
Row row;
Cell cell;
//遍历内容list,每行
for (int i=0;i//创建第一行
row =sheet.createRow(i);
//设置行高
row.setHeightInPoints(20.0F);
//遍历元素属性,每列
for (int j=0;j//创建单元格样式
CellStyle cellStyle=createStyleCell(wb);
cell = row.createCell(j);
//设置居中对齐
cellStyle=setCellStyleAlignment(cellStyle);
cellStyle=setCellFormat(helper,cellStyle);
//设置单元格样式
cell.setCellStyle(cellStyle);
//获取当前行内容对象
Object o = contentList.get(i);
try {
String fi = fields[j].getName();
String mname = "get" + fi.substring(0, 1).toUpperCase() + fi.substring(1);
Method mt = o.getClass().getMethod(mname);
//反射方法过去值
String val = mt.invoke(o) != null ? PramTypeJudgeUtil.obj2Str(mt.invoke(o)) : "";
//将值写入单元格
cell.setCellValue(val);
} catch (Exception e) {
e.printStackTrace();
}
}
}
for (int j=0;j//设置列宽自动调整
sheet.autoSizeColumn(j);
}
//输出文件
OutputStream os = new FileOutputStream(new File(outpath));
wb.write(os);
os.close();
}else{
System.err.println("传入参数存在空:contentList:"+contentList+"\t outpath:"+outpath);
logger.error("传入参数存在空:contentList:"+contentList+"\t outpath:"+outpath);
}
}
其实注释也都写有,水平有限,写的基本都是只能实现自己想要的功能,想必都能看懂。代码中为了提高通用性,使用了泛型,也就是
。其中涉及到单元格样式设置的也只是简单设置了下,可以根据自己需要自行设置或者屏蔽。这种封装方式适用于有时候从数据库读取数据,并且有对应的实体类,那么使用这个封装方法会方便点,当然,这只是简单的一个模版,许多都可以再调整,比如样式,比如还可以再加参数第一行的标题变成可自定义的,这个看自己需要可以调整,完整代码下面提供。在部分场合如果每次都要对应的实体类想必很麻烦,所以我在工具类中还封装有另一个不需要实体类的方法,但是传入参数需要两层list集合,代码如下:
/***
* 通用写入excel表,将需写入内容放入list集合
* @param list
* @param outpath
* @throws IOException
*/
public static void writeExcelUniversal(List> list, String outpath) throws IOException {
if(list !=null && outpath !=null) {
//创建工作簿,若包含".xlsx"则认为是10版本,否则用03版
Workbook wb = new HSSFWorkbook();
if (outpath.contains(".xlsx")) {
wb = new XSSFWorkbook();
}
CreationHelper helper = wb.getCreationHelper();
Sheet sheet1 = wb.createSheet("sheet1");
Row row;
Cell cell;
int maxCol=0;
//循环第一层list,每行
for(int i = 0; i < list.size(); ++i) {
List rowList = list.get(i);
row = sheet1.createRow(i);
row.setHeightInPoints(20.0F);
//获取最大列数
if(rowList.size()>maxCol){
maxCol=rowList.size();
}
//循环第二层list,每列
for(int j = 0; j < rowList.size(); ++j) {
CellStyle cellStyle = createStyleCell(wb);
cell = row.createCell(j);
cellStyle = setCellStyleAlignment(cellStyle);
cellStyle = setCellFormat(helper, cellStyle);
//设置单元格样式
cell.setCellStyle(cellStyle);
//设置单元格值
cell.setCellValue(PramTypeJudgeUtil.obj2Str(rowList.get(j)));
}
}
for (int j=0;j< maxCol;j++){
//设置列宽自动调整
sheet1.autoSizeColumn(j);
}
OutputStream os = new FileOutputStream(new File(outpath));
wb.write(os);
os.close();
}else {
System.err.println("传入参数存在空:contentList:"+list+"\t outpath:"+outpath);
logger.error("传入参数存在空:contentList:"+list+"\t outpath:"+outpath);
}
}
这个代码就相对简单了,大体思路和上面类似,只是第一种封装采用了泛型和反射,用于获取对象中的属性数据,第二种是单纯的放入object对象值,然后转换为string类型放入单元格。excel读取跟写是大同小异,只是因为excel数据类型和java不一样,同样是需要转换的,转换函数我也封装了,也是部分,可根据自身需要或者以后接触再扩展。先看第一种封装的读取:
/**
* 读取excel,返回传入对象的list集合
* @param excelpath
* @param t
* @param
* @return
* @throws Exception
*/
public static List readExcel(String excelpath, T t) throws Exception {
InputStream is = new FileInputStream(new File(excelpath));
Workbook wb = WorkbookFactory.create(is);
List list = new ArrayList<>();
Sheet ts = wb.getSheetAt(0);
//获取对象的所有属性
Field[] fields = t.getClass().getDeclaredFields();
if (ts != null) {
//读取每行内容
for(int rowN = 0; rowN <= ts.getLastRowNum(); ++rowN) {
Row row = ts.getRow(rowN);
if (row != null) {
Object obj = t.getClass().newInstance();
//循环次数小于对象的元素个数且小于表格列数
for(int i = 0; i < fields.length && i"set" + fi.substring(0, 1).toUpperCase() + fi.substring(1);
//利用反射注入读取的值
//获取属性的set方法
Method mt = obj.getClass().getMethod(sname, fields[i].getType());
//获取单元格的string类型的值
String strCellVal=PramTypeJudgeUtil.getCellStringValue(cell);
//注入数据
mt.invoke(obj, newInstance(fields[i].getType(),strCellVal) );
}
list.add((T) obj);
}
}
}
return list;
}
/**
* 得到带构造的类的实例
* 实现类的有参实例
* */
private static Object newInstance(Class clazz, Object... args){
try {
if(clazz.getName().contains("util.Date")){
java.util.Date date=DateConvertHelper.str2LongDate(args[0].toString());
return date;
}
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
Constructor cons = clazz.getConstructor(argsClass);
return cons.newInstance(args);
}catch (Exception e){
e.printStackTrace();
return null;
}
}
同样是通过反射进行数据注入对象的,有个思路就是先把读取的单元格的数据先转为string类型,然后构建带参数的对象实例化用于注入的匹配对应类型数据。同样的还有一种就是不注入到对象中,直接返回两层list集合的:
/**
* 通用方法读取excel返回list集合
* @param excelpath
* @return
* @throws Exception
*/
public static List> readExcelUniversal(String excelpath) throws Exception {
InputStream is = new FileInputStream(new File(excelpath));
Workbook wb = WorkbookFactory.create(is);
Sheet ts = wb.getSheetAt(0);
List> lastlL = new ArrayList<>();
if (ts != null) {
//读取每行内容
for(int rowN = 0; rowN <= ts.getLastRowNum(); ++rowN) {
//获取行对象
Row row = ts.getRow(rowN);
if (row != null) {
List rowList = new ArrayList<>();
//读取每列
for(int i = 0; i < row.getLastCellNum(); ++i) {
//获取单元格对象
Cell cell = row.getCell(i);
//将获取的值放入行内容list集合
rowList.add(PramTypeJudgeUtil.getCellStringValue(cell));
}
//将行内容list集合放入总list集合
lastlL.add(rowList);
}
}
}
return lastlL;
}
放下使用到的部分关键函数:
/**
* 获取单元格String类型的值
* @param cell
* @return
*/
public static String getCellStringValue(Cell cell)
{
String cellvalue = "";
if(cell != null)
switch(cell.getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
short format = cell.getCellStyle().getDataFormat();
if(format == 14 || format == 31 || format == 57 || format == 58)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
double value = cell.getNumericCellValue();
Date date = DateUtil.getJavaDate(value);
cellvalue = sdf.format(date);
} else
if(DateUtil.isCellDateFormatted(cell))
{
Date date = cell.getDateCellValue();
DateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
cellvalue = formater.format(date);
} else
{
cellvalue = NumberToTextConverter.toText(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_STRING:
cellvalue = cell.getStringCellValue().replaceAll("'", "''");
break;
case Cell.CELL_TYPE_BLANK:
cellvalue = null;
break;
case Cell.CELL_TYPE_FORMULA:
default:
cellvalue = "";
break;
}
else
cellvalue = "";
return cellvalue;
}
/**
* 对象转String
* @param param
* @return
*/
public static String obj2Str(Object param)
{
String res = null;
if(param == null)
res = null;
else if(param instanceof Integer)
res = ((Integer)param).toString();
else
if(param instanceof String)
res = param.toString();
else
if(param instanceof Double)
res = ((Double)param).toString();
else
if(param instanceof Float)
res = ((Float)param).toString();
else
if(param instanceof Long)
res = ((Long)param).toString();
else
if(param instanceof Boolean)
res = ((Boolean)param).booleanValue() ? "true" : "false";
else
if(param instanceof Date)
{
Date d = (Date)param;
DateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
res = dt.format(d);
} else
{
res = param.toString();
}
return res;
}
git源码链接:https://github.com/luoFrom/appinterface/tree/master/src/main/java/com/ryx/springboot/appinterface/util
新手进入,容我赚点积分,各位见谅:http://download.csdn.net/download/suiyilp/10231520