第五天 POI的神奇世界
功能:
对购销合同进行月统计,按船期进行统计。
合同、货物、生产厂家、附件传统设计,关联4张表;
通过冗余设计,只需要从合同、货物表中获取数据;取数据更加方便,代码更加简单。
分析表格,循环货物信息能方便实现打印数据。将这些数据打印到excel中。
1、POI Apache它是用来操作Office所有的软件excel/word/ppt/..。而且支持所有版本。
2、JXL 它是用来操作excel 2003以下版本,2007以上版本不支持。
早期微软Office系列,当时使用OLE2文档结构;微软在开发Office2207版本时,做了一个重大的改革。重写了Office,使用OOXML文档结构。现在excel文件实际上是一个xml格式文件。
POI支持OLE2格式文件,还支持OOXML,而且在OOXML格式文件时做了很大的优化。
JXL只支持OLE2格式文件。
POI低版本有个致命弱点,当数据量超大(海量数据),性能极具降低。JXL它解决数量大时性能的问题。POI在高版本时迎头追上,加了一个补丁。OOXML支持,解决大数量时的性能问题。
http://poi.apache.org/index.html POI 全方位的操作
http://www.andykhan.com/jexcelapi/index.html JXL 导入导出
java.lang.IllegalArgumentException: Invalid column index (256). Allowable column range for BIFF8 is (0..255) or ('A'..'IV')
java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535)
HSSF对象支持excel 2003,excel 2003它支持行65536,支持列256
XSSF对象支持excel2007版本以上,行1048576,支持列65536。Sheet
SXSSF对象,支持excel 2007版本以上,构造函数。不支持模板方式。只能作为数据导出。
HSSF/XSSF 它们在构建workbook中所有对象,全部放在内存中,数据全放在内存中,wb.write时才从内存向磁盘文件中写。写完才释放内存。数据量大,堆溢出。
SXSSF构造方法Workbook wb = new SXSSFWorkbook(100);
每处理完100个对象,将它写临时文件,这部分数据所占的内存,就释放。
File tmplFile = File.createTempFile("poi-sxssf-template", ".xlsx");
try
{
FileOutputStream os = new FileOutputStream(tmplFile);
try
{
_wb.write(os);
}
finally
{
os.close();
}
//Substitute the template entries with the generated sheet data files
injectData(tmplFile, stream);
}
在生成的xml临时文件中,只存放数据
CSV 实际文本文件,存放数据,数据之间,可以用逗号隔开,也可以用TAB隔开。通用导入导出文件。
当数据量大,跟当前电脑环境,堆溢出。
优化Myeclispse
优化jvm启动参数
Excel文件
1)创建excel文件,称作工作簿workbook
2)Excel文件在创建时,会默认创建3个工作表sheet
3)定位行
4)定位列,获得单元格
5)填写内容
6)保存,关闭
public void HSSF() throws IOException{
//1.创建一个工作簿excel文件
Workbook wb = new HSSFWorkbook(); //HSSF操作excel 2003以下版本
//2.创建一个工作表sheet
Sheet sheet = wb.createSheet();
//3.创建一个行对象Row
Row nRow = sheet.createRow(4); //第五行,坐标从0开始
//4.创建一个单元格对象,指定列
Cell nCell = nRow.createCell(3); //第四列
//5.给单元格设置内容
nCell.setCellValue("传智播客万年长!");
//6.保存
OutputStream os = new FileOutputStream(new File("c:\\testPOI.xls"));
wb.write(os);
//7.关闭
os.close();
}
上面代码存在的问题:
1)POI创建的这些对象统统在内存中
2)行对象,列对象,样式对象,字体对象重复创建
1)获取数据
select
c.custom_name,c.contract_no,cp.product_no,cp.cnumber,cp.factory_name,cp.exts,c.delivery_period,c.ship_time,c.trade_terms
from
(select contract_id,product_no,cnumber||packing_unit as cnumber,factory_name,exts from contract_product_c) cp
left join
(select contract_id,custom_name,contract_no,delivery_period,ship_time,trade_terms from contract_c) c
on cp.contract_id=c.contract_id
where to_char(ship_time,'yyyy-MM')='2011-12'
2)创建excel文件
3)修饰样式
4)将数据写入excel
5)下载文件
1)列的宽度不精确,272非常相近
2)设置纸张方向
3)设置页眉页脚
4)标题栏
5)内容样式稍有不同,就需要创建不同的样式,写很多样式应用的语句
6)表格头,写死表头,静态的文字方便维护
1)代码量急剧降低
2)POI日常API,将利用模板直接来设置,可视化修改。
3)业务功能非常方便维护。
//模板打印
@RequestMapping("/cargo/outproduct/printTemplate.action")
public void printTemplate(String inputDate, HttpServletRequest request, HttpServletResponse response) throws IOException{
List dataList = outProductService.find(inputDate);
//打开模板文件
String path = request.getSession().getServletContext().getRealPath("/"); //jdk1.8 bug 在linux下不带后面你写的路径
String tempFile = path + "/make/xlsprint/tOUTPRODUCT.xls";
Workbook wb = new HSSFWorkbook(new FileInputStream(new File(tempFile)));
//写入业务内容
Sheet sheet = wb.getSheetAt(0); //获得工作表sheet
Row nRow = null;
Cell nCell = null;
int rowNo = 2;
int colNo = 1;
//获取样式
nRow = sheet.getRow(2); //获得行对象
nCell = nRow.getCell(1); //获取单元格对象
CellStyle customNameStyle = nCell.getCellStyle(); //获取到样式
nCell = nRow.getCell(2);
CellStyle contractNoStyle = nCell.getCellStyle();
nCell = nRow.getCell(3);
CellStyle productNoStyle = nCell.getCellStyle();
nCell = nRow.getCell(4);
CellStyle cnumberStyle = nCell.getCellStyle();
nCell = nRow.getCell(5);
CellStyle factoryStyle = nCell.getCellStyle();
nCell = nRow.getCell(6);
CellStyle extStyle = nCell.getCellStyle();
nCell = nRow.getCell(7);
CellStyle dateStyle = nCell.getCellStyle();
nCell = nRow.getCell(9);
CellStyle tradeStyle = nCell.getCellStyle();
//大标题
nRow = sheet.getRow(0);
nCell = nRow.getCell(1);
nCell.setCellValue(inputDate.replaceFirst("-0", "-").replaceFirst("-", "年") + "月份出货表"); //yyyy-MM
//处理数据
for(int j=0;j
colNo = 1; //列号初始化
OutProductVO op = dataList.get(j); //获取出货表对象
nRow = sheet.createRow(rowNo++);
nRow.setHeightInPoints(24);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getCustomName());
nCell.setCellStyle(customNameStyle); //设置样式
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getContractNo());
nCell.setCellStyle(contractNoStyle);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getProductNo());
nCell.setCellStyle(productNoStyle);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getCnumber());
nCell.setCellStyle(cnumberStyle);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getFactoryName());
nCell.setCellStyle(factoryStyle);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getExts());
nCell.setCellStyle(extStyle);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getDeliveryPeriod());
nCell.setCellStyle(dateStyle);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getShipTime());
nCell.setCellStyle(dateStyle);
nCell = nRow.createCell(colNo++);
nCell.setCellValue(op.getTradeTerms());
nCell.setCellStyle(tradeStyle);
}
//下载
DownloadUtil du = new DownloadUtil();
ByteArrayOutputStream os = new ByteArrayOutputStream();
wb.write(os);
du.download(os, response, "出货表.xls");
}
JXL 它导入导出速度很快,业界一般用来数据的导入导出。
1)数据备份 txt,csv,excel(客户比较喜欢),xml
2)两个业务系统之间共享数据
JXL局限:它只能操作excel2003版本以下
POI 操作Office 支持excel,word,ppt等。业界习惯使用它来操作excel。
操作word,使用.net,它直接可以访问word对象;使用word宏,宏脚本语言,vba。网上政府办公,申请某个营业执照,下载一个word文件,填写。
业界习惯使用POI来操作excel。
OLE2 2003以下版本 HSSF 行:65536;列:255
OOXML 2007以上版本 XSSF/SXSSF 行:1048576 列:65536
HSSF它操作excel 2003版本,它数据量有限,它支持到65536条。
XSSF它操作excel 2007版本,它不能读取excel2003版本,它支持1048576,单个sheet。
SXSSF 它操作excel 2007版本,只用于大数据量的导出。它实现指定创建一定对象数量后,将这些不再使用的对象,写入临时文件。这样释放出这些对象所占用的内存,内存占用不高,才可以顺利完成海量数据的导出。
实际工作中最简单的一个表格
1)无需大量的设置样式,可视化
2)静态文字,图片,线,可以提前在模板中实现
3)Excel打印的一些设置,纸张方向,列宽,基础行高,标题,页眉页脚
4)代码功能的可维护性非常方便
5)通用性不强,根据具体的业务来实现。