在做项目的时候,客户都会把数据下载下来,所以一般都会有报表导出的功能,正常的是直接导出为xlsx格式的excel表格,由于博主参与的是停车场项目,在后续项目运行上线的时候,数据量会过大,再去导出的时候会报错 java.lang.IllegalArgumentException: Invalid row number (65536) outside allowable range (0..65535),然后百度发现: excel最大行数,不同版本有所不同。Excel2003版最大行数是65536行。Excel2007开始的版本最大行数是1048576行。 要不分sheet显示,要不改格式。 毋庸置疑,博主被要求改格式,好吧,只能改,改成csv文件的格式。

以上就是后面发生事情的前因。下面就来介绍一下做完之后的经验以及踩过的坑吧。

报表导出为xlsx格式

service层:

public Workbook export(CarRecordDTO carRecordDTO) throws Exception {

						Workbook workbook = new Workbook();
            Sheet sheet = workbook.createSheet("在线车辆数据");
            Row row = sheet.createRow(0);
            row.createCell(1).setCellValue("车牌照片");
            row.createCell(2).setCellValue("车牌号");
            row.createCell(3).setCellValue("进场时间");
            row.createCell(4).setCellValue("停车时长");
            row.createCell(5).setCellValue("进场闸口");
            row.createCell(6).setCellValue("有无跨场");
            row.createCell(7).setCellValue("有无校正");

            Date currentDate = new Date();
            for (int i = 0; i < carRecordList.size(); i++) {
                CarRecord carRecord = (CarRecord) carRecordList.get(i);
                row = sheet.createRow(i + 1);

                ExcelUtil.setCellValue(row, 1, carRecord.getEnterPlatePic());
                ExcelUtil.setCellValue(row, 2, carRecord.getPlateNum());
                ExcelUtil.setCellValue(row, 3, DateUtil.formatDate(carRecord.getEnterDate(), "yyyy-MM-dd HH:mm"));
                Date enterDate = carRecord.getEnterDate();
                Long stopTime = (currentDate.getTime() - enterDate.getTime()) / 60000;
                ExcelUtil.setCellValue(row, 4, TimeUtils.timeConvert(stopTime.intValue()));
                ExcelUtil.setCellValue(row, 5, list.get(carRecord.getEnterGate()));
                if (YES.equals(carRecord.getIsCross())) {
                    ExcelUtil.setCellValue(row, 6, "有跨场");
                } else {
                    ExcelUtil.setCellValue(row, 6, "无跨场");
                }

                if (YES.equals(carRecord.getIsRevise())) {
                    ExcelUtil.setCellValue(row, 7, "有校正");
                } else {
                    ExcelUtil.setCellValue(row, 7, "无校正");
                }
            }
						return workbook;
	}

controller层:

  Workbook workbook = carRecordService.export(carRecordDTO);
	super.writeExcel("carRecord.xls",workbook);
protected void writeExcel(String filename, Workbook workbook) throws Exception {
        this.response.setContentType("application/octet-stream; charset=iso-8859-1");
        StringBuffer contentDisposition = new StringBuffer("attachment; filename=\"");
        contentDisposition.append(filename).append("\"");
        this.response.setHeader("Content-disposition", contentDisposition.toString());
        ServletOutputStream out = this.response.getOutputStream();
        workbook.write(out);
        out.flush();
        out.close();
    }

上面的代码就可以导出xlsx格式的excil报表了。。是不是很简单。

报表导出为csv格式

service层:

public File export(CarRecordDTO carRecordDTO) throws Exception {

List<String> listPark = new ArrayList<>();
            listPark.add("车牌照片");
            listPark.add("车牌号");
            listPark.add("进场时间");
            listPark.add("停车时长");
            listPark.add("进场闸口");
            listPark.add("有无跨场");
            listPark.add("有无校正");

            tempFile =  new File("cardRecord.csv");

            CsvWriter csvOutput = new CsvWriter(tempFile.getCanonicalPath(), ',', Charset.forName("GBK"));
            csvOutput.setEscapeMode(CsvWriter.ESCAPE_MODE_DOUBLED);
            // 第一行
            for (String s : listPark) {
                csvOutput.write(s);
            }
            csvOutput.endRecord();
            // 循环写出数据

            Date currentDate = new Date();
            for (CarRecord carRecord : carRecordList) {
                csvOutput.write(carRecord.getEnterPlatePic());
                csvOutput.write(carRecord.getPlateNum());
                csvOutput.write(DateUtil.formatDate(carRecord.getEnterDate(), "yyyy-MM-dd HH:mm"));
                Date enterDate = carRecord.getEnterDate();
                Long stopTime = (currentDate.getTime() - enterDate.getTime()) / 60000;
                csvOutput.write(TimeUtils.timeConvert(stopTime.intValue()));
                csvOutput.write(list.get(carRecord.getEnterGate()));
                if (YES.equals(carRecord.getIsCross())) {
                    csvOutput.write("有跨场");
                } else {
                    csvOutput.write("无跨场");
                }

                if (YES.equals(carRecord.getIsRevise())) {
                    csvOutput.write("有校正");
                } else {
                    csvOutput.write("无校正");
                }

                csvOutput.endRecord();
            }
            csvOutput.close();
						return tempFile;
		}

controller层:

   File tempFile = carRecordService.export(carRecordDTO);
		java.io.OutputStream out = this.response.getOutputStream();

		this.response.reset();
		this.response.setContentType("application/csv; charset=iso-8859-1");
		this.response.setHeader("content-disposition", "attachment; filename="+tempFile.getPath());
		File fileLoad = new java.io.File(tempFile.getCanonicalPath());
		long fileLength = fileLoad.length();
		FileInputStream in = new FileInputStream(fileLoad);
		String length1 = String.valueOf(fileLength);

		byte[] b = new byte[10240];
		this.response.setHeader("Content_Length", length1);
		int n;
		while ((n = in.read(b)) != -1) {
			out.write(b, 0, n); //每次写入out1024字节
		}
		in.close();
		out.close();

这样就可以导出csv格式的报表了,下面就来讲讲踩到的坑和搞的乌龙吧:

  • 因为要引用import com.csvreader.CsvWriter 包,所以就去找相关的依赖包,然后就去maven官网去搜索,
<!-- https://mvnrepository.com/artifact/net.sourceforge.javacsv/javacsv -->
    <dependency>
      <groupId>net.sourceforge.javacsv</groupId>
      <artifactId>javacsv</artifactId>
      <version>2.0</version>
    </dependency>

把这个放进pom.xml文件中,要用的包还是import不进去,然后怀疑是maven的settings.xml没设置好,然后又前前后后叭叭叭的搞了挺久的,还是没有解决,后来实在没有办法了,向同事大神求助,后来经检查 是把这个按钮不知道什么时候按到了,导致idea离线状态,反正博主已经哭了

  • 在写完代码的时候,在本地测试是没有问题的,生成的excil可以存放65535以上的数据,文档打开也是没有问题的,然后部署到dev环境上测试,发现文件名又不是我改的英文名,格式也是乱了,都在同一个单元格里面,又叭叭叭的找问题,最后定位到应该是前端把文档名写死了,格式也有锁定吧(因为是前后端分离的,我基本上没去看前端代码)

  • 因为导出的报表由时间格式的,发现格式有问题,我在代码里面写了是yyyy-MM-dd hh:mm但是没有生效,比如2019-10-03 12:05 就显示为2019-10-3 12:5 反正就是很奇怪,百度上别人说要在前后都加"\t",我也试过了,没卵用,但是改excil表格里面单元格的格式是可以的;