您的位置:首页 > 编程语言 > Java开发

java 导出Excel 自定义Excel模版及表达式(毛坯)

2013-03-28 14:39 676 查看
为了满足用户Excel报表多变的需求,研究自定义Excel模版及表达式,通过表达式中的属性值 反射 找到对应的值。

初步研究

完成以下功能:

1、单元格一对一填值

2、单独一行表达式的循环

3、遍历多个list出多个表格

4、多个sheet

留下以下问题:

1、一个单元格 同时存在表达式和静态文本

2、一个单元格 同时存在两个以上表达式

4、如何在单独一行表达式的循环中加入静态文本框

3、如何控制多行级循环

现记录在此,供自己以后参考,要解决复杂报表问题,还有待优化

public class ExcelExportAction<T extends AbstractDomain> extends
AbstractAction<T> {

// 第一个F表达式的行号
private int writeRowNum = -1;// 写list数据到excel中的行号

// private ExcelWorkCell[] excelTable ;
private ExcelWorkTable excelTable = null;
private int excelTableRow, excelTableCol;// 暂未使用
private boolean excelTableLoading = false;// 正在装载table中 暂未使用
private HSSFWorkbook workbook = null;
private HSSFDataFormat df = null;// 单元格 格式化对象

/**
* 根据模版导出 单个sheet
*
* @param filename
*            导出的文件名
* @param param
*            导出的数据参数
* @param templatePath
*            模版路径
* @throws Exception
*/
public void export(String filename, Map<String, Object> param,
String templatePath) throws Exception {
init(filename, templatePath);
buildSheet(0, param);
printExcel();
}

/**
* 根据模版导出 多个sheet
*
* @param filename
*            导出的文件名
* @param params
*            导出的数据参数 数组序号与sheet序号匹配
* @param templatePath
*            模版路径
* @throws Exception
*/
public void export(String filename, Map<String, Object>[] params,
String templatePath) throws Exception {
init(filename, templatePath);
// 循环构建sheet
for (int i = 0; i < params.length; i++) {
buildSheet(i, params[i]);
}
printExcel();
}

private void init(String filename, String templatePath) throws Exception {
setResponseHeader(filename);

FileInputStream fi = new FileInputStream(templatePath);
POIFSFileSystem fs = new POIFSFileSystem(fi);
workbook = new HSSFWorkbook(fs);

df = workbook.createDataFormat();
}

/**
* 设置响应头
*
* @param filename
*            导出的文件名
*/
public void setResponseHeader(String filename) throws Exception {
// response.setContentType("application/msexcel;charset=UTF-8");
// //两种方法都可以
response.setContentType("application/octet-stream;charset=iso-8859-1");
response.setHeader("Content-Disposition", "attachment;filename="
+ java.net.URLEncoder.encode(filename, "UTF-8"));
// 客户端不缓存
response.addHeader("Pargam", "no-cache");
response.addHeader("Cache-Control", "no-cache");
}

private void buildSheet(int sheetIndex, Map<String, Object> param)
throws Exception {
HSSFRow row = null;// 行
HSSFCell cell = null;// 列

// 2、取得Sheet
if (sheetIndex > workbook.getNumberOfSheets() - 1) {// 如果sheet号大于excel的sheet数量
// 返回
return;
}
HSSFSheet sheet = workbook.getSheetAt(sheetIndex);

// 3、遍历sheet 解析表达式
for (int i = 0; i <= sheet.getLastRowNum(); i++) {// 遍历行 base 0
row = sheet.getRow(i);// 取得行
if (row == null) {
i++;
continue;
}

for (int j = 0; j < row.getLastCellNum(); j++) {// 遍历列 base 1
cell = row.getCell(j);
if (null != cell) {
String cellValue = getValue(cell);
// 判断是否为表达式 并 取字段名
Pattern pattern_ = Pattern
.compile("\\$([PF])\\{(\\w+[\\.\\w]*)\\}");
Matcher matcher_ = pattern_.matcher(cellValue);

if (matcher_.find()) { // 是表达式
// 创建单元格属性对象workcell 存放表达式的信息
ExcelWorkCell workcell = new ExcelWorkCell();
workcell.setHssfCell(cell);
String fieldType = matcher_.group(1);// 字段类型 F P
workcell.setParam(matcher_.group(2));
// 取表达式的其他信息
Pattern pattern = Pattern
.compile("[.](\\w+)\\(([^)]+)\\)");
Matcher matcher = pattern.matcher(cellValue);
while (matcher.find()) {
// 存放到workcell中
PropertyUtils.setProperty(workcell, matcher
.group(1), matcher.group(2));
}
// 如果是F属性,则先存放在excelTable中,最后构建
if ("F".equals(fieldType)) {
if (excelTable == null) {
excelTable = new ExcelWorkTable();
excelTable.setDataName(workcell.getList());
writeRowNum = row.getRowNum();
}
excelTable.add(workcell);
// 记住第一个F属性的行号, 表格从此行开始写入,并将此行以下的内容往下移
// if (writeRowNum == -1) {
// writeRowNum = row.getRowNum();
// }
} else {// 如果是p属性,则立即构建
buildCell(cell, workcell, param.get(workcell
.getParam()));
}
} else {// 不是表达式 保留原单元格

}
}
}
// 一行循环完 如果excelTable不为空 那么循环构建表格
if (excelTable != null) {
List data = (ArrayList) param.get(excelTable.getDataName());
if (writeRowNum + 1 <= sheet.getLastRowNum()) {
sheet.shiftRows(writeRowNum + 1, sheet.getLastRowNum(),
data.size() - 1, true, false);
}
// 根据data遍历出表格
for (int dataIndex = 0; dataIndex < data.size(); dataIndex++) {
Object t = data.get(dataIndex);

HSSFRow wirteRow = sheet.createRow(writeRowNum);
for (ExcelWorkCell workcell : excelTable) {
// 创建新的单元格
HSSFCell writeCell = wirteRow.createCell(workcell
.getHssfCell().getColumnIndex());
// 将原始单元格的样式 赋给 新的单元格
writeCell.setCellStyle(workcell.getHssfCell()
.getCellStyle());
// 构建新的单元格
buildCell(writeCell, workcell, getProperty(t, workcell
.getParam()));

// 根据groupby 合并单元格 行级别
if (StringUtils.isNotBlank(workcell.getGroupby())) {
// 如果为第一条数据 或者 本条数据的groupby对应值与前一条数据的groupby对应值不相同
// 那么创建region
if (dataIndex == 0
|| !getProperty(t, workcell.getGroupby())
.equals(
getProperty(
data
.get(dataIndex - 1),
workcell
.getGroupby()))) {
int dataIndexInner = -1;
// 从本条数据开始往后遍历 取groupby对应值相同的记录数dataIndexInner
for (dataIndexInner = dataIndex + 1; dataIndexInner < data
.size(); dataIndexInner++) {
if (!getProperty(t, workcell.getGroupby())
.equals(
getProperty(
data
.get(dataIndexInner),
workcell
.getGroupby()))) {
break;

}
}
// 创建 dataIndexInner - dataIndex - 1 合并行的region
CellRangeAddress newRegion = new CellRangeAddress(
writeRowNum,
writeRowNum
+ (dataIndexInner - dataIndex - 1),
workcell.getHssfCell().getColumnIndex(),
workcell.getHssfCell().getColumnIndex());
sheet.addMergedRegion(newRegion);
}
}
}
writeRowNum++;
}

// 表格构建完毕 表格对象置为null writeRowNum置为-1 以便存储下一张table
excelTable = null;
writeRowNum = -1;
i = i + data.size() - 1;// 行指针移到新表格以后 继续遍历行
}
}

}

/**
* 获取参数的值
*
* @param o
*            如果o为map 则从map里取值 否则反射从对象o中取值
* @param param
* @return
* @throws Exception
*/
private Object getProperty(Object o, String param) throws Exception {
if (o instanceof Map) {
Map<String, Object> map = (HashMap<String, Object>) o;
return map.get(param);
} else {
return PropertyUtils.getProperty(o, param);
}

}

/**
* 构建新的单元格
*
* @param cell
*            新单元格
* @param workcell
*            新单元格属性对象
* @param object
*            新单元格的值对象
*/
private void buildCell(HSSFCell cell, ExcelWorkCell workcell, Object object) {

// 处理type 字段类型 比如时间data或金额currency
if (StringUtils.isBlank(workcell.getType())) {// 如果没有type 直接toString()
cell.setCellValue(transNull(object));
} else if ("number".equals(workcell.getType())) {// 如果是number 以数字格式输出
if (object != null) {
cell.setCellValue(Double.parseDouble(object.toString()));
}
} else if ("date".equals(workcell.getType())) {// 如果是date 进行format
if (StringUtils.isBlank(workcell.getFormat())) {// 如果format为空
// 默认yyyy-MM-dd
workcell.setFormat("yyyy-MM-dd");
}
if (object != null) {
cell.setCellValue(new SimpleDateFormat(workcell.getFormat())
.format(object));
// Calendar cal = Calendar.getInstance();
// cal.setTime((Date)object);
// cell.setCellValue(cal);
}
} else if ("currency".equals(workcell.getType())) {// 如果是currency
// 进行format 并以数字格式输出
if (StringUtils.isBlank(workcell.getFormat())) {// 如果format为空
workcell.setFormat("#,##0.00");
}
if (object != null) {
cell.setCellValue(Double.parseDouble(object.toString()));
}
} else {// 其他不支持的type 直接toString() 可扩展
cell.setCellValue(transNull(object));
}

// 处理format 数据格式
// cell.getCellStyle().setDataFormat(df.getFormat("General"));//常规
if (StringUtils.isNotBlank(workcell.getFormat())) {// 如果format不为空
// 设置format格式
cell.getCellStyle().setDataFormat(
df.getFormat(workcell.getFormat()));
}

}

/**
* 输出xls文件
*
* @throws Exception
*/
private void printExcel() throws Exception {
workbook.write(response.getOutputStream());
response.getOutputStream().flush();
response.getOutputStream().close();
}

/**
* 将对象转换为字符串 如果对象为null 返回""
*
* @param o
* @return
*/
private String transNull(Object o) {
if (o == null) {
return "";
} else {
return o.toString();
}
}

/**
* 返回单元格的字符串值
*
* @param hssfCell
* @return
*/
private String getValue(HSSFCell hssfCell) {
if (hssfCell.getCellType() == hssfCell.CELL_TYPE_BOOLEAN) {
return String.valueOf(hssfCell.getBooleanCellValue());
} else if (hssfCell.getCellType() == hssfCell.CELL_TYPE_NUMERIC) {
return String.valueOf(hssfCell.getNumericCellValue());
} else {
return String.valueOf(hssfCell.getStringCellValue());
}
}
}


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