C#でExcelのセルデータを高速アクセス

ExcelオートメーションサーバーでセルデータをC#の2次元配列に入れる方法です。
今まで、Excelのセルデータをちまちま読んで、配列に展開していたのですが、
まとめてドカンと配列に取得する方法を学習したので、メモとして残しておきます。  ■従来やっていた方法 
WorkSheetにCellsプロパティがあるので、従来はこれを使用していました。
Cellsは、行、列の引数に数値を与えられるので、ループさせて処理を行うのが便利です。
これで2次元配列として扱うことが可能になるので、プログラムから目的のセルにアクセスできます。
ただし、これがそこそこ遅い感じで、少ない場合は問題がないのですが、大きい表を扱おうとすると、
結構待たされます。高速化が、悩みの種でした。  ■C#の2次元配列にセルデータを読み出す。 
MSのサイトで、高速にまとまったセルデータの読み出し方法が解説されていました。
RangeオブジェクトのValueプロパティを使用する方法で、C#で宣言した2次元配列にまとめて
セルデータを転送しています。
試しにこのサンプルを実行してみたところ、満足する速度が得られました。
参照 http://support.microsoft.com/default.aspx?scid=kb;ja;302096 
ソースを読むと、Objectの2次元配列を作って、範囲を指定したRangeオブジェクトの
Valueプロパティを使って読み出しているのがキーポイントなのが分かります。

---引用---
//Get a range of data.
range = objSheet.get_Range("A1", "E5");

//Retrieve the data from the range.
Object[,] saRet;

//EXCEL9 Use:
saRet = (System.Object[,])range.Value;

//EXCEL10 Use:
//saRet = (System.Object[,])range.get_Value( Missing.Value );

----------
このソースを見ると、バージョン10では、Valueプロパティの読み出し用アクセス関数の
get_Valueを直接呼び出しています。
何故、バージョン10では、Valueプロパティが使えないのかは、謎です。
試しにバージョン10のタイプライブラリで、バージョン9用のコードをコンパイルしたところ、
見事にエラーになりました。やはりバージョン10では、Valueプロパティは使えないようです。

具体的なEXCELバージョンと商品名の対応は
バージョン9 	EXCEL2000
バージョン10 	EXCEL XP
バージョン11 	EXCEL 2003
となっています。
試したところ、バージョン10のタイプライブラリで、バージョン11は動作します。


オブジェクト配列には、設定された様々な型が入ってきますが、一般的にはstring型として取得するために、
ToStringメソッドを使います。
(例)string mydata=saRet[row,col].ToString();
これによってオブジェクトの中身を文字型として得ることができます。


読み出しが可能であれば、書き込みもまた可能です。
オブジェクトの2次元配列をセルへ書き込むのも、似たような手順で簡単にできます。
---引用---
//Set the range value to the array.
//EXCEL9 Use:
range.Value = saRet;
//EXCEL10 Use:
//range.set_Value(Missing.Value, saRet );
----------

書き込みたい大きさのオブジェクトの2次元配列を作り、ここに文字列をポイポイ放り込みます。
次に、EXCELへ書き込みたい領域のRangeオブジェクトを作ります。
後は、上記のようにRangeオブジェクトのValueに対して代入すると、セルに展開することができます。


オブジェクトの配列を使って、EXCELのセルに対して、読み出し、書き込みが可能になるのですが、
文字列として読み出した場合には、書式や色情報等が失われます。
個人的には、文字列の取得のみでOKでしたので、深くは追求していませんが、書式等が必要な場合は、
Rangeオブジェクトで直接セルを操作することになると思います。  ■EXCELの使用セル範囲の取得時の問題点。 
WorkSheetのプロパティでUsedRangeがあり、これで現在のシートの使用有効範囲を取得できます。
ところが、表によっては、見た目の範囲以上の領域を返すことがあり、これが疑問でした。
調べていくと、遠く離れたセルに一旦、何かを入力して、バックスペースで文字を消したような場合が原因でした。
見た目では何も入っていないように見えるのですが、データ的にはヌル文字が格納されていますので、
有効範囲を取得すると、そこまでを範囲と認識していまいます。
これといった対策はないのですが、現在の有効範囲から、トリミングを行うのが、簡単かもです。
1 最下行から上に向かって、セルデータを読み出し、何も入っていない場合に行の有効範囲を縮める。
2 最右列から左にむかって、セルデータを読み出し、何も入っていない場合に列の有効範囲を縮める。

で、これにWorkSheetのCellsを使うと遅くてダメです。
なので、一旦、有効範囲のセルデータを2次元配列に読み出し、これに対してトリミングを行い、
正味の有効範囲を確定させます。

© Rakuten Group, Inc.
X
Design a Mobile Site
スマートフォン版を閲覧 | PC版を閲覧
Share by: