POI报表及百万数据导入导出方案
1、POI报表的概述
1.1 需求说明
在企业级应用开发中,Excel报表是一种最常见的报表需求。Excel报表开发一般分为两种形式:为了方便操作,基于Excel的报表批量上传数据;通过java代码生成Excel报表。
1.2 Excel的两种形式
目前世面上的Excel分为两个大的版本Excel2003和Excel2007及以上两个版本,两者之间的区别如下:
Excel2003是一个特有的二进制格式,其核心结构是复合文档类型的结构,存储数据量较小;Excel2007 的核心结构是 XML 类型的结构,采用的是基于 XML 的压缩方式,使其占用的空间更小,操作效率更高
1.3 常见excel操作工具
Java中常见的用来操作Excl的方式一般有2种:JXL和POI。
JXL只能对Excel进行操作,属于比较老的框架,它只支持到Excel 95-2000的版本。现在已经停止更新和维护。
Apache POI是Apache软件基金会的开源项目,由Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java语言操作Microsoft Office的功能。可对微软的Word,Excel,Ppt进行操作,包括office2003和2007,Excl2003和2007。poi现在一直有更新。所以现在主流使用POI。
1.4 POI的应用场景
- 数据报表生成
- 数据备份
- 数据批量上传
2、POI的入门操作
2.1 搭建环境
<dependencies><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.0.1</version></dependency>
</dependencies>
2.2 POI结构说明
- HSSF提供读写Microsoft Excel XLS格式档案的功能。
- XSSF提供读写Microsoft Excel OOXML XLSX格式档案的功能。
- HWPF提供读写Microsoft Word DOC格式档案的功能。
- HSLF提供读写Microsoft PowerPoint格式档案的功能。
- HDGF提供读Microsoft Visio格式档案的功能。
- HPBF提供读Microsoft Publisher格式档案的功能。
- HSMF提供读Microsoft Outlook格式档案的功能。
2.3 API介绍
- Workbook: Excel的文档对象,针对不同的Excel类型分为:HSSFWorkbook(2003)和 XSSFWorkbool(2007)
- Sheet: Excel的表单
- Row: Excel的行
- Cell: Excel的格子单元
- Font: Excel字体
- CellStyle: 格子单元样式
2.4 基本操作
2.4.1 创建Excel
@Test
public void createExcel throws Exception {//1.创建工作簿 HSSFWorkbook -- 2003Workbook wb = new XSSFWorkbook(); //2007版本//2.创建表单sheetSheet sheet = wb.createSheet("test");//3.文件流FileOutputStream pis = new FileOutputStream("E:\\excel\\poi\\test.xlsx");//4.写入文件wb.write(pis);pis.close();}
2.4.2 创建单元格
@Test
public void createCell throws Exception {//创建工作簿 HSSFWorkbook -- 2003Workbook wb = new XSSFWorkbook(); //2007版本//创建表单sheetSheet sheet = wb.createSheet("test");//创建行对象 参数:索引(从0开始)Row row = sheet.createRow(2);//创建单元格对象 参数:索引(从0开始)Cell cell = row.createCell(2);//向单元格中写入内容cell.setCellValue("君莫笑");//文件流FileOutputStream pis = new FileOutputStream("E:\\excel\\poi\\test1.xlsx");//写入文件wb.write(pis);pis.close();}
2.4.3 设置格式
@Testpublic void setStyle() throws Exception {//创建工作簿 HSSFWorkbook -- 2003Workbook wb = new XSSFWorkbook(); //2007版本//创建表单sheetSheet sheet = wb.createSheet("test");//创建行对象 参数:索引(从0开始)Row row = sheet.createRow(2);//创建单元格对象 参数:索引(从0开始)Cell cell = row.createCell(2);//向单元格中写入内容cell.setCellValue("君莫笑");//样式处理//创建样式对象CellStyle style = wb.createCellStyle();style.setBorderTop(BorderStyle.THIN);//上边框style.setBorderBottom(BorderStyle.THIN);//下边框style.setBorderLeft(BorderStyle.THIN);//左边框style.setBorderRight(BorderStyle.THIN);//右边框//创建字体对象Font font = wb.createFont();font.setFontName("华文行楷"); //字体font.setFontHeightInPoints((short)28);//字号style.setFont(font);//行高和列宽row.setHeightInPoints(50);//行高//列宽的宽度 字符宽度sheet.setColumnWidth(2,31 * 256);//列宽//剧中显示style.setAlignment(HorizontalAlignment.CENTER);//水平居中style.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中//向单元格设置样式cell.setCellStyle(style);//文件流FileOutputStream pis = new FileOutputStream("E:\\excel\\poi\\test2.xlsx");//写入文件wb.write(pis);pis.close();}
2.4.4 插入图形
blic void createPicture() throws Exception {//创建工作簿 HSSFWorkbook -- 2003Workbook wb = new XSSFWorkbook(); //2007版本//创建表单sheetSheet sheet = wb.createSheet("test");//读取图片流FileInputStream stream = new FileInputStream("E:\\excel\\poi\\test.jpg");//转化二进制数组byte[] bytes = IOUtils.toByteArray(stream);stream.read(bytes);//向POI内存中添加一张图片,返回图片在图片集合中的索引int index = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);//参数一:图片的二进制数据,参数二:图片类型//绘制图片工具类CreationHelper helper = wb.getCreationHelper();//创建一个绘图对象Drawing<?> patriarch = sheet.createDrawingPatriarch();//创建锚点,设置图片坐标ClientAnchor anchor = helper.createClientAnchor();anchor.setRow1(0);anchor.setCol1(0);//绘制图片Picture picture = patriarch.createPicture(anchor, index);//图片位置,图片的索引picture.resize();//自适应渲染图片//文件流FileOutputStream pis = new FileOutputStream("E:\\excel\\poi\\test3.xlsx");//写入文件wb.write(pis);pis.close();}
2.4.5 加载解析Excel
/*** 读取excel并解析* sheet.getLastRowNum() : 最后一行的索引* row.getLastCellNum() : 最后一个单元格的号码*/@Testpublic void parseExcel() throws Exception {//1.根据Excel文件创建工作簿Workbook wb = new XSSFWorkbook("E:\\excel\\poi\\test.xlsx");//2.获取SheetSheet sheet = wb.getSheetAt(0);//参数:索引//3.获取Sheet中的每一行,和每一个单元格for (int rowNum = 0; rowNum<= sheet.getLastRowNum() ;rowNum ++) {Row row = sheet.getRow(rowNum);//根据索引获取每一个行StringBuilder sb = new StringBuilder();for(int cellNum=2;cellNum< row.getLastCellNum(); cellNum ++) {//根据索引获取每一个单元格Cell cell = row.getCell(cellNum);//获取每一个单元格的内容Object value = getCellValue(cell);sb.append(value).append("-");}System.out.println(sb.toString());}}public static Object getCellValue(Cell cell) {//1.获取到单元格的属性类型CellType cellType = cell.getCellType();//2.根据单元格数据类型获取数据Object value = null;switch (cellType) {case STRING:value = cell.getStringCellValue();break;case BOOLEAN:value = cell.getBooleanCellValue();break;case NUMERIC:if(DateUtil.isCellDateFormatted(cell)) {//日期格式value = cell.getDateCellValue();}else{//数字value = cell.getNumericCellValue();}break;case FORMULA: //公式value = cell.getCellFormula();break;default:break;}return value;}
2.5 用户导入示例
/*** 导入Excel,添加用户* 文件上传:springboot*/@RequestMapping(value="/user/import",method = RequestMethod.POST)public Result importUser(@RequestParam(name="file") MultipartFile file) throws Exception {//1.解析Excel//1.1.根据Excel文件创建工作簿Workbook wb = new XSSFWorkbook(file.getInputStream());//1.2.获取SheetSheet sheet = wb.getSheetAt(0);//参数:索引//1.3.获取Sheet中的每一行,和每一个单元格//2.获取用户数据列表List<User> list = new ArrayList<>();System.out.println(sheet.getLastRowNum());for (int rowNum = 1; rowNum<= sheet.getLastRowNum() ;rowNum ++) {Row row = sheet.getRow(rowNum);//根据索引获取每一个行Object [] values = new Object[row.getLastCellNum()];for(int cellNum=1;cellNum< row.getLastCellNum(); cellNum ++) {Cell cell = row.getCell(cellNum);Object value = getCellValue(cell);values[cellNum] = value;}//在User的构造函数中,根据表格值顺序设置User对应的属性值User user = new User(values);list.add(user);}//3.调用服务层批量保存用户userService.saveAll(list);return new Result(ResultCode.SUCCESS);}public static Object getCellValue(Cell cell) {//1.获取到单元格的属性类型CellType cellType = cell.getCellType();//2.根据单元格数据类型获取数据Object value = null;switch (cellType) {case STRING:value = cell.getStringCellValue();break;case BOOLEAN:value = cell.getBooleanCellValue();break;case NUMERIC:if(DateUtil.isCellDateFormatted(cell)) {//日期格式value = cell.getDateCellValue();}else{//数字value = cell.getNumericCellValue();}break;case FORMULA: //公式value = cell.getCellFormula();break;default:break;}return value;}
2.6 用户导出示例
@RequestMapping(value = "/export/{month}", method = RequestMethod.GET)public void export(@PathVariable(name = "month") String month) throws Exception {//1.构造数据,某个月的用户数据List<User> list =userService.findByMonth(month);//2.创建工作簿XSSFWorkbook workbook = new XSSFWorkbook();//3.构造sheetString[] titles = {"编号", "姓名", "手机","最高学历", "国家地区","生日", "时间"};Sheet sheet = workbook.createSheet();Row row = sheet.createRow(0);AtomicInteger headersAi = new AtomicInteger();for (String title : titles) {Cell cell = row.createCell(headersAi.getAndIncrement());cell.setCellValue(title);}AtomicInteger datasAi = new AtomicInteger(1);Cell cell = null;for (User user : list) {Row dataRow = sheet.createRow(datasAi.getAndIncrement());//编号cell = dataRow.createCell(0);cell.setCellValue(user.getUserId());//姓名cell = dataRow.createCell(1);cell.setCellValue(user.getUsername());//手机cell = dataRow.createCell(2);cell.setCellValue(user.getMobile());//最高学历cell = dataRow.createCell(3);cell.setCellValue(user.getTheHighestDegreeOfEducation());//国家地区cell = dataRow.createCell(4);cell.setCellValue(user.getNationalArea());//生日cell = dataRow.createCell(7);cell.setCellValue(user.getBirthday());//时间cell = dataRow.createCell(12);cell.setCellValue(user.getCreateTime());}String fileName = URLEncoder.encode(month+"人员信息.xlsx", "UTF-8");response.setContentType("application/octet-stream");response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1")));response.setHeader("filename", fileName);workbook.write(response.getOutputStream());}
3、模板打印
3.1 概述
自定义生成Excel报表文件还是有很多不尽如意的地方,特别是针对复杂报表头,单元格样式,字体等操作。手写这些代码不仅费时费力,有时候效果还不太理想。那怎么样才能更方便的对报表样式,报表头进行处理呢?答案是使用已经准备好的Excel模板,只需要关注模板中的数据即可。
3.2 模板打印的操作步骤
- 制作模版文件(模版文件的路径)
- 导入(加载)模版文件,从而得到一个工作簿
- 读取工作表
- 读取行
- 读取单元格
- 读取单元格样式
- 设置单元格内容
- 其他单元格就可以使用读到的样式了
3.3 制作模板
3.4 代码实现
@RequestMapping(value = "/export/{month}", method = RequestMethod.GET)public void export(@PathVariable(name = "month") String month) throws Exception {//1.构造数据List<User> list =userService.findByMonth(month);//2.加载模板流数据Resource resource = new ClassPathResource("excel-template/demo.xlsx");FileInputStream fis = new FileInputStream(resource.getFile());//3.根据文件流,加载指定的工作簿XSSFWorkbook wb = new XSSFWorkbook(fis);//4.读取工作表Sheet sheet = wb.getSheetAt(0);//5.抽取公共的样式Row styleRow = sheet.getRow(2);CellStyle [] styles = new CellStyle[styleRow.getLastCellNum()];for(int i=0;i<styleRow.getLastCellNum();i++) {styles[i] = styleRow.getCell(i).getCellStyle();}//6.构造每行和单元格数据AtomicInteger datasAi = new AtomicInteger(2);Cell cell = null;for (EmployeeReportResult report : list) {Row dataRow = sheet.createRow(datasAi.getAndIncrement());//编号cell = dataRow.createCell(0);cell.setCellValue(report.getUserId());cell.setCellStyle(styles[0]);//姓名cell = dataRow.createCell(1);cell.setCellValue(report.getUsername());cell.setCellStyle(styles[1]);//手机cell = dataRow.createCell(2);cell.setCellValue(report.getMobile());cell.setCellStyle(styles[2]);//最高学历cell = dataRow.createCell(3);cell.setCellValue(report.getTheHighestDegreeOfEducation());cell.setCellStyle(styles[3]);//国家地区cell = dataRow.createCell(4);cell.setCellValue(report.getNationalArea());cell.setCellStyle(styles[4]);//生日cell = dataRow.createCell(7);cell.setCellValue(report.getBirthday());cell.setCellStyle(styles[7]);//离职时间cell = dataRow.createCell(12);cell.setCellStyle(styles[12]);cell.setCellValue(report.getCreateTime());}String fileName = URLEncoder.encode(month+"人员信息.xlsx", "UTF-8");response.setContentType("application/octet-stream");response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1")));response.setHeader("filename", fileName);wb.write(response.getOutputStream());}
4、自定义工具类
(1)自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAttribute {/** 对应的列名称 */String name() default "";/** 列序号 */int sort();/** 字段类型对应的格式 */String format() default "";
}
(2)导出工具类
@Getter
@Setter
public class ExcelExportUtil<T> {private int rowIndex;private int styleIndex;private String templatePath;private Class clazz;private Field fields[];public ExcelExportUtil(Class clazz,int rowIndex,int styleIndex) {this.clazz = clazz;this.rowIndex = rowIndex;this.styleIndex = styleIndex;fields = clazz.getDeclaredFields();}/*** 基于注解导出*/public void export(HttpServletResponse response,InputStream is, List<T> objs,String
fileName) throws Exception {XSSFWorkbook workbook = new XSSFWorkbook(is);Sheet sheet = workbook.getSheetAt(0);CellStyle[] styles = getTemplateStyles(sheet.getRow(styleIndex));AtomicInteger datasAi = new AtomicInteger(rowIndex);for (T t : objs) {Row row = sheet.createRow(datasAi.getAndIncrement());for(int i=0;i<styles.length;i++) {Cell cell = row.createCell(i);cell.setCellStyle(styles[i]);for (Field field : fields) {if(field.isAnnotationPresent(ExcelAttribute.class)){field.setAccessible(true);ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);if(i == ea.sort()) {cell.setCellValue(field.get(t).toString());}}}}}fileName = URLEncoder.encode(fileName, "UTF-8");response.setContentType("application/octet-stream");response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1")));response.setHeader("filename", fileName);workbook.write(response.getOutputStream());}public CellStyle[] getTemplateStyles(Row row) {CellStyle [] styles = new CellStyle[row.getLastCellNum()];for(int i=0;i<row.getLastCellNum();i++) {styles[i] = row.getCell(i).getCellStyle();}return styles;}
}
(3)导入工具类
public class ExcelImportUtil<T> {private Class clazz;private Field fields[];public ExcelImportUtil(Class clazz) {this.clazz = clazz;fields = clazz.getDeclaredFields();}/*** 基于注解读取excel*/public List<T> readExcel(InputStream is, int rowIndex,int cellIndex) {List<T> list = new ArrayList<T>();T entity = null;try {XSSFWorkbook workbook = new XSSFWorkbook(is);Sheet sheet = workbook.getSheetAt(0);// 不准确int rowLength = sheet.getLastRowNum();System.out.println(sheet.getLastRowNum());for (int rowNum = rowIndex; rowNum <= sheet.getLastRowNum(); rowNum++) {Row row = sheet.getRow(rowNum);entity = (T) clazz.newInstance();System.out.println(row.getLastCellNum());for (int j = cellIndex; j < row.getLastCellNum(); j++) {Cell cell = row.getCell(j);for (Field field : fields) {if(field.isAnnotationPresent(ExcelAttribute.class)){field.setAccessible(true);ExcelAttribute ea =
field.getAnnotation(ExcelAttribute.class);if(j == ea.sort()) {field.set(entity, covertAttrType(field, cell));}}}}list.add(entity);}} catch (Exception e) {e.printStackTrace();}return list;}/*** 类型转换 将cell 单元格格式转为 字段类型* */private Object covertAttrType(Field field, Cell cell) throws Exception {String fieldType = field.getType().getSimpleName();if ("String".equals(fieldType)) {return getValue(cell);}else if ("Date".equals(fieldType)) {return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(getValue(cell)) ;}else if ("int".equals(fieldType) || "Integer".equals(fieldType)) {return Integer.parseInt(getValue(cell));}else if ("double".equals(fieldType) || "Double".equals(fieldType)) {return Double.parseDouble(getValue(cell));}else {return null;}}/*** 格式转为String* @param cell* @return*/public String getValue(Cell cell) {if (cell == null) {return "";}switch (cell.getCellType()) {case STRING:return cell.getRichStringCellValue().getString().trim();case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {Date dt = DateUtil.getJavaDate(cell.getNumericCellValue());return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(dt);} else {// 防止数值变成科学计数法String strCell = "";Double num = cell.getNumericCellValue();BigDecimal bd = new BigDecimal(num.toString());if (bd != null) {strCell = bd.toPlainString();}// 去除 浮点型 自动加的 .0if (strCell.endsWith(".0")) {strCell = strCell.substring(0, strCell.indexOf("."));}return strCell;}case BOOLEAN:return String.valueOf(cell.getBooleanCellValue());default:return "";}}}
5、百万数据报表解决方案
5.1 百万数据报表导出
使用Apache POI完成百万数据量的Excel报表导出。
5.1.1 思路分析
基于XSSFWork导出Excel报表,是通过将所有单元格对象保存到内存中,当所有的Excel单元格全部创建完成之后一次性写入到Excel并导出。当百万数据级别的Excel导出时,随着表格的不断创建,内存中对象越来越多,直至内存溢出。Apache Poi提供了SXSSFWork对象,专门用于处理大数据量Excel报表导出。
5.1.2 原理分析
在实例化SXSSFWork这个对象时,可以指定在内存中所产生的POI导出相关对象的数量(默认100),一旦内存中的对象的个数达到这个指定值时,就将内存中的这些对象的内容写入到磁盘中(XML的文件格式),就可以将这些对象从内存中销毁,以后只要达到这个值,就会以类似的处理方式处理,直至Excel导出完成。
5.1.3 代码实现
在原有代码的基础上替换之前的XSSFWorkbook,使用SXSSFWorkbook完成创建过程即可,但是SXSSFWorkbook不支持模板导出。
@RequestMapping(value = "/export/{month}", method = RequestMethod.GET)public void export(@PathVariable(name = "month") String month) throws Exception {//1.构造数据,某个月的用户数据List<User> list =userService.findByMonth(month);//2.创建工作簿SXSSFWorkbook workbook = new SXSSFWorkbook();//3.构造sheetString[] titles = {"编号", "姓名", "手机","最高学历", "国家地区","生日", "时间"};Sheet sheet = workbook.createSheet();Row row = sheet.createRow(0);AtomicInteger headersAi = new AtomicInteger();for (String title : titles) {Cell cell = row.createCell(headersAi.getAndIncrement());cell.setCellValue(title);}AtomicInteger datasAi = new AtomicInteger(1);Cell cell = null;for (User user : list) {Row dataRow = sheet.createRow(datasAi.getAndIncrement());//编号cell = dataRow.createCell(0);cell.setCellValue(user.getUserId());//姓名cell = dataRow.createCell(1);cell.setCellValue(user.getUsername());//手机cell = dataRow.createCell(2);cell.setCellValue(user.getMobile());//最高学历cell = dataRow.createCell(3);cell.setCellValue(user.getTheHighestDegreeOfEducation());//国家地区cell = dataRow.createCell(4);cell.setCellValue(user.getNationalArea());//生日cell = dataRow.createCell(7);cell.setCellValue(user.getBirthday());//时间cell = dataRow.createCell(12);cell.setCellValue(user.getCreateTime());}String fileName = URLEncoder.encode(month+"人员信息.xlsx", "UTF-8");response.setContentType("application/octet-stream");response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1")));response.setHeader("filename", fileName);workbook.write(response.getOutputStream());}
5.2 百万数据报表导入
使用POI基于事件模式解析百万数据的Excel文件。
5.2.1 思路分析
用户模式:加载并读取Excel时,是通过一次性的将所有数据加载到内存中再去解析每个单元格内容。当Excel数据量较大时,由于不同的运行环境可能会造成内存不足甚至OOM异常。
事件模式:它逐行扫描文档,一边扫描一边解析。由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势。
5.2.2 步骤分析
(1)设置POI的事件模式
根据Excel获取文件流
根据文件流创建OPCPackage
创建XSSFReader对象
(2)Sax解析
自定义Sheet处理器
创建Sax的XmlReader对象
设置Sheet的事件处理器
逐行读取
5.2.3 原理分析
我们都知道对于Excel2007的实质是一种特殊的XML存储数据,那就可以使用基于SAX的方式解析XML完成Excel的读取。SAX提供了一种从XML文档中读取数据的机制。它逐行扫描文档,一边扫描一边解析。由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势。
5.2.4 代码实现
5.2.4.1 自定义处理器
import cn.itcast.poi.entity.PoiEntity;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.usermodel.XSSFComment;/*** 自定义的事件处理器* 处理每一行数据读取* 实现接口*/
public class SheetHandler implements XSSFSheetXMLHandler.SheetContentsHandler {private PoiEntity entity;/*** 当开始解析某一行的时候触发* i:行索引*/@Overridepublic void startRow(int i) {//实例化对象if(i>0) {entity = new PoiEntity();}}/*** 当结束解析某一行的时候触发* i:行索引*/@Overridepublic void endRow(int i) {//使用对象进行业务操作System.out.println(entity);}/*** 对行中的每一个表格进行处理* cellReference: 单元格名称* value:数据* xssfComment:批注*/@Overridepublic void cell(String cellReference, String value, XSSFComment xssfComment) {//对对象属性赋值if(entity != null) {String pix = cellReference.substring(0,1);switch (pix) {case "A":entity.setId(value);break;case "B":entity.setBreast(value);break;case "C":entity.setAdipocytes(value);break;case "D":entity.setNegative(value);break;case "E":entity.setStaining(value);break;case "F":entity.setSupportive(value);break;default:break;}}}
}
5.2.4.2 自定义解析
/**
* 自定义Excel解析器
*/
public class ExcelParser {public void parse (String path) throws Exception {//1.根据Excel获取OPCPackage对象OPCPackage pkg = OPCPackage.open(path, PackageAccess.READ);try {//2.创建XSSFReader对象XSSFReader reader = new XSSFReader(pkg);//3.获取SharedStringsTable对象SharedStringsTable sst = reader.getSharedStringsTable();//4.获取StylesTable对象StylesTable styles = reader.getStylesTable();//5.创建Sax的XmlReader对象XMLReader parser = XMLReaderFactory.createXMLReader();//6.设置处理器parser.setContentHandler(new XSSFSheetXMLHandler(styles,sst, new
SheetHandler(), false));XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator)
reader.getSheetsData();//7.逐行读取while (sheets.hasNext()) {InputStream sheetstream = sheets.next();InputSource sheetSource = new InputSource(sheetstream);try {parser.parse(sheetSource);} finally {sheetstream.close();}}} finally {pkg.close();}}
}
POI报表及百万数据导入导出方案相关推荐
- 报表技术2(百万数据导入导出,POI操作word)
POI模板导出,操作word 导出用户详情数据(图片,公式处理) 使用模板导出用户详细信息 使用模板引擎 1.编写模板引擎 2.使用模板引擎 百万数据导出 代码实现: 百万数据导入 步骤分析: 1.自 ...
- 300万数据导入导出优化方案,从80s优化到8s(实测)
前景 在项目开发中往往需要使用到数据的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上. 写本文的背景是因为在工作中遇到了大数据的导入和导出,问 ...
- 高性能 + 百万级excel数据导入导出
高性能 + 百万级excel数据导入导出 内容介绍 github地址 使用文档地址 安装注意事项 仅以mac举例 ide中提示相关代码 下载demo 内容介绍 [转载]https://learnku. ...
- Java Excel导入和导出(支持xls导入,xlsx导入,图片导出,百万数据量导出)
免费源码下载(提取码:qdhy) 工程结构目录 所需JAR包 <dependencies><!-- JUNIT 测试 --><dependency><grou ...
- JAVA语言(POI数据导入导出Excel)
POI数据导入导出Excel(样式可以自己设置) //----------------------------Controller层 --------------------------------- ...
- JAVA实现数据库数据导入/导出到Excel(POI)
原文地址为: JAVA实现数据库数据导入/导出到Excel(POI) 准备工作: 1.导入POI包:POI下载地址http://mirrors.tuna.tsinghua.edu.cn/apache/ ...
- POI报表——模板打印 AND 海量数据导出
准备工作 导入POI的Jar包: maven工程需要在:Pom.xml文件中的xml配置 <dependency> <groupId>org.apache.poi</gr ...
- php直接导出csv,PHP百万级数据导出方案(生成器直接输出单个CSV)
概述: 之前写过一篇文章叫PHP百万级数据导出方案(多csv文件压缩),发现很多朋友都很感兴趣,但是当时用的方法比较不方便,可能不太符合很多人的需求.后来想了一下如何优化时,了解到能用生成器来处理内存 ...
- MongoDB 教程六: MongoDB管理:数据导入导出,数据备份恢复及用户安全与认证
视频地址:MongoDB 教程六: MongoDB管理:数据导入导出,数据备份恢复及用户安全与认证 MongoDB数据库备份与恢复 一.备份 先介绍下命令语法: mongodump -h dbhost ...
最新文章
- java.io包对象读写_java.io 包中的____________和____________类主要用于对对象(Object)的读写_学小易找答案...
- 绍中考能不能用计算机了,全国计算机二级考什么内容
- GIT的基本操作(建立自己的git远程仓库)
- 【Unity开源项目精选】ML-Agents:给你的游戏加入AI
- 1.4 满足和优化指标
- ZOJ Problem Set - 1008
- 01 按指定格式读写文件出现乱码
- linux下python3源码安装及卸载
- C/C++回调方式系列之二class接口回调和lambda程式
- excel 合并单元格筛选
- Linux下deamon(服务)的实现
- 上原れな - 届かない恋
- 推荐一款微信小程序《诗词万卷》
- Node.js全栈开发笔记与心得
- 运行web项目提示异常:non-compatible bean definition of same name and class【com.xxx.xxx.XXX】
- Windows 10使用HDD硬盘出现占用率100%造成卡机假死的解决方法
- win10c 系统语言 英文,Win10英文版系统下中文软件显示为问号的解决方法
- app升级搭建服务器
- 盘点SaaS在高歌猛进路上的16个坑,总有一个你会遇到
- 月亮代表我的心计算机谱子,月亮代表我的心
热门文章
- ftp服务器 iis 文件名,iis 匿名 用户名ftp服务器
- 【mud】mud 骰子游戏截图
- Codeforces 144D. Missile Silos 最短路
- python装饰器,迭代,异常
- 在西湖泛舟,差点被坑
- 如何在keil5中新建.c和.h文件?
- 如何开启电脑的图片解锁功能和关闭电脑的图片解锁功能?
- Qt “error: C2065: “xxx”: 未声明的标识符”的问题
- java判断excel能否正常打开
- MinIO windos安装包百度云盘免费下载