最近在做一个报表生成系统,为了方便,采用了Servlet + jxl的方式进行报表生成,以excel的形式导出。但是在导出过程中发现了一些问题,研究了很久,也在网上查了很多资料,但是解决方法都不一样,且相对较为复杂,于是自己瞎捣腾了一下,找到了一个适合于自己的解决方法,暂时贴出来供大家参考。本文不一定对适用于你遇到的同类问题,但是希望能在解决问题时可以多提供一种方案。
我遇到的问题是这样的,在收到客户端请求生成报表时,第一次可以顺利生成并下载,但是再发送一个生成请求的时候会抛出异常:java.lang.ArrayIndexOutOfBoundsException: 5
原始测试代码如下:
package com.myCompany.excel.test;
import java.io.File;
import java.io.IOException;
import jxl.Workbook;
import jxl.format.Colour;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
public class App
{
public static void main( String[] args )
{
try {
ExcelGenerator excel = new ExcelGenerator();
for(int i = 1; i < 50; ++i)
{
String fileName = "Test" + i + ".xls";
excel.CreateExcel(fileName);
System.out.println(fileName + " Finished!");
}
} catch (WriteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ExcelGenerator
{
private WritableFont fontTitle = new WritableFont(WritableFont.TIMES, 20, WritableFont.BOLD );
private WritableFont fontHead = new WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD );
private WritableFont fontBody = new WritableFont(WritableFont.TIMES, 16 );
private WritableCellFormat cellTitle = new WritableCellFormat(fontTitle);
private WritableCellFormat cellHead = new WritableCellFormat(fontHead);
private WritableCellFormat cellBody = new WritableCellFormat(fontBody);
public ExcelGenerator() throws WriteException
{
cellTitle.setAlignment(jxl.format.Alignment.CENTRE);
cellTitle.setBackground(Colour.GREY_40_PERCENT);
cellTitle.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN);
cellHead.setAlignment(jxl.format.Alignment.CENTRE);
cellHead.setBackground(Colour.GREY_25_PERCENT);
cellHead.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN);
cellBody.setAlignment(jxl.format.Alignment.LEFT);
cellBody.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN);
}
public void CreateExcel(String fileName) throws IOException, RowsExceededException, WriteException
{
WritableWorkbook wb = Workbook.createWorkbook(new File(fileName));
WritableSheet sheet = wb.createSheet("Test", 0);
// 设置列宽
sheet.setColumnView(0, 30);
sheet.setColumnView(1, 30);
sheet.setColumnView(2, 15);
sheet.setColumnView(3, 15);
sheet.setColumnView(4, 30);
sheet.setColumnView(5, 40);
sheet.addCell(new Label(0, 0, "公司信息", this.cellTitle));
sheet.mergeCells(0, 0, 5, 0);
// 插入标题内容
sheet.addCell(new Label(0, 1, "条码", this.cellHead));
sheet.addCell(new Label(1, 1, "公司", this.cellHead));
sheet.addCell(new Label(2, 1, "部门", this.cellHead));
sheet.addCell(new Label(3, 1, "姓名", this.cellHead));
sheet.addCell(new Label(4, 1, "类型", this.cellHead));
sheet.addCell(new Label(5, 1, "描述", this.cellHead));
for(int i = 2; i < 2000; ++i)
{
int col = 0;
sheet.addCell(new Label(col++, i, "1353761413" + i, cellBody));
sheet.addCell(new Label(col++, i, "XX有限责任公司", cellBody));
sheet.addCell(new Label(col++, i, "XX", cellBody));
sheet.addCell(new Label(col++, i, "XX", cellBody));
sheet.addCell(new Label(col++, i, "XXXXX", cellBody));
sheet.addCell(new Label(col++, i, "XXXXX", cellBody));
}
wb.write();
wb.close();
}
}
结果在第二次生成报表时抛出异常:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at jxl.biff.IndexMapping.getNewIndex(IndexMapping.java:68)
at jxl.biff.FormattingRecords.rationalize(FormattingRecords.java:388)
at jxl.write.biff.WritableWorkbookImpl.rationalize(WritableWorkbookImpl.java:1023)
at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:701)
at com.myCompany.excel.test.ExcelGenerator.CreateExcel(App.java:101)
at com.myCompany.excel.test.App.main(App.java:29)
在网上查资料,有人说程序中不能使用太多static,本测试程序中不含static,所以该解决方案不适用。有人说修改jxl的源文件,但是因为jxl.jar已经被其他同事集成到库中,不受我控制,所以只能另找他法。在分析打印出来的异常信息是,发现该异常的产生与单元格的格式控制有关系(因为项目时间紧,没时间分析太久。我想可能是对格式的引用次数有限制之类的,所以在生成不同的文件循环引用同样的格式时,产生了越界,姑且认为是这个很肤浅的原因吧,有时间再仔细研究)。于是先是尝试把格式控制都删除掉,再次运行程序时不会抛出异常。但是如果报表不进行格式控制根本没法看,所以不能去掉格式。于是为了避免出现引用次数过多而造成的越界情况,我决定在每次生成报表时都重新定义格式,而非是在第一次初始化时定义共享格式。修改后的代码如下:
package com.myCompany.excel.test;
import java.io.File;
import java.io.IOException;
import jxl.Workbook;
import jxl.format.Colour;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
public class App
{
public static void main( String[] args )
{
try {
ExcelGenerator excel = new ExcelGenerator();
for(int i = 1; i < 50; ++i)
{
String fileName = "Test" + i + ".xls";
excel.CreateExcel(fileName);
System.out.println(fileName + " Finished!");
}
} catch (WriteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ExcelGenerator
{
public ExcelGenerator() throws WriteException
{
}
public void CreateExcel(String fileName) throws IOException, RowsExceededException, WriteException
{
// 定义格式
WritableFont fontTitle = new WritableFont(WritableFont.TIMES, 20, WritableFont.BOLD );
WritableFont fontHead = new WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD );
WritableFont fontBody = new WritableFont(WritableFont.TIMES, 16 );
WritableCellFormat cellTitle = new WritableCellFormat(fontTitle);
WritableCellFormat cellHead = new WritableCellFormat(fontHead);
WritableCellFormat cellBody = new WritableCellFormat(fontBody);
cellTitle.setAlignment(jxl.format.Alignment.CENTRE);
cellTitle.setBackground(Colour.GREY_40_PERCENT);
cellTitle.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN);
cellHead.setAlignment(jxl.format.Alignment.CENTRE);
cellHead.setBackground(Colour.GREY_25_PERCENT);
cellHead.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN);
cellBody.setAlignment(jxl.format.Alignment.LEFT);
cellBody.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN);
//创建工作薄
WritableWorkbook wb = Workbook.createWorkbook(new File(fileName));
WritableSheet sheet = wb.createSheet("Test", 0);
// 设置列宽
sheet.setColumnView(0, 30);
sheet.setColumnView(1, 30);
sheet.setColumnView(2, 15);
sheet.setColumnView(3, 15);
sheet.setColumnView(4, 30);
sheet.setColumnView(5, 40);
// 设置标题
sheet.addCell(new Label(0, 0, "公司信息", cellTitle));
sheet.mergeCells(0, 0, 5, 0);
// 插入标题内容
sheet.addCell(new Label(0, 1, "条码", cellHead));
sheet.addCell(new Label(1, 1, "公司", cellHead));
sheet.addCell(new Label(2, 1, "部门", cellHead));
sheet.addCell(new Label(3, 1, "姓名", cellHead));
sheet.addCell(new Label(4, 1, "类型", cellHead));
sheet.addCell(new Label(5, 1, "描述", cellHead));
for(int i = 2; i < 2000; ++i)
{
int col = 0;
sheet.addCell(new Label(col++, i, "1353761413" + i, cellBody));
sheet.addCell(new Label(col++, i, "XX有限责任公司", cellBody));
sheet.addCell(new Label(col++, i, "XX", cellBody));
sheet.addCell(new Label(col++, i, "XX", cellBody));
sheet.addCell(new Label(col++, i, "XXXXX", cellBody));
sheet.addCell(new Label(col++, i, "XXXXX", cellBody));
}
wb.write();
wb.close();
}
}
这样虽然程序效率降低,但是不会再抛出异常。而且考虑到报表生成不是一个频繁发生的事件,所以在每次生成报表时重新定义格式也是可以接受的。
分享到:
相关推荐
标题 "NoClassDefFoundError: jxl/WorkbookSettings" 是一个常见的Java运行时错误,意味着在尝试执行程序时,系统无法找到某个类的定义。这个错误通常发生在类路径(ClassPath)配置不正确或者缺少了必要的库依赖时...
本篇文章将深入探讨如何使用jxl.jar库来实现Java操作Excel。 首先,jxl是一个广泛使用的Java库,它允许开发者读写Microsoft Excel文件。它的主要优势在于简单易用且功能丰富,支持多种Excel格式,包括老版本的.BIFF...
**Java Excel工具包——jxl.jar** 在Java编程中,处理Excel文件是一项常见的任务,尤其在数据导入导出、报表生成或数据分析等场景下。jxl.jar是一个专门为Java设计的库,它允许开发者轻松地读取、写入和修改Excel...
"jxl.biff.drawing.dg"和"jxl.biff.drawingdg"则涉及到Excel文件内部的结构,BIFF(Binary Interchange File Format)是Excel的二进制文件格式,其中"drawing"部分与Excel的图形元素相关,"dg"可能是Drawing Group的...
Java Jxl库是一个专门用于处理Excel文件的开源Java库,它允许开发者在Java应用程序中进行Excel文件的读取、创建和修改。Jxl支持多种Excel版本,包括从Excel 95到2000,而且生成的文件格式符合Excel 2000的标准。这个...
at jxl.write.biff.WritableSheetCopier.shallowCopyCells(WritableSheetCopier.java:499) [jxl.ja r:na] at jxl.write.biff.WritableSheetCopier.copySheet(WritableSheetCopier.java:239) [jxl.jar:na] at ...
在Java编程环境中,处理Excel文件是一项常见的任务,而JXL库提供了一个简洁的API来实现这一功能。JXL是一个开源的Java库,专门用于读取和写入Microsoft Excel文件(.xls格式)。在这个"JXL读写Excel小例子"中,我们...
本教程将详细介绍如何使用`jxl`库在导出Excel时添加水印,以及涉及的核心类`WritableWorkbook`、`WritableSheet`和`WritableCellFormat`。 `jxl`库提供了一套完整的API来操作Excel文件,包括创建新的工作簿、添加...
在Java开发中,生成和处理Excel文件是一项常见的任务,特别是在数据导出或报表生成的场景。JXL库是一个广泛使用的Java库,它允许开发者读取、写入和修改Excel文件。本篇将深入探讨如何使用JXL库在Java中打印Excel...
在Java编程环境中,处理Excel文件是一项常见的任务,特别是在数据导入导出、数据分析或者报表生成时。JXL库是一个广泛使用的开源库,它允许开发者用Java来读写Microsoft Excel文件。标题"关于jxl操作excel说明以及...
在Java编程环境中,处理Excel文件是一项常见的任务,而JXL库提供了一个简洁的API来实现这一功能。JXL是一个开源的Java库,专门用于读取和写入Microsoft Excel文件(.xls格式)。在这个示例中,我们将深入探讨如何...
在Java编程领域,处理Excel文件是一项常见的任务,特别是在数据分析、数据导入导出或者报表生成等场景。JXL库是一个广泛使用的开源库,它允许开发者在Java应用程序中方便地读取和写入Excel文件。本篇将详细介绍如何...
【Java Jxl库详解:轻松实现Excel导入导出】 Java Jxl库是一个强大的工具,用于在Java应用程序中处理Microsoft Excel文件。它支持从Excel 95到2000的所有版本,同时也允许生成Excel 2000标准格式的文件。Jxl的主要...
本文将深入探讨Java编程语言中如何使用Apache POI库和JExcelAPI(JXL)来读取、写入及操作Excel文件,同时也包括设置列宽以及处理合并或拆分的单元格内容。 首先,Apache POI是Apache软件基金会的一个开源项目,专...
JavaExcel库,通常以jxl.jar的形式出现,是Java开发者用于读取和写入Microsoft Excel文件的一个强大工具。这个库提供了方便的API,使得在Java应用程序中操作Excel电子表格变得非常简单。它不仅支持基本的读写功能,...
在Java编程环境中,读取Excel文件是常见的任务,特别是在数据处理和分析的场景下。`jxl`库是一个广泛使用的第三方库,它允许开发者轻松地读取、写入和修改Excel文件。本篇文章将深入探讨如何利用`jxl.jar`包来实现这...
在这种情况下,`jxl.jar`库是一个非常实用的工具,它允许开发者用Java轻松地读取和写入Excel文件。`jxl.jar`库提供了丰富的API,使得操作Excel文件变得简单而高效。 `jxl`库的核心概念是工作簿(Workbook)、工作表...
Java中的JXL库是一个广泛使用的库,用于读取和写入Microsoft Excel文件。这个库使得在Java应用程序中处理Excel数据变得简单,而无需依赖于Microsoft Office。以下是对JXL库在进行Excel读写操作时的一些关键知识点的...