生成excel
两种方式:1.模板文件为.xls或.xlsx 2.模板文件.ftl
当然两种生成文件的方式都有各自的优点与缺点 以及技术上的不同。个人意见。本人亲自做了两种例子。
1.模板文件为.xls(.xlsx),我用的是org.apache.poi的包。优点就是:通俗易懂,生成的文件格式不会乱,不会出险兼容性问题(只要模板在原机器上能正常打开)。缺点就是:赋值麻烦,需要非常仔细。行与列要完全和数据的逻辑一一对应。
2.模板文件为.ftl ,当然对这个后缀名熟悉的小伙伴一看就知道用了 freemark引擎模板技术。优点:赋值简单,咱做java的对${}肯定很熟悉,没错,就是以这种方式赋值。 只要咱们在excel模板中提前定义号变量就OK。缺点:貌似有点多,1)生成ftl文件复杂,这里就不多做介绍;2)兼容性不太好;3)稍不注意生成的excel的格式可能就不是你想要的。
所以我推荐用poi技术来实现。说的有点多,上代码。
大家来简单看一下我的模板。
对没错,就是很多个sheet页,我需要向每个sheet页赋值。
第二个sheet页没有列表,第三个sheet页,甚至后面的20多个sheet页都是列表。
看代码。
/**
* 生成excel
* @param data 数据
* @param templateName 模板文件名称(huzhu.xlsx)
* @param generateFilePath 生成文件的路径(F:\generate\report\cwt1051577170794002\report)
* @param generateFileName 生成文件的名称(new99案(测试上海乐凡).xlsx)
* @param sourcePath 模板文件的源路径 (F:\templete)
* @return
*/
public static File generateReportPoi(TemplateHelpData data, String templateName, String generateFilePath, String generateFileName, String sourcePath){
try {
FileInputStream template = new FileInputStream(new File(sourcePath + File.separator + templateName));
File generateFile = new File(generateFilePath + File.separator + generateFileName + ".xlsx");
if (!generateFile.getParentFile().exists()){
generateFile.getParentFile().mkdirs();
}
FileOutputStream dataFile = new FileOutputStream(generateFile);
XSSFWorkbook templateWorkBook = new XSSFWorkbook(template);
XSSFWorkbook workbook = new XSSFWorkbook();
workbook = templateWorkBook;
//sheet0 sheet页 从0开始
//赋值数据 sheet1
XSSFSheet sheet1 = workbook.getSheetAt(1);
String cellValue1 = data.getHelpData2().getCellValue1();
String [] names = cellValue1.split(",");
for (int i = 0; i < names.length; i++) {
setCellValue(sheet1,1,i + 3,names[i]);
}
// setCellValue(sheet1,1,3,data.getHelpData2().getCellValue1());
setCellValue(sheet1,2,3,data.getHelpData2().getCellValue2());
Row rowD = sheet1.getRow(3 - 1);
Cell cellD = rowD.getCell(3 - 1);
cellD.setCellValue(new SimpleDateFormat("yyyy-MM-dd").parse(data.getHelpData2().getCellValue3()));
if (!StringUtils.isEmpty(data.getHelpData2().getCellValue4())){
Row rowDD = sheet1.getRow(4 - 1);
Cell cellDD = rowDD.getCell(3 - 1);
cellDD.setCellValue(new SimpleDateFormat("yyyy-MM-dd").parse(data.getHelpData2().getCellValue4()));
}
// setCellValue(sheet1,3,3,data.getHelpData2().getCellValue3());
// setCellValue(sheet1,4,3,data.getHelpData2().getCellValue4());
setCellValue(sheet1,5,3,data.getHelpData2().getCellValue5());
setCellValue(sheet1,6,3,data.getHelpData2().getCellValue6());
setCellValue(sheet1,7,3,data.getHelpData2().getCellValue7());
setCellValue(sheet1,8,3,data.getHelpData2().getCellValue8());
setCellValue(sheet1,9,3,data.getHelpData2().getCellValue9());
setCellValue(sheet1,10,3,data.getHelpData2().getCellValue10());
setCellValue(sheet1,11,3,data.getHelpData2().getCellValue11());
//后面21个sheet页 从 k + 1 个 sheet 页开始循环赋值
for (int k = 1; k < 22; k++) {
int index = 0;
List dataSheet = data.getHelpDataLists().getSheetValue(k);
XSSFSheet sheet = workbook.getSheetAt(k + 1);
int line = 2;
for (HelpDirectionLine helpDirectionLine : dataSheet) {
int lastCell = sheet.getRow(0).getPhysicalNumberOfCells();//获取每个sheet页的列数
XSSFRow row = sheet.createRow(line ++);//都从第二行开始增加
if (k == 5){//无索引列
XSSFCell cell = null;
for (int i = 1; i < lastCell + 1; i++) {
cell = row.createCell(i - 1,Cell.CELL_TYPE_STRING);
cell.setCellValue(helpDirectionLine.getColValue(i));//没有索引列 从第一列开始取值
}
}else{
for (int i = 0; i < lastCell; i++) {
XSSFCell cell = null;
if (i == 0){//索引列
cell = row.createCell(0,Cell.CELL_TYPE_NUMERIC);
cell.setCellValue(++index);
}else{
cell = row.createCell(i,Cell.CELL_TYPE_STRING);
cell.setCellValue(helpDirectionLine.getColValue(i));
}
}
}
}
}
workbook.write(dataFile);
return generateFile;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* 给单元格赋值
* @param sheet
* @param i 行 从1开始
* @param j 列 从1开始
* @param value
*/
private static void setCellValue(Sheet sheet,int i,int j,String value){
Row row = sheet.getRow(i - 1);
Cell cell = row.getCell(j - 1);
cell.setCellValue(value);
}
其实代码一看就明白,就是获取每个sheet页,然后向第i行,第j列赋值。
简单介绍写第二种实现方式:
生成.ftl文件, 就是将制作好的exel文件,另存为xml,然后格式化xml,把需要删除的删除。一下是我制作的excel模板
代码:
/**
* 根据模板 生成Excel 报告
* @param data
* @param templateName 模板名称
* @param generateFilePath 生成文件路径
* @param generateFileName 生成文件名称
* @param sourcePath 原始模板路径
* @return
*/
public static File generateReport(TemplateHelpData data, String templateName, String generateFilePath, String generateFileName, String sourcePath){
Map map = new HashMap();
map.put("surveyCompletion",data.getHelpData1().getSurveyCompletion());
map.put("cellValue1",data.getHelpData2().getCellValue1());
map.put("cellValue2",data.getHelpData2().getCellValue2());
map.put("cellValue3",data.getHelpData2().getCellValue3());
map.put("cellValue4",data.getHelpData2().getCellValue4());
map.put("cellValue5",data.getHelpData2().getCellValue5());
map.put("cellValue6",data.getHelpData2().getCellValue6());
map.put("cellValue7",data.getHelpData2().getCellValue7());
map.put("cellValue8",data.getHelpData2().getCellValue8());
map.put("cellValue9",data.getHelpData2().getCellValue9());
map.put("cellValue10",data.getHelpData2().getCellValue10());
map.put("cellValue11",data.getHelpData2().getCellValue11());
map.put("data1",data.getHelpDataLists().getDirections1());
map.put("data2",data.getHelpDataLists().getDirections2());
map.put("data3",data.getHelpDataLists().getDirections3());
map.put("data4",data.getHelpDataLists().getDirections4());
map.put("data5",data.getHelpDataLists().getDirections5());
map.put("data6",data.getHelpDataLists().getDirections6());
map.put("data7",data.getHelpDataLists().getDirections7());
map.put("data8",data.getHelpDataLists().getDirections8());
map.put("data9",data.getHelpDataLists().getDirections9());
map.put("data10",data.getHelpDataLists().getDirections10());
map.put("data11",data.getHelpDataLists().getDirections11());
map.put("data12",data.getHelpDataLists().getDirections12());
map.put("data13",data.getHelpDataLists().getDirections13());
map.put("data14",data.getHelpDataLists().getDirections14());
map.put("data15",data.getHelpDataLists().getDirections15());
map.put("data16",data.getHelpDataLists().getDirections16());
map.put("data17",data.getHelpDataLists().getDirections17());
map.put("data18",data.getHelpDataLists().getDirections18());
map.put("data19",data.getHelpDataLists().getDirections19());
map.put("data20",data.getHelpDataLists().getDirections20());
map.put("data21",data.getHelpDataLists().getDirections21());
//所有key 的value 不能为空 此处做转换
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext()){
String key = iterator.next();
Object value = map.get(key);
if (value == null) {
map.put(key,"");
}else{
String replacement = "
";//换行
if (value instanceof String){
String tempValue = value.toString();
tempValue = tempValue.replaceAll("<","<");
tempValue = tempValue.replaceAll(">",">");
tempValue = tempValue.replaceAll("\n",replacement);
map.put(key,tempValue);
} else if(value instanceof List){
List lines = (List)value;
for (HelpDirectionLine line : lines) {
Field[] fields = HelpDirectionLine.class.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
try {
Object object = field.get(line);
if (object == null){
field.set(line,"");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}else {
map.put(key,value);
}
}
}
File file = createExcel(map,templateName,generateFilePath,generateFileName,sourcePath);
return file;
}
private static File createExcel(Map dataMap,String templateName,String filePath,String fileName,String sourcePath){
try {
//创建配置实例
Configuration configuration = new Configuration();
//设置编码
configuration.setDefaultEncoding("UTF-8");
//ftl模板文件统一放至 com.lun.template 包下面
// configuration.setClassForTemplateLoading(WordUtil.class,sourcePath);
configuration.setDirectoryForTemplateLoading(new File(sourcePath));
//获取模板
Template template = configuration.getTemplate(templateName);
//输出文件
File outFile = new File(filePath+File.separator + fileName + ".xlsx");
//如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()){
outFile.getParentFile().mkdirs();
}
//将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
//生成文件
template.process(dataMap, out);
//关闭流
out.flush();
out.close();
return outFile;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
最后生成的文件: