后端动态生成报表导出

后端报表导出


把前端要导出的数据查询参数传递到后端,后端通过参数去数据库查询,得到的跟前端展示的一样,但是导出的规则是需要在后端从新写的。
参考博客 https://www.cnblogs.com/ywy8/p/11718467.html

前端

通过form表单的提交方式,来发起请求后端,后端处理之后返回数据,前端浏览器直接提示下载了。
同时做了一次导出请求的判断,因为是有时间和姓名的查询条件,而且我第一次默认展示了有数据,所以当查询条件没有的时候一定是刚进去就默认展示的数据导出,所以判断查询的参数是否为空,如果为空把参数给赋上跟展示页面的相同的默认值 这里默认的是今天的数据。

 $("#generate-excel").click(  //#generate-excel 导出按钮的id
            function () {
                tableget();
            }
        ); function tableget() {  //在这里进行判断 第一次加载为ba =undefined
            if (ba!=undefined&&ba!=null){
                var data = ba;
            } else {
                var data = {};
                data.entTime =new Date(new Date(new Date().toLocaleDateString()).getTime()).getTime();
                data.lastTime = data.entTime-86400000;
                data.name = "0";
            }
            var type = confirm("是否导出图片");
            if (type) {
                var typea = "1";
            } else {
                var typea = "0";
            }
            var urla = url + "tableb";
            $('<form method="post" action="' + urla + '"><input name="entTime" value="' + data.entTime + '">' +
                '<input name="lastTime" value="' + data.lastTime + '"> ' +
                '<input name="name" value="' + data.name + '">' +
                '<input name="typea" value="' + typea + '">' +
                '</form>').appendTo('body').submit().remove();
        }

后端

