Home | ArchiveList | Category | About
» ArchiveList
Home > PC > C#
1
C#のClosedXMLで、Excelの行を削除しようとすると、たった一行なのに異様に時間がかかった挙げ句、アウトオブメモリーになるという事象に悩まされていました。

sheet.Row(1).Delete();


あまりにも簡単な構文だし、構文ミスしてたらそもそもビルドエラーになるので、かなり悩んでしまいました。

こういう場合に考えるべきことは、その行を削除した時に、計算式や条件付き書式などにより、他セルに影響が多数出ないか、という点でしょう。

今回の場合、ためしに条件付き書式をシートから全削除(ルールのクリア>シート全体からルールをクリア、で一操作で可能)してから行削除を試したところ、即座に削除処理が終わりました。
C#のClosedXMLにて、特定のセルを読み込むときだけ数分かかったりしてたのですが、原因が分かりました。

そのセルには計算式が記載されていて、最初の行あたりだと参照範囲が少ないので即座に終わるものの、行範囲していしていた場合は遅くなっている状況でした。

連番をつけるときに、セル飛び飛びになっても番号が続くように最初のあたり入れた式をコピペした場合、$指定しなかったら適時にその位置を元に計算式が書き換わっていて、Excel上で動く場合は問題ないんですが、

【計算式の例】

速い場合
=IF(K9="削除","",COUNT($A$8:A8)+1)
→COUNTの範囲が1セルしかない

遅い場合
=IF(K25="削除","",COUNT($A$8:A24)+1)
→COUNTの範囲が多数ある

仕方ないので、今回はExcelの連番をC#で振り直して計算式をなくした状態にして、修正後のファイルを読み込むようにしたところ速度改善されました。
ClosedXMLを使って、セルの文字色、背景色、右寄せの設定記載例です。

なお row,col の代わりに直接"A1"といった記載でも可能ですが、繰り返し処理を想定するなら row,col で書くのが便利かと思います。

// 文字色をデフォルトにする
sheet.Cell(row, col).Style.Font.SetFontColor(XLColor.NoColor);

// 背景色を白にする
sheet.Cell(row, col).Style.Fill.BackgroundColor = XLColor.White;

// 水平方向に右寄せにする
sheet.Cell(row, col).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Right;


なおExcel2017だと、オプション>数式>R1C1参照形式を使用する のチェックをオンにすれば、AやBといった列名が数値になるので、コーディング時は分かりやすいかと思います。
C#でClosedXMLを使う場合、拡張子がxlsxである必要があります。

xlsxは中身がxmlなので、単純に拡張子をxlsから変更しただけでは使えないので、通常はExcel操作でxlsxへ別名保存することになります。ファイルが一個くらいなら手動でもいいですが、大量にあった場合はC#で簡単なツールを作って、一括で処理したほうが圧倒的に楽ですね。
C#でExcelを扱う場合、いくつか手法があるようですが、ClosedXMLが直感的でメモリ解放とかの手間もなくて扱いやすいかと思います。
C#のLINQ to XMLは様々なことが出来て素晴らしいですが、出来ることが多すぎてやりたいことを見つけられない時もあるので(贅沢な悩み)、備忘としてまとめました。ここではXML要素の追加・変更・削除、および対象要素の存在チェックについて書きます。
概要

世の中には、ゲームのスクリーンショットをゲームごとに千〜万枚単位で保存して、それらの画像内のセリフで全てリネームして管理してる、というスクショ仙人が存在してるそうです。す、すげぇ……


ここまでするとは、もはや修行……

呆然としつつも、この作業が少しでも楽にならないかな……と思って、C#2017でOCRツールを作ってみました。

PS4 :1920x1080
Switch:1280x 720
vita : 960x 544
3DS : 400x 240

上記のサイズの画像をいれた指定フォルダのjpg,png,bmp画像を読み込み、プレビュー表示させ、OCRでそれなりの精度で文字列を読取り、手動である程度修正してからファイルをリネームする、といったツールになります。
1
Home | PageTop | RSS2.0 | ATOM