写了一周poi了,准备把poi做一下封装,封装到一半觉得有些坑要踩,就去问了项目组里面写报表的同事,他给我展示了几种类型的报表,打消了我继续封装的想法.
因为报表一般只使用Excel,版本大多数都是2003!,遂着重说明这一块.
一个简单的excel的结构是:
一个Excel(WorkBook),
Excel有多个Sheet(表格),
每个表格都有多行(Row)
每行里面都有多列(Cell)
列里面存储数据.
理解了这个,一份简单的报表已经不是问题了.
下面开始讲解一下如何读写.
注意:
读写2003和2007的Excel使用的包是hssf
读写2010和更高的Excel使用的包是xssf
这里为了篇幅,只展示hssf
读Excel
private List<T> readExcel2003Or2007(File file) throws Throwable {
InputStream is = new FileInputStream(file);
//Excel
HSSFWorkbook workbook = new HSSFWorkbook(is);
List<T> items = new ArrayList<T>();
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
//Sheet
HSSFSheet hssfSheet = workbook.getSheetAt(i);
if (hssfSheet == null) {
continue;
}
for (int rowNum = 0; rowNum < hssfSheet.getLastRowNum(); rowNum++) {
//Row
HSSFRow hssfRow = hssfSheet.getRow(rowNum);
if (hssfRow == null) {
continue;
}
// 获取最后一个单元格+1的值
int cellNum = hssfSheet.getLastRowNum();
Map<Integer, String> cellData = new HashMap<>();
for (Integer cellIndex = 0; cellIndex < cellNum; cellIndex++) {
//Cell
HSSFCell cell = hssfRow.getCell(cellIndex);
String cellValue = this.getCellValue(cell);
cellData.put(cellIndex, cellValue);
}
T t = null;
try {
t = parseBeanToSaveData(cellNum, cellData);
} catch (Throwable e) {
e.printStackTrace();
} finally {
// 有错误在这里就关闭.
workbook.close();
}
items.add(t);
}
}
return items;
}
private void toWrite2003Or2007(File file, List<String> firstRow,
List<T> datas) throws Exception {
// TODO Auto-generated method stub
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet hssfSheet = workbook.createSheet(defaultSheetName);
// 行下标
int rowIndex = 0;
// 总列数
Integer totalCell = null;
// 列宽度
if(columnMap == null)
columnMap = new HashMap<>();
// 创建表头
if (firstRow != null && firstRow.size() > 0) {
totalCell = firstRow.size();
HSSFRow hssfRow = hssfSheet.createRow(rowIndex++);
for (int i = 0; i < firstRow.size(); i++) {
HSSFCell hssfCell = hssfRow.createCell(i);
String value = firstRow.get(i);
hssfCell.setCellValue(value);
}
}
// 获取类型
Class clazz = getClassByT();
// 写入数据
for (int i = 0; i < datas.size(); i++) {
HSSFRow hssfRow = hssfSheet.createRow(rowIndex++);
T data = datas.get(i);
// 列数不确定
int cellIndex = 0;
while (true) {
if (totalCell != null && cellIndex >= totalCell) {
// 如果有总列数据,那么单元数大于等于总列数据的时候就该停止.
break;
}
String cellName = data.getCellName(cellIndex);
if (totalCell == null && cellName == null) {
// 如果没有总列数据,并且从数据中获取的列名称没有了,那么就认为T的数据全部读取完成了.
break;
}
Object objValue = getValue(clazz, data, cellName);
String cellValue = "";
if (objValue != null) {
cellValue = objValue.toString();
}
HSSFCell hssfCell = hssfRow.createCell(cellIndex);
// 设置文本对齐方式
// hssfCell.setCellStyle();
// 检测宽度属性
if(switchWidth)
this.setColumnWidth(cellIndex, StringUtils.length(cellValue));
hssfCell.setCellValue(cellValue);
cellIndex++;
}
}
//更新每行宽度
if(switchWidth)
this.updateColumnWidth(hssfSheet);
workbook.write(file);
workbook.close();
}
这里我进行了一些简单的封装,但是觉得不太好,所以没有进行下去.