————————————HSSF、XSSF、SXSSF的比较——————————
HSSF是POI工程对Excel 97(-2007)文件操作的纯Java实现
XSSF是POI工程对Excel 2007 OOXML (.xlsx)文件操作的纯Java实现
从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的API----SXSSF
SXSSF通过一个滑动窗口来限制访问Row的数量从而达到低内存占用的目录,XSSF可以访问所有行。旧的行数据不再出现在滑动窗口中并变得无法访问,与此同时写到磁盘上。
在自动刷新的模式下,可以指定窗口中访问Row的数量,从而在内存中保持一定数量的Row。当达到这一数量时,在窗口中产生新的Row数据,并将低索引的数据从窗口中移动到磁盘中。
或者,滑动窗口的行数可以设定成自动增长的。它可以根据需要周期的根据一次明确的flushRow(int keepRows)调用来进行修改。
注意:针对 SXSSF Beta 3.8下,会有临时文件产生,比如:
poi-sxssf-sheet4654655121378979321.xml
文件位置:java.io.tmpdir这个环境变量下的位置
Windows 7下是C:\Users\xxxxxAppData\Local\Temp
Linux下是 /var/tmp/
要根据实际情况,看是否删除这些临时文件
官方也提供了一些解决方式:
https://issues.apache.org/bugzilla/show_bug.cgi?id=53493
与XSSF的对比
在一个时间点上,只可以访问一定数量的数据
不再支持Sheet.clone()
不再支持公式的求值
—————————————HSSF项目操作实例————————————
——————————ExcelReader预备数据处理文件——————————
从上传的文件中读取数据并返回:
package xxxxx
import java.io.File;
import java.io.FileInputStream;
import java.sql.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.ArrayUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* 操作Excel表格的功能类
*/
public class ExcelReader {
private Sheet sheet;
private Row row;
/**
* 读取Excel表格表头的内容
* @param InputStream
* @return String 表头内容的数组
*/
public String[] readExcelTitle(File file) {
String[] title = null;
try {
Workbook wb = null;
try{
wb = new HSSFWorkbook(new FileInputStream(file));
}catch(OfficeXmlFileException e){
wb = new XSSFWorkbook(new FileInputStream(file));
}
sheet = wb.getSheetAt(0);
row = sheet.getRow(0);
// 标题总列数
int colNum = row.getPhysicalNumberOfCells();
title = new String[colNum];
for (int i = 0; i < colNum; i++) {
Cell cell = row.getCell(i);
title[i] = cell.getStringCellValue();
}
} catch (Exception e) {
e.printStackTrace();
}
return title;
}
/**
* 读取Excel所有的sheet页名字
* @param InputStream
* @return String sheet内容的数组
*/
public String[] readExcelSheetName(File file) {
String[] sheetName = null;
try {
Workbook wb = null;
try{
wb = new HSSFWorkbook(new FileInputStream(file));
}catch(OfficeXmlFileException e){
wb = new XSSFWorkbook(new FileInputStream(file));
}
int maxSheet=wb.getNumberOfSheets();
sheetName=new String[maxSheet];
for (int i = 0; i < maxSheet; i++) {
sheet=wb.getSheetAt(i);
sheetName[i]=sheet.getSheetName();
}
} catch (Exception e) {
e.printStackTrace();
}
return sheetName;
}
public static void main(String[] args) {
ExcelReader excle=new ExcelReader();
//Map> tmp=excle.readExcelContent(new File("c:/test.xls"),74,31);
Map> tmp=excle.readExcelContent(new File("c:/2007.xlsx"),74,31);
Object[] obj=tmp.keySet().toArray();
Arrays.sort(obj);
for (int i = 1; i < obj.length; i++) {
System.out.println(tmp.get(obj[i]).toString());
}
}
/**
* 读取Excel数据内容
* @param InputStream
* @return Map 包含单元格数据内容的Map对象
*/
public Map> readExcelContent(File file) {
Map> content = new HashMap>();
try {
Workbook wb = null;
try{
wb = new HSSFWorkbook(new FileInputStream(file));
}catch(OfficeXmlFileException e){
wb = new XSSFWorkbook(new FileInputStream(file));
}
sheet = wb.getSheetAt(0);
// 得到总行数
int rowNum = sheet.getLastRowNum()+1;
row = sheet.getRow(0);
int colNum = row.getPhysicalNumberOfCells();
// 正文内容应该从第二行开始,第一行为表头的标题
for (int i = 1; i < rowNum; i++) {
row = sheet.getRow(i);
if(row==null){
break;
}
List list = new ArrayList();
for (int j = 0; j < colNum; j++) {
Cell cell = row.getCell(j);
if(cell != null) {
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_NUMERIC: // 数字
if (HSSFDateUtil.isCellDateFormatted(cell)) {
//如果是date类型则 ,获取该cell的date值
list.add(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString());
} else { // 纯数字
double d = cell.getNumericCellValue();
if (d - (int) d < Double.MIN_VALUE) {
// 是否为int型
list.add(Integer.toString((int) d));
} else {
// 是否为double型
list.add(Double.toString(cell.getNumericCellValue()));
}
}
break;
case HSSFCell.CELL_TYPE_STRING: // 字符串
list.add(cell.getStringCellValue() + "");
break;
case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
list.add(cell.getBooleanCellValue() + "");
break;
case HSSFCell.CELL_TYPE_FORMULA: // 公式
list.add(cell.getCellFormula() + "");
break;
case HSSFCell.CELL_TYPE_BLANK: // 空值
list.add("");
break;
case HSSFCell.CELL_TYPE_ERROR: // 故障
list.add("");
break;
default:
list.add("");
break;
}
} else {
list.add("");
}
}
content.put(i, list);
}
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
/**
* 读取Excel数据内容 限制取多少个Cell 从0开始算
*
* @param maxRow 想要获取excel的最大长度
* @return Map 包含单元格数据内容的Map对象
*/
public Map> readExcelContent(File file,int maxRow,int maxCell) {
return this.readExcelContent(file, maxRow, maxCell, 1);
}
/**
* 读取Excel数据内容 限制取多少个Cell 从0开始算
*
* @param maxRow 想要获取excel的最大长度
* @return Map 包含单元格数据内容的Map对象
*/
public Map> readExcelContent(File file,int maxRow,int maxCell,int startRow) {
return this.readExcelContent(file, maxRow, maxCell, startRow, 0);
}
/**
*
* @param file 文件
* @param maxRow 最大行 -1为不限制
* @param maxCell 最大列 -1为不限制
* @param startRow 开始行
* @param sheetIndex 第几个sheet页
* @return
*/
public Map> readExcelContent(File file,int maxRow,int maxCell,int startRow,int sheetIndex) {
Map> content = new HashMap>();
try {
Workbook wb = null;
try{
wb = new HSSFWorkbook(new FileInputStream(file));
}catch(OfficeXmlFileException e){
wb = new XSSFWorkbook(new FileInputStream(file));
}
sheet = wb.getSheetAt(sheetIndex);
// 得到总行数、总列数
int rowNum = sheet.getLastRowNum()+1;
row = sheet.getRow(0);
int colNum = row.getPhysicalNumberOfCells();
if(maxRow==-1){
maxRow=rowNum;
}
// 正文内容应该从第二行开始,第一行为表头的标题
for (int i = startRow; i < maxRow; i++) {
row = sheet.getRow(i);
if(row==null){
break;
}
if(row.getZeroHeight()==true)
{
System.out.println("row("+(i++)+")是隐藏的");
continue;
}
List list = new ArrayList();
for (int j = 0; j < colNum; j++) {
if(maxCell!=-1&&j>maxCell){//如限制行数
break;
}
Cell cell = row.getCell(j);
if(cell != null) {
boolean isMerge = isMergedRegion(sheet, i, cell.getColumnIndex());
if(isMerge) {
String rs = getMergedRegionValue(sheet, row.getRowNum(), cell.getColumnIndex());
list.add(rs);
}else{
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_NUMERIC: // 数字
if (HSSFDateUtil.isCellDateFormatted(cell)) {
//如果是date类型则 ,获取该cell的date值
list.add(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString());
} else { // 纯数字
double d = cell.getNumericCellValue();
if (d - (int) d < Double.MIN_VALUE) {
// 是否为int型
list.add(Integer.toString((int) d));
} else {
// 是否为double型
list.add(Double.toString(cell.getNumericCellValue()));
}
}
break;
case HSSFCell.CELL_TYPE_STRING: // 字符串
list.add(cell.getStringCellValue() + "");
break;
case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
list.add(cell.getBooleanCellValue() + "");
break;
case HSSFCell.CELL_TYPE_FORMULA: // 公式
list.add(cell.getCellFormula() + "");
break;
case HSSFCell.CELL_TYPE_BLANK: // 空值
list.add("");
break;
case HSSFCell.CELL_TYPE_ERROR: // 故障
list.add("");
break;
default:
list.add("");
break;
}
}
} else {
list.add("");
}
}
content.put(i, list);
}
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
/**
* 获取单元格数据内容为字符串类型的数据
*
* @param cell Excel单元格
* @return String 单元格数据内容
*/
private String getStringCellValue(HSSFCell cell) {
String strCell = "";
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
strCell = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_NUMERIC:
strCell = String.valueOf(cell.getNumericCellValue());
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
strCell = String.valueOf(cell.getBooleanCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK:
strCell = "";
break;
default:
strCell = "";
break;
}
if (strCell.equals("") || strCell == null) {
return "";
}
if (cell == null) {
return "";
}
return strCell;
}
/**
* 是否为单元格
* @param sheet
* @param row
* @param column
* @return
*/
private boolean isMergedRegion(Sheet sheet,int row ,int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
return true;
}
}
}
return false;
}
/**
* 获取合并单元格的值
* @param sheet
* @param row
* @param column
* @return
*/
public String getMergedRegionValue(Sheet sheet ,int row , int column){
int sheetMergeCount = sheet.getNumMergedRegions();
for(int i = 0 ; i < sheetMergeCount ; i++){
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell) ;
}
}
}
return null ;
}
/**
* 获取单元格的值
* @param cell
* @return
*/
public String getCellValue(Cell cell){
if(cell == null) return " ";
if(cell.getCellType() == Cell.CELL_TYPE_STRING){
return cell.getStringCellValue();
}else if(cell.getCellType() == Cell.CELL_TYPE_BOOLEAN){
return String.valueOf(cell.getBooleanCellValue());
}else if(cell.getCellType() == Cell.CELL_TYPE_FORMULA){
return cell.getCellFormula() ;
}else if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
return String.valueOf(cell.getNumericCellValue());
}
return " ";
}
}
——————————ExcelReader数据处理文件——————————
对从表中读取的内容进行处理并进行储存:
public void uploadBosPlan() throws Exception{
StringBuffer issues=new StringBuffer();
this.ddsManage.deleteBosPlan();
ExcelReader excle=new ExcelReader();
File f=new File(filename);
saveLatestExcel(f,"latestBosPlan.xls");//保存最近的中心线文件
String[] sheetNames=excle.readExcelSheetName(f);
for (int i = 0; i < sheetNames.length; i++) {
Map> contents=excle.readExcelContent(f,-1,-1,0,i);
Object[] linenos=contents.keySet().toArray();//行数列表
if(linenos==null||linenos.length==0){
continue;
}
String sheetname=sheetNames[i];//sheet名字=
//设置数据表关键字
String[] tagInfo=new String[11];
tagInfo[0] = "date";
tagInfo[1] = "banzu_night1";
tagInfo[2] = "banzu_night2";
tagInfo[3] = "banzu_morning1";
tagInfo[4] = "banzu_morning2";
tagInfo[5] = "banzu_morning3";
tagInfo[6] = "banzu_mid1";
tagInfo[7] = "banzu_mid2";
tagInfo[8] = "banci_night";
tagInfo[9] = "banci_morning";
tagInfo[10]= "banci_mid";
CData planInfo=new CData();
for (int k = 3; k < contents.size(); k++) {//从第4行有数据的位置开始遍历
List totalNames=contents.get(k);//获取第4行
for(int j = 0;j<11;j++){//遍历每一列
try { //现将string类型转成date型 然后转成需要的类型
if(j==0){
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd", java.util.Locale.US);
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", java.util.Locale.US);
try{
Date date = sdf.parse(totalNames.get(0));
String dateString = formatter.format(date);
data.set(tagInfo[0], dateString);
}catch(Exception e){
}
}else{
data.set(tagInfo[j],totalNames.get(j));
}
} catch (Exception e) {
String errorMsg=sheetname+":"+totalNames.get(j)+"列出错";
issues.append(errorMsg);
LogAdder.PrintLog("TestLog.txt", errorMsg,e.getStackTrace());
}
}
System.out.println(data);
this.ddsManage.insertBosPlan(data);
}
}
Struts2Utils.getResponse().getWriter().print(issues.toString());
}
对数据库中采集的数据进行处理并传入到Export处理程序中:
public String exportExcel() throws Exception{
page = this.ddsManage.bosplanconfig(page, data);
List tlist = page.getResult();
String[] tagInfo=new String[11];
tagInfo[0] = "date";
tagInfo[1] = "banzu_night1";
tagInfo[2] = "banzu_night2";
tagInfo[3] = "banzu_morning1";
tagInfo[4] = "banzu_morning2";
tagInfo[5] = "banzu_morning3";
tagInfo[6] = "banzu_mid1";
tagInfo[7] = "banzu_mid2";
tagInfo[8] = "banci_night";
tagInfo[9] = "banci_morning";
tagInfo[10]= "banci_mid";
ExportexcelBosPlan export = new ExportexcelBosPlan();
export.salesprotocol(tagInfo, tlist);
return "bosplanconfig";
}
对传来的数据进行处理并存储到Excel中:
package com.csValue.exportexcel;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.Region;
import org.springside.modules.utils.web.struts2.Struts2Utils;
import ssdevframework.core.collection.CData;
public class ExportexcelBosPlan
{
public static String salesprotocol(String[] tContent, List tlist1 )
throws Exception
{
HSSFWorkbook workbook = new HSSFWorkbook(); //一个新的excel表
HSSFSheet sheet1 = workbook.createSheet("BOS_OGM计划表"); //创建sheet页 并命名
HSSFCellStyle style = workbook.createCellStyle(); //创建新的style
style.setVerticalAlignment((short)1);
style.setAlignment((short)2);
HSSFCellStyle style1 = workbook.createCellStyle(); //创建新的style1
style1.setVerticalAlignment((short)1);
style1.setAlignment((short)2);
HSSFCellStyle style2 = workbook.createCellStyle(); //创建新的style2
style2.setVerticalAlignment((short)1);
style2.setAlignment((short)2);
//sheet1内容
sheet1.addMergedRegion(new Region(0, (short)0, 0, (short)10)); // 合并的是第一行的0到length-1列
HSSFRow row = sheet1.createRow(0);
HSSFFont font = workbook.createFont(); //创建字体格式
font.setFontName("黑体");
font.setFontHeightInPoints((short)16);
font.setBoldweight((short)700);
style.setFont(font);
HSSFCell cell = row.createCell((short)0); //从此处开始是对第一合并行赋值
cell.setCellValue("全员BOS/OGM计划");
cell.setCellStyle(style);
sheet1.addMergedRegion(new Region(1, (short)0, 2, (short)0));
sheet1.addMergedRegion(new Region(1, (short)1, 2, (short)2));
sheet1.addMergedRegion(new Region(1, (short)3, 2, (short)5));
sheet1.addMergedRegion(new Region(1, (short)6, 2, (short)7));
sheet1.addMergedRegion(new Region(1, (short)8, 2, (short)10));
HSSFFont font1 = workbook.createFont(); //创建字体格式
font1.setBoldweight((short)700);
row = sheet1.createRow(1); //第2行写入表头
//第一列
cell = row.createCell((short)0);
cell.setCellType(1);
cell.setCellValue("日期/班次");
style2.setFont(font1);
cell.setCellStyle(style2);
cell = row.createCell((short)1);
cell.setCellType(1);
cell.setCellValue("夜班");
style2.setFont(font1);
cell.setCellStyle(style2);
cell = row.createCell((short)3);
cell.setCellType(1);
cell.setCellValue("早班");
style2.setFont(font1);
cell.setCellStyle(style2);
cell = row.createCell((short)6);
cell.setCellType(1);
cell.setCellValue("中班");
style2.setFont(font1);
cell.setCellStyle(style2);
cell = row.createCell((short)8);
cell.setCellType(1);
cell.setCellValue("班次");
style2.setFont(font1);
cell.setCellStyle(style2);
for (int i = 0; i < tlist1.size(); i++) { //第四行 遍历每班成员
row = sheet1.createRow((short)(i + 3));
for (int j = 0; j < tContent.length; j++) {
fun(cell, i, j, tContent[j], row, style1, tlist1);
}
}
try
{
System.out.println("BOS_OGM计划.xls");
HttpServletResponse resp = Struts2Utils.getResponse();
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
resp.setContentType("application/x-download");
resp.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("BOS_OGM计划.xls", "UTF-8"));
OutputStream out = resp.getOutputStream();
workbook.write(out);
out.close();
return "yes";
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void fun(HSSFCell cell, int k, int j, String str, HSSFRow row, HSSFCellStyle style, List list) {
cell = row.createCell((short)j); //从一列开始遍历
cell.setCellType(1);
String cellvale = ((CData)list.get(k)).getString(str);
if ((cellvale == null) || (cellvale.equals("null"))) {
cellvale = "";
}
cell.setCellValue(cellvale);
cell.setCellType(1);
cell.setCellStyle(style);
}
}