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的应用场景

  1. 数据报表生成
  2. 数据备份
  3. 数据批量上传

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 模板打印的操作步骤

  1. 制作模版文件(模版文件的路径)
  2. 导入(加载)模版文件,从而得到一个工作簿
  3. 读取工作表
  4. 读取行
  5. 读取单元格
  6. 读取单元格样式
  7. 设置单元格内容
  8. 其他单元格就可以使用读到的样式了

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报表及百万数据导入导出方案相关推荐

  1. 报表技术2(百万数据导入导出,POI操作word)

    POI模板导出,操作word 导出用户详情数据(图片,公式处理) 使用模板导出用户详细信息 使用模板引擎 1.编写模板引擎 2.使用模板引擎 百万数据导出 代码实现: 百万数据导入 步骤分析: 1.自 ...

  2. 300万数据导入导出优化方案,从80s优化到8s(实测)

    前景 在项目开发中往往需要使用到数据的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上. 写本文的背景是因为在工作中遇到了大数据的导入和导出,问 ...

  3. 高性能 + 百万级excel数据导入导出

    高性能 + 百万级excel数据导入导出 内容介绍 github地址 使用文档地址 安装注意事项 仅以mac举例 ide中提示相关代码 下载demo 内容介绍 [转载]https://learnku. ...

  4. Java Excel导入和导出(支持xls导入,xlsx导入,图片导出,百万数据量导出)

    免费源码下载(提取码:qdhy) 工程结构目录 所需JAR包 <dependencies><!-- JUNIT 测试 --><dependency><grou ...

  5. JAVA语言(POI数据导入导出Excel)

    POI数据导入导出Excel(样式可以自己设置) //----------------------------Controller层 --------------------------------- ...

  6. JAVA实现数据库数据导入/导出到Excel(POI)

    原文地址为: JAVA实现数据库数据导入/导出到Excel(POI) 准备工作: 1.导入POI包:POI下载地址http://mirrors.tuna.tsinghua.edu.cn/apache/ ...

  7. POI报表——模板打印 AND 海量数据导出

    准备工作 导入POI的Jar包: maven工程需要在:Pom.xml文件中的xml配置 <dependency> <groupId>org.apache.poi</gr ...

  8. php直接导出csv,PHP百万级数据导出方案(生成器直接输出单个CSV)

    概述: 之前写过一篇文章叫PHP百万级数据导出方案(多csv文件压缩),发现很多朋友都很感兴趣,但是当时用的方法比较不方便,可能不太符合很多人的需求.后来想了一下如何优化时,了解到能用生成器来处理内存 ...

  9. MongoDB 教程六: MongoDB管理:数据导入导出,数据备份恢复及用户安全与认证

    视频地址:MongoDB 教程六: MongoDB管理:数据导入导出,数据备份恢复及用户安全与认证 MongoDB数据库备份与恢复 一.备份 先介绍下命令语法: mongodump -h dbhost ...

最新文章

  1. java.io包对象读写_java.io 包中的____________和____________类主要用于对对象(Object)的读写_学小易找答案...
  2. 绍中考能不能用计算机了,全国计算机二级考什么内容
  3. GIT的基本操作(建立自己的git远程仓库)
  4. 【Unity开源项目精选】ML-Agents:给你的游戏加入AI
  5. 1.4 满足和优化指标
  6. ZOJ Problem Set - 1008
  7. 01 按指定格式读写文件出现乱码
  8. linux下python3源码安装及卸载
  9. C/C++回调方式系列之二class接口回调和lambda程式
  10. excel 合并单元格筛选
  11. Linux下deamon(服务)的实现
  12. 上原れな - 届かない恋
  13. 推荐一款微信小程序《诗词万卷》
  14. Node.js全栈开发笔记与心得
  15. 运行web项目提示异常:non-compatible bean definition of same name and class【com.xxx.xxx.XXX】
  16. Windows 10使用HDD硬盘出现占用率100%造成卡机假死的解决方法
  17. win10c 系统语言 英文,Win10英文版系统下中文软件显示为问号的解决方法
  18. app升级搭建服务器
  19. 盘点SaaS在高歌猛进路上的16个坑,总有一个你会遇到
  20. 月亮代表我的心计算机谱子,月亮代表我的心

热门文章

  1. ftp服务器 iis 文件名,iis 匿名 用户名ftp服务器
  2. 【mud】mud 骰子游戏截图
  3. Codeforces 144D. Missile Silos 最短路
  4. python装饰器,迭代,异常
  5. 在西湖泛舟,差点被坑
  6. 如何在keil5中新建.c和.h文件?
  7. 如何开启电脑的图片解锁功能和关闭电脑的图片解锁功能?
  8. Qt “error: C2065: “xxx”: 未声明的标识符”的问题
  9. java判断excel能否正常打开
  10. MinIO windos安装包百度云盘免费下载