您的位置:首页 > 其它

POI对Excel自定义日期格式的读取

2018-02-01 22:22 731 查看
cell.getCellStyle().getDataFormat();根据这个值进行时间、日期格式的判断;

POI读取出来的结果也是有些变化的;需要在实际项目中进行确认;




时间格式的遍历:



/**
* 处理数据类型
*
* @param attributes
*/
public void setNextDataType(Attributes attributes) {
nextDataType = CellDataType.NUMBER;
formatIndex = -1;
formatString = null;
String cellType = attributes.getValue("t");
String cellStyleStr = attributes.getValue("s");
String columData = attributes.getValue("r");
if ("b".equals(cellType)) {
nextDataType = CellDataType.BOOL;
} else if ("e".equals(cellType)) {
nextDataType = CellDataType.ERROR;
} else if ("inlineStr".equals(cellType)) {
nextDataType = CellDataType.INLINESTR;
} else if ("s".equals(cellType)) {
nextDataType = CellDataType.SSTINDEX;
} else if ("str".equals(cellType)) {
nextDataType = CellDataType.FORMULA;
}
if (cellStyleStr != null) {
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = this.stylesTable.getStyleAt(styleIndex);
formatIndex = style.getDataFormat();
formatString = style.getDataFormatString();
short format=this.formatIndex;
if (format == 14 || format == 31 || format == 57 ||
format == 58 || (176 <= format && format <= 178)
|| (182 <= format && format <= 196) ||
(210 <= format && format <= 213) || (208 == format))
{ // 日期
this.formatString = "yyyy-MM-dd";
nextDataType = CellDataType.NUMBER;
} else if (format == 20 || format == 32 || format == 183 || (200 <= format && format <= 209)) { // 时间
this.formatString = "HH:mm";
nextDataType = CellDataType.NUMBER;
}
if (this.formatString == null)
{
nextDataType = CellDataType.NULL;
formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
}
}
}


package com.beyondsoft.util.base;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import com.beyondsoft.util.base.XLSXCovertCSVReader2.xssfDataType;

/**
* 抽象Excel2007读取器,excel2007的底层数据结构是xml文件,采用SAX的事件驱动的方法解析
* xml,需要继承DefaultHandler,在遇到文件内容时,事件会触发,这种做法可以大大降低
* 内存的耗费,特别使用于大数据量的文件。
* 作者:史红星
*
*/
public class Excel2007Reader extends DefaultHandler {
//共享字符串表
private   ReadOnlySharedStringsTable sharedStringsTable;
//上一次的内容
private String lastContents;
private boolean nextIsString;

// Set when V start element is seen
private boolean vIsOpen;
private int sheetIndex = -1;
private List<String> rowlist = new ArrayList<String>();
//当前行
private int curRow = 0;
//当前列
private int curCol = 0;
private int preCol = 0;     //上一列列索引
//日期标志
private boolean dateFlag;
//数字标志
private boolean numberFlag;
/**
* T元素标识
*/
private boolean isTElement;

/**
* 单元格数据类型,默认为字符串类型
*/
private CellDataType nextDataType = CellDataType.SSTINDEX;

private final DataFormatter formatter = new DataFormatter();

// 定义前一个元素和当前元素的位置,用来计算其中空的单元格数量,如A6和A8等
private String preRef = null, ref = null;

// 定义该文档一行最大的单元格数,用来补全一行最后可能缺失的单元格
private String maxRef = null;

// 定义该文档一行最小单元格,用来补全一行最后可能缺失的单元格
private Integer minIndex = null;

private short formatIndex;

private String formatString;

//首列是否为空
private boolean isRowStartNull;

/**
* 单元格
*/
private StylesTable stylesTable;

//填充字符串
private static final String CELL_FILL_STR = "@";
//列的最大位数
private static final int MAX_CELL_BIT = 3;
private IExcelRowReader rowReader;

public void setRowReader(IExcelRowReader rowReader){
this.rowReader = rowReader;
}

/**只遍历一个电子表格,其中sheetId为要遍历的sheet索引,从1开始,1-3
* @param filename
* @param sheetId
* @throws Exception
*/
public void processOneSheet(String filename,int sheetId) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader(pkg);
this.sharedStringsTable = new ReadOnlySharedStringsTable(pkg);
this.stylesTable = r.getStylesTable();
XMLReader parser = fetchSheetParser(this.sharedStringsTable);
// 根据 rId# 或 rSheet# 查找sheet
InputStream sheet2 = r.getSheet("rId"+sheetId);
sheetIndex++;
InputSource sheetSource = new InputSource(sheet2);
parser.parse(sheetSource);
sheet2.close();
}

