package org.dayatang.excel;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.*;
/**
* Excel读写类。记得使用完后要调用close()方法关闭。
*
* @author yyang (<a href="mailto:gdyangyu@gmail.com">gdyangyu@gmail.com</a>)
*
*/
public class ExcelHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelHandler.class);
private static final String DATE_FORMAT = "yyyy-MM-dd";
private Workbook workbook;
private Version version;
public ExcelHandler() {
workbook = new HSSFWorkbook();
workbook.createSheet();
this.version = Version.XLS;
}
public ExcelHandler(File excelFile) {
workbook = WorkbookFactory.createWorkbook(excelFile);
this.version = Version.of(excelFile.getName());
}
public ExcelHandler(File excelFile, Version version) {
workbook = WorkbookFactory.createWorkbook(excelFile, version);
this.version = version;
}
public ExcelHandler(InputStream excelStream, Version version) {
workbook = WorkbookFactory.createWorkbook(excelStream, version);
this.version = version;
}
public Workbook getWorkbook() {
return workbook;
}
/**
* 从指定的工作表范围读取数据
*
* @param excelRange
* @return
*/
public ExcelRangeData readRange(ExcelRange excelRange) {
Sheet sheet = getSheet(excelRange);
List<Object[]> data = new ArrayList<Object[]>();
int lastRow = excelRange.getRowTo() < 0 ? getLastRowNum(sheet, excelRange) : excelRange.getRowTo();
if (lastRow < excelRange.getRowFrom()) { // 没有数据
return new ExcelRangeData(data, version, isDate1904());
}
for (int rowIndex = excelRange.getRowFrom(); rowIndex <= lastRow; rowIndex++) {
Row row = sheet.getRow(rowIndex);
Object[] rowData = new Object[excelRange.getColumnTo() - excelRange.getColumnFrom() + 1];
for (int columnIndex = excelRange.getColumnFrom(); columnIndex <= excelRange.getColumnTo(); columnIndex++) {
Cell cell = row.getCell(columnIndex, Row.CREATE_NULL_AS_BLANK);
rowData[columnIndex - excelRange.getColumnFrom()] = getCellValue(cell);
}
data.add(rowData);
}
return new ExcelRangeData(data, version, isDate1904());
}
private Sheet getSheet(ExcelRange excelRange) {
int sheetIndex = excelRange.getSheetIndex();
String sheetName = excelRange.getSheetName();
if (workbook.getNumberOfSheets() == 0) {
return workbook.createSheet("sheet1");
}
return sheetIndex < 0 ? getSheet(sheetName) : getSheet(sheetIndex);
}
private Sheet getSheet(ExcelCell excelCell) {
int sheetIndex = excelCell.getSheetIndex();
String sheetName = excelCell.getSheetName();
if (workbook.getNumberOfSheets() == 0) {
return workbook.createSheet("sheet1");
}
return sheetIndex < 0 ? getSheet(sheetName) : getSheet(sheetIndex);
}
private Sheet getSheet(int sheetIndex) {
Sheet sheet = workbook.getSheetAt(sheetIndex);
if (sheet == null) {
throw new IllegalArgumentException("Sheet index (" + sheetIndex + ") is out of range (0.." + (workbook.getNumberOfSheets() - 1) + ")");
}
return sheet;
}
private Sheet getSheet(String sheetName) {
Sheet sheet = workbook.getSheet(sheetName);
if (sheet == null) {
throw new IllegalArgumentException("Sheet name (" + sheetName + ") does not exists.)");
}
return sheet;
}
private int getLastRowNum(Sheet sheet, ExcelRange excelRange) {
int lastRowNum = sheet.getLastRowNum();
for (int row = excelRange.getRowFrom(); row <= lastRowNum; row++) {
boolean isBlankRow = true;
for (int column = excelRange.getColumnFrom(); column <= excelRange.getColumnTo(); column++) {
if (sheet.getRow(row) == null) {
return row - 1;
}
Object cellValue = getCellValue(sheet.getRow(row).getCell(column));
if (cellValue != null && StringUtils.isNotBlank(cellValue.toString())) { // 本行非空行,检验下一行
isBlankRow = false;
break;
}
}
if (isBlankRow) { // 代码进入此处说明整行为空行,
return row - 1;
}
}
return lastRowNum;
}
/**
* 从工作表的指定单元格中读取字符串数据
* @param excelCell
* @return
*/
public String readString(ExcelCell excelCell) {
return ExcelUtils.getString(readCell(excelCell));
}
/**
* 从工作表的指定单元格中读取整数数据
* @param excelCell
* @return
*/
public Integer readInt(ExcelCell excelCell) {
return ExcelUtils.getInt(readCell(excelCell));
}
/**
* 从工作表的指定单元格中读取长整数数据
* @param excelCell
* @return
*/
public Long readLong(ExcelCell excelCell) {
return ExcelUtils.getLong(readCell(excelCell));
}
/**
* 从工作表的指定单元格中读取Double数据
* @param excelCell
* @return
*/
public Double readDouble(ExcelCell excelCell) {
return ExcelUtils.getDouble(readCell(excelCell));
}
/**
* 从工作表的指定单元格中读取布尔数据
* @param excelCell
* @return
*/
public Boolean readBoolean(ExcelCell excelCell) {
return ExcelUtils.getBoolean(readCell(excelCell));
}
/**
* 从工作表的指定单元格中读取日期数据
* @param excelCell
* @return
*/
public Date readDate(ExcelCell excelCell) {
return ExcelUtils.getDate(readCell(excelCell), version, isDate1904());
}
private Object readCell(ExcelCell excelCell) {
return getCellValue(getSheet(excelCell).getRow(excelCell.getRowIndex()).getCell(excelCell.getColumnIndex()));
}
/**
* 检测Excel工作簿是否采用1904日期系统
*/
private boolean isDate1904() {
Sheet sheet = workbook.createSheet();
int sheetIndex = workbook.getSheetIndex(sheet);
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue(0.0);
boolean is1994 = isDate1904(cell);
workbook.removeSheetAt(sheetIndex);
return is1994;
}
/**
* throws an exception for non-numeric cells
*/
private static boolean isDate1904(Cell cell) {
double value = cell.getNumericCellValue();
Date date = cell.getDateCellValue();
Calendar cal = new GregorianCalendar();
cal.setTime(date);
long year1900 = cal.get(Calendar.YEAR) - 1900;
long yearEst1900 = Math.round(value / (365.25));
return year1900 > yearEst1900;
}
private Object getCellValue(Cell cell) {
if (cell == null) {
return null;
}
try {
if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
LOGGER.error("Cell content is error. Sheet: {}, row: {}, column: {}",
new Object[] { cell.getSheet().getSheetName(), cell.getRowIndex(), cell.getColumnIndex() });
return null;
}
if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
return null;
}
if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
return cell.getBooleanCellValue();
}
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
return cell.getNumericCellValue();
}
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
return cell.getStringCellValue();
}
} catch (IllegalStateException e) {
LOGGER.error(e.getLocalizedMessage());
LOGGER.error("Read cell error. Sheet: {}, row: {}, column: {}",
new Object[] { cell.getSheet().getSheetName(), cell.getRowIndex(), cell.getColumnIndex() });
throw new ExcelException(e);
}
return null;
}
/**
* 以指定ExcelCell代表的单元格为左上角,将一批数据写入工作表
*
* @param topLeftCell
* @param data
*/
public void writeRange(ExcelCell topLeftCell, List<Object[]> data) {
writeRange(getSheet(topLeftCell), topLeftCell.getRowIndex(), topLeftCell.getColumnIndex(), data);
}
private void writeRange(Sheet sheet, int rowFrom, int colFrom, List<Object[]> data) {
int rowIndex = rowFrom;
for (Object[] dataRow : data) {
Row row = sheet.createRow(rowIndex);
int columnIndex = colFrom;
for (Object cellValue : dataRow) {
Cell cell = row.createCell(columnIndex);
setCellValue(cell, cellValue);
columnIndex++;
}
rowIndex++;
}
}
/**
* 将数据写入指定的Excel单元格中。
*
* @param excelCell
* @param value
*/
public void writeCell(ExcelCell excelCell, Object value) {
Sheet sheet = getSheet(excelCell);
Row row = sheet.createRow(excelCell.getRowIndex());
Cell cell = row.createCell(excelCell.getColumnIndex());
setCellValue(cell, value);
}
private void setCellValue(Cell cell, Object data) {
if (data == null) {
cell.setCellValue("");
return;
}
if (data instanceof Date) {
cell.setCellValue((Date) data);
cell.setCellStyle(getDateStyle(DATE_FORMAT, cell.getRow().getSheet().getWorkbook()));
return;
}
if (data instanceof Boolean) {
cell.setCellValue(((Boolean) data).booleanValue());
return;
}
if (data instanceof Number) {
cell.setCellValue(((Number) data).doubleValue());
return;
}
cell.setCellValue(data.toString());
}
private CellStyle getDateStyle(String dateFormat, Workbook workbook) {
DataFormat format = workbook.createDataFormat();
CellStyle result = workbook.createCellStyle();
result.setDataFormat(format.getFormat(dateFormat));
return result;
}
/**
* 将工作簿内容输出到输出流中
* @param out 要输出到的输出流
*/
public void outputTo(OutputStream out) {
try {
workbook.write(out);
} catch (IOException e) {
throw new ExcelException(e);
}
}
/**
* 将工作簿内容输出到excel文件中
* @param file 要输出到的文件
*/
public void outputTo(File file) {
OutputStream out = null;
try {
out = new FileOutputStream(file);
workbook.write(out);
} catch (IOException e) {
throw new ExcelException(e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 获取工作簿中工作表的数量
* @return 工作表数量
*/
public int getSheetCount() {
return workbook.getNumberOfSheets();
}
/**
* 关闭Excel处理器,在内部关闭工作簿
*/
public void close() {
try {
workbook.close();
} catch (IOException e) {
throw new ExcelException("Could not close workbook!", e);
}
}
}