我是靠谱客的博主 大方星月,最近开发中收集的这篇文章主要介绍java实现excel打包下载,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

最近公司让我做一个报表的打包下载功能,以前从来没有接触过,从问了下度娘,实现其功能的方式很多,其中我找到一篇博文就写得非常好,本人也是根据博文所讲做的,但是现在找不到他的链接地址了,难过,在这里就本人所做的项目所需的功能,简单罗列下。

使用到的主要类为:

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WritableCellFormat;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;


一、首先说下业务需求:主要是实现多个报表的下载,多个报表的样式和字段长度各不相同

二、功能实现:

在service中

String path = GlobalContext.contextPath + "/uploadtemp";//这个路径为生成的excel文件临时存储地址
//整个功能实现大致分为一下几步:
 
//1、创建excel临时存储文件夹
createFile(path);
//2、生成Excel文件;
createExcelFile(reportInfo,path,type);//参数reportInfo为生成excel所需要的数据,path是excel文件临时存放的地址,type是根据业务需求所需要的参数,
//3、生成.zip文件;
FileItem fileItem = craeteZipPath(path);
//4、删除临时目录下所有的文件;
File file = new File(path);
//删除文件;
deleteExcelPath(file);
//5、重新创建文件;
file.mkdirs();

/**
* 创建文件夹;
* @param path
* @return
*/
public String createFile(String path){
File file = new File(path);
//得到路径下的文件
if(!file.exists()){
//不存在就创建文件夹
//创建文件;
boolean bol = file.mkdirs();
if(bol){
System.out.println(path+" 路径创建成功!");
}else{
System.out.println(path+" 路径创建失败!");
}
}else{
System.out.println(path+" 文件已经存在!");
}
return path;
}

/**
* 在指定目录下创建Excel文件;
* @param path
* @throws IOException
* @throws WriteException
* @throws RowsExceededException
*/
public void createExcelFile(ReportInfo reportInfo,String path,String types) throws Exception{
//删掉的都是业务条件,不需要多做解释,
<del>String date = reportInfo.getYear()+"-"+reportInfo.getMonth();//
String [] typeArr = null;
//判断是不是全选
if(SysUtils.isBlank(types)){//全选
List<CodeitemInfo> clist = codeitemMapper.listByCodesetNo("RP001");
for (CodeitemInfo codeitemInfo : clist) {</del>
//生成excel
NewExcelUtil.strategy(reportsMapper, codeitemInfo, path, date);//调用工具类,生成excel文件;其中只有path是需要的,其他都是业务条件
<del>}
}else{
typeArr = types.split(",");
for (String str : typeArr) {
if(SysUtils.isBlank(str)){
continue;
}
//excel的标题和内容-----tablename,title
CodeitemInfo codeitem = codeitemMapper.detailBy2No("RP001", str);
//生成excel
NewExcelUtil.strategy(reportsMapper, codeitem, path, date);
}
}</del>
}