/**
* 遍历工作簿中所有的电子表格
* @param filename
* @throws Exception
*/
public void process(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader(pkg);
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);
this.stylesTable = r.getStylesTable();
XMLReader parser = fetchSheetParser(this.sharedStringsTable);
Iterator<InputStream> sheets = r.getSheetsData();
while (sheets.hasNext()) {
curRow = 0;
sheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
}
/**
* 遍历工作簿中所有的电子表格
* @param filename
* @throws Exception
*/
public void process(InputStream filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader(pkg);
this.stylesTable = r.getStylesTable();
//this.sharedStringsTable = new ReadOnlySharedStringsTable(pkg);
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);
XMLReader parser = fetchSheetParser(strings);
Iterator<InputStream> sheets = (XSSFReader.SheetIterator)r.getSheetsData();
while (sheets.hasNext()) {
curRow = 0;
sheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
}

public XMLReader fetchSheetParser(ReadOnlySharedStringsTable sharedStringsTable)
throws SAXException {
XMLReader parser = XMLReaderFactory
.createXMLReader("org.apache.xerces.parsers.SAXParser");
this.sharedStringsTable = sharedStringsTable;
parser.setContentHandler(this);
return parser;
}
//得到列索引,每一列c元素的r属性构成为字母加数字的形式,字母组合为列索引,数字组合为行索引,
//如AB45,表示为第(A-A+1)*26+(B-A+1)*26列,45行
public int getRowIndex(String rowStr){
rowStr = rowStr.replaceAll("[^A-Z]", "");
byte[] rowAbc = rowStr.getBytes();
int len = rowAbc.length;
float num = 0;
for (int i=0;i<len;i++){
num += (rowAbc[i]-'A'+1)*Math.pow(26,len-i-1 );
}
return (int) num;
}

/**
* 单元格中的数据可能的数据类型
*/
enum CellDataType {
BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, NULL,DATE
}
/**
* 处理数据类型
*
* @param attributes
*/
public void setNextDataType(Attributes attributes) {
nextDataType = CellDataType.NUMBER;
formatIndex = -1;
formatString = null;
String cellType = attributes.getValue("t");
String cellStyleStr = attributes.getValue("s");
String columData = attributes.getValue("r");
if ("b".equals(cellType)) {
nextDataType = CellDataType.BOOL;
} else if ("e".equals(cellType)) {
nextDataType = CellDataType.ERROR;
} else if ("inlineStr".equals(cellType)) {
nextDataType = CellDataType.INLINESTR;
} else if ("s".equals(cellType)) {
nextDataType = CellDataType.SSTINDEX;
} else if ("str".equals(cellType)) {
nextDataType = CellDataType.FORMULA;
}
if (cellStyleStr != null) {
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = this.stylesTable.getStyleAt(styleIndex);
formatIndex = style.getDataFormat();
formatString = style.getDataFormatString();
short format=this.formatIndex;
if (format == 14 || format == 31 || format == 57 ||
format == 58 || (176 <= format && format <= 178)
|| (182 <= format && format <= 196) ||
(210 <= format && format <= 213) || (208 == format))
{ // 日期
this.formatString = "yyyy-MM-dd";
nextDataType = CellDataType.NUMBER;
} else if (format == 20 || format == 32 || format == 183 || (200 <= format && format <= 209)) { // 时间
this.formatString = "HH:mm";
nextDataType = CellDataType.NUMBER;
}
if (this.formatString == null)
{
nextDataType = CellDataType.NULL;
formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
}
}
}

