最近在做一个项目,关于excel的导出问题,上网查了很多,最后自己整理并编写了关于模板导出的方法,可能会有一些局限性,但是对于简单的模板导出功能是可以实现的,先留下笔记,以供日后参考!思路其实很简单,主要分为:(1)读取模板excel(2)循环模板excel的每一行,将对应的标签替换成对应的数值
第一,模板如下:
导出后如下图所示:
第二,直接上代码吧
1.控制层(controller层)中主要是模板的路径问题,需要特别注意下!模板的位置如图:
具体的代码如下:
/**
* 列表导出逻辑
* @Title: excelExp
* @param voiceLandingBaseinfo
* @param request
* @param response
* @param model 设定文件
* @return void 返回类型
* @author duyp
* @date 2018年8月24日 下午2:55:23
*
*/
@RequestMapping(value = {"excelExp"})
public void excelExp(MsgCbmSpecialprovisions msgCbmSpecialprovisions,MsgCbmBaseinfo msgCbmBaseinfo, HttpServletRequest request,
HttpServletResponse response, Model model) {
try {
// 查询满足条件的业务建档信息
String id=request.getParameter("id");
msgCbmSpecialprovisions.setRefid(id);
Map<String, String> map = msgCbmSpecialprovisionsService.getExpList(msgCbmSpecialprovisions,msgCbmBaseinfo);
response.setContentType("application/OCTET-STREAM");
String filename = CommonUtil.encodeChineseDownloadFileName(request, Constants.EXP_EXCEL_NAME10);
response.setHeader("Content-Disposition", "attachment;filename=" + filename);
OutputStream out = response.getOutputStream();
String excelModelPath =request.getSession().getServletContext().getRealPath("")+ "/excelmodel/msgCbmSpecialprovisions.xls"; //这个是我的excel模板
ExcelUtilAddByDu.replaceModelNew(excelModelPath, 0, map, out);
} catch (IOException e) {
e.printStackTrace();
}
}
2,服务层(service层)代码
/**
*导出信息组装
* @Title: getExpList
* @param msgCbmSpecialprovisions
* @return 设定文件
* @return Map<String,String> 返回类型
* @author duyp
* @date 2018年10月18日 下午2:55:58
*
*/
public Map<String, String> getExpList(MsgCbmSpecialprovisions msgCbmSpecialprovisions,MsgCbmBaseinfo msgCbmBaseinfo){
//查找需要导出的信息
MsgCbmSpecialprovisions objEntity=findListByRefid(msgCbmSpecialprovisions);
Map<String, String> mapc = new HashMap<String, String>();
if(!ObjectUtils.isNullOrEmpty(objEntity)){
mapc.put("date",DateUtils.getDate("yyyy-MM-dd"));
mapc.put("sales",msgCbmBaseinfo.getSales());
mapc.put("customservice",msgCbmBaseinfo.getCustomservice());
mapc.put("customername",msgCbmBaseinfo.getCustomername());
mapc.put("customertype",msgCbmBaseinfo.getCustomertype());
mapc.put("demandBrief", StringEscapeUtils.unescapeHtml4(objEntity.getDemandBrief())); // 需求简述
mapc.put("cbmTerms", StringEscapeUtils.unescapeHtml4(objEntity.getCbmTerms())); // 合同条款
mapc.put("customerDemand", StringEscapeUtils.unescapeHtml4(objEntity.getCustomerDemand())); //客户要求
mapc.put("financialLegalOpinion", StringEscapeUtils.unescapeHtml4(objEntity.getFinancialLegalOpinion())); // 财经法务意见
mapc.put("legalOpinion", StringEscapeUtils.unescapeHtml4(objEntity.getLegalOpinion())); // 法务意见
mapc.put("upgradeDealInstruction", StringEscapeUtils.unescapeHtml4(objEntity.getUpgradeDealInstruction())); // 升级处理说明
mapc.put("upgradeDealPerson", StringEscapeUtils.unescapeHtml4(DictUtils.getDictLabelPeoples(objEntity.getUpgradeDealPerson(), ""))); // 升级处理人(自动显示为特批人)
}
return mapc;
}
3,导出excel处理的工具类如下:
/**
* 替换Excel模板文件内容 (自己写的方法,可能考虑不周,后面多多补充吧)
* @Title: replaceModelNew
* @param map 键值对存储要替换的数据
* @param sourceFilePath Excel模板文件路径
* @param sheetNum 代表第几个sheet,下标从0开始
* @param out
* @return 设定文件
* @return boolean 返回类型
* @author duyp
* @date 2018年10月18日 下午3:53:58
*
*/
public static void replaceModelNew(String sourceFilePath,int sheetNum, Map<String, String> map, OutputStream out) {
try {
POIFSFileSystem fs =new POIFSFileSystem(new FileInputStream(sourceFilePath));
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet = wb.getSheetAt(sheetNum);//获取第一个sheet里的内容
//循环map中的键值对,替换excel中对应的键的值(注意,excel模板中的要替换的值必须跟map中的key值对应,不然替换不成功)
if(!ObjectUtils.isNullOrEmpty(map)){
for(String atr:map.keySet()){
int rowNum= sheet.getLastRowNum();//该sheet页里最多有几行内容
for(int i=0;i<rowNum;i++){//循环每一行
HSSFRow row=sheet.getRow(i);
int colNum=row.getLastCellNum();//该行存在几列
for(int j=0;j<colNum;j++){//循环每一列
HSSFCell cell = row.getCell((short)j);
String str = cell.getStringCellValue();//获取单元格内容 (行列定位)
if(atr.equals(str)){
//写入单元格内容
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(map.get(atr)); //替换单元格内容
}
}
}
}
}
// 输出文件
wb.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
到此整个的模板导出方法就完事了!
下面我会贴出一些别的东西,可以直接进行测试的测试类等东西!
ExcelUtilAddByDu类
package com.thinkgem.jeesite.common.utils.excel.exportByModel;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import com.thinkgem.jeesite.common.utils.ObjectUtils;
public class ExcelUtilAddByDu {
/**
* 替换Excel模板文件内容
* @param datas 文档数据
* @param sourceFilePath Excel模板文件路径
* @param targetFilePath Excel生成文件路径
*/
public static boolean replaceModel(List<ExcelReplaceDataVO> datas, String sourceFilePath, String targetFilePath) {
boolean bool = true;
try {
POIFSFileSystem fs =new POIFSFileSystem(new FileInputStream(sourceFilePath));
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet = wb.getSheetAt(0);
for (ExcelReplaceDataVO data : datas) {
//获取单元格内容
HSSFRow row = sheet.getRow(data.getRow());
HSSFCell cell = row.getCell((short)data.getColumn());
String str = cell.getStringCellValue();
//替换单元格内容
str = str.replace(data.getKey(), data.getValue());
//写入单元格内容
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(str);
}
// 输出文件
FileOutputStream fileOut = new FileOutputStream(targetFilePath);
wb.write(fileOut);
fileOut.close();
} catch (Exception e) {
bool = false;
e.printStackTrace();
}
return bool;
}
/**
* 替换Excel模板文件内容 (主方法测试用)
* @Title: replaceModelTest
* @param sheetNum 代表第几个sheet,下标从0开始
* @param map 键值对存储要替换的数据
* @param sourceFilePath Excel模板文件路径
* @param targetFilePath Excel生成文件路径
* @return boolean 返回类型
* @author duyp
* @date 2018年10月18日 下午4:05:21
*
*/
public static boolean replaceModelTest(int sheetNum, Map<String, String> map, String sourceFilePath, String targetFilePath) {
boolean bool = true;
try {
POIFSFileSystem fs =new POIFSFileSystem(new FileInputStream(sourceFilePath));
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet = wb.getSheetAt(sheetNum);//获取第一个sheet里的内容
//循环map中的键值对,替换excel中对应的键的值(注意,excel模板中的要替换的值必须跟map中的key值对应,不然替换不成功)
if(!ObjectUtils.isNullOrEmpty(map)){
for(String atr:map.keySet()){
int rowNum= sheet.getLastRowNum();//该sheet页里最多有几行内容
for(int i=0;i<rowNum;i++){//循环每一行
HSSFRow row=sheet.getRow(i);
int colNum=row.getLastCellNum();//该行存在几列
for(int j=0;j<colNum;j++){//循环每一列
HSSFCell cell = row.getCell((short)j);
String str = cell.getStringCellValue();//获取单元格内容 (行列定位)
if(atr.equals(str)){
//写入单元格内容
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(map.get(atr)); //替换单元格内容
}
}
}
}
}
// 输出文件
FileOutputStream out = new FileOutputStream(targetFilePath);
wb.write(out);
out.close();
} catch (Exception e) {
bool = false;
e.printStackTrace();
}
return bool;
}
/**
* 替换Excel模板文件内容 (自己写的方法,可能考虑不周,后面多多补充吧)
* @Title: replaceModelNew
* @param map 键值对存储要替换的数据
* @param sourceFilePath Excel模板文件路径
* @param sheetNum 代表第几个sheet,下标从0开始
* @param out
* @return 设定文件
* @return boolean 返回类型
* @author duyp
* @date 2018年10月18日 下午3:53:58
*
*/
public static void replaceModelNew(String sourceFilePath,int sheetNum, Map<String, String> map, OutputStream out) {
try {
POIFSFileSystem fs =new POIFSFileSystem(new FileInputStream(sourceFilePath));
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet = wb.getSheetAt(sheetNum);//获取第一个sheet里的内容
//循环map中的键值对,替换excel中对应的键的值(注意,excel模板中的要替换的值必须跟map中的key值对应,不然替换不成功)
if(!ObjectUtils.isNullOrEmpty(map)){
for(String atr:map.keySet()){
int rowNum= sheet.getLastRowNum();//该sheet页里最多有几行内容
for(int i=0;i<rowNum;i++){//循环每一行
HSSFRow row=sheet.getRow(i);
int colNum=row.getLastCellNum();//该行存在几列
for(int j=0;j<colNum;j++){//循环每一列
HSSFCell cell = row.getCell((short)j);
String str = cell.getStringCellValue();//获取单元格内容 (行列定位)
if(atr.equals(str)){
//写入单元格内容
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(map.get(atr)); //替换单元格内容
}
}
}
}
}
// 输出文件
wb.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试类TestExcelReplace
package com.thinkgem.jeesite.common.utils.excel.exportByModel;
import java.util.HashMap;
import java.util.Map;
public class TestExcelReplace {
public static void main(String[] args) {
//原始的方法如下,我觉得不灵活,后面进行了改造
List<ExcelReplaceDataVO> datas = new ArrayList<ExcelReplaceDataVO>();
// 找到第14行第2列的company,用"XXX有限公司"替换掉company
ExcelReplaceDataVO vo1 = new ExcelReplaceDataVO();
vo1.setRow(1);
vo1.setColumn(1);
vo1.setKey("company");
vo1.setValue("XXX有限公司");
// 找到第5行第2列的content,用"aa替换的内容aa"替换掉content
ExcelReplaceDataVO vo2 = new ExcelReplaceDataVO();
vo2.setRow(1);
vo2.setColumn(3);
vo2.setKey("content");
vo2.setValue("aa替换的内容aa");
datas.add(vo1);
datas.add(vo2);
// d:\\template.xls为Excel模板文件,d:\\test.xls为程序根据Excel模板文件生成的新文件
ExcelUtil.replaceModel(datas, "d:\\test.xls", "d:\\test2.xls");
//改造后的测试方法
Map<String, String> map=new HashMap<String, String>();
map.put("company", "1");
map.put("content", "2");
ExcelUtilAddByDu.replaceModelTest(0,map, "d:\\test.xls", "d:\\test3.xls");
}
}
中间的实体类ExcelReplaceDataVO
package com.thinkgem.jeesite.common.utils.excel.exportByModel;
/**
* Excel替换内容存储对象
*
* @author Administrator
*
*/
public class ExcelReplaceDataVO {
private int row;// Excel单元格行
private int column;// Excel单元格列
private String key;// 替换的关键字
private String value;// 替换的文本
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getColumn() {
return column;
}
public void setColumn(int column) {
this.column = column;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
谨以此文章献给有帮助的人,当然了,注释中可以看出来,我有参考别人的文章,但是它的不灵活,我在此基础上进行了改造,确切的说是全部重写了方法,方便使用。有问题欢迎指出!多多探讨才能进步嘛!!