ManagementDay08(粗粒度权限控制 poi excel模版打印 )

excel 设置列宽 本身是个bug 可以通过模版来避免
//通过RequestAware, SessionAware, ApplicationAware实行接口获得request,session,application对象,action中就可直接调用
@Transactional
public class BaseAction extends ActionSupport implements RequestAware, SessionAware, ApplicationAware{
    private static Logger log = Logger.getLogger(BaseAction.class);

    private static final long serialVersionUID = 1L;

    //之前使用。。。来获取
    //ActionContext.getContext().getApplication().put(key, value)
    //protected为了子类也能用
    protected Map<String, Object> request;

哪个页面内嵌了登录页面就加上
<script type="text/javascript">
//点部门管理的时候 本来要到deptAction_list 但是配上了过滤器 过滤器指引到index.jsp 把顶层设置成index.jsp相当于重新加载了当前页面
if(self.location!=top.location){
    top.location=self.location;
}
</script> 让登录页面到顶部 也就是到整体

一、回顾
购销合同
1、什么是购销合同
2、分析出表结构的关系
3、设计表的三范式及反三范式
4、添加冗余字段,使得查询速度更快
5、分散计算原理
购销合同总金额的计算
1、购销合同、货物、附件的crud
二、细粒度权限控制
在粗粒度权限控制的基础上,加入对于不同用户显示的数据也不一样的控制,实质就是数据的控制
1、数据库表的准备
    createBy字段:代表创建者的id
    createDept字段:代表创建者所在部门id
    createTime字段
    updateBy字段
    updateTime字段
补充ContractAction中的方法
    public String insert() throws Exception {
        //1、加入细粒度权限控制的数据
        User user = (User) session.get(SysConstant.CURRENT_USER_INFO);
        model.setCreateBy(user.getId());//设置创建者的id
        model.setCreateDept(user.getDept().getDEPT_ID());//设置创建者所在部门的id

        //1、调用业务方法,实现保存 有oid执行update 没有save 因为不是已经存在的
        contractService.saveOrUpdate(model);
        //跳页面
        return "alist";
    }
从jUserCreate.jsp页面中,可以得出用户主要通过等级来决定可以看到什么数据
    <td class="tableContentAuto">
        <input type="radio" name="userinfo.degree" value="0" class="input"/>超级管理员
        <input type="radio" name="userinfo.degree" value="1" class="input"/>跨部门跨人员
        <input type="radio" name="userinfo.degree" value="2" class="input"/>管理所有下属部门和人员
        <input type="radio" name="userinfo.degree" value="3" class="input"/>管理本部门
        <input type="radio" name="userinfo.degree" value="4" class="input"/>普通员工
    </td>

修改ContractAciton.java类中的list()方法
    public String list() throws Exception {
        String hql = "from Contract where 1=1 ";

        //如何确定出用户的等级
        User user = super.getCurUser();
        int degree = user.getUserinfo().getDegree();
        if(degree == 4) {
            //是员工
            hql+= "and createBy='"+user.getId()+"'";
        }else if(degree==3) {
            //是部门经理,管理本部门
            hql+="and createDept='"+user.getDept().getDEPT_ID()+"'";
        }else if(degree==2) {
            //管理本部门及下属部门

        }else if(degree==1) {
            //副总

        }else if(degree==0) {
            //总经理

        }
        //引用数据类型在方法体内对它的修改是有用的
        contractService.findPage(hql, page, Contract.class, null);
        //设置分页的url地址
        page.setUrl("contractAction_list");
        //将page对象压入栈顶 集合用put
        super.push(page);
        return "list";
    }

三、添加购销合同下货物时的bug
    String hql = "from Factory where ctype='货物' and state = 1";
    List<Factory> factoryList = factoryService.find(hql, Factory.class, null);

购销合同显示附件数为0的bug
    ${o.contractProducts.size() }
    /
    <c:set var="extNo" value="0"></c:set>
    <c:forEach items="${o.contractProducts }"  var="cp" >
        <c:if test="${cp.extCproducts.size()!=0 }">
            <c:set var="extNo" value="${extNo+cp.extCproducts.size() }"></c:set>
        </c:if>

