SSM杰信商务平台项目day05

第五天 POI的神奇世界

1.业务,出货表

功能:
对购销合同进行月统计,按船期进行统计。
合同、货物、生产厂家、附件传统设计,关联4张表;
通过冗余设计,只需要从合同、货物表中获取数据;取数据更加方便,代码更加简单。

分析表格,循环货物信息能方便实现打印数据。将这些数据打印到excel中。

2.JAVA语言操作excel的api主流有两种方式:

比较

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版本以上,构造函数。不支持模板方式。只能作为数据导出。

SXSSF如何实现?

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);
        }

SSM杰信商务平台项目day05_第1张图片

在生成的xml临时文件中,只存放数据

CSV 实际文本文件,存放数据,数据之间,可以用逗号隔开,也可以用TAB隔开。通用导入导出文件。

当数据量大,跟当前电脑环境,堆溢出。
优化Myeclispse
优化jvm启动参数

a)POI入门

Excel文件
1)创建excel文件,称作工作簿workbook
2)Excel文件在创建时,会默认创建3个工作表sheet
3)定位行
4)定位列,获得单元格
5)填写内容
6)保存,关闭

POI开发步骤:

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)行对象,列对象,样式对象,字体对象重复创建

b)出货表开发步骤

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)下载文件

3.常规poi打印存在问题:

1)列的宽度不精确,272非常相近
2)设置纸张方向
3)设置页眉页脚
4)标题栏
5)内容样式稍有不同,就需要创建不同的样式,写很多样式应用的语句
6)表格头,写死表头,静态的文字方便维护

4.POI操作EXCEL,复杂报表终极解决方案~模板开发

1)代码量急剧降低
2)POI日常API,将利用模板直接来设置,可视化修改。
3)业务功能非常方便维护。

SSM杰信商务平台项目day05_第2张图片

//模板打印
    @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");
    }

5.重点知识回顾

a)全面了解POI

JXL 它导入导出速度很快,业界一般用来数据的导入导出。

b)导入导出:

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版本,只用于大数据量的导出。它实现指定创建一定对象数量后,将这些不再使用的对象,写入临时文件。这样释放出这些对象所占用的内存,内存占用不高,才可以顺利完成海量数据的导出。

c)出货表使用模板

实际工作中最简单的一个表格
1)无需大量的设置样式,可视化
2)静态文字,图片,线,可以提前在模板中实现
3)Excel打印的一些设置,纸张方向,列宽,基础行高,标题,页眉页脚
4)代码功能的可维护性非常方便
5)通用性不强,根据具体的业务来实现。

课程视频内容

SSM杰信商务平台项目day05_第3张图片

你可能感兴趣的:(SSM杰信商务平台项目)