Java操作excel

  前两天遇到一个这样的任务,需要将十多个Excel按指定模板整理,这种情况首先想到的就是用程序去解决这件事,人工的话,不仅费时费力,而且准确度不一定高,偶尔马虎一下,很难再去发现,最主要的是我们人力不够,就两个人,要整的话得一两天的工作量,但是领导给的时间也不是很多,遂用代码解决。
  一开始想到的是用python去写,但是换了电脑后还没装python环境,而且用python也不是特别多,写的话肯定是一边写一边学,如果时间充裕的话,这是最好的解决办法,但是奈何时间不是很多,就直接拿java写了。
  之前写过用java读取excel,这次是在两个excel间对比,写入第三个excel,涉及到整列数据的读取写入,两个sheet页首行数据的对比,多个sheet页之间的操作等。
  没写之前不知道,写完之后发现java操作excel还是比较不友好的,主要包括两点,
  1.java操作excel一般是用poi操作,poi操作不支持整列操作,一般都是按行操作,所以对于我的需求就比较难受了,每次操作列只能先读行,再读列,写入同理;
  2.一开始设想的是按列操作完成之后,保存再写入下一列,但是发现新建excel时写入数据没问题,但是再追加数据就不行了,网上找了半天,只发现两种解决方法,很不幸,都不行;
  对于第一种情况,没有办法,只能先读行,再读列,难受也没办法;对于第二种情况,有两种解决办法,要么就是读取完整个excel后再写入,要么就是读取原excel,然后增加要写入的数据,再写入到新的文件中,我是用第一种方法,通过二维数组记录下整个要写入的表格,然后通过二维数组写入到表格中。
现在记录下中间关键的几个操作点:

  1. 读取文件列表:
  // 读取某目录
  File dir = new File(strPath);
  // 获取文件夹下某所有文件
  File[] files = dir.listFiles();
  1. 读取Excel文件
        // 新建文件流
        FileInputStream templateFileInputStream = null;
        // 新建sheet对象
        XSSFWorkbook sheets = null;
        // 新建excel行
        XSSFRow row = null;
        try {
            // 读取文件流
            templateFileInputStream = new FileInputStream(filePath);
            // 解析xlsx格式文件
            sheets = new XSSFWorkbook(templateFileInputStream);
            // 获取指定sheet
            XSSFSheet sheet = sheets.getSheetAt(sheetIndex);
            // 获取第一行
            row = sheet.getRow(0);
            // 获取当前行包含列数
            int columns = row.getPhysicalNumberOfCells();
            // 获取当前表格行数
            int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
            jsonObject.put("row", row);
            jsonObject.put("columns", columns);
            jsonObject.put("rows", physicalNumberOfRows);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (templateFileInputStream != null) {
                templateFileInputStream.close();
            }
        }
  1. 写入excel文件
        //1、判断文件是否存在,存在的话,就追加新的sheet页,不存在就新建
        FileOutputStream out = null;
        // 声明一个工作薄
        XSSFWorkbook workbook = null;
        try {
            out = new FileOutputStream(newFilePath);
            workbook = new XSSFWorkbook();
            // 生成一个表格
            XSSFSheet sheet = workbook.createSheet(title);
            // array是要写入的二维数组,可以换成其他
            for (int i = 0; i < array[0].length; i++) {
            	// a是我代码中的一个值,createRow这个方法是创建下标为a的行
                XSSFRow row = sheet.createRow(a);
                for (int j = 0; j < array.length; j++) {
                    XSSFCell cell = row.createCell(j);
                    cell.setCellValue(array[j][i]);
                	}
            // 将建好的sheet写入到excel中
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
  1. 单元格类型判断
        switch (cell.getCellTypeEnum()) {
            case STRING:
                temp = cell.getRichStringCellValue().getString();
                break;
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    Date date = cell.getDateCellValue();
                    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                    temp = df.format(date);
                } else if (!String.valueOf(cell.getNumericCellValue()).contains("E")) {
                    return String.valueOf(cell.getNumericCellValue());
                } else {
                    // 对超长字符串进行格式化处理
                    return new DecimalFormat("#").format(cell.getNumericCellValue());
                }
                break;
            case BLANK:
                temp = "";
                break;
            default:
                temp = cell.toString();
                break;
        }

  已上就是处理的主要步骤,不过因为时间原因代码只实现了主要功能,算是半自动化吧,还得手动切换数据模板,不过这样已经可以顺利完成任务了,比全自动慢了一丢丢,从上边的2,3点就可以看出为什么支持追加了,对于同一个文件,不可能同时对它进行读入流和写入流操作,所以不能追加,再后边第四点写的比较简单,因为当前数据格式不是很多,这几个足以满足要求,如果有需要可以去网上找下,有不少例子可以参考。

posted @ 2021-11-30 21:14  iHADream  阅读(862)  评论(0编辑  收藏  举报