个人项目
GitHub地址:https://github.com/83945105/holygrail
Maven坐标: 目前最新版0.0.5
地址一:点击打开链接
地址二:点击打开链接
导入导出目前实现了常用功能,后续我会不断完善,如添加字体设置
/*模拟从数据库获取数据开始*/Collection
/*模拟从数据库获取数据开始*/Collection
/*模拟从数据库获取数据开始*/Collection
//构建用于描述标题的二维数组,获取数据代码略SXSSFExcelTitle[][] titles = new SXSSFExcelTitle[1][];SXSSFExcelTitle[] title = new SXSSFExcelTitle[3];title[0] = new SXSSFExcelTitle();title[1] = new SXSSFExcelTitle();title[2] = new SXSSFExcelTitle();title[0].setField("username");//设置标题所在列对应数据的字段title[1].setField("password");title[2].setField("mobile");title[0].setTitle("姓名");//设置标题名称title[1].setTitle("密码");title[2].setTitle("手机号");title[0].setWidth(50);//设置列宽,默认10,由于计算原因,实际效果稍有误差title[1].setWidth(60);title[2].setWidth(70);title[0].setHAlign(CellStyle.H_AlignType.LEFT);//设置水平对齐方式为左对齐,标题默认水平居中title[0].setVAlign(CellStyle.V_AlignType.BOTTOM);//设置垂直对齐方式为底部对齐,标题默认垂直居中title[0].setBorderLeft(CellStyle.BorderStyle.DASH_DOT);//设置左边框样式,同样还可以设置其它方向边框titles[0] = title;Export.buildSXSSFExportExcelWorkBook().createSheet().setTitles(titles)//设置标题.importData(records).export("E://测试.xlsx");
ExcelWorkBookExport.exportTemplateJavascriptFile("E://user.js");//你可以这样导出一个模板文件
[[{title: '姓名',field: 'username',width: 20,borderLeft: 'DASHED'
},{title: '密码',field: 'password',hAlign: 'Left',vAlign: 'top',width: 30
},{title: '手机号',field: 'mobile',width: 15
}]]
Export.buildSXSSFExportExcelWorkBook().createSheet()//解析一个标题文件,文件放在你能加载到的位置就可以,这里我使用输入流的方式 .parseTitlesJson(Test.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js")) .importData(records).export("E://测试.xlsx");
[[{title: '姓'
}, {title: '名'
}, {title: '密码+手机号',colSpan: 2
}, {title: '占用2行',rowSpan: 2
}], [{title: '姓名',field: 'username',width: 20,colSpan: 2}, {title: '密码',field: 'password',width: 15}, {title: '手机号',field: 'mobile',width: 15}
]]
Export.buildSXSSFExportExcelWorkBook()//构建查询对象.createSheet()//创建一个Sheet,可以传参设置Sheet名.parseTitlesJson(Test.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"))//使用lambda表达式作为第二个参数格式化单元格,如果你会写Javascript可以理解为JS的回调函数.importData(records, (value, record, cellHandler, field, rowCursor, index) -> {//value => 当前单元格的值//record => 当前行数据//cellHandler => 用于设置和获取单元格属性样式的对象,这个对象可以自己点进去看注释,可以干很多事情//field => 当前单元格对应的title field//rowCursor => 行游标,记录当前写入行的游标号,该号从0开始//index => 当前行数据也就是record在数据集合records中的下标if("num".equals(field)) {//如果是序号列cellHandler.setHAlign("center");//设置单元格为水平居中,支持直接传入字符串cellHandler.setVAlign(CellStyle.V_AlignType.CENTER);//设置单元格为垂直居中cellHandler.setType(CellOption.CellType.COMBOBOX);//设置单元格类型为下拉框cellHandler.setOptions(new String[]{"下拉框值1", "下拉框值2"});//设置下拉框值return index + 1;//使用下标号+1作为单元格值}return value;})//导入数据,支持多次导入.export("E://测试.xlsx");
再来一个更复杂点的例子
[[{title: '序号',field: 'num',rowSpan: '2'
主要说下writeEmpty属性,这个属性默认是true,表示当该列的单元格值为空的时候,也写入数据,
}, {title: '姓'
}, {title: '名'
}, {title: '密码+手机号',colSpan: 2
}, {title: '占用2行',rowSpan: 2,writeEmpty: false
}], [{title: '姓名',field: 'username',width: 20,colSpan: 2}, {title: '密码',field: 'password',width: 15}, {title: '手机号',field: 'mobile',width: 15}
]]
Export.buildSXSSFExportExcelWorkBook().createSheet().parseTitlesJson(Test.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js")).importData(records, (value, record, cellHandler, field, rowCursor, index) -> {//设置所有数据单元格为水平垂直居中cellHandler.setHAlign("center");cellHandler.setVAlign("center");if("num".equals(field)) {//如果是序号列,将值改为当前数据下标+1return index + 1;}if("username".equals(field)) {//如果是用户名列,将单元格改为占用3列cellHandler.setColSpan(3);}if("password".equals(field)) {//如果是密码列,将单元格起始行下移一行cellHandler.setStartRowNum(cellHandler.getStartRowNum() + 1);//占用行改为3行cellHandler.setRowSpan(3);}if("mobile".equals(field)) {//如果是手机号列//手机号列占用行改为5行cellHandler.setRowSpan(5);//占用列改为2行cellHandler.setColSpan(2);//将值格式化成数值类型return Integer.parseInt(value == null ? "" : value.toString());}return value;})//导入数据,支持多次导入.export("E://测试.xlsx");//导出成Excel
Export.buildSXSSFExportExcelWorkBook()//批量创建10个sheet.createSheets(10, (sheet, sheetIndex, index, totalAllSheetDataSize, totalSheetDataSize) -> {//sheet => 当前创建的sheet对象//sheetIndex => 当前创建的sheet在整个工作簿中的下标//index => 当前创建的sheet在这个批次sheet的下标//totalAllSheetDataSize => 整个工作簿已经导入的数据总数//totalSheetDataSize => 这个批次sheet已经导入的数据总数sheet.setColumnFields("").importData(new ArrayList<>());}).export("E://批量Sheet.xlsx");
Export.buildSXSSFExportExcelWorkBook()//批量创建10个sheet.createSheets(10, (sheetIndex, index) -> "格式化Sheet名", (sheet, sheetIndex, index, totalAllSheetDataSize, totalSheetDataSize) -> {sheet.setColumnFields("").importData(new ArrayList<>());}).export("E://批量Sheet.xlsx");
Export.buildSXSSFExportExcelWorkBook().createSheets((sheet, sheetIndex, index, totalAllSheetDataSize, totalSheetDataSize) -> {sheet.parseTitlesJson("").importData(new HashSet<>());if(totalSheetDataSize > 1000) {//当导入的数据大于1000条,停止创建Sheetreturn false;}return true;//继续创建Sheet,内部限制最大100个}).export("E://批量Sheet.xlsx");
此外还有一些方法,我就不贴代码了,如设置行号,设置列号控制导入数据的起始行之类的,方法都有详细的注释,用IDE提示就能看到所有方法,基本什么功能都能猜到。
ArrayList
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx"))//解析一个Excel.getSheet(0)//获取下标为0的Sheet.readRows((record, records, rowNum, index) -> {ArrayList> _record = (ArrayList>) record;//一行行获取数据System.out.println(_record.get(0));//取每条数据的第一列的值});
在lambda函数中获取当前读取行的数据
2、指定列值获取数据
ArrayList
指定了列值后,默认会将数据注入HashMap,列值为Key,单元格值为Value,如果此时存在没指定列值的单元格,将会使用坐标作为Key,如A1表示第一行第一列,B4表示第四行第二列。
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0).setColumnFields(2,"num", "username", "password")//设置列值,2表示标题占用2行,那么接下来读取数据将从第三行开始.readRows((record, records, rowNum, index) -> {HashMap
同样可以一行行获取数据
3、使用标题二维数组或者js文件读取Excel(详情见导出)
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0).parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js")).readRows((record, records, rowNum, index) -> {HashMap
二维数组方式同导出,这里就不写了
4、自定义全局接收数据对象
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0)//解析标题文件,并指定使用LinkedHashMap作为数据容器接收数据.parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"), LinkedHashMap.class).readRows((record, records, rowNum, index) -> {
LinkedHashMap
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0)//解析标题文件,并指定使用User对象作为数据容器接收数据.parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"), User.class).readRows((record, records, rowNum, index) -> {//这里可以转成User对象获取数据User _record = (User) record;System.out.println(_record.getUsername());});
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).getSheet(0).parseTitlesJson(Test2.class.getResourceAsStream("/com/xx/xx/xx/xx/user.js"), HashMap.class).readRows(User.class, (record, records, rowNum, index) -> {//读取行时指定对象,覆盖全局,此时不用强转,可直接推导出类型System.out.println(record.getUsername());});
6、连续读取存在的Sheet
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).readSheets((sheet, index) -> {//读取当前Sheet数据sheet.setColumnFields("").readRows(User.class, (record, records, rowNum, index1) -> {System.out.println(record.getUsername());});});
Import.buildXSSFImportExcelWorkBook().parseFile(new File("E://测试.xlsx")).readSheets((sheet, index) -> {//读取当前Sheet数据sheet.setColumnFields("").readRows(User.class, (record, records, rowNum, index1) -> {System.out.println(record.getUsername());});if(sheet.getAllReadData().size() > 1000) {//当读取的数据总数大于1000,停止读取下一个Sheetreturn false;}return true;});
读取比较简单,就不详细说了。