    </c:forEach>
    ${extNo }

购销合同中的货物数/附件数加载存在问题
    当加载一条购销合同记录时,会通过关联级别的数据加载,来加载购销合同下的货物列表,同时还要加载货物列表下的附件列表,造成加载速度慢
解决思路:
    在购销合同的表中加入两个冗余字段,在添加购销合同下的货物时就同时更新购销合同表中的货物数量,在添加附件时,就更新购销合同表中的附件数量

新的问题:
    因为冗余字段的添加,导致程序的开发和维护工作量增加,目的是保证数据的一致性

四、POI报表
1、poi介绍
Apache专门操作excel api
2、主流操作excel api
    1、Jxl 只能操作excel 2003
    2、poi 可以操作整个office(excel、doc(vb 宏)、ppt、visio)包括所有的excel版本

    excel2003           EXCEL2007及以上版本xlsx
基础 OLE技术实现,控件   OOXML技术
问题:支持数据量有限(二进制) 大数据量时,查询数据效率低  在2007版本,微软对office进行重构,基于xml,查询效率高
单Sheet 行:65536,列:256    行:1048576;列:16384

五、应用场景
将数据写入excel,用户可以共享数据,作为备份数据(不包括打字段)、还原数据
1、导入POI相关jar包
    poi-3.11.jar
    poi-ooxml-3.11.jar
    poi-ooxml-schemas-3.11.jar

