web-dev-qa-db-ja.com

Javaで2つのExcelファイルを比較する最も簡単な方法は?

Excelファイル(バイナリ)を生成するコードのJUnitテストを書いています。期待される出力を含む別のExcelファイルがあります。実際のファイルを期待されるファイルと比較する最も簡単な方法は何ですか?

確かに自分でコードを書くことはできますが、信頼できるサードパーティライブラリ(SpringやApache Commonsなど)にすでにこれを行っている既存のメソッドがあるかどうか疑問に思いました。

17
Andrew Swan

これが私がやったことです(重労働は DBUnit によって行われています):

/**
 * Compares the data in the two Excel files represented by the given input
 * streams, closing them on completion
 * 
 * @param expected can't be <code>null</code>
 * @param actual can't be <code>null</code>
 * @throws Exception
 */
private void compareExcelFiles(InputStream expected, InputStream actual)
  throws Exception
{
  try {
    Assertion.assertEquals(new XlsDataSet(expected), new XlsDataSet(actual));
  }
  finally {
    IOUtils.closeQuietly(expected);
    IOUtils.closeQuietly(actual);
  }
}

これにより、2つのファイルのデータが比較され、異なる可能性のある無関係なメタデータからの誤検知のリスクはありません。これが誰かを助けることを願っています。

9
Andrew Swan

あなたは私のプロジェクトを使用することを検討するかもしれません simple-Excel それは仕事をするためにたくさんのHamcrestMatchersを提供します。

次のようなことをすると、

assertThat(actual, WorkbookMatcher.sameWorkbook(expected));

たとえば、

Java.lang.AssertionError:
Expected: entire workbook to be equal
     but: cell at "C14" contained <"bananas"> expected <nothing>,
          cell at "C15" contained <"1,850,000 EUR"> expected <"1,850,000.00 EUR">,
          cell at "D16" contained <nothing> expected <"Tue Sep 04 06:30:00">
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.Java:20)

そうすれば、自動化されたテストから実行して、開発中に意味のあるフィードバックを得ることができます。

あなたはそれについてもっと読むことができます 私のサイトのこの記事

12
Toby

簡単なファイル比較は、チェックサム(MD5など)を使用するか、両方のファイルを読み取るだけで簡単に実行できます。

ただし、Excelファイルには大量のメタデータが含まれているため、James Burgessが指摘したように、ファイルがバイトごとに同一になることはおそらくありません。したがって、テストには別の種類の比較が必要になります。

どういうわけか、Excelファイルから「正規の」フォームを生成することをお勧めします。つまり、生成されたExcelファイルを読み取り、確認したい情報のみを保持するより単純な形式(CSVなど)に変換します。次に、「正規形式」を使用して、期待される結果と比較できます(もちろん、正規形式でも)。

Apache POI ファイルの読み取りに役立つ場合があります。

ところで:ファイル全体を読み取ってその正しさを確認することは、通常、単体テストとは見なされません。それは統合テストです...

6
sleske

私は同様のことをする必要があり、Excelファイルを作成するためにプロジェクトですでに Apache POIライブラリ を使用していました。そこで、含まれている ExcelExtractor インターフェイスを使用して、両方のブックをテキストの文字列としてエクスポートすることを選択し、文字列が等しいことを表明しました。 。xlsの場合はHSSF。xlsxの場合はXSSF の両方の実装があります。

文字列にダンプ:

XSSFWorkbook xssfWorkbookA = ...;
String workbookA = new XSSFExcelExtractor(xssfWorkbookA).getText();

ExcelExtractorには、文字列ダンプに何を含めるかについていくつかのオプションがあります。シート名を含めるという便利なデフォルトがあることがわかりました。さらに、セルのテキストコンテンツが含まれます。

4
joshden

Javaxdeltaを使用して、2つのファイルが同じであるかどうかを確認できます。ここから入手できます:

http://javaxdelta.sourceforge.net/

2
Jon

私が見つける最も簡単な方法は、Tikaを使用することです。私はそれを次のように使用します:

private void compareXlsx(File expected, File result) throws IOException, TikaException {
     Tika tika = new Tika();
     String expectedText = tika.parseToString(expected);
     String resultText = tika.parseToString(result);
     assertEquals(expectedText, resultText);
}


<dependency>
    <groupId>org.Apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.13</version>
    <scope>test</scope>
</dependency>
2
BuckBazooka

Kotlinの最初のシートのコンテンツのみをテストします(Javaに簡単に変換できます)。

_private fun checkEqualityExcelDocs(doc : XSSFWorkbook, doc1 : XSSFWorkbook) : Boolean{
        val mapOfCellDoc = doc.toList().first().toList().flatMap { row -> row.map { Pair(PivotExcelCreator.IndexInThePivotTable(it.rowIndex,it.columnIndex),it.stringCellValue) }}.toMap()
        val mapOfCellDoc1 = doc1.toList().first().toList().flatMap { row -> row.map { Pair(PivotExcelCreator.IndexInThePivotTable(it.rowIndex,it.columnIndex),it.stringCellValue) }}.toMap()
        if(mapOfCellDoc.size == mapOfCellDoc1.size){
            return mapOfCellDoc.entries.all { mapOfCellDoc1.containsKey(it.key) && mapOfCellDoc[it.key] == mapOfCellDoc1[it.key]}
        }
        return false
    }

data class IndexInThePivotTable(val row: Int, val col: Int)
_

そしてあなたのコードにassertを追加します

_    assertTrue(checkEqualityExcelDocs(expected, actual), "Docs aren't equal!")
_

ご覧のとおり、doc.toList().first()はドキュメントの最初のシートのみを取得します。各シートを比較する必要がある場合は、それぞれコードを少し変更してください。

また、空の文字列セルを考慮しないことをお勧めします。この機能は必要ありませんでした(また、必要に応じて、この部分を追加するだけです)。


また、それは有用な情報になることができます

_//first doc I've got from outputstream such way
val out = ByteArrayOutputStream()
//some method which writes Excel to outputstream
val firstDoc = XSSFWorkbook(ByteArrayInputStream(out.toByteArray()))
_

比較するファイルからの2番目のドキュメント

_val secondDoc = XSSFWorkbook(Test::class.Java.getClassLoader().getResource("yourfile.xlsx").path)
_
0
Alex

Commons-ioの FileUtils に何かがあることがわかりました。他の答えをありがとう。

0
Andrew Swan
0
Tiger

Beyond Compare を使用できます。これはコマンドラインから開始でき、Excelファイルを比較するさまざまな方法をサポートしています。

  • Excelシートをデータベーステーブルとして比較する
  • すべてのテキストコンテンツを確認する
  • いくつかのフォーマットでテキストコンテンツをチェックする
0
Wernight