範囲の自動調整をしないようにする
通常、ClosedXML は挿入・削除の処理を追跡し、関連する範囲を適切に調整します。以下はその例です。
Dim testRow = worksheet.Row(1) worksheet.Row(1).InsertRowsAbove(1) 'ここで testRow が指しているのはワークシートの2行目(1行目ではない)
もしもこの調整が不要な場合は、調整を行わないようにできます。そうすることにより、メモリの節約とパフォーマンスの改善が期待できます。
この機能をオフにするには、ワークブックを開く際の引数として XLEventTracking.Disabled を指定します。
適切なラムダ式を使用する
.Where などにすべてのオブジェクトを渡すかわりに、Cells/Rows/Columns のメソッドに述部を与えることを検討してください。
改善の余地があるやり方
For Each row in worksheet.RowsUsed.Where(Function(r) r.FirstCell.GetString = "A") 'row に対する処理 Next
適切なやり方
Dim rows = worksheet.RowsUsed(Function(r) r.FirstCell.GetString = "A") For Each row in rows 'row に対する処理 Next
元記事では rows に対して Using を使うように書かれているが、rows (IXLRows) には System.IDisposable が実装されていないので Using を使うことはできない。
改善の余地があるやり方
Dim column = range.Columns.First(Function(c) c.FirstCell.GetString = "A")
適切なやり方
Dim column = range.FirstColumnUsed(Function(c) c.FirstCell.GetString = "A")
Using キーワードの使用
ワークブックのイベント追跡をオフにしている場合、Using キーワードは不要です。詳細については「範囲の自動調整をしないようにする」を参照してください。
ループ内で範囲を表すオブジェクトを処理する場合は Using キーワードを使用してください。これにはワークブック、ワークシート、行(row, rows)、列(column, columns)が含まれます。
下記のサンプルコードで処理しているのは大きなファイルだと考えてください。
改善の余地があるやり方
Dim wb = New XLWorkbook Dim ws = wb.Worksheets.Add("Sheet1") For ro As Integer = 1 To 1000000 ws.Row(ro).FirstCell.Value = ro Next
適切なやり方
Using wb = New XLWorkbook 'worksheet は workbook によって破棄されるため、 'worksheet に対して Using を使用する必要はありません。 'worksheet はループの中で作成されているのではなく、 'worksheet の使用後すぐに workbook が破棄されます。 Dim ws = wb.Worksheets.Add("Sheet1") For ro As Integer = 1 To 1000000 Dim row = ws.Row(ro) row.FirstCell().Value = ro Next End Using
元記事では row に対しても Using を使うように書かれているが、row (IXLRow) には System.IDisposable が実装されていないので Using を使うことはできない。
改善の余地があるやり方
Dim wb = new XLWorkbook For wsNum As Integer = 1 To 10 Dim ws = wb.Worksheets.Add("Sheet" & wsNum) 'worksheet の処理 Next
適切なやり方
Using wb = New XLWorkbook For wsNum As Integer = 1 To 10 Dim ws = wb.Worksheets.Add("Sheet" & wsNum) 'worksheet の処理 Next End Using
元記事では ws に対しても Using を使うように書かれているが、ws (IXLWorksheet) には System.IDisposable が実装されていないので Using を使うことはできない。
パフォーマンスの改善に役立つその他のこと
- セルを取得するときは文字列ではなく数値を使用するようにしてください。たとえば Cell(“A1”) とするのではなく Cell(1, 1) と指定します。小さなシートではこの違いをほとんど感じられませんが、何万ものセルを処理する場合には無視できないものになります。
- ループの中で行や列の挿入・削除をしないでください。それよりも挿入する行や列の数を計算してから一度に処理したほうがずっと高速です。なぜなら、挿入や削除を行うたびに、ライブラリがすべての式を再計算することになるからです。
範囲の取得に便利なメソッド
最初・最後の行や列の取得は、頻繁に必要となる処理です。毎回めんどうなコードを書かなくても下記のメソッドが使用できます。
range.FirstCell range.FirstCellUsed range.FirstColumn range.FirstColumnUsed range.FirstRow range.FirstRowUsed range.LastCell range.LastCellUsed range.LastColumn range.LastColumnUsed range.LastRow range.LastRowUsed
使用済みの範囲を計算する必要もありません。次のコードを利用してください。
worksheet.RangeUsed