    maven项目
    pom.xml中的xml配置
        <dependency> 
            <groupId>org.apache.poi</groupId> 
            <artifactId>poi</artifactId> 
            <version>3.11</version> 
        </dependency>
        <dependency> 
            <groupId>org.apache.poi</groupId> 
            <artifactId>poi-ooxml</artifactId> 
            <version>3.11</version> 
        </dependency>
        <dependency> 
            <groupId>org.apache.poi</groupId> 
            <artifactId>poi-ooxml-schemas</artifactId> 
            <version>3.11</version> 
        </dependency>

2、需求:81、创建一个工作簿 workbook
    2、创建一个工作表 sheet
    3、创建一个行对象 row(下标起始值为04、创建一个单元格对象cell(下标起始值为05、给单元格设置内容
    6、设置单元格的样式,设置字体和字体的大小
    7、保存,关闭流对象
    8、下载

3、实现
    public void testPoi() throws IOException {
        //1、创建工作簿
        Workbook wb = new HSSFWorkbook();

        //2、创建工作表 sheet
        Sheet sheet = wb.createSheet();

        //3、创建行对象
        Row row = sheet.createRow(3);//下标从0开始 第四行

        //4、创建单元格对象 从0计数
        Cell cell = row.createCell(3);

        //5、设置单元格内容
        cell.setCellValue("我的天");

        //6、设置单元格的样式
        CellStyle cellStyle = wb.createCellStyle();

        Font font = wb.createFont();//创建字体对象
        font.setFontName("方正舒体");//设置字体名称
        font.setFontHeightInPoints((short) 48);//设置字体的大小

        cellStyle.setFont(font);//样式中添加一个字体样式

        cell.setCellStyle(cellStyle);

        //7、保存,关闭流
        OutputStream os = new FileOutputStream("g:/a.xls");//创建一个输出流

//      os.write(wb);
        wb.write(os);//给个流输出 上面的不行
        os.close();
        //8、下载
    }

六、出货表的打印
1、按船期进行统计
    是按照客户的需求 要根据什么就根据什么

     <!-- onclick="WdatePicker({el:this,isShowOthers:true,dateFmt:'yyyy-MM-dd HH:mm:ss'});"/> -->
    <div>
        <table class="commonTable" cellspacing="1">
            <tr>
                <td class="columnTitle">船期:</td>
                <td class="tableContent">
                    <input type="text" style="width:90px;" name="inputDate"
                     value="2015-07"
                    onclick="WdatePicker({el:this,isShowOthers:true,dateFmt:'yyyy-MM'});"/>

2、数据来源
    通过分析,可以知道是购销合同表,货物表

3、思考查询方法
    hql语句只要查询货物就行
        因为货物中有一个关联的对象(contract属性)
            from ContractProduct where ContractProduct.contract.shipTime=?
        obj就是货物
            obj.getContract().get...
        只要循环所有的货物,一边输出货物信息一边创建单元格
        String hql = " from ContractProduct where to_char(contract.shipTime,'yyyy-MM')='"+inputDate+"'";
        List<ContractProduct> list = contractProductService.find(hql, ContractProduct.class, null);//查询出符合指定船期的货物列表
    OutProductAction类添加
        注入ContractProductService
        toedit()
4、出货表页面的进入
    只要在该页面提供一个日历选择框就可以选择船期了,再使用POI实现数据打印

七、模版打印
1、制作模版文件
2、导入(加载)模版文件,从而得到一个工作簿
3、读取工作表
4、读取行
5、读取单元格
6、读取单元格样式
7、设置单元格内容
8、其他单元格使用读到的样式
    //使用模版打印
    public String print() throws Exception {
        //通用变量
        int rowNo = 0,cellNo = 1;
        Row nRow = null;
        Cell nCell = null;

        //1、读取工作簿 
        String path = ServletActionContext.getServletContext().getRealPath("/")+"make/xlsprint/tOUTPRODUCT.xls";
        System.out.println(path);

        InputStream is = new FileInputStream(path);
        Workbook wb = new HSSFWorkbook(is);

        //2、读取工作表
        Sheet sheet = wb.getSheetAt(0);


        cellNo = 1;//重置
        //3、创建行对象
        //============大标题============
        nRow = sheet.getRow(rowNo++);//读取行对象
        nCell = nRow.getCell(cellNo);
        //设置单元格的内容
        nCell.setCellValue(inputDate.replace("-0", "-").replace("-", "年")+"月份出货表");//2014-01


        //============小标题============
        rowNo++;
        //============数据输出============
        //
        nRow = sheet.getRow(rowNo);//读取第三行
//      nRow.getCell(cellNo).getStringCellValue();
        CellStyle customCellStyle = nRow.getCell(cellNo++).getCellStyle();
        CellStyle orderCellStyle = nRow.getCell(cellNo++).getCellStyle();
        CellStyle productCellStyle = nRow.getCell(cellNo++).getCellStyle();
        CellStyle cNumberCellStyle = nRow.getCell(cellNo++).getCellStyle();
        CellStyle factoryCellStyle = nRow.getCell(cellNo++).getCellStyle();
        CellStyle deliverlyPeriodCellStyle = nRow.getCell(cellNo++).getCellStyle();
        CellStyle shipTimeCellStyle = nRow.getCell(cellNo++).getCellStyle();
        CellStyle tradeTermsCellStyle = nRow.getCell(cellNo++).getCellStyle();
        String hql = " from ContractProduct where to_char(contract.shipTime,'yyyy-MM')='"+inputDate+"'";
        List<ContractProduct> list = contractProductService.find(hql, ContractProduct.class, null);//查询出符合指定船期的货物列表

        for (ContractProduct cp : list) {
            nRow = sheet.createRow(rowNo++);
            nRow.setHeightInPoints(24);//设置行高
            cellNo = 1;
            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getContract().getCustomName());//客户名称
            nCell.setCellStyle(customCellStyle);//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getContract().getContractNo());//订单号---合同号
            nCell.setCellStyle(orderCellStyle);//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getProductNo());//货号
            nCell.setCellStyle(productCellStyle);//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getCnumber());//数量
            nCell.setCellStyle(cNumberCellStyle);//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getFactoryName());//工厂名
            nCell.setCellStyle(factoryCellStyle);//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getDeliveryPeriod()));//交期
            nCell.setCellStyle(deliverlyPeriodCellStyle);//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getShipTime()));//船期
            nCell.setCellStyle(shipTimeCellStyle);//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getContract().getTradeTerms());//贸易条款
            nCell.setCellStyle(tradeTermsCellStyle);//设置文本样式

        }


        //输出
        DownloadUtil downUtil = new DownloadUtil();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();//流 内存中的缓存区
        wb.write(baos);//将excel表格中的内容输出到缓存
        baos.close();//刷新缓存

        HttpServletResponse response = ServletActionContext.getResponse();//得到response对象

        downUtil.download(baos, response, "出货.xls");

        return NONE;
    }
    /**
     * 打印出货表
     * @return
     * @throws Exception
     */
    /*public String printNotTemplate() throws Exception {
        //通用变量
        int rowNo = 0,cellNo = 1;
        Row nRow = null;
        Cell nCell = null;

        //1、创建工作簿  使用接口的实现类 而不是new接口的对象 可以直接用方法 而不是再次去实现
        Workbook wb = new HSSFWorkbook();

        //2、创建工作表
        Sheet sheet = wb.createSheet();

        //设置列宽 本身是个bug
        sheet.setColumnWidth(cellNo++, 26*256);
        sheet.setColumnWidth(cellNo++, 11*256);
        sheet.setColumnWidth(cellNo++, 29*256);
        sheet.setColumnWidth(cellNo++, 12*256);
        sheet.setColumnWidth(cellNo++, 15*256);
        sheet.setColumnWidth(cellNo++, 10*256);
        sheet.setColumnWidth(cellNo++, 10*256);
        sheet.setColumnWidth(cellNo++, 8*256);

        cellNo = 1;//重置
        //3、创建行对象
        //============大标题============
        nRow = sheet.createRow(rowNo++);//创建行镀锡
        nRow.setHeightInPoints(36);//设置行高
        nCell = nRow.createCell(cellNo);//创建单元格对象

        //合并单元格
        sheet.addMergedRegion(new CellRangeAddress(0,0,1,8));//横向合并单元格

        //设置单元格的内容
        nCell.setCellValue(inputDate.replace("-0", "-").replace("-", "年")+"月份出货表");//2014-01

        //设置样式
        nCell.setCellStyle(this.bigTitle(wb));

        //============小标题============
        String titles[] = {"客人","订单号","货号","数量","工厂","工厂交期","船期","贸易条款"};

        //创建小标题的行对象
        nRow = sheet.createRow(rowNo++);
        nRow.setHeightInPoints(26.25f);//设置行高

        //创建单元格对象,并设置内容,并设置样式
        for(String title:titles) {
            nCell = nRow.createCell(cellNo++);//创建单元格对象
            nCell.setCellValue(title);//设置内容
            nCell.setCellStyle(this.title(wb));
        }

        //============数据输出============
        String hql = " from ContractProduct where to_char(contract.shipTime,'yyyy-MM')='"+inputDate+"'";
        List<ContractProduct> list = contractProductService.find(hql, ContractProduct.class, null);//查询出符合指定船期的货物列表

        for (ContractProduct cp : list) {
            nRow = sheet.createRow(rowNo++);
            nRow.setHeightInPoints(24);//设置行高
            cellNo = 1;
            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getContract().getCustomName());//客户名称
            nCell.setCellStyle(this.text(wb));//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getContract().getContractNo());//订单号---合同号
            nCell.setCellStyle(this.text(wb));//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getProductNo());//货号
            nCell.setCellStyle(this.text(wb));//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getCnumber());//数量
            nCell.setCellStyle(this.text(wb));//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getFactoryName());//工厂名
            nCell.setCellStyle(this.text(wb));//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getDeliveryPeriod()));//交期
            nCell.setCellStyle(this.text(wb));//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getShipTime()));//船期
            nCell.setCellStyle(this.text(wb));//设置文本样式

            nCell = nRow.createCell(cellNo++);//产生单元格对象
            nCell.setCellValue(cp.getContract().getTradeTerms());//贸易条款
            nCell.setCellStyle(this.text(wb));//设置文本样式

        }


        //输出
        DownloadUtil downUtil = new DownloadUtil();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();//流 内存中的缓存区
        wb.write(baos);//将excel表格中的内容输出到缓存
        baos.close();//刷新缓存

        HttpServletResponse response = ServletActionContext.getResponse();//得到response对象

        downUtil.download(baos, response, "出货.xls");

        return NONE;
    }*/



    //大标题的样式
    public CellStyle bigTitle(Workbook wb){
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short)16);
        font.setBoldweight(Font.BOLDWEIGHT_BOLD);                   //字体加粗