/**
* 生成.zip文件; 这是关键方法
* @param path
* @throws IOException
*/
public FileItem craeteZipPath(String path) throws IOException{
FileItem fileItem = WebUtils.newFileItem("用户统计报表.zip", null);//创建zip文件
ZipOutputStream zipOutputStream = null;
zipOutputStream = new ZipOutputStream(fileItem.getOutputStream());//得到文件输出流
zipOutputStream.setEncoding("gbk");//设置编码方式
File[] files = new File(path).listFiles();
//得到path路径下已经创建的excel临时文件
FileInputStream fileInputStream = null;
byte[] buf = new byte[1024];
int len = 0;
if(files!=null && files.length > 0){
//
for(File excelFile:files){
//遍历文件
String fileName = excelFile.getName();
fileInputStream = new FileInputStream(excelFile);
//放入压缩zip包中;
zipOutputStream.putNextEntry(new ZipEntry(fileName));
//读取文件;
while((len=fileInputStream.read(buf)) >0){
zipOutputStream.write(buf, 0, len);
}
//关闭;
zipOutputStream.closeEntry();
if(fileInputStream != null){
fileInputStream.close();
}
}
}
if(zipOutputStream !=null){
zipOutputStream.close();
}
return fileItem;
}
 /**
* 删除目录下所有的文件;
* @param path
*/
public boolean deleteExcelPath(File file){
String[] files = null;
if(file != null){
files = file.list();
}
if(file.isDirectory()){
for(int i =0;i<files.length;i++){
boolean bol = deleteExcelPath(new File(file,files[i]));
if(bol){
System.out.println("删除成功!");
}else{
System.out.println("删除失败!");
}
}
}
return file.delete();
} 
NewExcelUtil工具类中的生成excel的strategy文件方法
//删除的是业务条件,不做过多解释
<pre name="code" class="java">public static void strategy(<del>ReportsMapper reportsMapper,CodeitemInfo codeitem,</del>String path<del>,String date</del>) throws Exception{
//方式一、解析xml文件
CreatExcel c = new CreatExcel();
c.execute(path, codeitem.getDesc(), date,reportsMapper);
//方式二、直接生成
//根据业务需求,这里用到了java 的反射机制,只是用了点皮毛而已,不难理解的
//简单说下为什么用到反射机制,因为业务上需要下载的多个excel表格的样式并不是一样的,因为就需要多个生成excel的模板,
//如果按照传统的if去一个一个判断得到的数据是属于哪个模板,则不利于程序的开发和维护,加大了耦合性,但是本人又没有想到更好的方法,因此用了反射
//
String classPath = GlobalContext.getProperty(codeitem.getDesc());//根据参数得到配置文件中的值,这个值就是所需要调用的java类的相对于根目录的路径
//
Class<?> onwclass = Class.forName(classPath);//创建Class对象
//
ExcelStrategy els = (ExcelStrategy) onwclass.newInstance();//得到反射的实例对象
//
<del>els.setReportsMapper(reportsMapper);</del>//调用实例对象的方法,创建excel
//
els.execute(codeitem, path, date);
}
 先说方式二,用java代码直接生成excel文件,因为报表所需要的字段非常的多,如果用java自己根据格式去写的话非常的浪费时间,基于这一点,后面我改进了生成方式,采用xml文件解析的方式,原理都是一样的,如果只是下载个简单的excel文件的话,采用方式二比较好,因为比较容易,这里先介绍方式二
ExcelStrategy 类中的代码
//定义个抽像类,所有的excel生成策略都集成此抽象类,实现抽象方法--------java反射机制所需
<pre name="code" class="java">public abstract class ExcelStrategy {
public abstract void execute(CodeitemInfo codeitem,String path,String date) throws Exception;
}

