C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: DBNullの入ったDataRowをExcelに出力


(過去ログ 29 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■13781 / inTopicNo.1)  DBNullの入ったDataRowをExcelに出力
  
□投稿者/ 春紫苑 (8回)-(2008/02/04(Mon) 21:25:29)

分類:[.NET 全般] 

現在、DataTable に格納されているデータを Excel に出力するプログラムを作成しています。

セルの1つ1つに値を設定するのは遅いので、
DataTable の内容をいったん2次元配列に格納し、
それを range.FormulaArray プロパティを使ってまとめてセットしています。

しかし DataTable の中に DBNull を含む行がある場合、
COMException が発生してしまいます。
調べてみたところ Excel 内部で、書き込まれた値をもとに列の型を決定しているようでした。
そのため、たとえば日付を出力していた列に DBNull を書き込もうとしてが例外発生…。

セルに1つ1つセットするようにし、DBNull のときは飛ばすようにすれば可能かな?
とは思いました。ですが、速度があまりに遅いので、できることならまとめてセット
したいのですが…。

手詰まりな状況です。

どうかお力を貸していただけませんか?

ちなみに、Excel 形式での出力には
Microsoft Excel 12.0 Object Library を使っています。

宜しくお願いします。
引用返信 編集キー/
■13782 / inTopicNo.2)  Re[1]: DBNullの入ったDataRowをExcelに出力
□投稿者/ やじゅ (96回)-(2008/02/04(Mon) 22:06:10)
やじゅ さんの Web サイト
2008/02/04(Mon) 22:53:39 編集(投稿者)

No13781 (春紫苑 さん) に返信
> しかし DataTable の中に DBNull を含む行がある場合、
> COMException が発生してしまいます。
> 調べてみたところ Excel 内部で、書き込まれた値をもとに列の型を決定しているようでした。
> そのため、たとえば日付を出力していた列に DBNull を書き込もうとしてが例外発生…。
>
> セルに1つ1つセットするようにし、DBNull のときは飛ばすようにすれば可能かな?
> とは思いました。ですが、速度があまりに遅いので、できることならまとめてセット
> したいのですが…。
>

手っ取りはやいのは
例外が発生されるであろう行または例外が発生した行のみ、セルに1つ1つセットして
それ以外はまとめてセットする。

↓も見つけたのでリンク
Excelに最速でデータをセットする方法(VB.NETの場合)
http://laika.e-dog.to/index.php?itemid=766
引用返信 編集キー/
■13784 / inTopicNo.3)  Re[1]: DBNullの入ったDataRowをExcelに出力
□投稿者/ 特攻隊長まるるう (119回)-(2008/02/04(Mon) 22:31:09)
No13781 (春紫苑 さん) に返信
2次元配列を加工すればいいだけの話では?
引用返信 編集キー/
■13786 / inTopicNo.4)  Re[2]: DBNullの入ったDataRowをExcelに出力
□投稿者/ 春紫苑 (9回)-(2008/02/04(Mon) 23:10:32)
No13784 (特攻隊長まるるう さん) に返信
> ■No13781 (春紫苑 さん) に返信
> 2次元配列を加工すればいいだけの話では?
引用返信 編集キー/
■13787 / inTopicNo.5)  Re[3]: DBNullの入ったDataRowをExcelに出力
□投稿者/ 春紫苑 (10回)-(2008/02/04(Mon) 23:11:16)
すみません、間違って送信してしまいました。


> 2次元配列を加工すればいいだけの話では?

DBNull のときはセルを空にしなければいけないため頭を悩ませています。

文字列なら string.Empty でそれっぽく出力できますが、
数値のときに 0 を使うと空にはなりませんし。


引用返信 編集キー/
■13800 / inTopicNo.6)  Re[4]: DBNullの入ったDataRowをExcelに出力
□投稿者/ 特攻隊長まるるう (122回)-(2008/02/05(Tue) 07:55:30)
2008/02/05(Tue) 07:56:02 編集(投稿者)

