2016-05-18 101 views
1

私はJavaとApache POIライブラリとのインターフェイスをプログラミングしています。空の行を削除する際に問題が発生しました。私のコードは次のとおりです。Java Excel POI - 空のセル例外を含む行を削除する

public class ExcelDeleteRowsCols { 
    final short ROW_START = 0; 
    final short COL_START = 0; 

    public void deleteRows() { 
     try { 
      // Open file 
      FileInputStream inf = new FileInputStream("in.xls"); 
      Workbook wb = WorkbookFactory.create(inf); 

      // Loop every sheets of workbook 
      for (Sheet sheet : wb){ 

       // Loop every rows of this sheet 
       int lastIndex = sheet.getLastRowNum(); 

       for (int i = ROW_START; i <= lastIndex; i++) { 
        if (sheet.getRow(i) == null || sheet.getRow(i).getCell(COL_START) == null || sheet.getRow(i).getCell(COL_START).toString().equals("")){ 
         sheet.removeRow(sheet.getRow(i)); //sheet.shiftRows(i, lastIndex, 2); 
        } 
       } 
      } 
      // Save as in another file 
      FileOutputStream fileOut = new FileOutputStream("out.xls"); 
      wb.write(fileOut); 
      fileOut.flush(); 
      fileOut.close(); 

      System.out.println("Finished!"); 

     } catch (IOException ioe) { 
      System.out.println(ioe); 
     } catch (Exception e) { 
      System.out.println(e); 
     } 
    } 
} 

正確に問題が空のセルを持つ行で例外メッセージのjava.lang.NullPointerExceptionを示すことです。私はそれを理解していない。エクセル例:空のセルがない

"空セル" 回線2 LINE3 LINE4 LINE5 "空セル" Line7 Line8 Line9 Line10 Line11 Line12 Line13

コードは正常に動作しています...

お願いします。

ありがとうございます。

+0

私は問題アナリストだと私はするSystem.out.printlnによってsheet.removeRowを変更します。結果は空のセルにあり、値はnullで、その他のセルは文字列オブジェクトです(例: '[email protected]')。この問題では、値がnullのセルは削除できません。 – ruzD

答えて

0

されましたこの問題は、JavaのOPIが最適な選択肢だと私は思っています。コードは:

public class ExcelDeleteRowsCols { 
    final short ROW_START = 0; 
    final short COL_START = 0; 

    public void deleteRows() { 
     try { 
      // Open file 
      FileInputStream inf = new FileInputStream("in.xls"); 
      Workbook wb = WorkbookFactory.create(inf); 

      // Loop every sheets of workbook 
      for (Sheet sheet : wb){ 

       // Loop every rows of this sheet 
       int lastIndex = sheet.getLastRowNum(); 

       for (int i = ROW_START; i <= lastIndex; i++) { 
        if (sheet.getRow(i) == null || sheet.getRow(i).getCell(COL_START) == null || sheet.getRow(i).getCell(COL_START).toString().equals("")){ 
         sheet.removeRow(sheet.getRow(i)); 
        } 
       } 
      } 
      // Save as in another file 
      FileOutputStream fileOut = new FileOutputStream("out.xls"); 
      wb.write(fileOut); 
      fileOut.flush(); 
      fileOut.close(); 

      System.out.println("Finished!"); 

     } catch (IOException ioe) { 
      System.out.println(ioe); 
     } catch (Exception e) { 
      System.out.println(e); 
     } 
    } 
} 

行は、コードが正常に動作して空であるが、列がNULLである場合に問題がある場合(sheet.getRow(I)== NULL)。たとえば、このxlsでは、行2、行12、行15および16の値がnullの場合、コマンドは削除されません。sheet.removeRow(sheet.getRow(i));NullPointerによって例外と例外がスローされます。

値がnullであるという行を削除する方法はありますか?もちろん

0

行を削除するのではなく、実際にスプレッドシートの空の行を閉じる必要があります。つまり、データを含む行をシフトし、その間に空白行がないようにします。

これを考慮に入れてこの回答を完全に変更しました。

FileInputStream inf = new FileInputStream("Row_Delete_Test.xlsx"); 

Workbook wb = WorkbookFactory.create(inf); 

for (Sheet sh : wb) { 
    int previousIndex = sh.getFirstRowNum(); 
    if (previousIndex > 0) { 
     sh.shiftRows(px, sh.getLastRowNum(), -px); 
     previousIndex = 0; 
    } 

    for (Row row : sh) { 
     boolean deleteRow = true; 
     for (Cell cell : row) { 
      if (!cell.toString().trim().equals("")) { 
       deleteRow = false; 
       break; 
      } 
     } 

     int currentIndex = row.getRowNum(); 
     if (deleteRow) { 
      sh.removeRow(row); 
     } else { 
      if (currentIndex > previousIndex + 1) { 
       sh.shiftRows(row.getRowNum(), sh.getLastRowNum(), previousIndex - currentIndex + 1); 
       currentIndex = previousIndex + 1; 
      } 
      previousIndex = currentIndex; 
     } 
    } 
} 

FileOutputStream fileOut = new FileOutputStream("Row_Delete_Test.xlsx"); 
wb.write(fileOut); 
wb.close(); 
fileOut.close(); 

これは、スプレッドシートから行を削除するという効果があります。

