package com.cabletech.business.excel;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
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;
/**
* 根据EXCEL自动生成HTML页面的业务工具
*
* @author 杨隽 2012-06-27 创建
* @author 杨隽 2012-07-31 修改获取单元格值的方法
*
*/
public class AutoGenerateUtils {
/**
* 序号字串
*/
public static final String SEQ_STRING = "序号";
/**
* 百分比后缀
*/
public static final String PERCENT_SUFFIX = "%";
/**
* 字符宽度比
*/
public static final double CHAR_WIDTH_PERCENT = 8d / 256;
/**
* 日志输出
*/
private static Logger logger = Logger.getLogger("AutoGenerateService");
/**
* 日期格式化对象
*/
private static final DateFormat DATE_FORMAT = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
/**
* 缺省的数值格式
*/
private static final DecimalFormat DEFAULT_NUMBER_FORMAT = new DecimalFormat(
"#0.00");
/**
* 根据文件名和sheet序号自动生成表格map
*
* @param fileName
* String 文件名
* @param parameter
* AutoGenerateParameter 工作表位置参数信息
* @return Map<String, Object> 生成表格map
*/
public static Map<String, Object> autoGenerate(String fileName,
AutoGenerateParameter parameter) {
Workbook xwb = null;
try {
xwb = AutoGenerateFactory.getWorkbook(fileName);
} catch (Exception e) {
logger.error("", e);
}
Map<String, Object> map = getGenerateMap(xwb, parameter);
return map;
}
/**
* 根据工作表sheet获取表格的宽度
*
* @param sheet
* Sheet 工作表sheet
* @param rowIndex
* int 数据行索引
* @return int 表格的宽度
*/
public static int getTableWidth(Sheet sheet, int rowIndex) {
Row row = sheet.getRow(rowIndex);
int width = 0;
for (int i = 0; i < row.getLastCellNum(); i++) {
width += sheet.getColumnWidth(i);
}
width = (int) (width * CHAR_WIDTH_PERCENT);
return width;
}
/**
* 根据当前行和单元格序号获取单元格内容
*
* @param row
* Row 当前行
* @param cellIndex
* int 单元格序号
* @return String 单元格内容
*/
public static String getCellValue(Row row, int cellIndex) {
if (row == null) {
return "";
}
Cell cell = row.getCell(cellIndex);
if (cell == null) {
return "";
}
String cellValue = "";
try {
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
cellValue = cell.getStringCellValue();
}
if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
cellValue = getNumberValue(cell);
}
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
cellValue = getNumberValue(cell);
}
} catch (Exception ex) {
cellValue = " ";
logger.error("格式转换错误:");
}
return cellValue;
}
/**
* 判断行数据是否都为空
*
* @param row
* Row 指定行
* @return boolean 行数据是否都为空
*/
public static boolean isEmpty(Row row) {
if (row == null) {
return true;
}
int firstCellIndex = row.getFirstCellNum();
int lastCellIndex = row.getLastCellNum();
for (int i = firstCellIndex; i < lastCellIndex; i++) {
if (StringUtils.isNotBlank(getCellValue(row, i))) {
return false;
}
}
return true;
}
/**
* 生成单元格的数据
*
* @param sheet
* Sheet 工作表sheet
* @param rowIndex
* int 行索引
* @param colIndex
* int 列索引
* @return TableCellData
*/
public static TableCellData getTdGenerateData(Sheet sheet, int rowIndex,
int colIndex) {
Row row = sheet.getRow(rowIndex);
int width = (int) (sheet.getColumnWidth(colIndex) * CHAR_WIDTH_PERCENT);
CellRangeAddress range = getMergedRegion(sheet, rowIndex, colIndex);
if (range != null) {
if (rowIndex == range.getFirstRow()
&& colIndex == range.getFirstColumn()) {
int rowSpan = range.getLastRow() - range.getFirstRow();
int colSpan = range.getLastColumn() - range.getFirstColumn();
width = getMergeColumnWidth(sheet, range.getFirstColumn(),
range.getLastColumn());
TableCellData data = new TableCellData();
data.setRowSpan(rowSpan + 1);
data.setColSpan(colSpan + 1);
data.setWidth(width);
data.setCellValue(getCellValue(row, colIndex));
return data;
}
} else {
TableCellData data = new TableCellData();
data.setWidth(width);
data.setCellValue(getCellValue(row, colIndex));
return data;
}
return null;
}
/**
* 根据工作表对象和sheet序号自动生成表格MAP
*
* @param xwb
* Workbook 工作表对象
* @param parameter
* AutoGenerateParameter 工作表位置参数信息
* @return Map<String, Object> 生成表格MAP
*/
private static Map<String, Object> getGenerateMap(Workbook xwb,
AutoGenerateParameter parameter) {
Map<String, Object> map = new HashMap<String, Object>();
if (xwb == null) {
return map;
}
Sheet sheet = xwb.getSheetAt(parameter.getSheetIndex());
Row firstRow = sheet.getRow(parameter.getStartRow());
Row row;
int tableWidth = getTableWidth(sheet, parameter.getDataStartRow());
int startColLastIndex = getStartColLastIndex(sheet,
parameter.getStartRow(), parameter.getStartCol());
map.put("tableWidth", tableWidth);
List<List<TableCellData>> rowDataList = new ArrayList<List<TableCellData>>();
for (int i = parameter.getStartRow(); i < sheet
.getPhysicalNumberOfRows(); i++) {
row = sheet.getRow(i);
if (isEmpty(row)) {
continue;
}
List<TableCellData> cellDataList = new ArrayList<TableCellData>();
String parentCellValue = "";
for (int j = parameter.getStartCol(); j < row.getLastCellNum(); j++) {
if (j <= startColLastIndex && i >= parameter.getDataStartRow()) {
CellRangeAddress range = getMergedRegion(sheet, i, j);
if (range != null) {
String cellValue = getCellValue(
sheet.getRow(range.getFirstRow()), j);
if (StringUtils.isNotBlank(cellValue)) {
parentCellValue += cellValue;
parentCellValue += "_";
}
} else if (j == startColLastIndex) {
parentCellValue += getCellValue(row, j);
}
}
TableCellData data = getTdGenerateData(sheet, i, j);
if (data != null) {
data.setRowIndex(i - parameter.getStartRow());
data.setColIndex(j - parameter.getStartCol());
if (i > parameter.getStartRow()
&& SEQ_STRING.equals(getCellValue(firstRow, j))) {
if (getCellValue(row, j) != null) {
try {
int num = (int) Double
.parseDouble(getCellValue(row, j));
data.setCellValue(Integer.toString(num));
} catch (Exception ex) {
}
}
}
data.setColumnInputName(getCellValue(firstRow, j));
data.setParentCellValue(parentCellValue);
cellDataList.add(data);
}
}
rowDataList.add(cellDataList);
}
map.put("dataList", rowDataList);
return map;
}
/**
* 获取标题的开始列所占列的最后一列的索引
*
* @param rowIndex
* int
* @param startCol
* int
* @param sheet
* Sheet
* @return int
*/
private static int getStartColLastIndex(Sheet sheet, int rowIndex,
int startCol) {
CellRangeAddress range = getMergedRegion(sheet, rowIndex, startCol);
if (range == null) {
return 0;
}
return range.getLastColumn();
}
/**
* 获取合并的单元格信息
*
* @param sheet
* Sheet 当前工作表sheet
* @param row
* int 指定的单元格所在行
* @param column
* int 指定的单元格所在列
* @return CellRangeAddress 合并的单元格信息
*/
private static CellRangeAddress getMergedRegion(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) {
return ca;
}
}
}
return null;
}
/**
* 获取合并的单元格宽度
*
* @param sheet
* Sheet 工作表sheet
* @param firstColumn
* int 合并单元格的开始列索引
* @param lastColumn
* int 合并单元格的终止列索引
* @return int 合并的单元格宽度
*/
private static int getMergeColumnWidth(Sheet sheet, int firstColumn,
int lastColumn) {
int width = 0;
for (int i = firstColumn; i <= lastColumn; i++) {
width += sheet.getColumnWidth(i);
}
width = (int) (width * CHAR_WIDTH_PERCENT);
return width;
}
/**
* 获取单元格的数据(数值类型、日期类型和公式类型)
*
* @param cell
* Cell
* @return String
*/
private static String getNumberValue(Cell cell) {
CellStyle style = cell.getCellStyle();
String cellValue;
if (HSSFDateUtil.isCellDateFormatted(cell)) {
cellValue = DATE_FORMAT.format(cell.getDateCellValue());
} else {
String fmt = style.getDataFormatString();
double number = cell.getNumericCellValue();
if (fmt.endsWith(PERCENT_SUFFIX)) {
DecimalFormat numberFmt = new DecimalFormat(fmt);
cellValue = numberFmt.format(number);
} else {
cellValue = DEFAULT_NUMBER_FORMAT.format(number);
}
}
return cellValue;
}
}