jxls在生成Excel文件时,提供一个批量生成Excel Sheet的功能,即可以一次生成一个包含多个Sheet的Excel文件。但是,jxls在处理这类操作的时候会出现性能问题,当一次形成的Excel的Sheet数量超过500个的时候就会出现很严重的性能问题,运算到最后,系统会提示OutOfMemeroyError,这种问题的出现是由于jxls的实现方式决定的。
如果,仔细查看jxls的源代码就会发现,无论是处理单个Sheet还是处理多个Sheet的时候,在XLSTransformer类的Transform处理的时候都是在内存中对Sheet进行处理,然后,在生成WorkBook。假如,需要一次形成的Sheet为500以上的时候,势必会出现严重的性能问题。
针对以上的问题,如果我们的应用需要形成500Sheet以上的Excel时,我们可以采用人为干预的方式,即在进行处理前对Beans的个数进行限制,最好将Beans的个数限制在200个以内,即每次只生成包含200个Sheet的WorkBook,在WorkBook形成以后,再对WorkBook进行合并,然后,将合并的WorkBook输出形成Excel文件,这样处理的时候,对一个Excel的总的Sheet也需要进行控制,否则在运算的过程中也会出现OutOfMemeroyError,最好控制在3000个以内,如果,超过3000个建议形成多个Excel文件,下面我通过一个具体的企业应用来说明怎么来进行操作。
我这个应用是Payslip导出的一个应用,具体要求是:
按照Division和Costcenter来组织Payslip卡片,每个Costcenter下面的员工组织到一个Excel文件里面
在具体实现的过程发现有一个Costcenter下面的员工数量超过了3000,开始是想是否能够一次将这个Costcenter下面的Payslip全部形成,结果遭到了可耻的失败。经过不断的测试以后,得到了以上的两个临界点的数字。下面说明一下我的具体实现:
1)从数据库按照Costcenter取出Payslip,得到一个payslipList对象。具体就是组装出取数据的SQL Script,利用JDBCTemplate取出数据。
2)形成Costcenter对应的Excel文件的名称,如果,得到的List的size大于3000,则每3000个记录形成一个Excel文件
3)将得到的List按照200进行分块处理,每200处理一次
4)利用jxls提供的方法transformMultipleSheetsList()对数据进行处理,得到一个HSSFWorkbook对象
5)合并得到的HSSFWorkbook,输出形成Excel文件
具体代码如下:
java 代码
-
public
void
exportPayslip(String costcenterCode)
throws
IOException{
-
List payslipList = payslipDao.getPaylipByCostcenter(String costcenterCode);
-
String xlsFileName;
-
-
if
(payslipList.size() <=
3000
){
-
xlsFileName =
"c:"
+File.separator+costcenterCode+
".xls"
;
-
transformXLSFile(payslipList ,xlsFileName );
-
}
else
{
-
for
(
int
i =
0
;i<(
int
)Math.ceil((
double
)payslipList.size()/
3000
;i++)){
-
xlsFileName =
"c:"
+File.separator+costcenterCode+
"_"
+
new
Integer(i+
1
).toString()+
".xls"
;
-
int
k = ((i+
1
)*
3000 < payslipList.size()
) ? (i+1)*
3000
: resultList.size();
-
List resultList = payslipList.subList(i*
3000
,k);
-
transformXLSFile(resultList ,xlsFileName );
-
}
-
}
-
}
-
-
private
void
transformXLSFile(List resultList,String fileName){
-
XLSTransformer transformer =
new
XLSTransformer();
-
HSSFWorkBook resultWorkBook =
null
;
-
-
for
(
int
i =
0
;i<(
int
)Math.ceil((
double
)resultList.size()/
200
;i++)){
-
List payslipMaps =
new
ArrayList();
-
List sheetNames =
new
ArrayList();
-
-
InputStream xlsTemplateIO =
new
BufferedInputStream(getClass().getResourceAsStream(
"payslip.xls"
));
-
-
int
k = ((i+
1
)*
200
< resultList.size()) ? (i+1)*
200
: resultList.size();
-
-
payslipMaps = resultList.subList(i*
200
,k);
-
-
for
(
int
j=
0
;j
-
Map payslip = (Map)resultList.get(i);
-
String sheetName = paysli.get(
"EMPLOYEE_ID"
);
-
-
sheetNames.add(sheetName);
-
}
-
-
HSSFWorkbook workBook = transformer.transformMultipleSheetsList(xlsTemplateIO , payslipMaps , sheetNames,
"map"
,
new
HashMap(),
0
);
-
-
if
(i ==
0
){
-
resultWorkBook = workBook;
-
}
else
{
-
for
(
int
h =
0
;h < workBook.getNumberOfSheets();h++){
-
-
HSSFSheet newSheet = resultWorkBook.createSheet( (String) sheetNames.get(i) );
-
HSSFSheet hssfSheet = workBook.getSheetAt(h);
-
Util.copySheets(newSheet, hssfSheet);
-
Util.copyPageSetup(newSheet, hssfSheet);
-
Util.copyPrintSetup(newSheet, hssfSheet);
-
}
-
}
-
-
saveWorkbook(resultWorkbook, fileName);
-
xlsTemplateIO.close();
-
}
-
}
-
-
private
void
saveWorkbook(HSSFWorkbook resultWorkbook, String fileName)
throws
IOException{
-
OutputStream os =
new
BufferedOutputStream(
new
FileOutputStream(fileName));
-
resultWorkbook.write(os);
-
os.flush();
-
os.close();
-
}
以上代码有部分代码需要被放在try/catch语句里面,确保Stream能够被关闭,否则,会影响程序的运行性能。代码只代表个人的一种实现方式。
以上代码有一个地方需要说明,就是jxls的transformMultipleSheetsList()方法,该方法的声明如下:
java 代码
-
public
HSSFWorkbook transformMultipleSheetsList(InputStream is, List objects, List newSheetNames, String beanName, Map beanParams,
int
startSheetNum)
throws
ParsePropertyException {
该方法里面的参数说明如下:
1)is:即Template文件的一个输入流
2)newSheetNames:即形成Excel文件的时候Sheet的Name
3)objects:即我们传入的对应每个Sheet的一个Java对象,这里传入的List的元素为一个Map对象
4)beanName:这个参数在jxls对我们传入的List进行解析的时候使用,而且,该参数还对应Template文件中的Tag,例如,beanName为map,那么在Template文件中取值的公式应该定义成${map.get("property1")};如果beanName为payslip,公式应该定义成${payslip.get("property1")}
5)beanParams:这个参数在使用的时候我的代码没有使用到,这个参数是在如果传入的objects还与其他的对象关联的时候使用的,该参数是一个HashMap类型的参数,如果不使用的话,直接传入new HashMap()即可
6)startSheetNo:传入0即可,即SheetNo从0开始
以上代码的原理与操作Simple Sheet的时候差别不大,主要是Template的文件的取值公式和调用的方法有所改变而已。关键是在大数据量操作的时候注意对处理的数据进行分块处理即可,否则,系统运行性能将很难保证。以上代码,在我实际的使用过程中速度还是比较理想的,16000条数据的导出时间是15分钟左右。
jxls 多个sheet 生成 jxls在生成Excel文件时,提供一个批量生成Excel Sheet的功能,即可以一次生成一个包含多个Sheet的Excel文件。但是,jxls在处理这类操作的时候会出现性能问题,当一次形成的Excel的Sheet数量超过500个的时候就会出现很严重的性能问题,运算到最后,系统会提示OutOfMemeroyError,这种问题的出现是由于jxl
example:
//
Jxls
Helper helper =
Jxls
Helper.getInstance();
//helper.setSource
Sheet
Name("template");
//helper.setFreezePane(0, 1, 0, 1).setDeleteTemplate
Sheet
(true).processTemplate(is, os, context);
helper.setSource
Sheet
Name("template");
定义模板页名称,默认是创建excel时指定的
sheet
1,若修改,需通过setSource
Sheet
Name("template")设置
helper.setFreezePane(0, 1, 0,
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.ut...
jxls
在
生成
Excel文件时,提供一个批量
生成
Excel
Sheet
的功能,即可以一次
生成
一个包含
多个
Sheet
的Excel文件。但是,
jxls
在处理这类操作的时候会出现性能问题,当一次形成的Excel的
Sheet
数量超过500个的时候就会出现很严重的性能问题,运算到最后,系统会提示OutOfMemeroyError,这种问题的出现是由于
jxls
的实现方式决定的。
1.//构造
sheet
中所需数据、
sheet
名--action中实现
private String templateFileName;//导出用的Excel模板名字,即我们定义的模板Excel名字
private String exportFileName;//导出时显示给客户端的Excel名字,即浏览器显示的Excel名字
publi...
java代码如果是这样:Maps.newHashMap("template", testTemplate)
testTemplate是dto对象,其中里面包含了testInformationTemplateDtos这个列表
那么excel的批注这样写:template.testInformationTemplateDtos
jxls
通过模板中的批注语法来渲染数据,所以写好模板已经成功了一大半,
我的模板如下:这里我定义了两个
sheet
页,第一个
sheet
页就是汇总的,直接取数据遍历;第二个
sheet
页就是动态
sheet
页的模板。
注意模板作用域的定义一定要写在第一个单元格jx:area(lastCell="E7");
动态
sheet
语法multi
sheet
属性 jx:each(items="userScoreList" var="userScore" multi
sheet
="userScore.
sheet
Name
最近项目用到 excel导入导出功能,找了很多插件,最后选择了
jxls
2 。相比
jxls
1有很大改变
官方文档:http://
jxls
.sourceforge.net/getting_started.html
maven依赖:
注意其poi版本为4.0
&lt;!--excel处理相关 start--&gt;
&lt;dependency&gt;
&lt;g...
jxls
是一个用于在Java应用程序中
生成
和导出Excel文档的开源框架。该框架支持多种数据源,包括列表、Map和JavaBean。
jxls
也支持导出带有附件的Excel文档。
要在
jxls
中导出带有附件的Excel文档,首先需要为模板文件添加一个附件。可以在模板文件中插入一个超链接或按钮,点击该链接或按钮会下载或打开附件。添加附件的步骤如下:
1. 将附件文件保存到任意位置。
2. 在Excel模板中插入一个超链接或按钮。
3. 在超链接或按钮的目标属性中指定附件的URL地址。例如:file://C:/附件.txt。
4. 在代码中使用
jxls
框架导出Excel文档时,将附件文件作为参数传递给框架。
下面是一个简单的示例代码,演示如何在
jxls
中导出带有附件的Excel文档:
```java
// 模板文件路径
String templatePath = "template.xls";
// 导出文件路径
String outputPath = "output.xls";
// 附件文件路径
String attachmentPath = "attachment.txt";
Map<String, Object> data = new HashMap<String, Object>();
// 设置导出数据
// 创建
jxls
导出器
Transformer transformer = TransformerFactory.createTransformer(
new File(templatePath),
new FileOutputStream(outputPath));
// 添加附件
transformer.addTool(new UrlTool(attachmentPath, "__attachment__"));
// 将数据导出到Excel文档
Workbook workbook = transformer.transform();
workbook.write(new FileOutputStream(outputPath));
在上面的代码中,我们通过调用UrlTool的构造函数将附件文件添加到导出器中。UrlTool是
jxls
框架中的一个工具类,用于添加超链接或按钮。__attachment__是一个占位符,将在模板中用于定位附件。在模板Excel中,用${__attachment__}代表这个占位符。最终,我们将数据导出到Excel文档,并将Excel文档写入输出流中。
总之,
jxls
支持导出带有附件的Excel文档。通过在模板文件中添加超链接或按钮,并在代码中将附件文件添加到导出器中,我们可以轻松地实现导出带有附件的Excel文档。