注:Excelスプレッドシートには、実際にはセルを含む行のみが含まれ、データを含むセルのみが含まれます。そのデータは空白を含むほとんどすべてのものになる可能性があります。そのため、セルの値が空白の行を「削除」したい場合は、それを検索する必要があります。ここで

は、私はあなたが共有した文字列を見ている以外に知ることができる方法がないとしてだけで、あなたに伝えるつもりです

<sheetData> 
    <row r="2" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B2" t="s"> 
      <v>0</v> 
     </c> 
    </row> 
    <row r="5" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B5" t="s"> 
      <v>1</v> 
     </c> 
    </row> 
    <row r="6" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="C6" t="s"> 
      <v>4</v> 
     </c> 
    </row> 
    <row r="7" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B7" t="s"> 
      <v>2</v> 
     </c> 
    </row> 
    <row r="8" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B8" t="s"> 
      <v>3</v> 
     </c> 
    </row> 
    <row r="9" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="C9" t="s"> 
      <v>4</v> 
     </c> 
    </row> 
</sheetData> 

(これはRow_Delete_Test.xlsxファイル内sheet1.xmlからであることに注意)いくつかの例のデータであり、テーブルの場合、<v>4</v>で指定された共有文字列4は空白の値に過ぎません。他の共有文字列値は、<v>0</v> = '行1'、<v>1</v> = '行2'、<v>2</v> = '行3'、および<v>3</v> = '行4'です。したがってここでは2行目と5行目から9行目のデータが入力され、各行にはデータが入った1つのセルがあります。行6,9それぞれは上記のコードを実行した後、カラム

C.においてブランク値を有するセルを有する、sheetData今この

<sheetData> 
    <row r="1" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B1" t="s"> 
      <v>0</v> 
     </c> 
    </row> 
    <row r="2" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B2" t="s"> 
      <v>1</v> 
     </c> 
    </row> 
    <row r="3" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B3" t="s"> 
      <v>2</v> 
     </c> 
    </row> 
    <row r="4" spans="2:3" x14ac:dyDescent="0.25"> 
     <c r="B4" t="s"> 
      <v>3</v> 
     </c> 
    </row> 
</sheetData> 

1-4スプレッドシートにある行だけのように見えます。私の目標は、のために、すべての空の行を削除している

enter image description here

:行2は、私はこのXLS文書を持っている3に2から1、5、7行に移動し、8 4に

+0

あなたの答えに感謝しますが、うまくいきません:(多分私はよく分かりません)問題はあなたのコードで値がnullである行を削除しても何も削除されません。詳細が表示されます。[OK]を – ruzD

+0

は、私は誤解。答えは空の行を「削除」に変更されます。空の行(データがないもの)が実際にスプレッドシートから抜けているので、実際に私が行のギャップを検出しています。だから、このコードは実際になりますその空の行を「削除」するまで行をシフトします。行のデータが残っていれば(セルの空白の値)、これを検出して削除してから、次の行を上に移動します。 – jmarkmurphy

+0

、私は理解しやすい方法で内部表現を表示する方が簡単ですので、私は '.XLSX'を使用していました。どちらの形式はしかし、同様に動作します。 – jmarkmurphy

1

あなたが使用することはできません

sheet.removeRow(row) 

私はあなたのコードで見たように、あなたの行は、あなたが「in.xlsにNULLでない行のみを残しておきたい

nullです

out.xls 『"にそれらをファイルと書き込み』ので、私は、アルゴリズムをこのように変更することをアドバイスします:

Workbook wbOut = new HSSFWorkbook(); // or whatever workbook you'd like to use 
for (Sheet sheet : wb){ 
      Sheet newSheet = wbOut.createSheet(); 
      int newI = 0; 
      // Loop every rows of this sheet 
      int lastIndex = sheet.getLastRowNum(); 

      for (int i = ROW_START; i <= lastIndex; i++) { 
       // the exact opposite condition 
       if (sheet.getRow(i) != null && 
        sheet.getRow(i).getCell(COL_START) != null && 
        !sheet.getRow(i).getCell(COL_START).toString().equals("")){ 
        // row is not null so you can copy it to a new sheet 
        Row newRow = newSheet.createRow(newI++); 
        newRow = sheet.getRow(i); 
       } 
      } 
     } 
     // Save as in another file 
     FileOutputStream fileOut = new FileOutputStream("out.xls"); 
     wbOut.write(fileOut); 
     fileOut.flush(); 
     fileOut.close(); 

だから、あなたはあなたが最終的に書くことができる新しいワークブックにのみnullではない行をコピーします。

+0

そうだね、それは良い考えです。あなたが' .XLS'を使用している知っている! – ruzD

+0

Iテストされましたが、彼は新しいファイルは、元のファイルから値を書き込みません。コードをデバッグし、条件が正しい場合、newRowは作成されますが、その後はout.xlsファイルが空です。 – ruzD

+0

私はnewRow = sheet.getRow(i)であまりにもoptmisticだったかもしれませんが、私はあなたが行を構成するすべてのセルに値を割り当てる必要があると思います。 (http://stackoverflow.com/questions/5578535/get-cell-value-from-excel-sheet-with-apache-poi)のような たぶん何か[ここでは、セルの右の値を取得するためのコードです] : 'Row oldRow = sheet.getRow(i); int pos = 0; 一方(oldRow.getCell(POS)= NULL!){ newRow.createCell(POS).setCellValue(値)。 } ' ここで、 'value'はoldRowのセルの値です –

関連する問題