//这是一样excel的生成模板
public class DatebizttlStrategy extends ExcelStrategy {
@Override
public void execute(CodeitemInfo codeitem, String path, String date)
throws Exception {
List<ReportsInfo> reportsList = reportsMapper.findReports(codeitem.getDesc(),date);//根据查询条件得到excel内容
/**生成头*/
//excel名
String name = path+"/" + date+codeitem.getName();
//创建Excel;
File file = new File(name+".xls");
WritableWorkbook workbook = Workbook.createWorkbook(file);
//创建第一个sheet文件;
WritableSheet sheet = workbook.createSheet(codeitem.getName(), 0);
//创建标题单元格 列、行、内容、样式
Label label1 = new Label(0, 0, codeitem.getName(),ExcelFormatUtil.firstRowF());//第一行,
//添加到行中;
sheet.addCell(label1);
//合并单元格
sheet.mergeCells(0, 0, 32, 0);//第一行
Label label2 = new Label(0, 1, "(日期)
"+date.substring(0, 4)+" 年 "+date.substring(5)+" 月"+"
单位:家、笔、万元",ExcelFormatUtil.secondRowF());//第二行
sheet.addCell(label2);
sheet.mergeCells(0, 1, 32, 1);//第二行
Object[] sum = new Object[35];//设置统计数据
Integer intt = 0;
Double dout = 0.00;
/***输入内容**/
Label label = null;
int i = 0;
for (; i < reportsList.size(); i++) {
label = new Label(0 , i+4, reportsList.get(i).getRptdate(),ExcelFormatUtil.contentRowF());
sheet.addCell(label);
label = new Label(1 , i+4, String.valueOf(reportsList.get(i).getSellercnt()),ExcelFormatUtil.contentRowF());
sheet.addCell(label);
if(sum[1] != null){
intt = Integer.parseInt(sum[1].toString());
}
intt = intt + reportsList.get(i).getSellercnt();
sum[1] = intt;
sum =
NewExcelUtil.addSheetCE(2,i+4,reportsList.get(i),sum,sheet,ExcelFormatUtil.contentRowF());//提取的公共字段封装的方法
}
//写合计
sheet = NewExcelUtil.printSum(1,32,(i+4),sum,sheet);
//写入Excel表格中;
workbook.write();
//关闭流;
workbook.close();
}
到此,方式二的excel生成方式介绍完成。下面介绍下方式一
public class CreatExcel {
//	@InjectMapper
//	protected ReportsMapper reportsMapper;
public void execute(String path,String tableName,String date,ReportsMapper reportsMapper) throws Exception {
// 得到xml文件
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(this.getClass().getResourceAsStream(
"ExcelFile.xml"));
//
List<String> columns = new ArrayList<String>();
List<Map<String, String>> datecolumns = new ArrayList<Map<String,String>>();
Attribute item=null;
Element tables = document.getRootElement();
Iterator iter = tables.elementIterator();// 子节点
Element table = null;
while (iter.hasNext()) {
table = (Element) iter.next();
if (table.attributeValue("tname").equals(tableName)) {
break;
}
}
/** 生成头 */
// excel名
String name = path + "/" + table.attributeValue("desc");
// 创建Excel;
File file = new File(name + ".xls");
WritableWorkbook workbook = Workbook.createWorkbook(file);
// 创建第一个sheet文件;
WritableSheet sheet = workbook.createSheet(table.attributeValue("desc"), 0);
// 创建标题单元格 列、行、内容、样式
Label label = null;
Iterator trs = table.elementIterator();// 子节点
Element tr = null;
int j = 0,i = 0,r = 0;//列和行
while(trs.hasNext()){
tr = (Element) trs.next();
Iterator tds = tr.elementIterator();// 子节点
Element td = null;
while(tds.hasNext()){
td = (Element) tds.next();
if(SysUtils.isNonBlank(td.attributeValue("exists")) && td.attributeValue("exists").equals("1")){
String call = td.attributeValue("callspan");
String row = td.attributeValue("rowspan");
String formatName = td.attributeValue("format");
String content = td.getText();
if(content.indexOf("${data}") != -1){
content = content.replace("${data}", date.substring(0, 4)+" 年
"+date.substring(5)+" 月");
}
label = new Label(j,i,content,ExcelFormatFactory.execute(formatName));// 第一行
//添加到行中;
sheet.addCell(label);
//合并单元格
int kj = 0,ki = 0;
if(SysUtils.isNonBlank(call) && !"0".equals(call)){//合并列存在
kj = Integer.parseInt(call) -1;
}
if(SysUtils.isNonBlank(row) && !"0".equals(row)){//合并行存在
ki = Integer.parseInt(row) -1;
}
if(kj >= 0 && ki >= 0){
sheet.mergeCells(j,i, j+kj, i+ki);//第一行
}
}
//获取column属性
List attributesList = td.attributes();//获取td的所有的属性
Map<String, String> datamap = new HashMap<String, String>();
String key = null;
String value = null;
for(int a=0;a<attributesList.size();a++){
//属性的取得
item =(Attribute)attributesList.get(a);//取得所有属性的集合
if("column".equals(item.getName())){
key = item.getValue();
//
columns.add(item.getValue());
}
if("datatype".equals(item.getName())){
value = item.getValue();
}
}
if(SysUtils.isNonBlank(key)){
datamap.put(key, value);
datecolumns.add(datamap);
}
//
j++;
}
i++;
j = 0;
}
//内容----此处也用到了java反射机制,主要功能是得到excel的内容
List<Map<String, Object>> list = null;
String classPath = GlobalContext.getProperty(tableName);
Class<?> onwclass = Class.forName(classPath);
ExcelStrategy els = (ExcelStrategy) onwclass.newInstance();
els.setReportsMapper(reportsMapper);
list = els.getData(tableName, date);
String unitt = table.attributeValue("unit");//计量单位
if(SysUtils.isBlank(unitt)){
unitt = "1";
}
double unit = Double.parseDouble(unitt);
Object[] sum = new Object[50];//合计数组
//
if(list != null){
for(r = 0;r < list.size(); r++){//行
for (j = 0; j < datecolumns.size(); j++) {//列
//
Map<String, String> colums = datecolumns.get(j);//得到列名和数据类型map
Iterator<String> keyiter = colums.keySet().iterator();//
if(keyiter.hasNext()){
String mname = keyiter.next();//列名
String mvalue = colums.get(mname);//数据类型
String content = null;
//得到值
Object cont = list.get(r).get(mname);
if(cont != null){
if("int".equals(mvalue)){//值为int
Integer intt = Integer.parseInt(cont.toString());
if(sum[j] != null){
sum[j] = Integer.parseInt(sum[j].toString()) + intt;
}else{
sum[j] = intt;
}
content = intt.toString();
}else if("double".equals(mvalue)){//值为double
double d = Double.parseDouble(cont.toString());
d = new BigDecimal(d/unit).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
content = String.format("%.2f", d);
if(sum[j] != null){
sum[j] = Double.parseDouble(sum[j].toString()) + d;
}else{
sum[j] = d;
}
}else{
content = cont.toString();
sum[j] = null;
}
}
label = new Label(j,i+r,content ,ExcelFormatFactory.execute(null));
sheet.addCell(label);
}
//输出返回类型
}
}
//
}
//合计
if("true".equals(table.attributeValue("total"))){//需要合计
sheet = NewExcelUtil.printSum(1,(j-1),(i+r),sum,sheet);
}
//写入Excel表格中;
workbook.write();
//关闭流;
workbook.close();
}
}
xml文件内容,部分内容已遮挡。但是无关文件的解析
<?xml version="1.0" encoding="UTF-8"?>
<tables>
<table tname="T_RPT_DATEBIZMON" desc="<span style="background-color: rgb(0, 0, 0);">****************</span>" unit="10000" total="true">
<tr>
<td callspan="29" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">****************</span></td>
</tr>
<tr>
<td callspan="29" exists="1" format="SECOND"><span style="background-color: rgb(0, 0, 0);">***********</span>
${data}
<span style="background-color: rgb(0, 0, 0);"><span style="font-family: Arial, Helvetica, sans-serif;">*******</span><span style="font-family: Arial, Helvetica, sans-serif;"></span></td></span>
</tr>
<tr>
<td rowspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">**</span></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">**</span></td>
<td exists="0"></td>
<td rowspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">**</span></td>
<td rowspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">**</span></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">**</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">****</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">******</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">**</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">****</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">***</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">****</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">*****</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">*****</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">*****</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">******</span></td>
<td exists="0"></td>
<td callspan="2" exists="1" format="FIRST"><span style="background-color: rgb(0, 0, 0);">******</span></td>
</tr>
<tr>
<td exists="0" column="RPTDATE"></td>
<td exists="1" format="FIRST" column="SELLERCNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="BUYERCNT" datatype="int">**</td>
<td exists="0" column="CDDCNT" datatype="int"></td>
<td exists="0" column="CRECNT" datatype="int"></td>
<td exists="1" format="FIRST" column="FNCONECNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="FNCPOOLCNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="INVCONECNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="INVCPOOLCNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="INVCONEAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="INVCPOOLAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="APPONECNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="APPPOOLCNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="APPONEAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="APPPOOLAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="SENDONECNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="SENDPOOLCNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="SENDONEAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="SENDPOOLAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="SENDONEINT" datatype="double">**</td>
<td exists="1" format="FIRST" column="SENDPOOLINT" datatype="double">**</td>
<td exists="1" format="FIRST" column="BACKONECNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="BACKPOOLCNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="BACKONEAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="BACKPOOLAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="CLRONECNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="CLRPOOLCNT" datatype="int">**</td>
<td exists="1" format="FIRST" column="CLRONEAMT" datatype="double">**</td>
<td exists="1" format="FIRST" column="CLRPOOLAMT" datatype="double">**</td>
</tr>
</table>
</tables>

至此,生成excel打包下载已经全部完成。

其中遇到了excel中文乱码的问题,使用这个jar包里的类就没问题了



最后

以上就是大方星月为你收集整理的java实现excel打包下载的全部内容,希望文章能够帮你解决java实现excel打包下载所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部