/**
* 对解析出来的数据进行类型处理
*
* @param value
*            单元格的值(这时候是一串数字)
* @param thisStr
*            一个空字符串
* @return
*/
@SuppressWarnings("deprecation")
public String getDataValue(String value, String thisStr)
{
switch (nextDataType) {
// 这几个的顺序不能随便交换,交换了很可能会导致数据错误
case BOOL:
char first = value.charAt(0);
thisStr = first == '0' ? "FALSE" : "TRUE";
break;
case ERROR:
thisStr = "\"ERROR:" + value.toString() + '"';
break;
case FORMULA:
thisStr = '"' + value.toString() + '"';
break;
case INLINESTR:
XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());

thisStr = rtsi.toString();
rtsi = null;
break;
case SSTINDEX:
String sstIndex = value.toString();
try {
int idx = Integer.parseInt(sstIndex);
XSSFRichTextString rtss = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx));
thisStr = rtss.toString();
rtss = null;
} catch (NumberFormatException ex) {
thisStr = value.toString();
}
break;
case NUMBER:
String n = value.toString();
// 判断是否是日期格式
if (HSSFDateUtil.isADateFormat(this.formatIndex, n)) {
Double d = Double.parseDouble(n);
Date date = HSSFDateUtil.getJavaDate(d);
thisStr = formateDateToString(date);
} else if (this.formatString != null) {
thisStr = this.formatter.formatRawCellContents(
Double.parseDouble(n), this.formatIndex,
this.formatString);
} else {
thisStr = n;
}
break;
default:
thisStr = " ";

break;
}

return thisStr;
}

/**
* 字符串的填充
*
* @param str
* @param len
* @param let
* @param isPre
* @return
*/
String fillChar(String str, int len, char let, boolean isPre) {
int len_1 = str.length();
if (len_1 < len) {
if (isPre) {
for (int i = 0; i < (len - len_1); i++) {
str = let + str;
}
} else {
for (int i = 0; i < (len - len_1); i++) {
str = str + let;
}
}
}
return str;
}

public static void main(String[] args) {
String ref="C1";
String preRef="A1";
Excel2007Reader Excel2007Reader=new Excel2007Reader();
System.out.println(Excel2007Reader.countNullCell(ref,preRef));
}

/**
* 计算两个单元格之间的单元格数目(同一行)
*
* @param ref
* @param preRef
* @return
*/
public int countNullCell(String ref, String preRef) {
// excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD
String xfd = ref.replaceAll("\\d+", "");
String xfd_1 = preRef.replaceAll("\\d+", "");

xfd = fillChar(xfd, 3, '@', true);
xfd_1 = fillChar(xfd_1, 3, '@', true);

char[] letter = xfd.toCharArray();
char[] letter_1 = xfd_1.toCharArray();
int res = (letter[0] - letter_1[0]) * 26 * 26 + (letter[1] - letter_1[1]) * 26 + (letter[2] - letter_1[2]);
return res;
}

