大数据量导出Excel的方案 java 大excel文件
FineReport报表打印导出EXCEL的四种方式
FineReport报表打印导出EXCEL的四种方式在实际的应用中会经常需要将数据导出成excel,导出的方式除原样导出还有分页导出、分页分sheet导出和大数据量导出。
对于excel 2003版,由于限制了每个sheet的最大行数和列数,大数据量导出时会默认时分多个sheet,而excel2007不会出现这样的问题。
这些导出方式在JAVA程序中分别有不同的接口来实现:1、原样导出原样导出就是不预览直接导出excel其程序接口代码如下:outputStream = new FileOutputStream(new File("E:\\ExcelExport.xls"));ExcelExporter excel = new ExcelExporter();//导出2007版outputStream = new FileOutputStream(new File("E:\\ExcelExport.xlsx")); excel Excel2007Exporter excel = new Excel2007Exporter();excel.export(outputStream, rworkbook);效果图:2、分页导出分页导出,如果报表模版是分页的,会按照分页的结果形式导出,重复的标题等也会重复。
其程序接口代码如下:outputStream = new FileOutputStream(new File("E:\\PageExcelExport.xls")); PageExcelExporter page = new PageExcelExporter(ReportUtils.getPaperSettingListFromWorkBook(rworkbook));//导出2007版outputStream = new FileOutputStream(new File("E:\\PageExcelExport.xlsx")); excel PageExcel2007Exporter page = new PageExcel2007Exporter(ReportUtils.getPaperSettingListFromWorkBook(rworkbook));page.export(outputStream, rworkbook);效果图:3、分页分sheet导出分页分Sheet导出时报表结果的每一页为一个Sheet保存在Excel文件中其代码如下:outputStream = new FileOutputStream(new File("E:\\PageSheetExcelExport.xls")); PageToSheetExcelExporter sheet = newPageToSheetExcelExporter(ReportUtils.getPaperSettingListFromWorkBook(rworkbook));//导出2007版outputStream = new FileOutputStream(new File("E:\\PageSheetExcelExport.xlsx")); excel PageToSheetExcel2007Exporter sheet = new PageToSheetExcel2007Exporter(ReportUtils.getPaperSettingListFromWorkBook(rworkbook)); sheet.export(outputStream, rworkbook);效果图:4、大数据量导出这是比较常见的,例如以50000行为一个excel文件其代码如下:outputStream = new FileOutputStream(new File("E:\\LargeExcelExport.zip")); LargeDataPageExcelExporter large = new LargeDataPageExcelExporter(ReportUtils.getPaperSettingListFromWorkBook(rworkbook), true); //导出2007版outputStream = new FileOutputStream(new File("E:\\LargeExcelExport.xlsx")); excel LargeDataPageExcel2007Exporter large = new LargeDataPageExcel2007Exporter(ReportUtils.getPaperSettingListFromWorkBook(rworkbook), true);large.export(outputStream, rworkbook);对于大数据量导出报表时,可能会出现如下两种情况:一,导出成功,数据会显示在多个Sheet中;二,二,导出失败,导出的Excel内容无效。
java实现导出Excel(跨行跨列)
java实现导出Excel(跨行跨列)在Java中,可以使用Apache POI库来实现导出Excel文件,并且可以实现跨行和跨列的功能。
Apache POI是一个开源的Java库,可以处理Microsoft Office格式的文档,包括Excel。
以下是使用Apache POI库实现导出Excel文件的步骤:1. 首先,需要引入Apache POI依赖。
可以在Maven或Gradle中添加以下依赖项:```xml<!-- Apache POI --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency>2. 创建一个Workbook对象,该对象代表一个Excel文件:```javaWorkbook workbook = new XSSFWorkbook(;```3. 创建一个Sheet对象,该对象代表Excel文件中的一个工作表:```javaSheet sheet = workbook.createSheet("Sheet1");```4. 创建行和单元格,根据需要设置跨行和跨列的属性。
可以使用CellRangeAddress类来实现跨行和跨列的功能:```javaRow row = sheet.createRow(0);Cell cell = row.createCell(0);cell.setCellValue("跨行跨列");//合并单元格,从第1行到第3行,从第1列到第5列CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 2, 0, 4);sheet.addMergedRegion(cellRangeAddress);5. 将数据写入Excel文件中的单元格:```javaRow row = sheet.createRow(0);Cell cell = row.createCell(0);cell.setCellValue("Hello");```6. 将Workbook对象写入到文件中:```javaFileOutputStream fileOutputStream = new FileOutputStream("output.xlsx");workbook.write(fileOutputStream);fileOutputStream.close(;```完整的示例代码如下所示:```javaimport ermodel.*;import org.apache.poi.ss.util.CellRangeAddress;import ermodel.XSSFWorkbook;import java.io.FileOutputStream;import java.io.IOException;public class ExcelExporterpublic static void main(String[] args) throws IOExceptionWorkbook workbook = new XSSFWorkbook(;Sheet sheet = workbook.createSheet("Sheet1");Row row = sheet.createRow(0);Cell cell = row.createCell(0);cell.setCellValue("跨行跨列");//合并单元格,从第1行到第3行,从第1列到第5列CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 2, 0, 4);sheet.addMergedRegion(cellRangeAddress);FileOutputStream fileOutputStream = newFileOutputStream("output.xlsx");workbook.write(fileOutputStream);fileOutputStream.close(;System.out.println("Excel文件导出成功!");}```执行该代码后,会在项目的根目录下生成一个名为`output.xlsx`的Excel文件,其中包含一个跨行和跨列的单元格。
java导出excel浏览器直接下载或者或以文件形式导出
java导出excel浏览器直接下载或者或以⽂件形式导出看代码吧~/*** excel表格直接下载*/public static void exportExcelByDownload(HSSFWorkbook wb,HttpServletResponse httpServletResponse,String fileName) throws Exception {//响应类型为application/octet- stream情况下使⽤了这个头信息的话,那就意味着不想直接显⽰内容httpServletResponse.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);//attachment为以附件⽅式下载httpServletResponse.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName + ".xls","utf-8"));/*** 代码⾥⾯使⽤Content-Disposition来确保浏览器弹出下载对话框的时候。
* response.addHeader("Content-Disposition","attachment");⼀定要确保没有做过关于禁⽌浏览器缓存的操作*/httpServletResponse.setHeader("Cache-Control", "No-cache");httpServletResponse.flushBuffer();wb.write(httpServletResponse.getOutputStream());wb.close();}/*** excel以⽂件的形式导出* @throws Exception*/public static void exportExcelByFile(HSSFWorkbook wb,String fileName,String path) throws Exception{ByteArrayOutputStream stream = new ByteArrayOutputStream();wb.write(stream);FileOutputStream outputStream = new FileOutputStream(path + fileName);outputStream.write(stream.toByteArray());stream.close();outputStream.close();}java查询数据导出excel并返回给浏览器下载效果图:1.点击导出表按钮2.接着就会出现下图3.点击上图中的确定按钮再接着就会出现下图4.点击上图中的保存按钮接着就会出现下图,浏览器下载完成后的提⽰5.打开下载好的⽂件如下图好了,废话不多少,上代码jsp前端代码<div style="height:30px;"><a>时间:</a><input id="startDateConsume" type="text" class="easyui-datebox"> <a>-</a><input id="endDateConsume" type="text" class="easyui-datebox"><a>消费类型:</a><select id="consumesType" name=""><option value="0" selected="selected">所有</option><option value="1">报名费</option><option value="2">酒⽔零⾷类</option></select><a>⽀付状态:</a><select id="conPaymentStatus" name=""><option value="0" selected="selected">所有</option><option value="1">未⽀付</option><option value="2">已⽀付</option></select><a id="btnConsumesSearch" class="easyui-linkbutton"data-options="iconCls:'icon-search'" style="margin-left:10px">查询</a><a>(查询出来的数据可统计)</a><a id="consumesOutExcel" class="easyui-linkbutton" style="" data-options="iconCls:'icon-redo'">导出表</a></div>js前端代码$(function() {//导出excel表$('#consumesOutExcel').on('click',function(){exportExcel();});});function exportExcel() {$.messager.confirm('确认', '确认把该搜索结果导出Excel表格?', function(r) {if (r) {var startTime = $('#startDateConsume').val();var endTime = $('#endDateConsume').val();var consumesType = $('#consumesType').val();var conPaymentStatus = $('#conPaymentStatus').val();$.messager.progress({title : '处理中',msg : '请稍后',});$.messager.progress('close');location.href="web/vip/exportExcel.xlsx?startTime=" rel="external nofollow" +startTime+"&endTime="+endTime+"&consumesType="+consumesType+"&conPaymentStatus="+conPaymentStatus; }});}java后端代码@Controller@RequestMapping("/vip")public class VipController {//⽂件下载:导出excel表@RequestMapping(value = "/exportExcel.xlsx",method = RequestMethod.GET)@ResponseBodypublic void exportExcel(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException{//⼀、从后台拿数据if (null == request || null == response){return;}List<VipConsumes> list = null;String startTime = request.getParameter("startTime");String endTime = request.getParameter("endTime");int consumesType = Integer.parseInt(request.getParameter("consumesType"));int conPaymentStatus =Integer.parseInt(request.getParameter("conPaymentStatus"));VipConsumesExample example = new VipConsumesExample();if(consumesType!=0 && conPaymentStatus!=0){example.createCriteria().andTimeBetween(startTime, endTime).andConsumeTypeEqualTo(consumesType).andStatusEqualTo(conPaymentStatus);}else if(consumesType ==0 && conPaymentStatus!=0) {example.createCriteria().andTimeBetween(startTime, endTime).andStatusEqualTo(conPaymentStatus);}else if(consumesType!=0 && conPaymentStatus==0){example.createCriteria().andTimeBetween(startTime, endTime).andConsumeTypeEqualTo(consumesType);}else {example.createCriteria().andTimeBetween(startTime, endTime);}list = this.vipConsumesDao.selectByExample(example);//⼆、数据转成excelrequest.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");response.setContentType("application/x-download");String fileName = "消费记录.xlsx";fileName = URLEncoder.encode(fileName, "UTF-8");response.addHeader("Content-Disposition", "attachment;filename=" + fileName); // 第⼀步:定义⼀个新的⼯作簿XSSFWorkbook wb = new XSSFWorkbook();// 第⼆步:创建⼀个Sheet页XSSFSheet sheet = wb.createSheet("startTimeendTime");sheet.setDefaultRowHeight((short) (2 * 256));//设置⾏⾼sheet.setColumnWidth(0, 4000);//设置列宽sheet.setColumnWidth(1,5500);sheet.setColumnWidth(2,5500);sheet.setColumnWidth(3,5500);sheet.setColumnWidth(11,3000);sheet.setColumnWidth(12,3000);sheet.setColumnWidth(13,3000);XSSFFont font = wb.createFont();font.setFontName("宋体");font.setFontHeightInPoints((short) 16);XSSFRow row = sheet.createRow(0);XSSFCell cell = row.createCell(0);cell.setCellValue("流⽔号 ");cell = row.createCell(1);cell.setCellValue("微信名 ");cell = row.createCell(2);cell.setCellValue("微信订单号");cell = row.createCell(3);cell.setCellValue("消费时间");cell = row.createCell(4);cell.setCellValue("消费类型");cell = row.createCell(5);cell.setCellValue("剩余积分 ");cell = row.createCell(6);cell.setCellValue("新增积分 ");cell = row.createCell(7);cell.setCellValue("扣除积分 ");cell = row.createCell(8);cell.setCellValue("消费⾦额");cell = row.createCell(9);cell.setCellValue("⽀付⽅式");cell = row.createCell(10);cell.setCellValue("⽀付状态 ");cell = row.createCell(11);cell.setCellValue("钱包原始⾦额");cell = row.createCell(12);cell.setCellValue("钱包扣除⾦额");cell = row.createCell(13);cell.setCellValue("钱包剩余⾦额");XSSFRow rows;XSSFCell cells;for (int i = 0; i < list.size(); i++) {// 第三步:在这个sheet页⾥创建⼀⾏rows = sheet.createRow(i+1);// 第四步:在该⾏创建⼀个单元格cells = rows.createCell(0);// 第五步:在该单元格⾥设置值cells.setCellValue(list.get(i).getConsumeId());cells = rows.createCell(1);cells.setCellValue(list.get(i).getName());cells = rows.createCell(2);cells.setCellValue(list.get(i).getOrderNumber());cells = rows.createCell(3);cells.setCellValue(list.get(i).getTime());cells = rows.createCell(4);if (list.get(i).getConsumeType() == 2) {cells.setCellValue("酒⽔零⾷费");} else {cells.setCellValue("报名费");}cells = rows.createCell(5);cells.setCellValue(list.get(i).getIntegral());cells = rows.createCell(6);cells.setCellValue(list.get(i).getIntegralIn());cells = rows.createCell(7);cells.setCellValue(list.get(i).getIntegralOut());cells = rows.createCell(8);cells.setCellValue(list.get(i).getMoney());cells = rows.createCell(9);if (list.get(i).getPayment() == 2) {cells.setCellValue("积分抵现");} else if (list.get(i).getPayment() == 3) {cells.setCellValue("微信⽀付");} else if (list.get(i).getPayment() == 4) {cells.setCellValue("现⾦");} else if (list.get(i).getPayment() == 1) {cells.setCellValue("钱包");}cells = rows.createCell(10);if (list.get(i).getStatus() == 2) {cells.setCellValue("已⽀付");} else if (list.get(i).getStatus() == 1) {cells.setCellValue("未⽀付");}cells = rows.createCell(11);cells.setCellValue(list.get(i).getWalletOriginal());cells = rows.createCell(12);cells.setCellValue(list.get(i).getWalletOut());cells = rows.createCell(13);cells.setCellValue(list.get(i).getWalletSurplus());}try {OutputStream out = response.getOutputStream();wb.write(out);out.close();wb.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
Java实现大批量数据导入导出(100W以上) -(二)导出
Java实现⼤批量数据导⼊导出(100W以上) -(⼆)导出使⽤POI或JXLS导出⼤数据量(百万级)Excel报表常常⾯临两个问题:1. 服务器内存溢出;2. ⼀次从数据库查询出这么⼤数据,查询缓慢。
当然也可以分页查询出数据,分别⽣成多个Excel打包下载,但这种⽣成还是很缓慢。
⼤数据量导⼊请参考:那么如何解决呢?我们可以借助XML格式利⽤模板替换,分页查询出数据从磁盘写⼊XML,最终会以Excel多sheet形式⽣成。
亲测2400万⾏数据,⽣成Excel⽂件4.5G,总耗时1.5分钟。
我利⽤StringTemplate模板解析技术对XML模板进⾏填充。
当然也可以使⽤FreeMarker, Velocity等Java模板技术实现。
⾸先引⼊StringTemplate所需Jar包:使⽤技术为 stringTemplatepom.xml:1 <dependency>2<groupId>antlr</groupId>3<artifactId>antlr</artifactId>4<version>2.7.7</version>5</dependency>67<dependency>8<groupId>org.antlr</groupId>9<artifactId>stringtemplate</artifactId>10<version>3.2.1</version>11</dependency>⾸先准备导出Excel模板,然后打开-》另存为-》选择格式为XML,然后⽤⽂本打开XML,提取XML头模板(head.st可通⽤),数据体模板(boday.st):head.st可通⽤:1<?xml version="1.0"?>2<?mso-application progid="Excel.Sheet"?>3<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"4 xmlns:o="urn:schemas-microsoft-com:office:office"5 xmlns:x="urn:schemas-microsoft-com:office:excel"6 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"7 xmlns:html="/TR/REC-html40">8<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">9<Created>1996-12-17T01:32:42Z</Created>10<LastSaved>2013-08-02T09:21:24Z</LastSaved>11<Version>11.9999</Version>12</DocumentProperties>13<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">14<RemovePersonalInformation/>15</OfficeDocumentSettings>16<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">17<WindowHeight>4530</WindowHeight>18<WindowWidth>8505</WindowWidth>19<WindowTopX>480</WindowTopX>20<WindowTopY>120</WindowTopY>21<AcceptLabelsInFormulas/>22<ProtectStructure>False</ProtectStructure>23<ProtectWindows>False</ProtectWindows>24</ExcelWorkbook>25<Styles>26<Style ss:ID="Default" ss:Name="Normal">27<Alignment ss:Vertical="Bottom"/>28<Borders/>29<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12"/>30<Interior/>31<NumberFormat/>32<Protection/>33</Style>34</Styles>boday.st:1 $worksheet:{2<Worksheet ss:Name="$it.sheet$">3<Table ss:ExpandedColumnCount="$it.columnNum$" ss:ExpandedRowCount="$it.rowNum$" x:FullColumns="1"4 x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">5 $it.rows:{6<Row>7<Cell><Data ss:Type="String">$1$</Data></Cell>8<Cell><Data ss:Type="String">$2$</Data></Cell>9<Cell><Data ss:Type="String">$3$</Data></Cell>10</Row>11 }$12</Table>13</Worksheet>14 }$⽣成⼤数据量Excel类:ExcelGenerator:1package test.exportexcel;23import org.antlr.stringtemplate.StringTemplate;4import org.antlr.stringtemplate.StringTemplateGroup;5import test.exportexcel.bean.Row;6import test.exportexcel.bean.Worksheet;78import java.io.*;9import java.util.ArrayList;10import java.util.List;11import java.util.Random;1213/**14 * 类功能描述:generator big data Excel15 *16 * @author WangXueXing create at 19-4-13 下午10:2317 * @version 1.0.018*/19public class ExcelGenerator {20public static void main(String[] args) throws FileNotFoundException{21 ExcelGenerator template = new ExcelGenerator();22 template.output2();23 }2425/**26 * ⽣成数据量⼤的时候,该⽅法会出现内存溢出27 * @throws FileNotFoundException28*/29public void output1() throws FileNotFoundException{30 StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");31 StringTemplate st4 = stGroup.getInstanceOf("test/exportexcel/template/test");32 List<Worksheet> worksheets = new ArrayList<>();3334 File file = new File("/home/barry/data/output.xls");35 PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));3637for(int i=0;i<30;i++){38 Worksheet worksheet = new Worksheet();39 worksheet.setSheet("第"+(i+1)+"页");40 List<Row> rows = new ArrayList<>();41for(int j=0;j<6000;j++){42 Row row = new Row();43 row.setName1("zhangzehao");44 row.setName2(""+j);45 row.setName3(i+" "+j);46 rows.add(row);47 }48 worksheet.setRows(rows);49 worksheets.add(worksheet);50 }5152 st4.setAttribute("worksheets", worksheets);53 writer.write(st4.toString());54 writer.flush();55 writer.close();56 System.out.println("⽣成excel完成");57 }5859/**60 * 该⽅法不管⽣成多⼤的数据量,都不会出现内存溢出,只是时间的长短61 * 经测试,⽣成2400万数据,2分钟内,4.5G⼤的⽂件,打开⼤⽂件就看内存是否⾜够⼤了62 * 数据量⼩的时候,推荐⽤JXLS的模板技术⽣成excel⽂件,谁⽤谁知道,⼤数据量可以结合该⽅法使⽤63 * @throws FileNotFoundException64*/65public void output2() throws FileNotFoundException{66long startTimne = System.currentTimeMillis();67 StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");6869//写⼊excel⽂件头部信息70 StringTemplate head = stGroup.getInstanceOf("test/exportexcel/template/head");71 File file = new File("/home/barry/data/output.xls");72 PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));73 writer.print(head.toString());74 writer.flush();7576int sheets = 400;77//excel单表最⼤⾏数是6553578int maxRowNum = 60000;7980//写⼊excel⽂件数据信息81for(int i=0;i<sheets;i++){82 StringTemplate body = stGroup.getInstanceOf("test/exportexcel/template/body");83 Worksheet worksheet = new Worksheet();84 worksheet.setSheet(" "+(i+1)+" ");85 worksheet.setColumnNum(3);86 worksheet.setRowNum(maxRowNum);87 List<Row> rows = new ArrayList<>();88for(int j=0;j<maxRowNum;j++){89 Row row = new Row();90 row.setName1(""+new Random().nextInt(100000));91 row.setName2(""+j);92 row.setName3(i+""+j);93 rows.add(row);94 }95 worksheet.setRows(rows);96 body.setAttribute("worksheet", worksheet);97 writer.print(body.toString());98 writer.flush();99 rows.clear();100 rows = null;101 worksheet = null;102 body = null;103 Runtime.getRuntime().gc();104 System.out.println("正在⽣成excel⽂件的 sheet"+(i+1));105 }106107//写⼊excel⽂件尾部108 writer.print("</Workbook>");109 writer.flush();110 writer.close();111 System.out.println("⽣成excel⽂件完成");112long endTime = System.currentTimeMillis();113 System.out.println("⽤时="+((endTime-startTimne)/1000)+"秒");114 }115 }定义JavaBean:WorkSheet.java:1package test.exportexcel.bean;23import java.util.List;45/**6 * 类功能描述:Excel sheet Bean7 *8 * @author WangXueXing create at 19-4-13 下午10:219 * @version 1.0.010*/11public class Worksheet {12private String sheet;13private int columnNum;14private int rowNum;15private List<Row> rows;1617public String getSheet() {18return sheet;19 }20public void setSheet(String sheet) {21this.sheet = sheet;22 }2324public List<Row> getRows() {25return rows;26 }27public void setRows(List<Row> rows) {28this.rows = rows;29 }3031public int getColumnNum() {32return columnNum;33 }34public void setColumnNum(int columnNum) {35this.columnNum = columnNum;36 }3738public int getRowNum() {39return rowNum;40 }41public void setRowNum(int rowNum) {42this.rowNum = rowNum;43 }44 }Row.java:1package test.exportexcel.bean;23/**4 * 类功能描述:Excel row bean5 *6 * @author WangXueXing create at 19-4-13 下午10:227 * @version 1.0.08*/9public class Row {10private String name1;11private String name2;12private String name3;1314public String getName1() {15return name1;16 }17public void setName1(String name1) {1 = name1;19 }2021public String getName2() {22return name2;23 }24public void setName2(String name2) {2 = name2;26 }2728public String getName3() {29return name3;30 }31public void setName3(String name3) {3 = name3;33 }34 }另附实现源码: 此外,⼤数据量并并且Excel列较多时,会出现内存溢出。
前端大数据导出excel导致内存溢出的解决方案
前端大数据导出excel导致内存溢出的解决方案在前端开发中,我们经常需要导出大量数据到Excel表格中。
然而,当数据量过大时,导出操作可能会导致内存溢出的问题。
为了解决这个问题,我们可以采取以下几个方案:1. 分段导出:将大数据量切分成多个小块,分多次导出。
这样可以减少单次导出的数据量,降低内存压力。
可以通过设置导出的起止位置、每次导出的数量来实现分段导出。
2. 延迟加载:仅在需要导出时加载数据,而不是一次性加载所有数据到内存中。
可以通过异步加载或者懒加载技术来实现。
例如,可以使用分页查询的方式,每次只加载当前页的数据进行导出。
3. 压缩导出:将数据进行压缩后再进行导出,减少导出文件的大小。
可以使用压缩算法如gzip或zip对导出的数据进行压缩处理,然后再将压缩文件导出。
4. 服务器端导出:将导出的任务放在服务器端进行处理,减少前端内存的占用。
可以通过向服务器发送导出请求,服务器将数据处理导出并返回下载链接或文件。
前端只负责展示导出进度和下载导出文件。
5. 优化数据处理:在前端导出Excel之前,对数据进行优化处理。
例如,可以对数据进行过滤、排序或者聚合操作,减少导出数据的大小和复杂性。
6. 增加内存限制:对前端应用的内存限制进行适当调整,确保不会因为导出操作导致内存溢出。
可以通过调整浏览器或者前端开发工具的相关配置进行设置。
总之,前端大数据导出到Excel时可能会面临内存溢出的问题,我们可以通过分段导出、延迟加载、压缩导出、服务器端导出、优化数据处理以及增加内存限制等策略来解决这个问题,确保导出操作的安全和稳定性。
记一次Java导出大批量Excel优化
记⼀次Java导出⼤批量Excel优化常⽤的excel导出⽅案,详情见,其中jxl、esayEscel 底层都是基于 poi,它们仅仅是对 poi 进⾏了封装,使导出 excel 的代码更加简洁(封装poi,导出 excel 的⼯具类有很多,jxl 和 esayExcel 使⽤的⽐较多)。
所以,如果遇到 excel 导出效率低下,直接基于 poi 导出 Excel,效率肯定是最⾼的,只是代码⽐较繁琐与杂乱。
我主要是基于 esayExcel (⽬前使⽤⽐较多),对其 api 进⾏衍⽣与应⽤,解决导出⼤量 Excel 导致的 OOM,或者数据超界异常:ng.IllegalArgumentException: Invalid row number (1048576) outside allowable range (0..1048575)应⽤是基于100W条数据进⾏的测试,数据的获取代码如下1package bean;23import com.alibaba.excel.annotation.ExcelProperty;4import com.alibaba.excel.annotation.format.DateTimeFormat;5import com.alibaba.excel.annotation.format.NumberFormat;6import lombok.Data;7import lombok.experimental.Accessors;89import java.util.Date;1011/**12 * @author dz13 * @date 2021-11-06 上午 9:1414*/15 @Accessors(chain = true)16 @Data17public class ExcelBean {1819 @ExcelProperty("主键id")20private String id;2122 @ExcelProperty("姓名")23private String name;2425 @ExcelProperty("地址")26private String address;2728 @ExcelProperty("年龄")29private Integer age;3031 @ExcelProperty("数量")32private Integer number;3334 @NumberFormat("#.##")35 @ExcelProperty("⾝⾼")36private Double high;3738 @ExcelProperty("距离")39private Double distance;4041 @DateTimeFormat("yyyy-MM-dd HH:mm:ss")42 @ExcelProperty("开始时间")43private Date startTime;4445 @ExcelProperty("结束时间")46private Date endTime;47 }1/**2 * 获取excel 导出的数据3 *4 * @return list 集合5*/6private List<ExcelBean> getDate() {7 ("开始⽣成数据");8 Date date = new Date();9long startTime = System.currentTimeMillis();10 List<ExcelBean> list = Lists.newArrayList();11for (int i = 0; i < 1000000; i++) {12 ExcelBean bean = new ExcelBean();13 bean.setId(UUID.randomUUID().toString()).14 setName("隔壁⽼樊" + i).15 setAddress("北京市朝阳区酒仙桥" + i + "路").16 setAge(i).17 setNumber(i + 10000).18 setHigh(1.234 * i).19 setDistance(1.234 * i).20 setStartTime(date).21 setEndTime(date);22 list.add(bean);23 }24 ("数据⽣成结束,数据量={},耗时={}ms", list.size(), System.currentTimeMillis() - startTime);25return list;26 }pom 依赖1<dependency>2<groupId>org.projectlombok</groupId>3<artifactId>lombok</artifactId>4</dependency>5<dependency>6<groupId>com.alibaba</groupId>7<artifactId>easyexcel</artifactId>8<version>2.2.10</version>9</dependency>依赖 esayexcel 时,如果项⽬已经依赖了 poi,有可能会产⽣jar 包依赖冲突(easyexcel底层也是基于 poi),解决⽅案如下:⽅案⼀:查看 easyexcel 中依赖的 poi 的版本,然后将项⽬其余地⽅的版本修改成该版本,使项⽬依赖的 poi 版本和 easyexcel 依赖的版本⼀致⽅案⼆:在 esayexcel 中将 poi 的依赖排除掉,如下<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.10</version><exclusions><exclusion><groupId>org.apache.poi</groupId><artifactId>poi</artifactId></exclusion><exclusion><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId></exclusion><exclusion><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId></exclusion></exclusions></dependency>常量的定义1public static final String FILE_NAME = "D:\\test_" + System.currentTimeMillis() + ".xlsx";2// 每个 sheet 写⼊的数据3public static final int NUM_PER_SHEET = 300000;4// 每次向 sheet 中写⼊的数据(分页写⼊)5public static final int NUM_BY_TIMES = 50000;1.EasyExcel 导出 excel 应⽤使⽤ esayExcel ⾃带的 api 导出 excel 的应⽤,代码如下1/**2 * ⽅法⼀:将数据写⼊到excel3 * 直接调⽤api,适合⼩数据量4 * 100W条数据33s5*/6 @Test7public void writeExcelByApi() {8 String fileName = FILE_NAME;9 ("导出excel名称={}", fileName);10long startTime = System.currentTimeMillis();11// 直接调⽤api12 List<ExcelBean> date = getDate();13 EasyExcel.write(fileName, ExcelBean.class).sheet().doWrite(date);14 ("导出excel结束,数据量={},耗时={}ms", date.size(), System.currentTimeMillis() - startTime);15 }当 list 对象数据量太多,就会产⽣异常:原因是单个 excel ⼀个 sheet 的最⼤数据量为 10485751 ng.IllegalArgumentException: Invalid row number (1048576) outside allowable range (0..1048575)23 at org.apache.poi.xssf.streaming.SXSSFSheet.createRow(SXSSFSheet.java:123)4 at org.apache.poi.xssf.streaming.SXSSFSheet.createRow(SXSSFSheet.java:65)5 at com.alibaba.excel.util.WorkBookUtil.createRow(WorkBookUtil.java:70)6 at com.alibaba.excel.write.executor.ExcelWriteAddExecutor.addOneRowOfDataToExcel(ExcelWriteAddExecutor.java:67)7 at com.alibaba.excel.write.executor.ExcelWriteAddExecutor.add(ExcelWriteAddExecutor.java:56)8 at com.alibaba.excel.write.ExcelBuilderImpl.addContent(ExcelBuilderImpl.java:58)9 at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:161)10 at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:146)11 at com.alibaba.excel.write.builder.ExcelWriterSheetBuilder.doWrite(ExcelWriterSheetBuilder.java:61)12 at mytest.TestExcel.writeExcelByApi(TestExcel.java:40)13 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)14 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)15 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)16 at ng.reflect.Method.invoke(Method.java:498)17 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)18 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)19 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)20 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)21 at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)22 at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)23 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)24 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)25 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)26 at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)27 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)28 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)29 at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)30 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)31 at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)32 at org.junit.runners.ParentRunner.run(ParentRunner.java:413)33 at org.junit.runner.JUnitCore.run(JUnitCore.java:137)34 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)35 at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)36 at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)37 at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)2.EasyExcel 导出 excel 应⽤优化⼀:execl 数据量超过1048575将数据写⼊到不同的 sheet,保证每个 sheet 的数据量⼩于 1048575 ⾏,解决此问题,代码如下1/**2 * ⽅法⼆:导出多个sheet3 * easyExcel 底层是 POI 实现的,POI 单个sheet 最多只能导出 1048576 ⾏,超过该⾏数,会产⽣如下异常4 * ng.IllegalArgumentException: Invalid row number (1048576) outside allowable range (0..1048575)5 * <p>6 * 11:57:55.541 [main] INFO mytest.TestExcel - 写⼊sheet=sheet0,数据量300000-0=300000,耗时=6055ms7 * 11:57:59.701 [main] INFO mytest.TestExcel - 写⼊sheet=sheet1,数据量600000-300000=300000,耗时=4159ms8 * 11:58:03.827 [main] INFO mytest.TestExcel - 写⼊sheet=sheet2,数据量900000-600000=300000,耗时=4126ms9 * 11:58:05.193 [main] INFO mytest.TestExcel - 写⼊sheet=sheet3,数据量1000000-900000=100000,耗时=1366ms10 * 11:58:17.418 [main] INFO mytest.TestExcel - 导出excel结束,总数据量=1000000,耗时=31297ms11*/12 @Test13public void writeExcelByMulSheet() {14 String fileName = FILE_NAME;15 ("导出excel名称={}", fileName);16long startTime = System.currentTimeMillis();17// 获取数据18 List<ExcelBean> date = getDate();19// 获取 sheet 的个数20int sheetNum = date.size() % NUM_PER_SHEET == 0 ? date.size() / NUM_PER_SHEET : date.size() / NUM_PER_SHEET + 1;21// 指定写⼊的⽂件22 ExcelWriter excelWriter = EasyExcel.write(fileName, ExcelBean.class).build();23for (int i = 0; i < sheetNum; i++) {24long l = System.currentTimeMillis();25// 设置 sheet 的名字(sheet不能相同)26 String sheetName = "sheet" + i;27 WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetName).build();28int startNum = i * NUM_PER_SHEET;29int endNum = i == sheetNum - 1 ? date.size() : (i + 1) * NUM_PER_SHEET;30 excelWriter.write(date.subList(startNum, endNum), writeSheet);31 ("写⼊sheet={},数据量{}-{}={},耗时={}ms", sheetName, endNum, startNum, endNum - startNum, System.currentTimeMillis() - l);32 }33// 最好放在 finally中34 excelWriter.finish();35 ("导出excel结束,总数据量={},耗时={}ms", date.size(), System.currentTimeMillis() - startTime);36 }3.EasyExcel 导出 excel 应⽤优化⼆:数据源 list 太⼤,直接读取全部的 list 数据导致 OOM将 list 数据进⾏分页读取,并进⾏分页写⼊到 excel。
java实现数据的Excel导出,自定义导出字段,转换字典值
java实现数据的Excel导出,⾃定义导出字段,转换字典值第⼀版代码:基础功能跳转此⽂章:简介新增功能:1. 添加⾃定义字段导出功能, ⽤户可以选择字段进⾏导出2. 将字典类型数据进⾏转换(如:0=⼥,1=男, 将0转换为⼥, 1转换为男)3. 添加表头格式4. 随机⽂件名称, 防⽌多次导出时⽂件覆盖问题实现代码Excel注解@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface Excel {/*** 导出到Excel中的名字*/String name() default "";/*** ⽇期格式, 如: yyyy-MM-dd*/String dateFormat() default "";/*** 字典的key值*/String dictKey() default "";/*** 读取内容转表达式 (如: 0=男,1=⼥,2=未知)*/String dictExp() default "";}123456789101112131415161718192021222324public class ExcelUtil<T> {/*** ⼯作薄*/private Workbook wb;/*** ⼯作表*/private Sheet sheet;/*** 需要导出的数据*/private List<T> exportList;/*** 对象的class对象*/private Class<T> clazz;/*** 被选中需要导出的字段名称*/private Map<String, Object> checkedFieldsName;/*** 被选中需要导出的字段对象*/private List<Field> checkedFields;/*** 包含需要字典转换的字段对象*/private List<Field> fieldsContainDict;/*** 对象中的字典值*/private Map<String, Map<String, String>> dicts;private ExcelUtil(){}public ExcelUtil(Class<T> clazz){this.clazz = clazz;}/**** @param list* @param sheetName* @param fieldsName*/public void exportExcel(List<T> list, Map<String, Object> fieldsName, String sheetName){ // 初始化数据init(list, sheetName, fieldsName);// 转换字典值try {convertDict();} catch (IllegalAccessException e) {e.printStackTrace();}// sheet第⼀⾏加⼊名称数据createTopRow();// sheet其他⾏,添加⽬标数据try {createOtherRow();} catch (IllegalAccessException e) {e.printStackTrace();}// 导出wbtry(OutputStream outFile = new FileOutputStream(generateFileName())){wb.write(outFile);} catch (IOException e) {e.printStackTrace();}}}/*** 添加导出数据*/private void createOtherRow() throws IllegalAccessException {for (int rowNum = 1; rowNum <= exportList.size(); rowNum++) {Row row = sheet.createRow(rowNum);T t = exportList.get(rowNum - 1);for (int colNum = 0; colNum < checkedFields.size(); colNum++) {Cell cell = row.createCell(colNum);Field field = checkedFields.get(colNum);field.setAccessible(true);// 单元格设置值addCell(cell, field, t);}}}/*** 单元格中添加数据** @param cell 单元格* @param field 字段* @param t list中的⼀条数据*/private void addCell(Cell cell, Field field, T t) throws IllegalAccessException {Class<?> fieldType = field.getType();if (String.class == fieldType) {cell.setCellValue((String) field.get(t));} else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {cell.setCellValue((Integer) field.get(t));} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {cell.setCellValue((Long) field.get(t));} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {cell.setCellValue((Double) field.get(t));} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {cell.setCellValue((Float) field.get(t));} else if (Date.class == fieldType) {String dateFormat = field.getAnnotation(Excels.class).dateFormat();cell.setCellValue(dateFormat((Date) field.get(t), dateFormat));}}/*** 时间格式转换* @param date ⽇期* @param dateFormat ⽇期格式* @return*/private String dateFormat(Date date, String dateFormat) {if (dateFormat == null || "".equals(dateFormat)) {dateFormat = "yyyy-MM-dd HH:mm:ss";}SimpleDateFormat df = new SimpleDateFormat(dateFormat);return df.format(date);}/*** sheet第⼀⾏加⼊名称数据*/private void createTopRow() {Row row = sheet.createRow(0);Map<String, CellStyle> styles = createStyles(wb);for (int index = 0; index < checkedFields.size(); index++) {Cell cell = row.createCell(index);cell.setCellValue(checkedFields.get(index).getAnnotation(Excels.class).name()); System.out.println(styles.get("header"));cell.setCellStyle(styles.get("header"));}}private void convertDict() throws IllegalAccessException {for (Field field : fieldsContainDict) {Excels annotation = field.getAnnotation(Excels.class);String dictKey = annotation.dictKey();field.setAccessible(true);for (T t : exportList) {// 获取字段值String o = (String) field.get(t);field.set(t, dicts.get(dictKey).get(o));}}}/*** 将数据导出Excel** @param list 需要导出的数据* @param sheetName ⼯作表名称*/public void exportExcel(List<T> list, String sheetName){exportExcel(list, null, sheetName);}/*** 将数据导出Excel** @param list 需要导出的数据*/public void exportExcel(List<T> list) {exportExcel(list, null, "sheet");}/*** 初始化*/public void init(List<T> list ,String sheetName, Map<String, Object> fieldsName){ this.checkedFieldsName = fieldsName;this.exportList = list;// 初始化导出数据initExportList();// 初始化⼯作薄initWorkbook();// 初始化⼯作表initSheet(sheetName);// 初始化checkedFields, fieldsContainDictinitFields();// 根据注解⽣成⽣成字典generateObjDict();}/*** 初始化导出数据*/private void initExportList(){// 防⽌导出过程中出现空指针if(Objects.isNull(this.exportList)) {this.exportList = new ArrayList<>();}}/*** 初始化⼯作簿*/private void initWorkbook(){this.wb = new SXSSFWorkbook();}/*** 初始化⼯作表*/private void initSheet(String sheetName){this.sheet = wb.createSheet(sheetName);}* 1.如果checkedFieldsName没有定义(未⾃定义导出字段),所有字段全部导出 * 2.如果checkedFieldsName进⾏了定义,根据定义字段进⾏导出*/private void initFields(){// 获取对象所有字段对象Field[] fields = clazz.getDeclaredFields();// 过滤出checkedFieldsthis.checkedFields = Arrays.asList(fields).stream().filter(item -> {if(!Objects.isNull(this.checkedFieldsName)) {if (item.isAnnotationPresent(Excel.class)) {return checkedFieldsName.containsKey(item.getName());}} else {return item.isAnnotationPresent(Excel.class);}return false;}).collect(Collectors.toList());// 过滤出fieldsContainDictthis.fieldsContainDict = Arrays.asList(clazz.getDeclaredFields()).stream().filter(item -> !"".equals(item.getAnnotation(Excel.class).dictExp())).collect(Collectors.toList(}/*** 通过扫描字段注解⽣成字典数据*/private void generateObjDict(){if(fieldsContainDict.size() == 0) {return;}if(dicts == null) {dicts = new HashMap<>(); // Map<String, List<Map<String, String>>>}for (Field field : fieldsContainDict) {String dictKey = field.getAnnotation(Excel.class).dictKey();String exps = field.getAnnotation(Excel.class).dictExp();String[] exp = exps.split(",");Map<String, String> keyV = new HashMap<>();dicts.put(dictKey, keyV);for (String s : exp) {String[] out = s.split("=");keyV.put(out[0], out[1]);}System.out.println("字典值:"+ dicts);}}/*** 创建表格样式** @param wb ⼯作薄对象* @return 样式列表*/private Map<String, CellStyle> createStyles(Workbook wb){Map<String, CellStyle> styles = new HashMap<String, CellStyle>();// 数据格式CellStyle style = wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setBorderRight(BorderStyle.THIN);style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBorderLeft(BorderStyle.THIN);style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderTop(BorderStyle.THIN);dataFont.setFontHeightInPoints((short) 10);style.setFont(dataFont);styles.put("data", style);// 表头格式style = wb.createCellStyle();style.cloneStyleFrom(styles.get("data"));style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setFillPattern(FillPatternType.SOLID_FOREGROUND);Font headerFont = wb.createFont();headerFont.setFontName("Arial");headerFont.setFontHeightInPoints((short) 10);headerFont.setBold(true);headerFont.setColor(IndexedColors.WHITE.getIndex());style.setFont(headerFont);styles.put("header", style);return styles;}/*** ⽣成随机名称,防⽌⽂件复写* @return*/private String generateFileName(){return "D:\\" + UUID.randomUUID().toString().replace("-", "") + ".xlsx";}}12345678910111213141516171819202122232425262728293031323334353637383948 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369使⽤⽅法将对象加上⼯具类需要的注解: @Data@NoArgsConstructor@AllArgsConstructorpublic class Student {@Excel(name = "姓名")private String name;@Excel(name = "年龄")private Integer age;@Excel(name = "出⽣⽇期", dateFormat = "yyyy-MM-dd")private Date birthday;@Excel(name = "性别", dictKey = "sex", dictExp = "1=男,2=⼥")private String sex;}1234567891011121314151617测试字典转换public static void main(String[] args) {ArrayList<Student> data = new ArrayList<>();Student student = new Student();student.setName("tom");student.setAge(19);student.setSex("1");student.setBirthday(new Date());data.add(student);ExcelUtil<Student> util = new ExcelUtil<>(Student.class);util.exportExcel(data, "⼈员信息表");}123456789101112输出结果:结果可以看出, 已将1转换为男了测试选择字段导出:若不⾃定义导出的字段, ⼯具将会把所有带有Excel注解的字段进⾏导出, 如上⽅所⽰。
java导出大批量(百万以上)数据的excel文件
java导出⼤批量(百万以上)数据的excel⽂件本⽂实例为⼤家分享了java导出百万以上数据的excel⽂件,供⼤家参考,具体内容如下1.传统的导出⽅式会消耗⼤量的内存,2003每个sheet页最多65536条数据,2007每个sheet页可以达到100万条数据以上,2007会在⽣成Workbook时清理数据,所以2007导出量更⼤;2.可以导出多个excel⽂件到某个⽬录中,然后打包下载;3.导出excel格式的xml⽂件,这种⽅式可以分批导出数据,适⽤于⼤批量数据的导出,以下简单介绍这种⽅式:代码如下:package com.epay.utils;/*** ⼤数据量导出成EXCEL或XML* @author qad* 2017-04-22*/import java.io.BufferedOutputStream;import java.io.DataOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class Test {public static void main(String[] args) {StringBuffer sb = new StringBuffer();try {DataOutputStream rafs = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File("d://test.xls"))));sb.append("<?xml version=\"1.0\" encoding=\"GBK\" ?>");sb.append("\n");sb.append("<?mso-application progid=\"Excel.Sheet\"?>");sb.append("\n");sb.append("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"");sb.append("\n");sb.append(" xmlns:o=\"urn:schemas-microsoft-com:office:office\"");sb.append("\n");sb.append(" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");sb.append("\n");sb.append(" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"");sb.append("\n");sb.append(" xmlns:html=\"/TR/REC-html40\">");sb.append("\n");sb.append("<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\"> ");sb.append("\n");sb.append(" <Styles>\n");sb.append(" <Style ss:ID=\"Default\" ss:Name=\"Normal\">\n");sb.append(" <Alignment ss:Vertical=\"Center\"/>\n");sb.append(" <Borders/>\n");sb.append(" <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"12\"/>\n");sb.append(" <Interior/>\n");sb.append(" <NumberFormat/>\n");sb.append(" <Protection/>\n");sb.append(" </Style>\n");sb.append(" </Styles>\n");int sheetcount = 0;int recordcount = 65535;int currentRecord = 0;int total = 100000;int col = 20;sb.append("<Worksheet ss:Name=\"Sheet0\">");sb.append("\n");sb.append("<Table ss:ExpandedColumnCount=\"" + col+ "\" ss:ExpandedRowCount=\"" + total+ "\" x:FullColumns=\"1\" x:FullRows=\"1\">");sb.append("\n");for (int i = 0; i < total; i++) {if ((currentRecord == recordcount|| currentRecord > recordcount || currentRecord == 0)&& i != 0) {// ⼀个sheet写满currentRecord = 0;rafs.write(sb.toString().getBytes());sb.setLength(0);sb.append("</Table>");sb.append("<WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">");sb.append("\n");sb.append("<ProtectObjects>False</ProtectObjects>");sb.append("\n");sb.append("<ProtectScenarios>False</ProtectScenarios>");sb.append("\n");sb.append("</WorksheetOptions>");sb.append("\n");sb.append("</Worksheet>");sb.append("<Worksheet ss:Name=\"Sheet" + i / recordcount+ "\">");sb.append("\n");sb.append("<Table ss:ExpandedColumnCount=\"" + col+ "\" ss:ExpandedRowCount=\"" + recordcount+ "\" x:FullColumns=\"1\" x:FullRows=\"1\">");sb.append("\n");}sb.append("<Row>");for (int j = 0; j < col; j++) {System.out.println(i);sb.append("<Cell><Data ss:Type=\"String\">111</Data></Cell>");sb.append("\n");}sb.append("</Row>");if (i % 5000 == 0) {rafs.write(sb.toString().getBytes());rafs.flush();sb.setLength(0);}sb.append("\n");currentRecord++;}rafs.write(sb.toString().getBytes());sb.setLength(0);sb.append("</Table>");sb.append("<WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">");sb.append("\n");sb.append("<ProtectObjects>False</ProtectObjects>");sb.append("\n");sb.append("<ProtectScenarios>False</ProtectScenarios>");sb.append("\n");sb.append("</WorksheetOptions>");sb.append("\n");sb.append("</Worksheet>");sb.append("</Workbook>");sb.append("\n");rafs.write(sb.toString().getBytes());rafs.flush();rafs.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}导出xml⽂件之后直接修改后缀名为.xlsx就可以直接打开,弊端:⽆法导出.xls格式的excel⽂件.以上只是⼀种简单想法,留待以后具体实现.扩展:既然可以使⽤xml⽂件导出excel,那么导出csv⽂件之后也可以直接改后缀名为.xls,⽬前只是⼀种想法,尚未证实可⾏性.以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
mongo百万数据导出excel java代码
MongoDB是一个广泛使用的文档数据库,在处理大量数据时非常高效。
以mongo百万数据导出excel为主题,我将针对这一需求展开讨论。
在文章中,我将从mongo数据库的基本概念开始,逐步深入探讨如何使用java代码实现百万数据导出excel的功能。
1. MongoDB简介MongoDB是一个开源的文档型数据库,它以高性能、高可用性和灵活的数据模型而闻名。
在处理大量数据时,MongoDB能够提供出色的性能表现,因此在实际应用中被广泛使用。
其文档式数据存储结构和灵活的数据模型为程序员提供了很大的便利。
2. MongoDB数据导出在实际项目中,有时候我们需要将MongoDB中的数据导出到excel 表格中,以便进行进一步的分析和处理。
在这个过程中,需要使用java代码来实现数据的读取和导出功能。
在这篇文章中,我将共享一个实现百万数据导出excel的java代码示例,并提供详细的解释和分析。
3. Java代码实现在实际操作中,我们可以使用Java语言搭配MongoDB的Java驱动程序来实现数据的读取和导出功能。
我们需要建立连接到MongoDB 数据库的连接,并且查询需要导出的数据。
通过java代码将数据逐行写入excel表格中,最终完成百万数据导出excel的功能。
4. 个人观点和总结从个人观点来看,使用MongoDB进行大数据处理可以极大地提高程序的性能和灵活性。
与传统的关系型数据库相比,MongoDB在处理大量数据时更为高效和简洁。
而在实际操作中,通过java代码实现百万数据导出excel功能也为数据分析和处理提供了便利。
通过这篇文章,我希望读者能够深入了解MongoDB数据库的基本概念和数据导出功能,并能够通过java代码实现百万数据导出excel的功能。
我也希望读者能够在实际项目中灵活应用这些知识,提高工作效率和数据处理能力。
在撰写本文的过程中,我充分考虑了你对mongo百万数据导出excel java代码的需求,以多角度展开讨论,希望能够帮助你更深入地理解和使用相关知识。
JAVA导出数据到excel中大数据量的解决方法
JAVA导出数据到excel中⼤数据量的解决⽅法最近在做项⽬功能时,发现有20万以上的数据。
要求导出时直接导出成压缩包。
原来的逻辑是使⽤poi导出到excel,他是操作对象集合然后将结果写到excel中。
使⽤poi等导出时,没有考虑数据量的问题,量⽆法满⾜,有个⼏千⾏jvm就哭了。
更别提⼏万⾏⼏百万⾏数据了。
经过⼀天的研究发现⼀种不会消耗过多内存的⽅法:导出成csv格式⼤数据量的导出成csv格式分为以下⼏步:1.⾸先引⼊需要的jar包⼀下是我maven的配置⽅式<dependency><groupId>org.mvel</groupId><artifactId>mvel2</artifactId><version>2.2.8.Final</version></dependency><dependency><groupId>net.sourceforge.javacsv</groupId><artifactId>javacsv</artifactId><version>2.0</version></dependency>2.以下是具体的执⾏代码,我是⽤的是jdbcTemplatepublic class DownloadVehicleRepair extends AbstractJob {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overrideprotected void executeBusiness(Long aLong) {System.out.println("开始执⾏!!!!!!!!!!");final String fileName = "车辆维修清单.csv";//压缩包⾥⾯的⽂件final String[] header = {"序号", "第三⽅机构代码", "机构名称", "分公司", "合作机构", "单位类别", "主品牌", "品牌名称","被投诉", "涉及欺诈", "⿊名单", "审核状态", "维护时间", "维护⼈员代码"};final String sql = "您需要执⾏sql”;jdbcTemplate.execute(new PreparedStatementCreator() {@Overridepublic PreparedStatement createPreparedStatement(Connection connection) throws SQLException {PreparedStatement pstmt = connection.prepareStatement(sql);return pstmt;}}, new PreparedStatementCallback<Integer>() {@Overridepublic Integer doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException {ResultSet rs = preparedStatement.executeQuery();try {CsvUtil.writeCsv(RuntimeEnvironmentUtil.getValue(SysConstent.code,SysConstent.path) + "\\VehicleRepairDetail.zip",fileName, header, rs);//RuntimeEnvironmentUtil.getValue()是为了获取你导出到服务器的路径} catch (Exception e) {e.printStackTrace();}return 0;}});System.out.println("导出完成!!!!!!!!!!!");}}3.以下是帮助类public class CsvUtil {// 编码类型public static final Charset CHARSET = Charset.forName("GBK");// 分隔符public static final char DELIMITER = ',';// ⽂件后缀public static final String SUFFIX = ".csv";public static void writeCsv(OutputStream out, String[] header, ResultSet rs)throws IOException, SQLException {CsvWriter writer = null;try {writer = new CsvWriter(out, CsvUtil.DELIMITER, CsvUtil.CHARSET);writeCsv(writer, header, rs);} finally {if (writer != null)writer.close();}}public static void writeCsv(CsvWriter writer, String[] header, ResultSet rs)throws IOException, SQLException {if (header != null)writer.writeRecord(header);ResultSetMetaData md = rs.getMetaData();int columnCount = md.getColumnCount();while (rs.next()) {for (int i = 1; i <= columnCount; i++)writer.write(rs.getString(i));writer.endRecord();}}public static void writeCsv(File file, String[] header, ResultSet rs)throws IOException, SQLException {BufferedOutputStream out = null;FileOutputStream fileOutputStream = null;try {fileOutputStream = new FileOutputStream(file);out = new BufferedOutputStream(fileOutputStream);writeCsv(out, header, rs);} finally {if (out != null) {out.flush();out.close();}if (fileOutputStream != null) {fileOutputStream.close();}}}public static void writeCsv(String csvFilePath, String[] header,ResultSet rs) throws IOException, SQLException {writeCsv(new File(csvFilePath), header, rs);}public static void writeCsv(String zipFilePath, String csvName, String[] header, ResultSet rs) throws IOException, SQLException {FileOutputStream fos = null;BufferedOutputStream bos = null;ZipOutputStream zos = null;try {fos = new FileOutputStream(zipFilePath);bos = new BufferedOutputStream(fos);zos = new ZipOutputStream(bos);zos.putNextEntry(new ZipEntry(csvName));writeCsv(zos, header, rs);} finally {StreamUtil.flush(zos);StreamUtil.close(zos);//StreamUtil.flush(bos);StreamUtil.close(bos);//StreamUtil.flush(fos);StreamUtil.close(fos);}}}public class StreamUtil {public static void flush(Flushable flushable) {if (flushable != null) {try {flushable.flush();} catch (IOException e) {e.printStackTrace();}}}public static void close(Closeable closeable){if(closeable!=null){try {closeable.close();} catch (IOException e) {e.printStackTrace();}}}}4.下⾯是下载时的action@RequestMapping(value = "/downloadVehicleRepair", method = RequestMethod.POST)public ResponseEntity<byte[]> download() throws IOException {String path = RuntimeEnvironmentUtil.getValue(SysConstent.code,SysConstent.path)+"\\VehicleRepairDetail.zip"; File file = new File(path);HttpHeaders headers = new HttpHeaders();String fileName = new String("车辆维修清单.zip".getBytes("UTF-8"), "iso-8859-1");//为了解决中⽂名称乱码问题headers.setContentDispositionFormData("attachment", fileName);headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);}总结:以上只是关键代码。
大量数据导入EXCEL的方法
⼤量数据导⼊EXCEL的⽅法
⼤量数据导⼊EXCEL的⽅法
⼀. 导⼊⽣成Excel
原始的做法:
将数据加载到内存中,导⼊Excel,此⽅法的弊端:
1.⼤量数据加载到内存中,使机器变得缓慢
2.⼤量数据在导⼊Excel时形成⼤量cell对象产⽣OOM
在使⽤TOMCAT的情况下,JVM最⾼只能⽀持到2G内存,则会发⽣内存溢出的情况。
此时的内存开销主要是两部分,⼀部分是⼤量数据加载到内存,另⼀部分是写⼊⼀个EXCEL 时形成⼤量cell对象的开销。
由于JVM的GC机制是不能强制回收的.
采⽤的⽅案是:将⼤量要导出的数据放⼊临时表分批次形成多个Excel⽂件后合并.说明:1.⼤量要导出的数据放⼊临时表
⼤量数据有可能是在海量数据表⾥通过条件查询出来的,这样可以有效避免多次在海量数据中查询,提⾼了查询效率
2.分批次形成多个Excel
⽐形成⼀个Excel的多个sheet好,因为多个sheet形式需要将整个Excel加载到内存中,那么sheet越多,Excel越⼤.改多个SHEET页为多个EXCEL。
通过多次⽣成,可以在后⾯EXCEL⽣成所需要的内存不⾜时,有效回收前⾯⽣成EXCEL时占⽤的内存。
3.将多个Excel合并
⼆. Excel导出⼊库
1.excel⽂件上传⾄服务器
2.采⽤eventusermodel⽅式读取excel数据,分块读取数据并批量⼊临时表
3.利⽤存储过程或其他纯sql语句来验证临时表(Temp1)中的数据
4.将验证失败数据放⼊存储⾄校验失败的临时表中(Temp2)
5.将临时表(Temp1)中的数据插⼊库表。
java大数据量导出通用方法
java大数据量导出通用方法
在现代数据处理过程中,导出数据是一个非常重要的步骤。
然而,当涉及到处理大量数据时,导出数据可能会变得非常困难。
这是因为大数据集合往往需要更长时间才能处理完毕,而且可能会导致内存溢出或其他性能问题。
为帮助开发人员轻松处理大数据集合的导出问题,本文将介绍一种通用方法,可以在Java中使用。
以下是我们将解决的问题:
1. 如何处理大的数据集合并将其导出到Excel或CSV格式的文件中。
2. 如何避免内存溢出等性能问题。
首先,我们需要引入Apache POI和OpenCSV库。
Apache POI用于创建和编辑Excel文件,而OpenCSV库用于创建和编辑CSV文件。
接着,我们需要使用Java的流处理来处理大数据集合。
流处理可以将数据按需读取,而不是一次性将所有数据都读入内存中。
这样可以避免内存溢出等问题。
最后,我们需要将数据写入Excel或CSV文件中。
为了避免将数据全部写入内存中,我们可以使用批处理方式,将数据划分为小块写入文件中。
综上所述,使用流处理和批处理方式,结合Apache POI和OpenCSV 库,可以轻松地处理大数据集合的导出问题。
这种通用方法不仅能提高性能,还可以减少内存使用,确保导出任务的成功完成。
- 1 -。
使用NPOI或POI导出Excel大数据(百万级以上),导致内存溢出的解决方案(NPOI,POI)
使⽤NPOI或POI导出Excel⼤数据(百万级以上),导致内存溢出的解决⽅案(NPOI,POI)使⽤⼯具:POI(JAVA),NPOI(.Net)致谢博主 Crazy_Jeff 提供的思路⼀、问题描述:导出任务数据量近100W甚⾄更多,导出的项⽬就会内存溢出,挂掉。
⼆、原因分析:1、每个进程在写Excel⽂件时,都是先将数据加载到内存,然后再将内存⾥⾯的数据⽣成⽂件;因此单个进程任务的数据量过⼤,将⽆法及时回收系统内存,最终导致系统内存耗尽⽽宕机。
2、导出中查询结果是⼀次性全部查询出来,占⽤⼤量系统内存资源。
三、优化⽅案思路:1、将所有导出查询全部改成分页的⽅式查询;2、将写Excel⽂件使⽤IO流来实现,采⽤POI,或NPOI拼接xml字符串完成,迭代⼀批数据就flush进硬盘,同时把list,⼤对象赋值为空,显式调⽤垃圾回收器,及时回收内存。
⾸先提供Java版代码POI实现,来⾃:import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.Writer;import ng.reflect.Method;import java.util.Calendar;import java.util.Enumeration;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.UUID;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import java.util.zip.ZipOutputStream;import ermodel.DateUtil;import ermodel.IndexedColors;import org.apache.poi.ss.util.CellReference;import ermodel.XSSFCellStyle;import ermodel.XSSFDataFormat;import ermodel.XSSFSheet;import ermodel.XSSFWorkbook;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.chengfeng.ne.global.service.ITaskService;import com.thinkjf.core.config.GlobalConfig;/*** 功能描述:⽣成Excel⽂件类* @author Jeff* @version 1.0* @date 2015-08-03*/@Service("xlsxOutPutService")public class XlsxOutPutService {@Autowiredprivate ITaskService taskService;/*** 导出每个sheet⾏数*/public int pageSize = Integer.parseInt(GlobalConfig.getPropertyValue("common.exoprt.Worksheet.max.rownum"));/*** 根据传⼊的不同serviceName来执⾏不同的查询语句* @param serviceName* @param execMethod* @param params* @param pageIndex* @return*/public List<?> queryBySerivceName(String serviceName,String execMethod, Map<String, Object> params,int pageIndex)throws Exception{List<?> resultList = null;if("taskService".equals(serviceName)){resultList = taskService.queryExportResultPage(execMethod,params, pageIndex, pageSize);}return resultList;}/*** ⽣成Excel⽂件外部调⽤⽅法* @param headList 标题列表* @param fieldName 字段列表* @param sheetName ⼯作薄sheet名称* @param tempFilePath 临时⽂件⽬录* @param filePath ⽬标⽂件* @param execMethod 执⾏sql* @param params 查询参数* @param serviceName 执⾏service⽅法对象名称* @throws Exception*/public void generateExcel(List<String> headList,List<String> fieldName,String sheetName, String tempFilePath,String filePath,String execMethod, Map<String, O throws Exception {XSSFWorkbook wb = new XSSFWorkbook();Map<String, XSSFCellStyle> styles = createStyles(wb);XSSFSheet sheet = wb.createSheet(sheetName);String sheetRef = sheet.getPackagePart().getPartName().getName();String sheetRefList = sheetRef.substring(1);File tempFiledir = new File(tempFilePath);if(!tempFiledir.exists()){tempFiledir.mkdirs();}String uuid = UUID.randomUUID().toString();uuid = uuid.replace("-", "");File sheetFileList = new File(tempFilePath + "/sheet_" + uuid + ".xml");File tmpFile = new File(tempFilePath + "/"+uuid+".xlsx");FileOutputStream os = new FileOutputStream(tmpFile);wb.write(os);os.close();Writer fw = new OutputStreamWriter(new FileOutputStream(sheetFileList), "UTF-8");//⽣成sheetgenerateExcelSheet(headList,fieldName, fw, styles,execMethod,params,serviceName);fw.close();//将临时⽂件压缩替换FileOutputStream out = new FileOutputStream(filePath);substituteAll(tmpFile, sheetFileList, sheetRefList, out);out.close();// 删除临时⽂件tmpFile.delete();sheetFileList.delete();tmpFile = null;sheetFileList = null;os = null;fw = null;out = null;Runtime.getRuntime().gc();}/*** ⽣成sheet* @param headList* @param fields* @param out* @param styles* @param execMethod* @param params* @throws Exception*/private void generateExcelSheet(List<String> headList,List<String> fields,Writer out,Map<String, XSSFCellStyle> styles,String execMethod, Map<String, Object> params,String serviceName) throws Exception { XSSFCellStyle stringStyle = styles.get("cell_string");XSSFCellStyle longStyle = styles.get("cell_long");XSSFCellStyle doubleStyle = styles.get("cell_double");XSSFCellStyle dateStyle = styles.get("cell_date");Calendar calendar = Calendar.getInstance();SpreadsheetWriter sw = new SpreadsheetWriter(out);sw.beginWorkSheet();sw.beginSetColWidth();for (int i = 10, len = headList.size() - 2; i < len; i++) {sw.setColWidthBeforeSheet(i, 13);}sw.setColWidthBeforeSheet(headList.size() - 1, 16);sw.endSetColWidth();sw.beginSheet();// 表头sw.insertRowWithheight(0, headList.size(), 25);int styleIndex = ((XSSFCellStyle) styles.get("sheet_title")).getIndex();for (int i = 0, len = headList.size(); i < len; i++) {sw.createCell(i, headList.get(i), styleIndex);}sw.endWithheight();//int pageIndex = 1;// 查询起始页Boolean isEnd = false;// 是否是最后⼀页,循环条件do {// 开始分页查询// 导出查询改为分页查询⽅式,替代原有queryExportResult()⽅法long startTimne = System.currentTimeMillis();List<?> dataList = this.queryBySerivceName(serviceName, execMethod, params, pageIndex);long endTime = System.currentTimeMillis();System.out.println("查询"+pageIndex+"完成⽤时="+((endTime-startTimne))+"毫秒");if (dataList != null && dataList.size() > 0) {//写⽅法-------int cellIndex = 0;for (int rownum = 1, len = dataList.size() + 1; rownum < len; rownum++) {cellIndex = 0;sw.insertRow((pageIndex-1)*pageSize+rownum);Object data = dataList.get(rownum-1);Object val = null;Method fieldMethod = null;for (int k = 0, len2 = fields.size(); k < len2; k++) {fieldMethod = (Method) data.getClass().getMethod("get"+ fields.get(k));fieldMethod.setAccessible(true);// 不进⾏安全检测val = fieldMethod.invoke(data);if(val == null){sw.createCell(cellIndex,"",stringStyle.getIndex());}else{String typeName = fieldMethod.getGenericReturnType().toString();if (typeName.endsWith("int") || typeName.endsWith("nteger")) {sw.createCell(cellIndex, (Integer) val,longStyle.getIndex());} else if (typeName.endsWith("ong")) {sw.createCell(cellIndex, (Long) val, longStyle.getIndex());} else if (typeName.endsWith("ouble")) {sw.createCell(cellIndex, (Double) val,doubleStyle.getIndex());} else if (typeName.endsWith("util.Date")) {calendar.setTime((java.util.Date) val);sw.createCell(cellIndex, calendar, dateStyle.getIndex());} else if (typeName.endsWith("sql.Date")) {calendar.setTime((java.sql.Date) val);sw.createCell(cellIndex, calendar, dateStyle.getIndex());} else {sw.createCell(cellIndex, val==null?"":val.toString().replace("<", "<").replace(">", ">"), stringStyle.getIndex());}}cellIndex++;}sw.endRow();if (rownum % 2000 == 0) {out.flush();}}//------------isEnd = true;pageIndex++;} else {isEnd = false;}dataList = null;Runtime.getRuntime().gc();} while (isEnd);sw.endSheet();// 合并单元格// sw.beginMergerCell();// for (int i = 0, len = dataList.size() + 1; i < len; i++) {// sw.setMergeCell(i, 8, i, 9);// }// sw.endMergerCell();sw.endWorkSheet();}/*** 创建Excel样式* @param wb* @return*/private static Map<String, XSSFCellStyle> createStyles(XSSFWorkbook wb) {Map<String, XSSFCellStyle> stylesMap = new HashMap<String, XSSFCellStyle>();XSSFDataFormat fmt = wb.createDataFormat();XSSFCellStyle style = wb.createCellStyle();style.setAlignment(XSSFCellStyle.ALIGN_CENTER);style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);stylesMap.put("cell_string", style);XSSFCellStyle style2 = wb.createCellStyle();style2.setDataFormat(fmt.getFormat("0"));style2.setAlignment(XSSFCellStyle.ALIGN_CENTER);style2.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);stylesMap.put("cell_long", style2);XSSFCellStyle style3 = wb.createCellStyle();style3.setDataFormat(fmt.getFormat("0.00"));style3.setAlignment(XSSFCellStyle.ALIGN_CENTER);style3.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);stylesMap.put("cell_double", style3);XSSFCellStyle style4 = wb.createCellStyle();style4.setDataFormat(fmt.getFormat("yyyy-MM-dd HH:mm:ss"));style4.setAlignment(XSSFCellStyle.ALIGN_CENTER);style4.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);stylesMap.put("cell_date", style4);XSSFCellStyle style5 = wb.createCellStyle();style5.setFillForegroundColor(IndexedColors.AQUA.getIndex());style5.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);style5.setAlignment(XSSFCellStyle.ALIGN_CENTER);style5.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);stylesMap.put("sheet_title", style5);return stylesMap;}/*** 打包压缩* @param zipfile* @param tmpfileList* @param entryList* @param out* @throws IOException*/private void substituteAll(File zipfile,File tmpfileList,String entryList, OutputStream out) throws IOException {ZipFile zip = new ZipFile(zipfile);ZipOutputStream zos = new ZipOutputStream(out);@SuppressWarnings("unchecked")Enumeration<ZipEntry> en = (Enumeration<ZipEntry>)zip.entries();while (en.hasMoreElements()) {ZipEntry ze = en.nextElement();if (!entryList.contains(ze.getName())) {zos.putNextEntry(new ZipEntry(ze.getName()));InputStream is = zip.getInputStream(ze);copyStream(is, zos);is.close();is = null;System.gc();}}InputStream is = null;zos.putNextEntry(new ZipEntry(entryList));is = new FileInputStream(tmpfileList);copyStream(is, zos);is.close();zos.close();zip.close();is = null;zos = null;zip = null;System.gc();}private static void copyStream(InputStream in, OutputStream out)throws IOException {byte[] chunk = new byte[1024*10];int count;while ((count = in.read(chunk)) >= 0)out.write(chunk, 0, count);}public int getTrueColumnNum(String address) {address = address.replaceAll("[^a-zA-Z]", "").toLowerCase();char[] adds = address.toCharArray();int base = 1;int total = 0;for (int i = adds.length - 1; i >= 0; i--) {total += (adds[i] - 'a' + 1) * base;base = 26 * base;}return total;}public static class SpreadsheetWriter {private final Writer _out;private int _rownum;public SpreadsheetWriter(Writer out) {this._out = out;}public void beginWorkSheet() throws IOException {this._out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?><worksheet xmlns=\"/spreadsheetml/2006/main\">"); }public void beginSheet() throws IOException {this._out.write("<sheetData>\n");}public void endSheet() throws IOException {this._out.write("</sheetData>");// 合并单元格}public void endWorkSheet() throws IOException {this._out.write("</worksheet>");}//插⼊⾏不带⾼度public void insertRow(int rownum) throws IOException {this._out.write("<row r=\"" + (rownum + 1) + "\">\n");this._rownum = rownum;}public void endRow() throws IOException {this._out.write("</row>\n");}//插⼊⾏且设置⾼度public void insertRowWithheight(int rownum, int columnNum, double height)throws IOException {this._out.write("<row r=\"" + (rownum + 1) + "\" spans=\"1:"+ columnNum + "\" ht=\"" + height+ "\" customHeight=\"1\">\n");this._rownum = rownum;}public void endWithheight() throws IOException {this._out.write("</row>\n");}public void beginSetColWidth() throws IOException {this._out.write("<cols>\n");}// 设置列宽下标从0开始public void setColWidthBeforeSheet(int columnIndex, double columnWidth)throws IOException {this._out.write("<col min=\"" + (columnIndex + 1) + "\" max=\""+ (columnIndex + 1) + "\" width=\"" + columnWidth+ "\" customWidth=\"1\"/>\n");}public void endSetColWidth() throws IOException {this._out.write("</cols>\n");}public void beginMergerCell() throws IOException {this._out.write("<mergeCells>\n");}public void endMergerCell() throws IOException {this._out.write("</mergeCells>\n");}// 合并单元格下标从0开始public void setMergeCell(int beginColumn, int beginCell, int endColumn,int endCell) throws IOException {this._out.write("<mergeCell ref=\"" + getExcelName(beginCell + 1)+ (beginColumn + 1) + ":" + getExcelName(endCell + 1)+ (endColumn + 1) + "\"/>\n");// 列⾏:列⾏}public void createCell(int columnIndex, String value, int styleIndex)throws IOException {String ref = new CellReference(this._rownum, columnIndex).formatAsString();this._out.write("<c r=\"" + ref + "\" t=\"inlineStr\"");if (styleIndex != -1)this._out.write(" s=\"" + styleIndex + "\"");this._out.write(">");this._out.write("<is><t>" + value + "</t></is>");this._out.write("</c>");}public void createCell(int columnIndex, String value)throws IOException {createCell(columnIndex, value, -1);}public void createCell(int columnIndex, double value, int styleIndex)throws IOException {String ref = new CellReference(this._rownum, columnIndex).formatAsString();this._out.write("<c r=\"" + ref + "\" t=\"n\"");if (styleIndex != -1)this._out.write(" s=\"" + styleIndex + "\"");this._out.write(">");this._out.write("<v>" + value + "</v>");this._out.write("</c>");}public void createCell(int columnIndex, double value)throws IOException {createCell(columnIndex, value, -1);}public void createCell(int columnIndex, Calendar value, int styleIndex)throws IOException {createCell(columnIndex, DateUtil.getExcelDate(value, false),styleIndex);}//10 进制转26进制private String getExcelName(int i) {char[] allChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();StringBuilder sb = new StringBuilder();while (i > 0) {sb.append(allChar[i % 26 - 1]);i /= 26;}return sb.reverse().toString();}}}调⽤⽅法如下String tempFilePath = GlobalConfig.getPropertyValue("common.attach.upload_dir") + "/task/tmp/";//调⽤新的⽣成⽅法xlsxOutPutService.generateExcel(Arrays.asList(cellName), fieldName,MessageUtils.getMessage(exportDateType.toString()),tempFilePath, expFilePath, execMetho .net NPOI实现,这⾥没有使⽤list对象,⽽是将list转成了datatable后再来⽣成execl,⽀持多sheet操作using System;using System.Collections;using System.Collections.Generic;using System.Data;using System.IO;using System.Text;using ICSharpCode.SharpZipLib.Zip;using erModel;using NPOI.SS.Util;using erModel;///<summary>/// Xlsx输出/// editor:571115139@///</summary>public class XlsxOutputHelper{private const int FlushCnt = 2000;private static readonly string _tempFilePath = LocalStorge.TempDirectory;public int TotalCnt = 0;public Action<int> ProgressShow = null;private readonly string _batchId;private List<EntryPackage> _sheetFileList = new List<EntryPackage>();private readonly string _filePath;private readonly string _tempFile;private Dictionary<string, XSSFCellStyle> _styles;public XlsxOutputHelper(string filePath){var ext = Path.GetExtension(filePath);if (ext != ".xlsx"){_filePath = Path.GetFileNameWithoutExtension(filePath) + ".xlsx";}else{_filePath = filePath;}File.Create(_filePath).Close();_batchId = Guid.NewGuid().ToString("N");_tempFile = _tempFilePath + "/" + _batchId + ".xlsx";}public void BeginGenerate(List<string> sheetNames){XSSFWorkbook wb = new XSSFWorkbook();_styles = CreateStyles(wb);foreach (var sheetName in sheetNames){wb.CreateSheet(sheetName);}using (var os = new FileStream(_tempFile, FileMode.Create, FileAccess.ReadWrite)){wb.Write(os);}}///<summary>///⽣成Excel,多个sheet⽂件外部调⽤⽅法///</summary>///<param name="headList">标题列表</param>///<param name="sheetName">⼯作薄sheet名称</param>///<param name="querySerivce">查询服务</param>public bool GenerateSheet(List<string> headList, string sheetName, Func<int/*页码*/,int/*数据标识*/, DataPackage/*返回数据*/> querySerivce) {if (!File.Exists(_tempFile)) throw new Exception("请先执⾏BeginGenerate⽅法");XSSFWorkbook wb = new XSSFWorkbook(_tempFile);XSSFSheet sheet = (XSSFSheet)wb.GetSheet(sheetName);string sheetRef = sheet.GetPackagePart();string sheetRefList = sheetRef.Substring(1);wb.Close();if (!Directory.Exists(_tempFilePath)){Directory.CreateDirectory(_tempFilePath);}string guid = Guid.NewGuid().ToString("N");string sheetFileListFile = _tempFilePath + "/sheet_" + guid + ".xml";bool isOk = true;using (var s = File.OpenWrite(sheetFileListFile)){using (StreamWriter fw = new StreamWriter(s, Encoding.UTF8)){//⽣成sheetif (!GenerateExcelSheet(headList, fw, _styles,querySerivce)){isOk = false;}}}if (!isOk){FileHelper.DeleteFile(sheetFileListFile);return false;}_sheetFileList.Add(new EntryPackage() { EntryPath = sheetRefList, XmlFile = sheetFileListFile });return true;}///<summary>///结束⽣成Excel写⼊⽂件到本地///</summary>///<param name="writefileConsole"></param>///<returns></returns>public bool EndGenerate(Action<string> writefileConsole){if (!File.Exists(_tempFile)) throw new Exception("请先执⾏BeginGenerate⽅法");if (_sheetFileList == null || _sheetFileList.Count == 0) return false;writefileConsole("正在写⼊⽂件,请耐⼼等待....");//将临时⽂件压缩替换using (var output = File.OpenWrite(_filePath)){SubstituteAll(_tempFile, _sheetFileList, output);}// 删除临时⽂件FileHelper.DeleteFile(_tempFile);foreach (var entryPackage in _sheetFileList){FileHelper.DeleteFile(entryPackage.XmlFile);}return true;}///// <summary>///// ⽣成Excel⽂件外部调⽤⽅法///// </summary>///// <param name="headList">标题列表</param>///// <param name="sheetName">⼯作薄sheet名称</param>///// <param name="filePath">⽬标⽂件</param>///// <param name="writefileConsole">进度输出</param>//public bool GenerateExcel(List<string> headList, string sheetName, string filePath, Action<string> writefileConsole) //{// XSSFWorkbook wb = new XSSFWorkbook();// Dictionary<string, XSSFCellStyle> styles = CreateStyles(wb);// XSSFSheet sheet = (XSSFSheet)wb.CreateSheet(sheetName);// string sheetRef = sheet.GetPackagePart();// string sheetRefList = sheetRef.Substring(1);// if (!Directory.Exists(_tempFilePath))// {// Directory.CreateDirectory(_tempFilePath);// }// string guid = Guid.NewGuid().ToString("N");// string sheetFileListFile = _tempFilePath + "/sheet_" + guid + ".xml";// string tmpFile = _tempFilePath + "/" + guid + ".xlsx";// using (var os = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite))// {// wb.Write(os);// }// using (var s = File.OpenWrite(sheetFileListFile))// {// using (StreamWriter fw = new StreamWriter(s, Encoding.UTF8))// {////⽣成sheet// if (!GenerateExcelSheet(headList, fw, styles))// {// return false;// }// }// }// writefileConsole("正在写⼊⽂件,请耐⼼等待....");////将临时⽂件压缩替换// using (var output = File.OpenWrite(filePath))// {// SubstituteAll(tmpFile, sheetFileListFile, sheetRefList, output);// }//// 删除临时⽂件// File.Delete(tmpFile);// File.Delete(sheetFileListFile);// return true;//}///<summary>///⽣成sheet///</summary>///<param name="headList"></param>///<param name="output"></param>///<param name="styles"></param>///<param name="querySerivce"></param>private bool GenerateExcelSheet(List<string> headList, StreamWriter output,Dictionary<string, XSSFCellStyle> styles, Func<int/*页码*/, int/*数据标识*/, DataPackage/*返回数据*/> querySerivce) {XSSFCellStyle stringStyle = styles["cell_string"];XSSFCellStyle longStyle = styles["cell_long"];XSSFCellStyle doubleStyle = styles["cell_double"];XSSFCellStyle dateStyle = styles["cell_date"];SpreadsheetWriter sw = new SpreadsheetWriter(output);int[] arrColWidth = new int[headList.Count];for (int i = 0; i < headList.Count; i++){arrColWidth[i] = Math.Max(Encoding.GetEncoding(936).GetBytes(headList[i]).Length, 10);}sw.BeginWorkSheet();sw.BeginSetColWidth();for (int i = 0; i < headList.Count; i++){sw.SetColWidthBeforeSheet(i, arrColWidth[i]+1);}sw.EndSetColWidth();sw.BeginSheet();// 表头sw.InsertRowWithheight(0, headList.Count, 15);int styleIndex = styles["sheet_title"].Index;for (int i = 0, len = headList.Count; i < len; i++){sw.CreateCell(i, headList[i], styleIndex);}sw.EndWithheight();//int pageIndex = 1;// 查询起始页bool hasNextRow;// 是否还有数据,循环条件int flag = 0;//⽤于多批数据的处理int rownum = 1;//总⾏数do{// 开始分页查询// 导出查询改为分页查询⽅式,替代原有queryExportResult()⽅法DataPackage data = querySerivce(pageIndex, flag);if (!data.IsSucess) return false;if(flag==0 || data.Flag==0) flag = data.Flag;if (flag != 0 && flag != data.Flag){flag = data.Flag;pageIndex = 1;hasNextRow = true;continue;}var dt = data.Table;if (dt != null && dt.Rows.Count > 0){int cellIndex;foreach (DataRow row in dt.Rows){cellIndex = 0;sw.InsertRow(rownum);#region填充内容foreach (DataColumn column in dt.Columns){string drValue = row[column].ToString();if (drValue.IsNullOrWiteSpace()){sw.CreateCell(cellIndex, "", stringStyle.Index);}else{switch (column.DataType.ToString()){case"System.DateTime"://⽇期类型DateTime.TryParse(drValue, out DateTime dateV);sw.CreateCell(cellIndex, dateV, dateStyle.Index);break;case"System.Int16"://整型case"System.Int32":case"System.Int64":case"System.Byte":int.TryParse(drValue, out int intV);sw.CreateCell(cellIndex, intV, longStyle.Index);break;case"System.Decimal"://浮点型case"System.Double":double.TryParse(drValue, out double doubV);sw.CreateCell(cellIndex, doubV, doubleStyle.Index);break;case"System.DBNull"://空值处理sw.CreateCell(cellIndex, "", stringStyle.Index);break;default:sw.CreateCell(cellIndex, drValue.Replace("<", "<").Replace(">", ">"), stringStyle.Index);break;}}cellIndex++;}#endregionsw.EndRow();if (rownum % FlushCnt == 0){output.Flush();}rownum++;}ProgressShow?.Invoke(TotalCnt += rownum - 1);hasNextRow = true;pageIndex++;}else{hasNextRow = false;}GC.Collect();} while (hasNextRow);sw.EndSheet();sw.EndWorkSheet();return true;}///<summary>///创建Excel样式///</summary>///<param name="wb"></param>///<returns></returns>private static Dictionary<string, XSSFCellStyle> CreateStyles(XSSFWorkbook wb){Dictionary<string, XSSFCellStyle> stylesMap = new Dictionary<string, XSSFCellStyle>(); IDataFormat fmt = wb.CreateDataFormat();ICellStyle style = wb.CreateCellStyle();style.Alignment = HorizontalAlignment.Left;style.VerticalAlignment = VerticalAlignment.Center;stylesMap.Add("cell_string", (XSSFCellStyle)style);ICellStyle style2 = wb.CreateCellStyle();style2.DataFormat = fmt.GetFormat("0");style2.Alignment = HorizontalAlignment.Center;style2.VerticalAlignment = VerticalAlignment.Center;stylesMap.Add("cell_long", (XSSFCellStyle)style2);ICellStyle style3 = wb.CreateCellStyle();style3.DataFormat = fmt.GetFormat("0");style3.Alignment = HorizontalAlignment.Center;style3.VerticalAlignment = VerticalAlignment.Center;stylesMap.Add("cell_double", (XSSFCellStyle)style3);ICellStyle style4 = wb.CreateCellStyle();style4.DataFormat = fmt.GetFormat("yyyy-MM-dd HH:mm");style4.Alignment = HorizontalAlignment.Center;style4.VerticalAlignment = VerticalAlignment.Center;stylesMap.Add("cell_date", (XSSFCellStyle)style4);ICellStyle style5 = wb.CreateCellStyle();style5.FillForegroundColor = IndexedColors.Grey25Percent.Index;style5.FillPattern = FillPattern.SolidForeground;style5.Alignment = HorizontalAlignment.Center;style5.VerticalAlignment = VerticalAlignment.Center;IFont font = wb.CreateFont();font.FontHeightInPoints = 10;font.Boldweight = 700;style5.SetFont(font);stylesMap.Add("sheet_title", (XSSFCellStyle)style5);return stylesMap;}///<summary>///打包压缩///</summary>///<param name="zipfile"></param>///<param name="sheetList"></param>///<param name="output"></param>private void SubstituteAll(string zipfile, List<EntryPackage> sheetList, Stream output){using (ZipOutputStream zos = new ZipOutputStream(output)){using (ZipFile zip = new ZipFile(zipfile)){IEnumerator en = zip.GetEnumerator();while (en.MoveNext()){if (en.Current == null) continue;ZipEntry ze = (ZipEntry)en.Current;if (!sheetList.Exists(e => e.EntryPath.Contains())){zos.PutNextEntry(new ZipEntry());Stream tis = zip.GetInputStream(ze);var length = ze.Size;StreamUtils.Copy(tis, zos, null, (position) =>{ProgressShow?.Invoke(Convert.ToInt32((position / (length + 0M)) * 100));});}}foreach (var sheetEntry in sheetList){zos.PutNextEntry(new ZipEntry(sheetEntry.EntryPath));using (Stream lis = new FileStream(sheetEntry.XmlFile, FileMode.Open, FileAccess.ReadWrite)) {var length = lis.Length;StreamUtils.Copy(lis, zos, null, (position) =>{ProgressShow?.Invoke(Convert.ToInt32((position / (length + 0M)) * 100));});}}}}}///<summary>///打包压缩///</summary>///<param name="zipfile"></param>///<param name="xmlfile"></param>///<param name="entryList"></param>///<param name="output"></param>private void SubstituteAll(string zipfile, string xmlfile, string entryList, Stream output){using (ZipOutputStream zos = new ZipOutputStream(output)){using (ZipFile zip = new ZipFile(zipfile)){IEnumerator en = zip.GetEnumerator();while (en.MoveNext()){if (en.Current == null) continue;ZipEntry ze = (ZipEntry)en.Current;if (!entryList.Contains()){zos.PutNextEntry(new ZipEntry());Stream tis = zip.GetInputStream(ze);var length = ze.Size;StreamUtils.Copy(tis, zos, null, (position) =>{ProgressShow?.Invoke(Convert.ToInt32((position / (length + 0M)) * 100));});}}zos.PutNextEntry(new ZipEntry(entryList));using (Stream lis = new FileStream(xmlfile, FileMode.Open, FileAccess.ReadWrite)){var length = lis.Length;StreamUtils.Copy(lis, zos, null, (position) =>{。
Java通过导出超大Excel文件解决内存溢出问题
Java通过导出超⼤Excel⽂件解决内存溢出问题前⾔将业务数据导出到Excel表中,导出任务数据量较⼤时,导出的项⽬就会内存溢出,本⽂通过Java操作Poi的SXSSFWorkbook 类进⾏导出,解决内存溢出问题。
1.采⽤Poi中的SXSSFWorkbook在实现excel导出时,在数据量过⼤的情况下,总是容易发⽣内存溢出的情况。
可以使⽤POI提供的 SXSSFWorkbook 类来避免内存溢出。
2.maven中引⼊Poi<!-- poi start --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version></dependency><!-- poi end -->3.测试过程先使⽤普通的写法测试(XSSFWorkbook),编写writeNormalExcelTest测试⽅法,写⼊的⾏数太多时,会报内存溢出(在设置-server -Xmx64m -Xms64m -Xmn32m的情况下)。
关于Java导出100万行数据到Excel的优化方案
关于Java导出100万⾏数据到Excel的优化⽅案1》场景 项⽬中需要从数据库中导出100万⾏数据,以excel形式下载并且只要⼀张sheet(打开这么⼤⽂件有多慢另说,呵呵)。
ps:xlsx最⼤容纳1048576⾏,csv最⼤容纳1048576⾏,xls最⼤容纳65536⾏,但是存放相同的数据量⽂件⼤⼩排序:xls>csv>xlsx ;xls是biff8的⼆进制⽂件,就是个B+树⽽xlsx是 xml的zip压缩⽂件。
2》常规做法 按照平常的做法,先到数据库中取数然后循环组装成⼀个list,然后⽤excel⼯具(我⽤的是POI)⽣成excel。
3》遇到的问题 1' 内存经常溢出。
2' 组装list,⽣成excel慢,50万的数据花了⼀个⼩时都没见完成。
4》解决⽅法 1' POI 改⽤ SXSSFWorkbook ⽐如SXSSFWorkbook wb = new SXSSFWorkbook(100);在内存中只保留100⾏记录,超过100就将之前的存储到磁盘⾥,2' 调整JVM 相关的参数 -Xmx.... 3' 循环中减少使⽤new,尽量复⽤;String改为StringBuffer就不说了,重点是在组装⼀⾏数据时,⼀直⽐较喜欢⽤map来拼装,但是在我功能上发现还是耗内存的,后来的GC时间太长,造成严重拖累组装数据的效率,后来发现由HashMap改为⽤StringBuffer拼接⾏数据效率直接就上去了,当然指定合理的StringBuffer的起始容量效率就更好了。
ps:StringBuffer 的构造器会创建⼀个默认⼤⼩(通常是16)的字符数组。
在使⽤中,如果超出这个⼤⼩,就会重新分配内存,创建⼀个更⼤的数组,并将原先的数组复制过来,再丢弃旧的数组。
在⼤多数情况下,你可以在创建 StringBuffer的时候指定⼤⼩,这样就避免了在容量不够的时候⾃动增长,以提⾼性能。
解决大批量数据导出Excel产生内存溢出的方案
//以第一篇文档的最后一个sheet为根,以后的数据都追加在这个sheet后面
Sheet rootSheet = sheets.get(sheets.size() - 1);
int rootRows = getRowsOfSheet(rootSheet); //记录第一篇文档的行数,以后的行数在此基础上增加
records.remove(k);
LabelSSTRecord newrec = new LabelSSTRecord();
int stringid = workbook.addSSTString(new UnicodeString(oldrec.getValue()));
newrec.setRow(oldrec.getRow());
for (int i = 0; i < nSheets; i++) {
sheets[i].preSerialize();
}
int totalsize = workbook.getSize();
// pre-calculate all the sheet sizes and set BOF indexes
while(sheet.getNextRow() != null) {
rows++;
}
return rows;
}
@SuppressWarnings("deprecation")
static List<Record> getRecords(InputStream input) {
try {
POIFSFileSystem poifs = new POIFSFileSystem(input);
【Easyexcel】java导入导出超大数据量的xlsx文件解决方法
【Easyexcel】java导⼊导出超⼤数据量的xlsx⽂件解决⽅法解决⽅法:使⽤easyexcel解决超⼤数据量的导⼊导出xlsx⽂件easyexcel最⼤⽀持⾏数 1048576。
官⽹地址:GitHub地址:使⽤⽰例:Java数据类【重点是属性上的注解】:package com.proengine.domain.man.partner.bean;import com.alibaba.excel.annotation.ExcelIgnore;import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.write.style.ColumnWidth;import mon.enums.PromotionStatusEnum;import com.proengine.sdk.enums.PromotionSubTypeEnum;import java.math.BigDecimal;import java.util.Date;/*** @Author: SXD* @Description:* @Date: create in 2019/9/26 11:43*/@ColumnWidth(25)public class ProSkuSearchInfoDisplay {/*** 促销ID*/@ExcelProperty(value = "促销编码",index = 6)private String proId;/*** 参与类型*/@ExcelIgnoreprivate Integer itemType;/*** 商品sku 或商品mc* DB查询出来的值*/@ExcelIgnoreprivate String itemCode;/*** 商品sku* 最终结果值*/@ExcelProperty(value = "商品sku",index = 0)private Long sku;/*** 物料编码*/@ExcelProperty(value = "物料编码",index = 1)private String matnrCode;/*** 商品名称*/@ExcelProperty(value = "商品名称",index = 2)private String skuName;/*** 国条码*/@ExcelProperty(value = "国条码",index = 3)private String barCode;/*** 商品MC* 最终结果值*/@ExcelProperty(value = "商品MC",index = 4)private String skuMc;/*** 商品MC Name*/@ExcelIgnoreprivate String skuMcName;/*** 促销档期*/@ExcelProperty(value = "促销档期",index = 5)private String proSchedule;/*** 促销编码*/@ExcelIgnoreprivate String proCode;/*** 促销名称*/@ExcelProperty(value = "促销名称",index =7)private String proName;/*** 促销详情*/@ColumnWidth(50)@ExcelProperty(value = "促销详情",index =8)private String proDetail;/*** 促销类型*/@ExcelIgnoreprivate Integer proType;/*** 促销⼦类型*/@ExcelIgnoreprivate Integer proSubType;/*** 促销类型名称*/@ExcelProperty(value = "促销类型",index =9)private String proTypeName;/*** 促销售价单位:分*/@ExcelProperty(value = "促销售价",index =10)private Double proPrice;/*** 促销折扣值* 仅单品促销实际应⽤本字段* 单品直降 101 skuPrice-rewardValue = proPrice* 单品特价 102 proPrice = rewardValue* 单品折扣 103 skuPrice*(rewardValue/10000) = proPrice*/@ExcelIgnoreprivate Long rewardValue;/*** 商品原价单位:分*/@ExcelProperty(value = "商品原价",index =11)private Double skuPrice;/*** 促销状态*/@ExcelIgnoreprivate Integer proStatus;/*** 促销状态名称*/@ExcelProperty(value = "促销状态",index =12)private String proStatusName;/*** PO订单号暂⽆* 采销系统相关*/@ExcelIgnoreprivate String poOrderCode;/*** STO订单号暂⽆* 采销系统相关*/@ExcelIgnoreprivate String stoOrderCode;/*** 预期到店⽇暂⽆* 采销系统相关*/@ExcelIgnoreprivate Date expectedDate;/*** 促销开始时间*/@ExcelProperty(value = "促销开始时间",index =13)private Date proStartTime;/*** 促销结束时间*/@ExcelProperty(value = "促销结束时间",index =14)private Date proEndTime;/*** 单品三种折扣计算促销价格*/public void calcuProPrice(){if (skuPrice != null){if (proSubType == PromotionSubTypeEnum.SINGLE_CUT_PRICE.getValue()){ proPrice = skuPrice-rewardValue;}if (proSubType == PromotionSubTypeEnum.SINGLE_SPECIAL_PRICE.getValue()){proPrice = (double)rewardValue;}if (proSubType == PromotionSubTypeEnum.SINGLE_REBATE.getValue()){proPrice = skuPrice - BigDecimal.valueOf(skuPrice).subtract(BigDecimal.valueOf(rewardValue * skuPrice).divide(BigDecimal.valueOf(10000), 2, BigDecimal.ROUND_HALF_UP)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue }}}/*** 组装最终展⽰数据*/public void assembleParams(){proTypeName = PromotionSubTypeEnum.getDesc(proSubType);proStatusName = PromotionStatusEnum.getDesc(proStatus);proPrice = proPrice != null ? proPrice/(double)100 : null;skuPrice = skuPrice != null ? skuPrice/(double)100 : null;}public String getBarCode() {return barCode;}public void setBarCode(String barCode) {this.barCode = barCode;}public String getProTypeName() {return proTypeName;}public void setProTypeName(String proTypeName) {this.proTypeName = proTypeName;}public String getProStatusName() {return proStatusName;}public void setProStatusName(String proStatusName) {this.proStatusName = proStatusName;}public Date getProStartTime() {return proStartTime;}public void setProStartTime(Date proStartTime) {this.proStartTime = proStartTime;}public Date getProEndTime() {return proEndTime;}public void setProEndTime(Date proEndTime) {this.proEndTime = proEndTime;}public Long getRewardValue() {return rewardValue;}public void setRewardValue(Long rewardValue) {this.rewardValue = rewardValue;}public String getProId() {return proId;}public void setProId(String proId) {this.proId = proId;}public Long getSku() {if (sku == null){setSkuFromItemCode();}return sku;}public void setSkuFromItemCode(){setSku(Long.parseLong(itemCode));}public void setSku(Long sku) {this.sku = sku;}public Integer getItemType() {return itemType;}public void setItemType(Integer itemType) {this.itemType = itemType;}public String getItemCode() {return itemCode;}public void setItemCode(String itemCode) {this.itemCode = itemCode;}public String getMatnrCode() {return matnrCode;}public void setMatnrCode(String matnrCode) {this.matnrCode = matnrCode;}public String getSkuName() {return skuName;}public void setSkuName(String skuName) {this.skuName = skuName;}public String getSkuMc() {return skuMc;}public void setSkuMc(String skuMc) {this.skuMc = skuMc;}public String getSkuMcName() {return skuMcName;}public void setSkuMcName(String skuMcName) {this.skuMcName = skuMcName;}public String getProSchedule() {return proSchedule;}public void setProSchedule(String proSchedule) {this.proSchedule = proSchedule;}public String getProCode() {return proCode;}public void setProCode(String proCode) {this.proCode = proCode;}public String getProName() {return proName;}public void setProName(String proName) {this.proName = proName;}public String getProDetail() {return proDetail;}public void setProDetail(String proDetail) {this.proDetail = proDetail;}public Integer getProType() {return proType;}public void setProType(Integer proType) {this.proType = proType;}public Integer getProSubType() {return proSubType;}public void setProSubType(Integer proSubType) {this.proSubType = proSubType;}public Double getProPrice() {return proPrice;}public void setProPrice(Double proPrice) {this.proPrice = proPrice;}public Double getSkuPrice() {return skuPrice;}public void setSkuPrice(Double skuPrice) {this.skuPrice = skuPrice;}public Integer getProStatus() {return proStatus;}public void setProStatus(Integer proStatus) {this.proStatus = proStatus;}public String getPoOrderCode() {return poOrderCode;}public void setPoOrderCode(String poOrderCode) {this.poOrderCode = poOrderCode;}public String getStoOrderCode() {return stoOrderCode;}public void setStoOrderCode(String stoOrderCode) {this.stoOrderCode = stoOrderCode;}public Date getExpectedDate() {return expectedDate;}public void setExpectedDate(Date expectedDate) {this.expectedDate = expectedDate;}}View Code⽣成xlsx⽂件:private static final String UPLOAD_TEMP_FILE_NAME = "导出xlsx⽂件-%s.xlsx";private File createXlsxFile2(List<ProSkuSearchInfoDisplay> list,String recordKey){String filePath = getFilePath(recordKey);ExcelWriter excelWriter = EasyExcel.write(filePath, ProSkuSearchInfoDisplay.class).build();WriteSheet writeSheet = EasyExcel.writerSheet("促销商品数据").build();excelWriter.write(list, writeSheet);/// 千万别忘记finish 会帮忙关闭流excelWriter.finish();return new File(filePath);}/*** 获取临时⽂件路径* @return*/private String getFilePath(String recordKey){String path = ProExportSkuDataJob.class.getResource("/").getPath()+String.format(UPLOAD_TEMP_FILE_NAME, recordKey.substring(stIndexOf(":")+1)); ("dpePartner#ProExportSkuDataJob createFilePath={"+path+"}");return path;}使⽤过程中报异常和处理的⽅法:。
JeeSite的Excel导入、导出、支持大数据量,使用annotation最小化配置
JeeSite的Excel导⼊、导出、⽀持⼤数据量,使⽤annotation最⼩化配置介绍:优点:1. 简单易⽤,⽀持⼤数量导出,配置简单,代码量少。
2. ⽀持Excel 2003、2007、2010(xls、xlsx)格式。
3. ⽀持简单格式设置,对齐⽅式,排序等4. 可导出字典类型数据,⾃定义数据字段类型(例如:部门关联对象,部门名称与部门编号互转)。
5. ⽆需建⽴导⼊模板,系统⾃动⽣成。
缺点:1. 格式单⼀,⽆法导出格式⽐较复杂的表格。
2. 不能使⽤模板进⾏导⼊,导出。
使⽤⽰例:1、导出实体对象中的annotation的定义(ExcelField说明见:5、ExcelField定义说明):Java代码1. @Entity2. @Table(name = "sys_user")3. public class User extends BaseEntity {4.5. private Long id; // 编号6. ...7. ...8. ...9. private List<Role> roleList = Lists.newArrayList(); // 拥有⾓⾊列表10.11. @Id12. @ExcelField(title="ID", type=1, align=2, sort=1)13. public Long getId() {14. return id;15. }16. @ManyToOne17. @ExcelField(title="所属区域", align=2, sort=10)18. public Area getArea() {19. return area;20. }21. @ManyToOne22. @ExcelField(title="所属部门", align=2, sort=20)23. public Office getOffice() {24. return office;25. }26. @Length(min=1, max=100)27. @ExcelField(title="姓名", align=2, sort=40)28. public String getName() {29. return name;30. }31. @Length(min=0, max=100)32. @ExcelField(title="⽤户类型", align=2, sort=80, dictType="sys_user_type")33. public String getUserType() {34. return userType;35. }36. @ExcelField(title="创建时间", type=0, align=1, sort=90)37. public Date getCreateDate() {38. return createDate;39. }40. @ExcelField(title="最后登录⽇期", type=1, align=1, sort=110)41. public Date getLoginDate() {42. return loginDate;43. }44. @ManyToMany45. @ExcelField(title="拥有⾓⾊", align=1, sort=800, fieldType=RoleListType.class)46. public List<Role> getRoleList() {47. return roleList;48. }49. }2、Excel导出⽰例:Java代码1. public String exportFile(User user) {2. try {3. String fileName = "⽤户数据"+DateUtils.getDate("yyyyMMddHHmmss")+".xlsx";4. // 查询数据5. Page<User> page = systemService.findUser(new Page<User>(request, response, -1), user);6. // 1:创建Excel导出对象;2:设置数据;3:写⼊输出流;4:临时数据销毁7. new ExportExcel("⽤户数据", User.class)8. .setDataList(page.getList())9. .write(response, fileName)10. .dispose();11. return null;12. } catch (Exception e) {13. addFlashMessage("导出⽤户失败!失败信息:"+e.getMessage());14. }15. return "redirect:"+BaseController.ADMIN_PATH+"/sys/user/?repage";16. }3、Excel 导⼊⽰例:Java代码1. public String importFile(MultipartFile file) {2. try {3. int successNum = 0;4. int failureNum = 0;5. StringBuilder failureMsg = new StringBuilder();6. // 创建导⼊Excel对象7. ImportExcel ei = new ImportExcel(file, 1, 0);8. // 获取传⼊Excel⽂件的数据,根据传⼊参数类型,⾃动转换为对象9. List<User> list = ei.getDataList(User.class);10. // 遍历数据,保存数据11. for (User user : list){12. try{13. if ("true".equals(checkLoginName("", user.getLoginName()))){14. user.setPassword(SystemService.entryptPassword("123456"));15. BeanValidators.validateWithException(validator, user);16. systemService.saveUser(user);17. successNum++;18. }else{19. failureMsg.append("<br/>登录名 "+user.getLoginName()+" 已存在; ");20. failureNum++;21. }22. }catch(ConstraintViolationException ex){23. failureMsg.append("<br/>登录名 "+user.getLoginName()+" 导⼊失败:");24. List<String> messageList = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");25. for (String message : messageList){26. failureMsg.append(message+"; ");27. failureNum++;28. }29. }catch (Exception ex) {30. failureMsg.append("<br/>登录名 "+user.getLoginName()+" 导⼊失败:"+ex.getMessage());31. }32. }33. if (failureNum>0){34. failureMsg.insert(0, ",失败 "+failureNum+" 条⽤户,导⼊信息如下:");35. }36. addFlashMessage("已成功导⼊ "+successNum+" 条⽤户"+failureMsg);37. } catch (Exception e) {38. addFlashMessage("导⼊⽤户失败!失败信息:"+e.getMessage());39. }40. return "redirect:"+BaseController.ADMIN_PATH+"/sys/user/?repage";41. }4、Excel 导⼊模板下载⽰例Java代码1. public String importFileTemplate() {2. try {3. String fileName = "⽤户数据导⼊模板.xlsx";4. List<User> list = Lists.newArrayList(); list.add(UserUtils.getUser(true));5. // 第三个参数设置为“2”表⽰输出为导⼊模板(1:导出数据;2:导⼊模板)6. new ExportExcel("⽤户数据", User.class, 2).setDataList(list).write(response, fileName).dispose();7. return null;8. } catch (Exception e) {9. addFlashMessage("导出⽤户失败!失败信息:"+e.getMessage());10. }11. return "redirect:"+BaseController.ADMIN_PATH+"/sys/user/?repage";12. }5、ExcelField定义说明:Java代码1. /**2. * Copyright © 2012-2013 <a href="https:///thinkgem/jeesite">JeeSite</a> All rights reserved.3. *4. * Licensed under the Apache License, Version 2.0 (the "License");5. */6. package mon.utils.excel.annotation;7.8. import ng.annotation.ElementType;9. import ng.annotation.Retention;10. import ng.annotation.RetentionPolicy;11. import ng.annotation.Target;12.13. /**14. * Excel注解定义15. * @author ThinkGem16. * @version 2013-03-1017. */18. @Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})19. @Retention(RetentionPolicy.RUNTIME)20. public @interface ExcelField {21.22. /**23. * 导出字段名(默认调⽤当前字段的“get”⽅法,如指定导出字段为对象,请填写“对象名.对象属性”,例:“”、“”)24. */25. String value() default "";26.27. /**28. * 导出字段标题29. */30. String title();31.32. /**33. * 字段类型(0:导出导⼊;1:仅导出;2:仅导⼊)34. */35. int type() default 0;36.37. /**38. * 导出字段对齐⽅式(0:⾃动;1:靠左;2:居中;3:靠右)39. */40. int align() default 0;41.42. /**43. * 导出字段字段排序(升序)44. */45. int sort() default 0;46.47. /**48. * 如果是字典类型,请设置字典的type值49. */50. String dictType() default "";51.52. /**53. * 反射类型54. */55. Class<?> fieldType() default Class.class;56.57. }。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
小结:
使用POI对文件进行合并速度较快,但有数据量的限制。
总结:方案二比较可行,但是数据量有限制,为5万条。
二、导出XML 的电子表格
导出的格式类似为纯文本,能实现大数据量的存储,并能实现分Sheet查看,且能添加简单的样式,符合项目要求。经实际测试Excel2003和Excel2007均能识别并正常打开查看。使用时间测试如表4所示,数据均测试3次取平均。
55000数据/sheet 26.8秒
59000数据/sheet 30.1秒
59500数据/sheet 发生假死机现象
60000数据/sheet 发生假死机现象
但是导出的数据为XML不是纯正的Excel文件,如使用Excel文件的xls后缀保存,打开文件会弹出警告,但不影响阅读。
注意:为了不给内存增加压力,要把a.htm源代码分成三部分:头(伪数据部分 前的代码) + 伪数据部分 + 尾(伪数据部分 后的代码)。
先把 头 写到文件,并flush。然后是 伪数据部分 ,替一条数据库里的记录就写到文件里,并flush。最后把 尾 写到文件,并flush。
等我实现了第二的方法,把代码贴出来。
大数据量导出Excel的方案 java 大excel文件
测试共同条件:
数据总数为110011条,每条数据条数为19个字段。
电脑配置为:P4 2.67GHz,1G内存。
一、POI、JXL、FastExcel比较
POI、JXL、FastExcel均为java第三方开源导出Excel的开源项目。
还有另一个文章 供参考/jjpx/blog/item/b647acadb2e9db064b36d6ae.html
导出方案一:一次性全部导出到一个Excel文件中。
实际情况均报OutOfMemery错误,以下数据为报OutOfMemery数据时,数据到的最大数据数目,如表1所示:
表1:报OutOfMemery错误时所能处理的数据量
FastExecl POI JXL
导出方案二:先分多个Excel文件将数据全部导出,然后对多个Excel文件进行合并。
首先,测试将全部数据导出所用的时间,如表2所示,数据均测试三次取平均。
表2:导出全部数据所用时间
FastExecl POI JXL
10000数据/文件 68s 33s 30s
10000数据/sheet 37465 28996 42270
5000数据/sheet 39096 31487 46270
3000数据/sheet 39000 32493 47860
小结:
多分sheet能一定程度上减少内存的使用,但是均因为程序中创建的Cell(即为Excel中的一个单元格)无法释放,消耗大量内存,导致OutOfMemery错误;JXL表现最好,创建Cell内存使用较少。
3.用jdbc访问数据库,循环遍历,每5万条,用io流写文件,格式为"xxx.xls”。
a.html的头代码+记录行代码(已经被5万条替换)+尾代码。
没有看太懂你的意思Байду номын сангаас 用html是干什么?
用java的io写txt格式的文件,大家都会吧?
其实,也可以用java的io写xls格式的文件的。关键是你得按一定的excel文件格式写,才能保证生成的是excel文件。
5000数据/文件 68s 32s 33s
3000数据/文件 59s 33s 39s
小结:
均成功导出Excel文件,原因是导出一个Excel文件,释放所占用的创建Cell的内存。
FastExecl表现最差,POI表现稳定,JXL随着数据的增大,速度一定程度上增快。
这个格式怎样得到呢?方法是这样:
你先建一个excel文件,如a.xls。填上两条伪数据。然后另存为网页,即htm格式,如a.htm。
然后,用记事本打开htm格式的a.htm,这样excel文件格式代码就暴露在你面前。
剩下的事,呵呵,就是把a.htm源代码的伪数据部分,替成数据库里的数据,然后把替换后的整个a.htm源代码,用java的io写成一个后缀为xls的文件。就打完收工了。
表4:生成全部数据所用时间
时间
10000数据/sheet 28.0秒
20000数据/sheet 30.1秒
30000数据/sheet 28.1秒
40000数据/sheet 26.5秒
50000数据/sheet 28.2秒
然后,进行整合,由于将多Excel合并成一个Excel文件的功能只有POI所有,故使用POI测试,结果如表3所示。
注:数据量大合并还会报OutOfMemery错误,故合并总数据量以5万为准。
表3:合并5万数据所用时间
时间
10000数据/文件 11s
5000数据/文件 11s
表5:合并5万数据所用时间
POI、JXL、FastExcel XML 的电子表格
导出数据格式 为纯Execl文件 为XML文件
导出数据量 小 较大
且经实际测试,在Access2007和Access2003中可通过导入外部数据的方式,将导出的XML导入进Access数据库。
三、总结
项目要求是大数据量导出Excel文件,POI、JXL、FastExcel不能完全满足要求;使用XML 的电子表格导出实现了大数据量导出,但是格式为XML不是纯正的Excel文件,为曲线救国。两种导出形式的比较,如表5所示。
导出数据能否导入Access 能 能
原文链接:/thread-46-1-1.html
tidus2005 写道
biguan 写道
我同事最近要把1000万条记录从数据库导到excel里,在我的帮助下解决了。
能否分Sheet 能 能
能否添加样式 能 能
能否添加图片 POI 能 不能
呵呵。原创的。
因每个excel最多放5万条,所以他把这1000万条记录记录放到了200个excel文件里。用时40分钟。
采用基本的jdbc技术+io流。
1.先进一个excel文件。填上要的表头和两条记录。然后另存为网页a.html。
2.用记事本打开网页a.html,就看到源代码。把源代码分成三部分:头+记录行+尾。