Excel大批量数据导出
package com.tebon.ams.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.util.SAXHelper;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @description: ${description}
* @author: dfz
* @create: 2018-12-14
**/
@Slf4j
public class XLSX2CSV {
/**
* Uses the XSSF Event SAX helpers to do most of the work
* of parsing the Sheet XML, and outputs the contents
* as a (basic) CSV.
*/
private List<String[]> rows = new ArrayList<String[]>();
private final OPCPackage xlsxPackage;
/**
* Number of columns to read starting with leftmost
*/
private int[] minColumns;
/**
* Destination for data
*/
private class SheetToCSV implements SheetContentsHandler {
private String[] record;
private int minColumns;
private int thisColumn = 0;
public SheetToCSV(int minColumns) {
super();
this.minColumns = minColumns;
}
@Override
public void startRow(int rowNum) {
record = new String[this.minColumns];
// System.out.println("################################:"+rowNum);
}
@Override
public void endRow(int rowNum) {
thisColumn = 0;
if (!ObjectUtil.isEmpty(this.record) && !ObjectUtil.isEmpty(this.record[0])) {
rows.add(this.record);
}
//一行结束要把此属性置""
preXy = "";
//System.out.println("**********************************");
}
//前一个单元格的xy
private String preXy = "";
//当前单元格的xy
private String currXy = "";
//前一个单元格的x
private String preX = "";
//当前单元格的x
private String currX = "";
//两个不为空的单元格之间隔了多少个空的单元格
private int flag = 0;
@Override
public void cell(String cellReference, String formattedValue, XSSFComment comment) {
//与判断空单元格有关
if ("".equals(preXy)) {
preXy = cellReference;
}
currXy = cellReference;
preX = preXy.replaceAll("\\d", "").trim();
currX = currXy.replaceAll("\\d", "").trim();
int preAscii = 0;
int curAscii = 0;
preAscii = excelColStrToNum(preX, preX.length());
curAscii = excelColStrToNum(currX, currX.length());
flag = curAscii - preAscii;
if (flag != 0 && flag != 1 && flag > 0) {
//isSkipCeil = true;
for (int i = 0; i < (flag - 1); i++) {
//appStr = appStr + ",";
record[thisColumn] = null;
thisColumn++;
}
}
preXy = cellReference;
if (thisColumn < this.minColumns)
record[thisColumn] = formattedValue.trim();
thisColumn++;
}
@Override
public void headerFooter(String text, boolean isHeader, String tagName) {
// Skip, no headers or footers in CSV
}
}
/**
* Creates a new XLSX -> CSV converter
*
* @param pkg The XLSX package to process
* @param minColumns The minimum number of columns to output, or -1 for no minimum
*/
public XLSX2CSV(OPCPackage pkg, int... minColumns) {
this.xlsxPackage = pkg;
this.minColumns = minColumns;
}
/**
* Parses and shows the content of one sheet
* using the specified styles and shared-strings tables.
*
* @param styles
* @param strings
* @param sheetInputStream
*/
public void processSheet(StylesTable styles, ReadOnlySharedStringsTable strings, SheetContentsHandler sheetHandler, InputStream sheetInputStream)
throws IOException, ParserConfigurationException, SAXException {
DataFormatter formatter = new DataFormatter();
InputSource sheetSource = new InputSource(sheetInputStream);
try {
XMLReader sheetParser = SAXHelper.newXMLReader();
ContentHandler handler = new XSSFSheetXMLHandler(styles, null, strings, sheetHandler, formatter, false);
sheetParser.setContentHandler(handler);
sheetParser.parse(sheetSource);
} catch (ParserConfigurationException e) {
throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
}
}
/**
* Initiates the processing of the XLS workbook file to CSV.
*
* @throws IOException
* @throws OpenXML4JException
* @throws ParserConfigurationException
* @throws SAXException
*/
public Map<Integer, List<String[]>> process() throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
Map<Integer, List<String[]>> map = new HashMap<>();
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(this.xlsxPackage);
XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
StylesTable styles = xssfReader.getStylesTable();
XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
int index = 0;
int length = 0;
while (iter.hasNext()) {
InputStream stream = iter.next();
String sheetName = iter.getSheetName();
//this.output.println();
//this.output.println(sheetName + " [index=" + index + "]:");
if (this.minColumns.length < index + 1) {
log.info("请求参数不符合sheet页数...直接退出");
return map;
}
processSheet(styles, strings, new SheetToCSV(this.minColumns[index]), stream);
stream.close();
//map.put(index, this.rows.subList(length, this.rows.size()));
length = length + this.rows.size();
map.put(index, this.rows);
this.rows = new ArrayList<String[]>();
++index;
}
return map;
}
/**
* 得到excel的记录
*
* @param excelPath
* @param minColumns 输出多少列
* @return
* @throws Exception
*/
public static Map<Integer, List<String[]>> getRecords(String excelPath, int... minColumns) throws Exception {
File xlsxFile = new File(excelPath);
if (!xlsxFile.exists()) {
System.err.println("Not found or not a file: " + xlsxFile.getPath());
return null;
}
// The package open is instantaneous, as it should be.
OPCPackage p = OPCPackage.open(xlsxFile.getPath(), PackageAccess.READ);
XLSX2CSV xlsx2csv = new XLSX2CSV(p, minColumns);
Map<Integer, List<String[]>> map = xlsx2csv.process();
p.close();
return map;
}
/**
* 得到excel的记录
*
* @param minColumns 输出多少列
* @return
* @throws Exception
*/
public static Map<Integer, List<String[]>> getRecords(File file, int... minColumns) throws Exception {
OPCPackage p = OPCPackage.open(file);
XLSX2CSV xlsx2csv = new XLSX2CSV(p, minColumns);
Map<Integer, List<String[]>> map = xlsx2csv.process();
p.close();
return map;
}
/**
* Excel列号数字与字母互换
* Excel column index begin 1
*
* @param colStr
* @param length
* @return
*/
public static int excelColStrToNum(String colStr, int length) {
int num = 0;
int result = 0;
for (int i = 0; i < length; i++) {
char ch = colStr.charAt(length - i - 1);
num = (int) (ch - 'A' + 1);
num *= Math.pow(26, i);
result += num;
}
return result;
}
public static void main(String[] args) throws Exception {
Map<Integer, List<String[]>> map = getRecords("C:\\Users\\lenovo\\Desktop\\333.xlsx", 63, 4, 4);
int preAscii = excelColStrToNum("AC", 2);
int curAscii = excelColStrToNum("Z", 1);
System.out.println(preAscii);
System.out.println(curAscii);
}
}
参考文档:https://blog.csdn.net/daiyutage/article/details/53023020
Excel大批量数据导出的更多相关文章
- 大批量数据导出到Excel的实现
在平时的项目中,将数据导出到Excel的需求是很常见的,在此对一些常见的方法做以总结,并提供一种大数据量导出的实现. OLEDB 使用OLEDB可以很方便导出Excel,思路很简单,处理时将Exc ...
- 大批量数据导出excel
有次面试时,老板问我大批量数据一次性导出会有什么问题 感谢度娘提供,感谢原博主提供 https://www.cnblogs.com/zou90512/p/3989450.html
- Java:导出Excel大批量数据的优化过程
背景 团队目前在做一个用户数据看板(下面简称看板),基本覆盖用户的所有行为数据,并生成分析报表,用户行为由多个数据来源组成(餐饮.生活日用.充值消费.交通出行.通讯物流.交通出行.医疗保健.住房物业. ...
- jxl写入excel实现数据导出功能
@RequestMapping(params = "method=export", method = RequestMethod.GET) public void exportCo ...
- Java 导出大批量数据excel(百万级)(转载)
参考资料:http://bbs.51cto.com/thread-1074293-1-1.html http://bbs.51cto.com/viewthread.ph ...
- Java实现大批量数据导入导出(100W以上) -(三)超过25列Excel导出
前面一篇文章介绍大数据量导出实现: Java实现大批量数据导入导出(100W以上) -(二)导出 这篇文章在Excel列较少时,按以上实际验证能很快实现生成.但如果列较多时用StringTemplat ...
- Java 使用stringTemplate导出大批量数据excel(百万级)
目前java框架中能够生成excel文件的的确不少,但是,能够生成大数据量的excel框架,我倒是没发现,一般数据量大了都会出现内存溢出,所以,生成大数据量的excel文件要返璞归真,用java的基础 ...
- Java实现大批量数据导入导出(100W以上) -(二)导出
使用POI或JXLS导出大数据量(百万级)Excel报表常常面临两个问题: 1. 服务器内存溢出: 2. 一次从数据库查询出这么大数据,查询缓慢. 当然也可以分页查询出数据,分别生成多个Excel打包 ...
- [django]数据导出excel升级强化版(很强大!)
不多说了,原理采用xlwt导出excel文件,所谓的强化版指的是实现在网页上选择一定条件导出对应的数据 之前我的博文出过这类文章,但只是实现导出数据,这次左思右想,再加上网上的搜索,终于找出方法实现条 ...
随机推荐
- Java字符串中常用字符占用字节数
java中一个char型的数据(也就是一个字符)占两个字节.而Java中常用的字符包括数字.英文字母.英文符号.中文汉字.中文符号等,若在字符串中包含里面的多种字符,它们是否都占两个字符呢?答案是否定 ...
- .NET Core----zipkin链路追踪使用
本文主要是说明core怎么使用链路追踪 一.添加nuget包 二.在Startup中添加配置 /// <summary> /// 注册zipkinTrace /// </summar ...
- 学习笔记_J2EE_SpringMVC_02_注解配置
SpringMVC注解配置 1.测试环境: 名称 版本 备注 操作系统 Windows10 专业版1809X64 WEB服务器 Tomcat 8.5 X64 浏览器 Google Chrome ...
- python-os创建文件夹-create_dir_if_not_exist.py
#!/bin/usr/env python3 __author__ = 'nxz' import os import argparse MESSAGE = '%s 文件夹已经存在' def creat ...
- EF core的模型映射
在EF core里,可以通过实现IEntityTypeConfiguration来进行映射. 一.官网文档 https://docs.microsoft.com/en-us/ef/core/what- ...
- 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)
需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...
- RabbitMQ通过Exchange.Direct、同一个队列绑定不同的routekey实现不同的消费
通过消费者去进行Exchange和Queue通过不同的RouteKey进行绑定 消费者1: static void Main(string[] args) { ConnectionFactory fa ...
- OpenSSL MD5 API
#include <stdlib.h> #define _GNU_SOURCE /* for getline API */ #include <stdio.h> /* Open ...
- POSIX信号量
DESCRIPTION POSIX 信号量允许进程间和线程间同步他们的操作. 一个信号量是一个整型(integer),其值不能小于0. 信号量允许2中操作:给信号量的值加1(sem_post); 给信 ...
- SourceTree推送分支时遇到ArgumentException encountered错误的解决办法
下载并安装: https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases/tag/v1.17.2 然后重新推送即可 ...