/**
* 填充空白单元格
*
* @param curCoordinate
* @param preCoordinate
*/
private void fillBlackCell(String curCoordinate, String preCoordinate, boolean isEnd) {
if (!curCoordinate.equals(preCoordinate)) {
int len = calNullCellCount(curCoordinate, preCoordinate, isEnd);
//            for (int i = 0; i < len; i++) {
//                rowCellList.add(curCell++, "");
//            }
}
}
private String formateDateToString(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化日期
return sdf.format(date);

}
/**
* 计算当前单元格和前一个单元格之间的空白单元格数量
* 如果是尾部则不减1
*
* @param curCoordinate
* @param preCoordinate
* @return
*/
private int calNullCellCount(String curCoordinate, String preCoordinate, boolean isEnd) {
// excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD
String curCellCoordinate = curCoordinate.replaceAll("\\d+", "");
String preCellCoordinate = preCoordinate.replaceAll("\\d+", "");

curCellCoordinate = fillChar(curCellCoordinate, MAX_CELL_BIT, CELL_FILL_STR);
preCellCoordinate = fillChar(preCellCoordinate, MAX_CELL_BIT, CELL_FILL_STR);

char[] cur = curCellCoordinate.toCharArray();
char[] pre = preCellCoordinate.toCharArray();

int len = (cur[0] - pre[0]) * 26 * 26 + (cur[1] - pre[1]) * 26 + (cur[2] - pre[2]);
if (!isEnd) {
len = len - 1;
}
return len;
}

/**
* 将不足指定位数的字符串补全,高位补上指定字符串
*
* @param cellCoordinate
* @param maxLen
* @param fillChar
* @return
*/
private String fillChar(String cellCoordinate, int maxLen, String fillChar) {
int coordinateLen = cellCoordinate.length();
if (coordinateLen < maxLen) {
for (int i = 0; i < (maxLen - coordinateLen); i++) {
cellCoordinate = fillChar + cellCoordinate;
}
}
return cellCoordinate;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
if ("inlineStr".equals(name) || "v".equals(name)) {
vIsOpen = true;
// Clear contents cache
lastContents = "";
}
// c => cell
else if ("c".equals(name)) {
// 前一个单元格的位置
// 当前单元格的位置
ref = attributes.getValue("r");// 设定单元格类型
this.setNextDataType(attributes);
// Figure out if the value is an index in the SST
String cellType = attributes.getValue("t");
if (cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
//当元素为t时
if("t".equals(name)){
isTElement = true;
} else {
isTElement = false;
}

// 置空
lastContents = "";
}

public void endElement(String uri, String localName, String name)
throws SAXException {
if(isTElement){
String value = lastContents.trim();
rowlist.add(curCol, value);
curCol++;
isTElement = false;
if(ref!=null&&preRef!=null)
{
preRef = ref;
}
// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
} else if ("v".equals(name)) {
// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引

String value = this.getDataValue(lastContents.trim(), "");

if (preRef==null) {
if(this.maxRef!=null&&this.getRowIndex(maxRef)>0)
{
char index_row = (char) ('A'+minIndex);
preRef=""+index_row+(curRow+1);
if(!ref.equals(preRef))
{
// 补全单元格之间的空单元格
int len = calNullCellCount(ref, preRef,false);
for (int i = 0; i <=len; i++) {
rowlist.add(curCol, "");
curCol++;
}
}
}
}
else {
if(!ref.equals(preRef)){
int len = calNullCellCount(ref, preRef,false);
for (int i = 0; i <len; i++) {
rowlist.add(curCol, "");
curCol++;
}
}
}
rowlist.add(curCol, value);
curCol++;
preRef = ref;

}else {
//如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
if (name.equals("row")) {
// 默认第一行为表头,以该行单元格数目为最大数目
if (curRow == 0) {
maxRef = ref;
minIndex=this.getRowIndex(ref)-rowlist.size();
}
// 补全一行尾部可能缺失的单元格
if (maxRef != null) {
int len = calNullCellCount(maxRef, ref,true);
for (int i = 0; i <len; i++) {
rowlist.add(curCol, "");
curCol++;
}
}
rowReader.getRows(sheetIndex,curRow,rowlist);
rowlist.clear();
curRow++;
curCol = 0;
//preCol = 0;
preRef = null;
ref = null;
//isRowStartNull=false;
}
}

}

@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 得到单元格内容的值
if (this.vIsOpen) {
lastContents += new String(ch, start, length);
}

}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: