1. 程式人生 > 其它 >Java操作excel

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點就可以看出為什麼支援追加了,對於同一個檔案,不可能同時對它進行讀入流和寫入流操作,所以不能追加,再後邊第四點寫的比較簡單,因為當前資料格式不是很多,這幾個足以滿足要求,如果有需要可以去網上找下,有不少例子可以參考。

金無足赤,人無完人,若有文章什麼問題歡迎各位批評指正,共同交流,共同進步。 另,人過留名,雁過留聲,少俠覺得還行的話留下個贊吧!:)