您的位置:首页 > 其它

简单OA项目笔记(5):生成、下载excel格式的动态表格(POI)

2012-11-13 20:54 736 查看
把动态表格生成excel用的库叫POI,从数据库提取出数据之后,利用POI可以产生一个stream。

大体步骤:

步骤一:从数据库读信息

步骤二:数据组装成excel

步骤三:用InputStream发回浏览器

数据流:

1.struts.xml中action配置

result:是“stream”

vnd.ms-excel:文件类型是tomcat提供的

"contentDisposition">filename="AllUsers.xls":配置下载全都是附件形式,文件名以配置为准

"inputName">downloadFile:需要具体action中的get“downloadFile”

<action name="generateExcel" class="generateExcelAction">
<result name="success" type="stream"><!-- result是“stream”-->
<param name="contentType">application/vnd.ms-excel</param> <!--文件类型是tomcat提供的-->
<param name="contentDisposition">attachment;filename="AllUsers.xls"</param> <!--配置下载全都是附件形式,文件名以配置为准-->
<param name="inputName">downloadFile</param> <!--需要具体action中的get“downloadFile”-->
</result>
</action>

attachment;

临时文件“打开时”创建两次(下载时创建一次)tomcat/bin下:两个临时文件

要配置action:contentDisposition 要配成attachment(点开下载时,无论什么文件都会弹窗提示下载)

2.GenerateExcelAction

这个getter和上边"inputName">downloadFile 一致

public InputStream getDownloadFile()
{
return this.service.getInputStream();
}


3.UserServiceImpl

这里边是生成excel的核心代码,组装好之后,要把生成的excel转换成InputStream类型还给action。action根据下载配置,把文件用附件的形式发给客户端,完成下载。

生成excel的过程是

1.创建sheet

2.由sheet创建:行

3.表头:short表示0号格

设置中文

4.迭代创建表格:

5.把表格写进 ByteArrayOutputStream 对象,再转换成InputStream 对象返还给action

public InputStream getInputStream()
{
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("sheet1");

HSSFRow row = sheet.createRow(0);

HSSFCell cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("序号");

cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("姓");

cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("名");

cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue("年龄");

List<User> list = this.findAll();

for (int i = 0; i < list.size(); ++i)
{
User user = list.get(i);

row = sheet.createRow(i + 1);

cell = row.createCell((short) 0);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(i + 1);

cell = row.createCell((short) 1);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getFirstname());

cell = row.createCell((short) 2);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getLastname());

cell = row.createCell((short) 3);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellValue(user.getAge());
}

ByteArrayOutputStream os = new ByteArrayOutputStream();

try
{
wb.write(os);
}
catch (IOException e)
{
e.printStackTrace();
}

byte[] content = os.toByteArray();

InputStream is = new ByteArrayInputStream(content);

return is;

}


4.用另一种思路:产生临时文件

上边产生excel的的方式没有用到临时文件,直接在内存里就都完成了。还有一种方法是利用临时文件保存excel表信息。

这种方法比较麻烦,首先是下载的文件名不能重复,否则多线程情况下就该互相覆盖掉了

String fileName = RandomStringUtils.randomAlphanumeric(10);

fileName = new StringBuffer(fileName).append(".xls").toString();

final File file = new File(fileName);

try
{
OutputStream os = new FileOutputStream(file);
wb.write(os);
os.close();
}
catch (Exception e)
{
e.printStackTrace();
}

InputStream is = null;
try
{
is = new FileInputStream(file);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}

new Thread(new Runnable()
{
public void run()
{
try
{
Thread.sleep(15000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}

file.delete();//删除临时文件
}
}).start();

return is;


而且产生的随机文件名的临时文件,还要自己估摸一个时间延迟删除:

new Thread(new Runnable()
{
public void run()
{
try
{
Thread.sleep(15000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}

file.delete();//删除临时文件
}
}).start();


如果没删掉还有靠其他方法比如servlet启动时删除:

public void init() throws ServletException
{
File file = new File(".");

File[] subFiles = file.listFiles(new FileFilter()
{
public boolean accept(File pathname)
{
if(pathname.getName().endsWith("xls"))
{
return true;
}

return false;
}
}
);

for(File f : subFiles)
{
f.delete();
}
}


这个比较恶心,目前来看还是用第一种说的 在内存里 ByteArrayOutputStream 完成吧,内存很紧张的时候可能才会用临时文件吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