忽略return null; 不会走这个返回

    /**
     * 导出数据
     *
     * @param entTime
     * @param lastTime
     * @return
     */
    @RequestMapping("/tableb")
    @ResponseBody
    public ResponseEntity getTableb(
            @RequestParam(name = "entTime", defaultValue = "1") long entTime,
            @RequestParam(name = "lastTime", defaultValue = "0") long lastTime,
            @RequestParam(name = "name", defaultValue = "0") String name,
            @RequestParam(name = "type", defaultValue = "1") String type,
            @RequestParam(name = "lj", defaultValue = "1") String lj
    ) throws SQLException, IOException {
        //存放每次查询结果
        List<Map<String, Object>> select = new ArrayList<Map<String, Object>>();
        //存放最后返回结果
        List<tableVo> listtable = new ArrayList<tableVo>();
        name = name.equals("undefined") ? "0" : name;
        if (1 == 1) {
            //没有设置时间
            if (entTime == 1 || lastTime == 0) {
                entTime = gettime();
                long a = entTime + 86400000;
                //姓名查
                //没有设置查询姓名的情况
                if (name.equals("0")) {
                    select = qianDaoMapper.selecta(entTime, a);
                }//设置了姓名
                if (!name.equals("0")) {
                    if (name.equals("售后服务部")) {
                        select = qianDaoMapper.selecta(entTime, a);
                    } else {

                        for (long ent = entTime + 86400000; entTime < a; entTime += 86400000) {
                            select = qianDaoMapper.selectb(entTime, a, name);
                        }
                    }
                }

                //部门查
                if (select.size() == 0) {
                    select = qianDaoMapper.selectc(entTime, a, name);
                }//完整部门查
                if (select.size() == 0) {
                    select = qianDaoMapper.selectc(entTime, a, name);
                }

                listtable = this.setDate(select, listtable);
            }
            //设置了查询时间
            long str = 0l;
            //查姓名
            long entTime1 = entTime;
            if (entTime != 1 && lastTime != 0) {
                for (int i = 0; i < 100; ) {
                    //当遍历时间戳到最大的时间戳时退出循环
                    if (str >= lastTime) {
                        break;
                    } else {
                        str = entTime1 + 86400000;
                        if (name.equals("0")) {
                            select = qianDaoMapper.selecta(entTime1, str);
                        } else {
                            if (name.equals("售后服务部")) {
                                select = qianDaoMapper.selecta(entTime1, str);
                            } else {
                                select = qianDaoMapper.selectb(entTime1, str, name);
                            }
                        }
                        entTime1 = str;

                        listtable = this.setDate(select, listtable);
                    }
                }
            }

            //查部门
            long entTime2 = entTime;
            if (listtable.size() == 0) {
                long stra = 0l;
                if (entTime != 1 && lastTime != 0) {
                    for (int i = 0; i < 100; ) {
                        //当遍历时间戳到最大的时间戳时退出循环
                        if (stra > lastTime) {
                            break;
                        } else {
                            stra = entTime2 + 86400000;
                            String bumen = name;
                            select = qianDaoMapper.selectc(entTime2, stra, bumen);
                            entTime2 = stra;


                            listtable = this.setDate(select, listtable);
                        }
                    }
                }
            }
            //查完整部门
            long entTime3 = entTime;
            if (listtable.size() == 0) {
                long strb = 0l;
                if (entTime != 1 && lastTime != 0) {
                    for (int i = 0; i < 100; ) {
                        //当遍历时间戳到最大的时间戳时退出循环
                        if (strb > lastTime) {
                            break;
                        } else {
                            strb = entTime3 + 86400000;
                            String wzbumen = name;
                            select = qianDaoMapper.selectd(entTime3, strb, wzbumen);
                            entTime3 = strb;
                            listtable = this.setDate(select, listtable);
                        }
                    }
                }

            }

        }
        int lengtha = 0;
        int lengthb = 0;
        //获取最大的签到时间个数 和签到图片个数
        for (int i = 0; i < listtable.size(); i++) {
            if (lengtha < listtable.get(i).getCheckinTime().size()) {
                lengtha = listtable.get(i).getCheckinTime().size();
            }
        }
        for (int i = 0; i < listtable.size(); i++) {
            if (lengthb < listtable.get(i).getImageList().size()) {
                lengthb = listtable.get(i).getImageList().size();
            }
        }
        lengthb = type.equals("1") ? lengthb : 0;
        //文件的名称
        name = name.equals("0") ? "表格" : name;
        //相当于创建一个文件对象
        XSSFWorkbook workbook = new XSSFWorkbook();
        //给文件命名
        XSSFSheet sheet = workbook.createSheet(name + ".xlsx");
        //设置字体----------表格样式----------------------------------
        XSSFFont font = workbook.createFont();
        font.setFontName("Times New Roman");
        font.setFontHeightInPoints((short) 12);
        //设置下边框,并使高度居中
        CellStyle rowHB = Poi.getBorderBC(workbook);
        rowHB.setFont(font);
        //水平居中,四边设置边框,并设置自动换行
        XSSFCellStyle mediumStyle = Poi.getHorizontalCenterBorder(workbook);
        mediumStyle.setWrapText(true);
        mediumStyle.setFont(font);
        //-----------------表格样式--------------------------------
        //创建行属性,下标从0开始
        XSSFRow row = sheet.createRow(0);
        //创建这行中的列,下标从0开始 (表头)
        XSSFCell cell = row.createCell(0);
        //判断签到时间是否是偶数 如果不是那要再加一个签到时间签到时间变成偶数 方便计算工时
        lengtha = lengtha % 2 == 0 ? lengtha : lengtha + 1;
        //创建表头
        if (1 == 1) {

            //获取工时(i)的字段个数
            int lengtha1 = lengtha / 2;
            //9个字段里含有总工时
            int ce = 4 + lengtha + 1 + 4 + lengthb;
            //创建这行中的列,并给该列直接赋值
            row.createCell(0).setCellValue("姓名");
            row.createCell(1).setCellValue("部门");
            row.createCell(2).setCellValue("完整部门");
            row.createCell(3).setCellValue("日期");
            int index = 4;
            //遍历有几组 签到时间1 签到时间2 工时1h
            for (int i = 1; i <= (lengtha + lengtha1) / 3; i++) {
                for (int j = 1; j <= 3; j++) {
                    if (j == 3) {
                        row.createCell(index).setCellValue("工时" + i + "(h)");
                    } else {
                        row.createCell(index).setCellValue("签到时间" + j * i);
                    }
                    index += 1;
                }
            }
            //总工时
            row.createCell(index).setCellValue("总工时(h)");
            row.createCell(index + 1).setCellValue("地点");
            row.createCell(index + 2).setCellValue("详细地址");
            row.createCell(index + 3).setCellValue("拜访对象");
            row.createCell(index + 4).setCellValue("备注");
            index += 5;
            for (int i = 1; i <= lengthb; i++) {
                row.createCell(index).setCellValue("签到图片" + i);
                index++;
            }
        }
        int Zindex = 1;
        for (tableVo next : listtable) {
            row = sheet.createRow(Zindex);
            Zindex += 1;
            row.createCell(0).setCellValue(next.getName());
            row.createCell(1).setCellValue(next.getBumen());
            row.createCell(2).setCellValue(next.getWzbumen());
            Object s1 = next.getCheckinTime().get(0);
            row.createCell(3).setCellValue(this.dateString(s1.toString()));
            int index = 4;
            int lengtha1 = lengtha / 2;
            List list = next.getCheckinTime();
            //遍历有几组 签到时间1 签到时间2 工时1h
            int j = 1;
            long zong = 0l; //总工时计算提前声明
            for (int i = 0; i < lengtha; i++) {  //不管有没有跟表头一样长的签到时间都要生成数据
                //如果这条数据的签到时间次数小于表头签到时间的个数那么空缺的签到时间就用无代替
                if (i < list.size()) {
                    String s = dateStringOne(list.get(i).toString());
                    row.createCell(index).setCellValue(s);
                    index++;
                } else {
                    row.createCell(index).setCellValue("无");
                    index++;
                }
                //判断当时间签到次数为2得时候生成工时1 为4生成工时2
                if ((i + 1) % 2 == 0) {
                    //当这条数据有两次签到时间的时候再生成工时
                    if (i < list.size()) {
                        long date1 = Long.parseLong(list.get(i - 1).toString());//两次签到时间的第一个
                        long date2 = Long.parseLong(list.get(i).toString());//两次签到时间的第二个
                        long difference = date2 - date1;//相差得毫秒数
                        zong += difference;
                        double floor = Math.floor(difference / 3600000);// 向下取整 小时数  确定小时数
                        if (difference - (floor * 3600000) > 1800000) {   //判断他除了小时之外是否大于半个小时大于就加一个小时
                            floor += 1;
                        } else {  //除此之外大概率为小于半个小时
                            floor += 0.5;
                        }
                        floor = difference - (floor * 3600000) == 0 ? floor -= 0.5 : floor;
                        row.createCell(index).setCellValue(floor);
                        index++;
                    } else {//当不满足两次签到时间的时候生成签到时间为0
                        row.createCell(index).setCellValue(0);
                        index++;
                    }
                }
            }
            //签到时间和工时之后就是总工时 要在生成签到时间循环的外部
            if (list.size() >= 2) {  //当签到次数大于等于2 的时候计算总工时
                double floor = (long) Math.floor(zong / 3600000);//小时数
                if ((zong - (floor * 3600000)) > 1800000) {  //因为总工时的计算和工时123....无关所以要统计毫秒差 重新根据规则去计算
                    floor = floor + 1;
                } else {
                    floor = floor + 0.5;
                }

                if ((zong - (floor * 3600000)) == 0) {
                    floor = floor - 0.5;
                }
                row.createCell(index).setCellValue(floor);
                index++;
            } else {//当不满足两次签到时间的时候生成总工时为0
                row.createCell(index).setCellValue("0");
                index++;
            }
            //地点
            row.createCell(index).setCellValue(this.StirngList(next.getPlace()));
            index++;
            //详细地点
            row.createCell(index).setCellValue(this.StirngList(next.getDetailPlace()));
            index++;
            //拜访对象
            row.createCell(index).setCellValue(next.getVisitUser());
            index++;
            //备注
            row.createCell(index).setCellValue(this.StirngList(next.getRemark()));
            index++;
            //签到图片
            for (int i = 0; i < lengthb; i++) {
                if (i < next.getImageList().size()) {
                    String s = next.getImageList().get(i);
                    row.createCell(index).setCellValue(s);
                    index++;
                } else {
                    row.createCell(index).setCellValue("");
                    index++;
                }
            }
        }


        if (1 == 1) {
            try {
                File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name + ".xlsx");// 提示下载文件
                OutputStream out = new FileOutputStream(file);
                workbook.write(out);
                out.flush();
                out.close();
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                headers.setContentDispositionFormData("attachment", StringUtils.newStringIso8859_1(StringUtils.getBytesUtf8(file.getName())));
                return new ResponseEntity<byte[]>(Files.toByteArray(file), headers, HttpStatus.CREATED);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public String StirngList(List<String> list) {
        String wer = "";
        for (String str : list) {
            wer += (str + ",");
        }
        if (wer.length() > list.size() + 1) {  // WKY
            wer = wer.substring(0, wer.length());
        }
        return wer;
    }


    public static String getDate(String date1, String date2) {
        Long c = Long.parseLong(date1) - Long.parseLong(date2);
        int min = (int) (c / 60 / 60 / 1000);
        if (min == 0) {
            return "0";
        }
        if (min % 60 <= 30) {
            return (min / 60 + 0.5) + "";
        } else {
            return (min / 60 + 1) + "";
        }
    }

    private String dateString(String str) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        Date date = new Date(Long.parseLong(str));
        String format = formatter.format(date);
        return format;
    }

    private String dateStringOne(String str) {
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
        Date date = new Date(Long.parseLong(str));
        String format = formatter.format(date);
        return format;
    }

    //转换数据类型
    private List<tableVo> setDate(List<Map<String, Object>> select, List<tableVo> listtable) {
        for (Map<String, Object> a : select) {
            tableVo t = new tableVo();
            t.setName((String) a.get("姓名"));
            t.setVisitUser((String) a.get("拜访对象"));
            t.setBumen((String) a.get("部门"));
            t.setWzbumen((String) a.get("完整部门"));
            t.setCheckinTime(strToList((String) a.get("签到时间")));
            String[] strings = ((String) a.get("签到地点")).split(",");
            List dataList = Arrays.asList(strings);
            t.setPlace(dataList);
            t.setDetailPlace(this.Stringsplic((String) a.get("详细地点")));
            t.setRemark(this.Stringsplic((String) a.get("备注")));
            t.setImageList(this.aa((String) a.get("签到图片")));
            listtable.add(t);
        }
        System.out.println(listtable.toString());
        return listtable;

    }

    public static List strToList(String str) {
        List lsit = new ArrayList();
        String[] strs = str.split(",");
        for (String s : strs) {
            lsit.add(Long.parseLong(s.trim()));
        }
        Collections.sort(lsit);
        return lsit;
    }

    /**
     * 获取当前天得时间
     *
     * @return
     */
    private long gettime() {
        Date date = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        TimeZone timeZone = formatter.getTimeZone();
        String format = formatter.format(date);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long time = 0;
        try {
            time = sdf.parse(format).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println("查询起始时间" + time);
        return time;
    }

    /**
     * 处理签到图片
     *
     * @param demo
     * @return
     */
    private List<String> aa(String demo) {
        List<String> imglist = new ArrayList<String>();
        String replace = demo.replace("]", " ");
        String replace1 = replace.replace("[", " ");
        imglist = Arrays.asList(replace1.split(","));
        return imglist;

    }

    /**
     * 按照“,”给它转换成List<String>  签到时间 签到地点 详细地点 备注  字段都是用的这个方法
     *
     * @param demo
     * @return
     */
    private List<String> Stringsplic(String demo) {
        List<String> qdsja = new ArrayList<String>();
        int i1 = 0;
        for (int i = 0; i < 1; ) {
            i1 = demo.indexOf(",");
            if (i1 != -1) {  //如果走这个if 最少还有一个, 就代表最少还有两个数据
                String a = demo.substring(i, i1);
                demo = demo.substring(i1 + 1, demo.length());
                qdsja.add(a);
                if (demo.indexOf(",") == -1) {
                    qdsja.add(demo);
                    break;
                }
            }
            //这里有问题
            if ((demo.length() > 1 && i1 == -1) || demo.equals("")) {
                qdsja.add(demo);
                break;
            } else {
            }
        }
        return qdsja;
    }

需要的pom依赖

```java
<!--        下面都是poi所需要的-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-examples</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-excelant</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>stax</groupId>
            <artifactId>stax-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>2.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>26.0-jre</version>
        </dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值