No13787 (春紫苑 さん) に返信
> DBNull のときはセルを空にしなければいけないため頭を悩ませています。
Nothing を設定?
引用返信 編集キー/
■13829 / inTopicNo.7)  Re[5]: DBNullの入ったDataRowをExcelに出力
□投稿者/ 春紫苑 (11回)-(2008/02/05(Tue) 14:47:14)
しまった。頭が茹っていたせいで、環境を書いてませんでした。
Windows Vista, Visual Studio 2005, C# です。

No13800 (特攻隊長まるるう さん) に返信
> 2008/02/05(Tue) 07:56:02 編集(投稿者)
>
> ■No13787 (春紫苑 さん) に返信
>>DBNull のときはセルを空にしなければいけないため頭を悩ませています。
> Nothing を設定?

C# なので Nothing の代わりになるのは Type.Missing や Missing.Value
ですが、ためしにこれをそのまま使っても駄目でした。

いろいろと調べてみても、やはり列に違う型が混在する場合、
その箇所だけはセル単位で値をセットする方法がほとんどでした。

DBNull が混在してようが一括でセットしようというのは
やはり無理なのでしょうか…。

引用返信 編集キー/
■13832 / inTopicNo.8)  Re[6]: DBNullの入ったDataRowをExcelに出力
□投稿者/ やじゅ (102回)-(2008/02/05(Tue) 15:20:37)
No13829 (春紫苑 さん) に返信
>
>セルの1つ1つに値を設定するのは遅いので
>

この際、発想を変えるってのもありかも

Excelに最速でデータをセットする方法(VB.NETの場合)
http://laika.e-dog.to/index.php?itemid=766
引用返信 編集キー/
■13860 / inTopicNo.9)  Re[6]: DBNullの入ったDataRowをExcelに出力
□投稿者/ 七曜 (72回)-(2008/02/05(Tue) 19:45:24)
No13829 (春紫苑 さん) に返信
> Windows Vista, Visual Studio 2005, C# です。

セットするExcelのシートにフォーマットがある場合にうまく動くかどうかわかりませんが、
Range.Value2に配列を設定するのでは、目的に合わないのかな?
#これだとDbNullのままでも平気みたいな・・・。

試したのはこんなコードです。

            DataSet1 ds = new DataSet1();
            DataSet1TableAdapters.EmployeesTableAdapter adapter = new ExcelConsole.DataSet1TableAdapters.EmployeesTableAdapter();
            adapter.Fill(ds.Employees);
            Object[,] excelArray = new Object[ds.Employees.Rows.Count, ds.Employees.Columns.Count];
            Int32 rowNumber = 0;
            Int32 colNumber = 0;
            foreach (DataSet1.EmployeesRow row in ds.Employees.Rows)
            {
                foreach (DataColumn column in ds.Employees.Columns)
                {
                    if (row[column] == DBNull.Value)
                    {
                        Console.WriteLine("{0}:{1}", column.ColumnName, "DbNull");
                    }
                    //excelArray[rowNumber, colNumber] = (row[column] == DBNull.Value) ? null : row[column];
                    excelArray[rowNumber, colNumber] = row[column];
                    colNumber++;
                }
                rowNumber++;
                colNumber = 0;
            }

            Application xlApp = new Application();
            xlApp.Visible = true;
            Workbooks xlbooks = xlApp.Workbooks;
            Workbook xlbook = xlbooks.Add("");
            Sheets xlsheets = xlbook.Worksheets;
            Worksheet xlsheet = xlsheets[1] as Worksheet;
            Range xlrange = xlsheet.get_Range(xlsheet.Cells[1, 1], xlsheet.Cells[ds.Employees.Rows.Count, ds.Employees.Columns.Count]);
            xlrange.Value2 = excelArray;
            Marshal.ReleaseComObject(xlrange);
            Marshal.ReleaseComObject(xlsheet);
            Marshal.ReleaseComObject(xlsheets);
            xlbook.Saved = true;
            Marshal.ReleaseComObject(xlbook);
            Marshal.ReleaseComObject(xlbooks);
            xlApp.Quit();
            Marshal.ReleaseComObject(xlApp);


Rangeの大きさとか、ReleaseComObjectとかは割と適当に書いていますので、適宜確認して下さい。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -