最近查看了很多关于Excel中的中导入导出的文章和文档,发现一个严重的问题,就是距离最最近一次更新是17年。还是写的不完全的那种,有很多都是过期的函数没有去掉,本人在尝试了JXL和POI两种方法后,终于将这两种不同方法的工具测试出来了,下面直接上代码:
首先是JXL版本,一下有meven依赖包!
中央仓库地址
<!-- https://mvnrepository.com/artifact/net.sourceforge.jexcelapi/jxl --><dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
包com.shjd.jinding.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import com.shjd.jinding.entity.TestO;
import jxl.Cell;
importjxl.Workbook; import jxl.write.Label; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; class Excel { / ** *针对测试类进行导出的操作 * @参数列表 * / public static void excleOut(List <TestO> list){ WritableWorkbook test = null; try{ //创建一个excle对象 test = Workbook.createWorkbook(new File(“F:\\ test1.xls”)); //通过excle对象创建一个选项卡对象 WritableSheet sheet = test.createSheet(“sheet1”,0); //创建一个单元格对象列行值 // Label label = new Label(0,2,“test”); for(int i = 0; i <list.size(); i ++){ TestO test2 = list.get(i); label1 = new Label(0,i,String.valueOf(test2.getId())); label2 = new Label(1,i,test2.getName()); label3 = new Label(2,i,String.valueOf(test2.getAge())); //将创建好的单元格对象放入选项卡中 sheet.addCell(label1的); sheet.addCell(LABEL2); sheet.addCell(LABEL3); } //写入目标路径 test.write(); catch(Exception e){ e.printStackTrace(); } finally { try{ test.close(); } catch(WriteException | IOException e){ e.printStackTrace(); } } } / ** *针对TestO类进行的操作 * @返回 * / public static List <TestO> excleIn(){ List <TestO> list = new ArrayList <TestO>(); 工作簿worktest = null; try{ //获取Ecle对象 worktest = Workbook.getWorkbook(new File(“F:\\ test.xls”)); //获取选项卡对象第0个选项卡 Sheet sheet = worktest.getSheet(0); //循环选项卡中的值 for(int i = 0; i <sheet.getRows(); i ++){ TestO test = new TestO(); //获取单元格对象 Cell cell0 = sheet.getCell(0,i); 如果(ⅰ> = 2) { //取得单元格的值,并设置到对象中 test.setId(Integer.valueOf(cell0.getContents())); //获取单元格对象,然后取得单元格的值,并设置到对象中 test.setName(sheet.getCell(1,i).getContents()); test.setAge(Integer.valueOf(sheet.getCell(2,i).getContents())); list.add(测试); } } catch(Exception e){ e.printStackTrace(); } finally { worktest.close(); } return list; } //将TESTO对象转换为TestVo用于导出。 private static List <TestVo> convertStu2VO(List <TestO> list){ List <TestVo> list2 = new ArrayList <TestVo>(); SimpleDateFormat sdf = new SimpleDateFormat(“yyyy / M / d HH:mm:ss”); for(int i = 0; i <list.size(); i ++){ TestVo stuVo = new TestVo(); TestO stu = list.get(i); stuVo.setName(stu.getName()); stuVo.setId(stu.getId()); stuVo.setAge(stu.getAge()); list2.add(stuVo); } return list2; } public static void main(String [] args){ FileInputStream fis = null; try{ fis = new FileInputStream(“F:\\\\ test.xls”); ExcelUtil <TestVo> util = new ExcelUtil <TestVo>(( TestVo.class); //创建excel工具类 List <TestVo> list = util.importExcel(“”,fis); //导入 System.out.println(list); } catch(FileNotFoundException e){ e.printStackTrace(); } //初始数据 / * List <TestO> list = new ArrayList <TestO>(); TestO stu = new TestO(); stu.setId(1); stu.setName( “李坤”); stu.setAge(14); list.add(STU); TestO stu2 = new TestO(); stu2.setId(2); stu2.setName( “曹贵生”); stu2.setAge(20); list.add(STU2); TestO stu3 = new TestO(); stu3.setId(3); stu3.setName( “李学宇”); stu3.setAge(15); list.add(stu3); FileOutputStream out = null; try{ out = new FileOutputStream(“F:\\\\ test.xls”); } catch(FileNotFoundException e){ e.printStackTrace(); } ExcelUtil <TestVo> util = new ExcelUtil <TestVo>(TestVo.class); util.exportExcel(convertStu2VO(list),“学生信息”,60000,out); System.out.println( “----执行完毕----------”); * / //sexcel.importFromExcel("F:\\\\test.xls","0“,(Class <TestO>)TestO.class,map); / * TestO test2 = new TestO(); test2.setId(1); test2.setName( “书本名1”); test2.setAge(13); TestO test3 = new TestO(); test3.setId(2); test3.setName( “书本名2”); test3.setAge(42); list.add(TEST2); list.add(TEST3); test.excleOut(列表); * / / * for(TestO bo:Excel.excleIn()){ System.out.println(bo.getId()+“”+ bo.getName()+“”+ bo.getAge()); } * / } }
里面有对应的注解,基本上能满足基本的导入导出,当然,对于数据较多且对样式有要求的肯定是不能满足了,这个时候还有一个比较完善的poi版。
包com.shjd.jinding.util; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.poi.hssf.usermodel.DVConstraint; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; impoort org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.util.CellRangeAddressList; / * * ExcelUtil工具类实现功能: *导出时传入列表<T>,即可实现导出为一个excel,其中每个对象T为Excel中的一条记录。 *导入时读取excel,得到的结果是一个list <T> .T是自己定义的对象。 *需要导出的实体对象只需简单配置注解就能实现灵活导出,通过注解您可以方便实现下面功能: * 1.实体属性配置了注解就能导出到excel中,每个属性都对应一列。 * 2.列名称可以通过注解配置。 * 3.导出到哪一列可以通过注解配置。 * 4.鼠标移动到该列时提示信息可以通过注解配置。 * 5.用注解设置只能下拉选择不能随意填写功能。 * 6.用注解设置是否只导出标题而不导出内容,这在导出内容作为模板以供用户填写时比较实用。 *本工具类以后可能还会加功能,请关注我的博客:http://blog.csdn.net/lk_blog * / public class ExcelUtil <T> { Class <T> clazz; public ExcelUtil(Class <T> clazz){ this.clazz = clazz; } public List <T> importExcel(String sheetName,InputStream input){ List <T> list = new ArrayList <T>(); try{ HSSFWorkbook workbook=new HSSFWorkbook(输入); HSSFSheet sheet = workbook.getSheet(sheetName); if(!sheetName.trim()。equals(“”)){ sheet = workbook.getSheet(sheetName); //如果指定sheet名,则取指定sheet的内容。 } if(sheet == null){ sheet = workbook.getSheetAt(0); //如果传入的表名不存在则默认指向第1个表。 } int rows = sheet.getPhysicalNumberOfRows(); if(rows> 0){//有数据时才处理 Field [] allFields = clazz.getDeclaredFields(); //得到类的所有字段。 Map <Integer,Field> fieldsMap = new HashMap <Integer,Field>(); //定义一个map用于存放列的序号和字段。 for(Field field:allFields){ //将有注解的字段存放到地图中。 if(field.isAnnotationPresent(ExcelVOAttribute.class)){ ExcelVOAttribute attr =字段 .getAnnotation(ExcelVOAttribute.class); int col = getExcelCol(attr.column()); //获得列号 // System.out.println(col +“====”+ field.getName()); field.setAccessible(true); //设置类的私有字段属性可访问。 fieldsMap.put(col,field); } } for(int i = 1; i <rows; i ++){//从第2行开始取数据,默认第一行是表头。 HSSFRow row = sheet.getRow(i); int cellNum = row.getPhysicalNumberOfCells(); T entity = null; for(int j = 0; j <cellNum; j ++){ HSSFCell cell = row.getCell(j); if(cell == null){ return; } String c = cell.getStringCellValue(); 的System.out.println(C); if(c.equals(“”)){ return; } entity =(entity == null?clazz.newInstance():entity); //如果不存在实例则新建。 // System.out.println(cells [j] .getContents()); Field field = fieldsMap.get(j); //从地图中得到对应列的字段。 //取得类型,并根据对象类型设置值。 Class <?> fieldType = field.getType(); if(String.class == fieldType){ field.set(entity,String.valueOf(c)); } else if((Integer.TYPE == fieldType) || (Integer.class == fieldType)){ field.set(entity,Integer.parseInt(c)); } else if((Long.TYPE == fieldType) || (Long.class == fieldType)){ field.set(entity,Long.valueOf(c)); } else if((Float.TYPE == fieldType) || (Float.class == fieldType)){ field.set(entity,Float.valueOf(c)); } else if((Short.TYPE == fieldType) || (Short.class == fieldType)){ field.set(entity,Short.valueOf(c)); } else if((Double.TYPE == fieldType) || (Double.class == fieldType)){ field.set(entity,Double.valueOf(c)); } else if(Character.TYPE == fieldType){ if((c!= null)&&(c.length()> 0)){ field.set(entity,Character .valueOf(c.charAt(0))); } } } if(entity!= null){ list.add(entity); } } } } catch(IOException e){ e.printStackTrace(); } catch(InstantiationException e){ e.printStackTrace(); } catch(IllegalAccessException e){ e.printStackTrace(); } catch(IllegalArgumentException e){ e.printStackTrace(); } 退货清单; } / ** *对列表数据源将其里面的数据导入到excel表单 * * @参数sheetName *工作表的名称 * @参数sheetSize *每个表中数据的行数,此数值必须小于65536 * @param输出 * java输出流 * / public boolean exportExcel(List <T> list,String sheetName,int sheetSize, OutputStream output){ Field [] allFields = clazz.getDeclaredFields(); //得到所有定义字段 List <Field> fields = new ArrayList <Field>(); //得到所有field并存放到一个list中。 for(Field field:allFields){ if(field.isAnnotationPresent(ExcelVOAttribute.class)){ fields.add(field); } } HSSFWorkbook workbook = new HSSFWorkbook(); //产生工作薄对象 // excel2003中每个sheet中最多有65536行,为避免产生错误所以加这个逻辑。 if(sheetSize> 65536 || sheetSize <1){ sheetSize = 65536; } double sheetNo = Math.ceil(list.size()/ sheetSize); //取出一共有多少个工作表。 for(int index = 0; index <= sheetNo; index ++){ HSSFSheet sheet = workbook.createSheet(); //产生工作表对象 if(sheetNo == 0){ workbook.setSheetName(index,sheetName); } else { workbook.setSheetName(index,sheetName + index); //设置工作表的名称。 } HSSFRow row; HSSFCell cell; //产生单元格 row = sheet.createRow(0); //产生一行 //写入各个字段的列头名称 for(int i = 0; i <fields.size(); i ++){ Field field = fields.get(i); ExcelVOAttribute attr =字段 .getAnnotation(ExcelVOAttribute.class); int col = getExcelCol(attr.column()); //获得列号 cell = row.createCell(col); //创建列 cell.setCellValue(attr.name()); //写入列名 //如果设置了提示信息则鼠标放上去提示。 if(!attr.prompt().trim().equals(“”)){ setHSSFPrompt(sheet,“”,attr.prompt(),1,100,col,col); //这里默认设了2-101列提示。 } //如果设置了combo属性则本列只能选择不能输入 if(attr.combo().length> 0){ setHSSFValidation(sheet,attr.combo(),1,100,col,col); //这里默认设了2-101列表只能选择不能输入。 } } int startNo = index * sheetSize; int endNo = Math.min(startNo + sheetSize,list.size()); //写入各条记录,每条记录对应excel表中的一行 for(int i = startNo; i <endNo; i ++){ row = sheet.createRow(i + 1 - startNo); T vo =(T)list.get(i); //得到导出对象。 for(int j = 0; j <fields.size(); j ++){ Field field = fields.get(j); //获得field。 field.setAccessible(true); //设置实体类私有属性可访问 ExcelVOAttribute attr =field .getAnnotation(ExcelVOAttribute.class); try{ //根据ExcelVOAttribute中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列。 if(attr.isExport()){ cell = row.createCell(getExcelCol(attr.column())); //创建单元格 cell.setCellValue(field.get(vo)== null?“” :String.valueOf(field.get(vo))); //如果数据存在就填入,不存在填入空格。 } } catch(IllegalArgumentException e){ e.printStackTrace(); } catch(IllegalAccessException e){ e.printStackTrace(); } } } } try{ output.flush(); workbook.write(output); output.close(); return true; } catch(IOException e){ e.printStackTrace(); System.out.println(“输出已关闭”); return false; } } / ** *将EXCEL中的A,B,C,D,E列映射成0,1,2,3 * * @param col * / public static int getExcelCol(String col){ col = col.toUpperCase(); //从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。 int count = -1; char [] cs = col.toCharArray(); for(int i = 0; i <cs.length; i ++){ count + =(cs [i] - 64)* Math.pow(26,cs.length - 1 - i); } 返回计数; } / ** *设置单元格上提示 * * @参数表 *要设置的工作表。 * @参数promptTitle *标题 * @param promptContent *内容 * @参数firstRow *开始行 * @param endRow *结束行 * @param firstCol *开始列 * @param endCol *结束列 * @return设置好的工作表。 * / public static HSSFSheet setHSSFPrompt(HSSFSheet表单,字符串promptTitle, 字符串promptContent,int firstRow,int endRow,int firstCol, int endCol){ //构造约束对象 DVConstraint约束= DVConstraint .createCustomFormulaConstraint( “DD1”); //四个参数分别是:起始行,终止行,起始列,终止列 CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow,firstCol,endCol); //数据有效性对象 HSSFDataValidation data_validation_view = new HSSFDataValidation( regions,constraint); data_validation_view.createPromptBox(promptTitle,promptContent); sheet.addValidationData(data_validation_view); return sheet; } / ** *设置某些列的值只能输入预制的数据,显示下拉框。 * * @参数表 *要设置的工作表。 * @参数文本列表 *下拉框显示的内容 * @参数firstRow *开始行 * @param endRow *结束行 * @param firstCol *开始列 * @param endCol *结束列 * @return设置好的工作表。 * / public static HSSFSheet setHSSFValidation(HSSFSheet表, String [] textlist,int firstRow,int endRow,int firstCol, int endCol){ //加载下拉列表内容 DVConstraint constraint= DVConstraint .createExplicitListConstraint(textlist); //设置数据有效性加载在哪个单元格上,四个参数分别是:起始行,终止行,起始列,终止列 CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow,firstCol,endCol); //数据有效性对象 HSSFDataValidation data_validation_list = new HSSFDataValidation( 地区,约束); sheet.addValidationData(data_validation_list); return sheet; } }测试类在第一个jxl下有这个静态方法,其中包括了poi的测试方法,朋友们在参考代码的时候这个不能直接用在开发工具上,有些地方中英文字符需要手动调下。如有不对之处还请指出谢谢。