        style.setFont(font);

        style.setAlignment(CellStyle.ALIGN_CENTER);                 //横向居中
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);      //纵向居中

        return style;
    }
    //小标题的样式
    public CellStyle title(Workbook wb){
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontName("黑体");
        font.setFontHeightInPoints((short)12);
        style.setFont(font);

        style.setAlignment(CellStyle.ALIGN_CENTER);                 //横向居中
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);      //纵向居中
        style.setBorderTop(CellStyle.BORDER_THIN);                  //上细线
        style.setBorderBottom(CellStyle.BORDER_THIN);               //下细线
        style.setBorderLeft(CellStyle.BORDER_THIN);                 //左细线
        style.setBorderRight(CellStyle.BORDER_THIN);                //右细线

        return style;
    }

    //文字样式
    public CellStyle text(Workbook wb){
        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short)10);

        style.setFont(font);

        style.setAlignment(CellStyle.ALIGN_LEFT);                   //横向居左
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);      //纵向居中

        style.setBorderTop(CellStyle.BORDER_THIN);                  //上细线
        style.setBorderBottom(CellStyle.BORDER_THIN);               //下细线
        style.setBorderLeft(CellStyle.BORDER_THIN);                 //左细线
        style.setBorderRight(CellStyle.BORDER_THIN);                //右细线

        return style;
    }
}







猜你喜欢

转载自blog.csdn.net/civilizationv/article/details/80404473