イージーエクセル
再現された
mob604756ef7d06 2021-09-15 15:28:00
記事ラベルデータエンティティ クラスソリューションApacheパッケージ記事分類コード 寿命読み取り番号1276
イージーエクセル
1. EasyExcel について知る
1.Apache POI
Apache POI
は、Apache Software Foundation のオープンソースの小規模プロジェクトMicrosoft Office
(であり。しかし、次のようないくつかの問題があります。
- 学習と使用のコストが高い
1. POI を深く理解している人は、POI にも (Dom 分析モードと比較して) SAX モードがあることを知っています。
Dom 解析モード: ドキュメントを一度にメモリにロードします。これにより大量のメモリが消費されます。
SAX モード: ドキュメントを 1 行ずつ読み取ります。これは Dom 解析モードを最適化したものです。
2. ただし、SAX モードは比較的複雑で、excel 03 (xls) と 07 (xlsx) の 2 つのバージョンがあり、データの保存方法がまったく異なり、SAX の分析方法も異なります。(バージョンによって解析方法が異なるため、学習コストがまた高くなります)
3. これら 2 つの分析方法を明確に理解したい場合は、コード テストを作成できます (所要時間は 2 日と見積もられます)。さらに、解析した後でも、独自のビジネス モデルに変換するには多くの面倒なコードが必要になります。全体としては少なくとも 3 日かかりますが、コードが複雑なため、その後のメンテナンスのコストが膨大になります。(学習コストと維持コストが高い)
4. POI の SAX モード API は、メモリ オーバーフローの問題をある程度解決できますが、Excel バージョン 07 の解凍と解凍後の保存がすべてメモリ上で完了し、メモリ消費量が依然として大きいなど、POI にはまだいくつかの欠陥があります。 POI の SAX を使用した 3M Excel 分析には、依然として約 100M のメモリが必要です。(07バージョンでもメモリ消費量が非常に多いです)
- POIは大量のメモリを消費します
POI の使用のほとんどは、userModel モードを使用することです。userModel の利点は、簡単に始められ、使いやすいことです。コードをコピーして実行するだけで、残りはビジネス変換を記述するだけです。変換には数百行のコードを記述する必要がありますが、比較的簡単です理解すること。ただし、userModel モードの最大の問題はメモリ消費量が非常に大きいことであり、数メガバイトのファイル解析で数百メガバイトのメモリを消費します。現在、多くのアプリケーションがこのモードを採用していますが、それらが正常に動作しているのは、同時実行数が大きくないためでしょう。同時実行数が増加すると、間違いなく OOM または頻繁なフル gc が発生します。(すぐに使い始めたい場合、メモリの消費量が非常に多く、同時実行性の高い環境ではメモリがオーバーフローしやすくなります)
一般に、単純な書き方は記憶に大きく依存し、複雑な書き方は習得に費用がかかります。ただし、POI の機能は依然として特に豊富で強力です。
2.イージーエクセル
1. EasyExcel は、Excel バージョン 07 の POI の分析を書き換え、メモリ消費量を約 100M から 10M 未満に削減でき、さらに大きな Excel でもメモリ オーバーフローは発生しません。(メモリ消費量は一桁少なくなります)
2. ただし、EasyExcel は Excel バージョン 03 の POI の SAX モードを引き続き使用します。
3. EasyExcelの効率も非常に高く、64Mメモリ環境下では75M(46W行25列)のExcelを1分以内に読み終えることができます。(良い成果)
4. 上位層はモデル変換用にパッケージ化されており、ユーザーにとってより簡単で便利です。(使い方は簡単)
一般に、使いやすく、メモリ消費量も少ない (OOM を効果的に回避できる) のですが、操作できるのは Excel だけであり、画像を読み取ることはできません。
2. クイックスタート
通常、Excel でコンテンツを読み取り、対応するエンティティ クラスでカプセル化して、最終的にデータベースに保存します。(エクセル読み取り)
または、データベース内のデータを対応するエンティティ クラスでカプセル化し、Excel に書き込みます。(Excel用に書く)
1. Excelの読み込み
1. 依存関係、easyexcel、lombok を導入する
<依存関係>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId >lombok</artifactId>
<バージョン>1.18.16</version>
</dependency>
easyExcellがApacheを含むpoiに依存していることが判明
2. Excel データに対応するエンティティ クラスを作成する
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student { private String id; プライベート文字列名。プライベート文字列の性別。プライベート 日付 誕生日; }
3. テスト クラスを作成し、Excel を読み取るための簡単なデモを作成します。
@Test
public void testReadExcel() { /*ワークブック読み取りオブジェクトを取得します。パラメーター 1: Excel ファイル パスパラメーター 2: データの各行に対応するエンティティ タイプパラメーター 3: 読み取りリスナー。読み取り行ごとに 1 回呼び出されます。リスナーのメソッド*/ ExcelReaderBuilder readWorkBook = EasyExcel.read("E:/Student Information.xlsx", Student.class, new StudentReadListener()); // ワークシートオブジェクトを取得ExcelReaderSheetBuilder Sheet = readWorkBook.sheet(); //ワークシートの内容を読み取りますsheet.doRead(); }
EasyExcel.read メソッドには、読み取られたデータの各行を処理するための読み取りリスナーが必要です。各行が読み取られると invoke メソッドがトリガーされ、読み取られたデータはエンティティにカプセル化されてパラメーターに渡されます。
public class StudentReadListener extends AnalysisEventListener<Student> { /** * EasyExcel は行を読み取るたびにこのメソッドを呼び出し、読み取られたデータを Student に保存します* @param Student 読み取られた各行のデータ* @param AnalysisContext */ @ Override public void invoke(Student Student, AnalysisContext AnalysisContext) { System.out.println(student); } /** * ドキュメント全体を読み取った後に呼び出されるメソッド* @param AnalysisContext */ @Override public void doAfterAllAnalysed(AnalysisContext AnalysisContext) { System.out.println("Excel はすべて読み取られています!"); } }
4. Excel を読み取るデモを実行し、結果を表示します。
2. Excelライティング
1. テスト クラスを作成し、Excel を作成するための簡単なデモを作成します。
@Test
public void testWriteExcel() { /*ワークブック書き込みオブジェクトの取得パラメーター 1: エクスポートされた Excel ファイルのパスパラメーター 2: データの各行に対応するエンティティの種類*/ ExcelWriterBuilder writeWorkBook = EasyExcel.write("E:/学生情報 2. xlsx", Student.class); // ワークシート オブジェクトを取得ExcelWriterSheetBuilder Sheet = writeWorkBook.sheet(); // 生徒データを準備List<Student> students = initData(); // ワークシートシートに書き込みます。 doWrite(students) ; } private List<Student> initData(){ List<Student> students = new ArrayList<>(); for (int i = 1; i <= 10; i++) { Student Student = new Student() ; student.setName ("学生"+i);学生.setBirthday(new Date());学生。setGender("男");
students.add(学生);
}
学生を帰国させる。
}
2. Excel で作成されたデモを実行し、結果を表示します。
質問:
- id欄を非表示にすることは可能でしょうか?
- ヘッダー名は変更できますか?
- テーブルヘッダーの列幅は変更できますか?
- 各列の順序を逆にすることはできますか?
3. 問題の最適化
1. ヘッダーの名前を変更します
1. 解決策: エンティティ クラス属性の名前によってテーブル ヘッダーの名前が決まり、エンティティ クラス属性に@ExcelProperty
注釈を、対応する名前の値を指定します。
public class Student { @ExcelProperty(value = "ID") // ヘッダーの名前を変更しますprivate String id; @ExcelProperty(value = "Student Name") // ヘッダーの名前を変更しますprivate String name; @ExcelProperty( value = "Student Gender") // ヘッダー名を変更private String 性別; @ExcelProperty(value = "Student Birthday") // ヘッダー名を変更private Date Birthday; }
2. Excel を作成するためのデモを再度実行します。結果は次のようになります。
2. ヘッダーの列幅を変更する
1. 解決策: エンティティ クラスの属性に@ColumnWidth
コメント。その値は Excel テーブルの列幅です。
public class Student { @ExcelProperty(value = "ID") private String id; @ExcelProperty(value = "Student Name") @ColumnWidth(20) // ヘッダーの列幅を変更しますprivate String name; @ExcelProperty(value = " Student sex") @ColumnWidth(20) // ヘッダーの列幅を変更private String 性別; @ExcelProperty(value = "Student's Birthday") @ColumnWidth(20) // ヘッダーの列幅を変更private Date 誕生日; }
2. Excel を作成するためのデモを再度実行します。結果は次のようになります。
クラスで
@ColumnWidth
アノテーションを、ヘッダー全体が同じ列幅になります。
3. 行高さの変更
1. Excel テーブルのコンテンツの行の高さを変更し、クラスに@ContentRowHeight
コメントを。値はコンテンツの行の高さのサイズです。
2. テーブルヘッダーの行の高さを変更し、クラスに@HeadRowHeight
コメント。その値はテーブルヘッダーの行の高さのサイズです。
@ContentRowHeight(10) // Excel テーブルのコンテンツの行の高さを変更します
@HeadRowHeight(15) // ヘッダーの行の高さを変更します
public class Student { @ExcelProperty(value = "ID") private String id; @ ExcelProperty(value = "生徒名") @ColumnWidth(20) private 文字列名; @ExcelProperty(value = "生徒の性別") @ColumnWidth(20) private String 性別; @ExcelProperty(value = "生徒の誕生日") @ColumnWidth( 20)プライベート日付誕生日; }
3. デモを実行して Excel を再度作成すると、結果は次のようになります。
4. 列の順序を変更する
1. エンティティクラスの属性の@ExcelProperty
アノテーション、列の位置に対応する属性インデックスを追加します。
注: インデックスは、0 から始まる列の位置に対応します。
インデックスが 1 から始まる場合、Excel シートの最初の列は空になります。
インデックスが 5 と書かれている場合、Excel シートの 6 列目に配置されます。
@ContentRowHeight(10)
@HeadRowHeight(15)
public class Student { @ExcelProperty(value = "ID", Index = 3) private String id; @ExcelProperty(value = "学生姓名", Index = 0) @ColumnWidth(20) private String name; @ExcelProperty(value = "学生性别", Index = 1) @ColumnWidth(20) private String 性別。@ExcelProperty(value = "学生生日", Index = 2) @ColumnWidth(20) private Date 誕生日; }
2. Excel を作成するためのデモを再度実行します。結果は次のようになります。
5. Excelの読み込みについて
1.@ExcelProperty
アノテーション、Excel テーブルの左から右の列の値がエンティティ クラスの上から下の属性に読み込まれます。
2. エンティティ クラスの属性に@ExcelProperty(value = "学生姓名", index = 0)
アノテーション、同じヘッダ名と「生徒名」を持つ列の値が値 value に従って検索され、エンティティ クラスの属性に格納されます。最初 (0) インデックスに従って検索できます+1) 列の値はエンティティ クラスの属性に格納されます。
Excel によって読み取られるエンティティ クラスの場合は、すべての属性に
@ExcelProperty
注釈が付けられ、すべての属性が @ExcelProperty(value="xxx")
値で一致するか、すべての属性が列数@ExcelProperty(index=x)
でお勧めします。3 つを混合しないことをお勧めします。 。
6. 非表示の列を指定します
1. 解決策: エンティティ クラスで非表示にする必要がある属性に@ExcelIgnore
注釈と、このデータは Excel に書き込まれたり、Excel から読み取られたりしなくなります。
@ContentRowHeight(10)
@HeadRowHeight(15)
public class Student { @ExcelIgnore // プロパティを無視し、読み取りおよび書き込みには関与しませんprivate String id; @ExcelProperty(value = "Student Name", Index = 0) @ColumnWidth(20) ) private String 名; @ExcelProperty(value = "学生の性別", インデックス = 1) @ColumnWidth(20) private String 性別; @ExcelProperty(value = "学生の誕生日", インデックス = 2) @ColumnWidth(20) private 日付 誕生日; }
2. Excel を作成するためのデモを再度実行します。結果は次のようになります。
クラス に
@ExcelIgnoreUnannotated
注釈を。この注釈を追加すると、エンティティ クラスの属性の @ExcelProperty 注釈のみが読み取りと書き込みに参加します。
7. 日付形式の変換
1. 解決策: エンティティ クラスの date 属性に@DateTimeFormat
アノテーション。値は日付形式になります。
@ContentRowHeight(10)
@HeadRowHeight(15)
public class Student { @ExcelProperty(value = "ID",index = 3) @ExcelIgnore private String id; @ExcelProperty(value = "生徒名",index = 0) @ColumnWidth( 20)プライベート文字列名; @ExcelProperty(値 = "学生の性別", インデックス = 1) @ColumnWidth(20)プライベート文字列の性別; @ExcelProperty(値 = "学生の誕生日", インデックス = 2) @ColumnWidth(20) @DateTimeFormat ("yyyy-MM-dd") // 日付形式を変更しますprivate Date 誕生日; }
2. Excel を作成するためのデモを再度実行します。結果は次のようになります。
数値型の形式も指定可能で、エンティティクラスのnumber属性に
@NumberFormat
アノテーションをjava.text.DecimalFormat
。
8. 複数のヘッダーの書き込み
1. 解決策: エンティティクラスの@ExcelProperty
アノテーション、複数の値を追加できることがわかります。
2. 1 つの属性のアノテーションに複数の値のみを追加する場合は、その効果を確認します。
公開授業 学生 {
@ExcelIgnore
private String id;
@ExcelProperty(value = {"学生情報フォーム", "学生名"}, Index = 0)
@ColumnWidth(20)
private String name;
@ExcelProperty(value = "学生の性別", Index = 1 )
@ColumnWidth(20)
private String 性別;
@ExcelProperty(value = "生徒の誕生日", Index = 2)
@ColumnWidth(20)
@DateTimeFormat("yyyy-MM-dd")
private Date 誕生日;
}
3. すべての属性のアノテーションに複数の値を追加すると、その効果を確認し、ヘッダーが自動的にマージされることを確認すると、同じ値を持つヘッダー属性が自動的にマージされることがわかります。
public class Student { @ExcelIgnore private String id; @ExcelProperty(value = {"学生情報テーブル","学生名"}, Index = 0) @ColumnWidth(20) private String name; @ExcelProperty(value = {"学生情報Table","生徒の性別"},index = 1) @ColumnWidth(20) private String 性別; @ExcelProperty(value = {"生徒情報テーブル", "生徒の誕生日"},index = 2) @ColumnWidth(20) @ DateTimeFormat("yyyy-MM-dd")プライベート日付 誕生日; }
複数のヘッダーを持つ Excel を読み取る場合、ExcelReaderBuilder の headRowNumber(Integer num) メソッドを使用して、最初の num 行をスキップしてデータを読み取ることができます。
2 が設定されている場合、テーブル ヘッダーの最初の 2 行をスキップし、3 行目からデータの読み取りを開始します。
4. レポートの記入
1. EasyExcel は行の高さ、列の幅、背景色、フォント サイズなどの調整をサポートしていますが、制御方法はネイティブ POI を使用するのと同じであるため、煩雑で推奨されません。
2. 通常、最初に数セットの Excel テンプレートを作成しますが、テンプレートにはデータは保存されず、レポートのスタイルのみが保存されます。
3. この時点では、easyExcel を使用してレポート データを入力する必要があります。
1. 単一のデータ入力
1. テンプレートを準備する
Excel の表では、入力する変数を囲むために {} が使用されています。セルのテキスト{
に}
左右の中\{
括弧がある場合は、括弧の前でスラッシュを使用してエスケープする必要があります\}
。
コード内のデータの入力に使用されるエンティティ オブジェクトのメンバー変数名、または入力されたマップ コレクションのキーは、Excel で {} で囲まれた変数名と一致している必要があります。
テンプレートのファイル名はここでは次のようにexcel_template_01.xlsx
名前が付けられています
2.エンティティクラスの準備
@Data
public class FillData { private String 名; プライベートの年齢。}
3. 充填デモを作成する
@Test
public void testFullExcel() { // ワークブック オブジェクトExcelWriterBuilder を取得します writeWorkBook = EasyExcel.write("E:/Fill a set of data.xlsx", FillData.class) .withTemplate("E:/excel_template_01.xlsx") ; // withTemplate はテンプレート ファイルを指定します// ワークシート オブジェクトを取得しますExcelWriterSheetBuilder Sheet = writeWorkBook.sheet(); // データを入力する準備をしますFillData fillData = new FillData(); fillData.setName("Xiaoming"); fillData.setAge( 18) ; // ワークシートに書き込みますsheet.doFill(fillData); // doFill で塗りつぶしを開始します}
2. 複数セットのデータ入力
1. テンプレートを準備する
単一データのテンプレートと同様に、中括弧の前に を.
追加
テンプレートのファイル名はここでは次のようにexcel_template_02.xlsx
名前が付けられています
2. 充填デモを作成する
追加(fillData); fillDataList を返します。
}
3. 結合されたデータ入力
単一のデータと複数のデータ セットがあります。
1. テンプレートを準備する
つまり、複数のデータ埋め込みと単一データ埋め込みがあり、2つのデータの競合や上書きを避けるために、複数セットを埋め込む際にはFillConfig
オブジェクト
2. 充填デモを作成する
@Test
public void testFullExcel() { ExcelWriter writeWorkBook = EasyExcel.write("E:/combined fill.xlsx", FillData.class) .withTemplate("E:/excel_template_03.xlsx").build(); // を取得Worksheet オブジェクトWriteSheet writeSheet = EasyExcel.writerSheet().build(); // データを入力する準備をしますList<FillData> fillDataList = this.initFillData(); Map<String,String> dateAndTotal = new HashMap<>(); dateAndTotal. put("date","2021-9-15"); dateAndTotal.put("total","10086"); // 複数のグループが入力しますwriteWorkBook.fill(fillDataList,writeSheet); // 単一のグループが入力しますwriteWorkBook.fill (dateAndTotal,writeSheet); // ストリームを閉じることを忘れないでください! writeWorkBook.finish(); }
テストの結果、複数グループの塗りつぶしが前にある場合、複数グループの塗りつぶしの後に新しい行が追加されず、後続の単一グループの塗りつぶしによって前の複数グループの塗りつぶしの値が上書きされることがわかりました。
3. 単一のデータを複数のデータの前に置くことも、複数のグループのパディングを設定する必要がある場合に行を追加することも、FillConfig
オブジェクト
@Test
public void testFullExcel() { ExcelWriter writeWorkBook = EasyExcel.write("E:/combined fill.xlsx", FillData.class) .withTemplate("E:/excel_template_03.xlsx").build(); // を取得Worksheet オブジェクトWriteSheet writeSheet = EasyExcel.writerSheet().build(); // データを入力する準備をしますList<FillData> fillDataList = this.initFillData(); Map<String, String> dateAndTotal = new HashMap<>(); dateAndTotal. put("date", "2021-9-15"); dateAndTotal.put("total", "10086"); // FillConfig を入力した後に改行fillConfig = FillConfig.builder().forceNewRow(true).build( ) ; // 複数グループの塗りつぶし、塗りつぶし後は改行が必要ですwriteWorkBook.fill(fillDataList, fillConfig,writeSheet); // 単一グループの充填writeWorkBook.fill(dateAndTotal, writeSheet);
// ストリームを閉じます、覚えておいてください!
writeWorkBook.finish();
}
4. 水平方向のデータ充填
データは、デフォルトのように下方向ではなく、右方向に水平に埋められます。
1. テンプレートを準備する
2. 塗りつぶしのデモを作成します。FillConfig
オブジェクト。
@Test
public void test水平Excel() { ExcelWriter writeWorkBook = EasyExcel.write("E:/水平 Fill.xlsx", FillData.class) .withTemplate("E:/excel_template_04.xlsx").build(); // を取得します。 Worksheet オブジェクトWriteSheet writeSheet = EasyExcel.writerSheet().build(); // データを入力する準備をしますList<FillData> fillDataList = this.initFillData(); Map<String, String> dateAndTotal = new HashMap<>(); dateAndTotal. put("date", "2021-9-15"); dateAndTotal.put("total", "10086"); // FillConfig を水平方向に塗りつぶしますfillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build( ); // 複数の塗りつぶしグループを水平方向に塗りつぶす必要があるwriteWorkBook.fill(fillDataList, fillConfig,writeSheet); // 単一グループの入力
writeWorkBook.fill(dateAndTotal, writeSheet);
// ストリームを閉じることを忘れないでください!
writeWorkBook.finish();
}
この記事は複製されたコンテンツであり、記事に関する元の著者の著作権を尊重します。内容に誤りや著作権侵害がある場合は、元の著者に連絡して内容を修正または記事を削除してください。