C# Excel遅延バインディングで操作の方法とクリアできない問題

このQ&Aのポイント
  • C#でExcelファイルを出力するプログラムを作成している際に、バージョンの制約に遭遇し、遅延バインディング仕様に作り変えている最中です。
  • 解決できない問題が2つあります。1つ目は枠線を引く処理で発生する例外(0x800A03EC)の解決方法が分からず困っています。
  • 2つ目はファイル保存時の拡張子の指定方法です。遅延バインディングを使用する場合に、保存する拡張子を統一したいのですが、方法がわかりません。
回答を見る
  • ベストアンサー

C# Excelを遅延バインディングで操作する方法

いつもお世話になっております 只今C#でExcelファイルを出力するプログラムを作成しています。 以前やり方が分からずここに質問し、なんとかExcelに出力できるようになったのですが Excelのバージョンが2007にしか対応していないことが分かり 遅延バインディング仕様に作り変えている最中です。 ところが、あと少しというところでクリアできない問題が2つ出てきたので、質問させていただきます。 1つは枠線を引く処理です。現在以下のように記述していますが どうしても例外が発生してしまいます(0x800A03EC) Type line = Type.GetTypeFromProgID("Excel.XlLineStyle.xlContinuous"); Type insidevertical = Type.GetTypeFromProgID("Excel.XlBordersIndex.xlInsideVertical"); Object tempA = objRange.GetType().InvokeMember("Borders", BindingFlags.GetProperty, null, objRange, null); Object tempB = tempA.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, tempA, new object[] { insidevertical }); tempB.GetType().InvokeMember("LineStyle", BindingFlags.SetProperty, null, tempB, new object[] { line }); これがどう解決していいかわかりません・・・ 遅延バインディングという手法も最近知ったばかりで、見よう見まねという状況です。 2つ目は、ファイル保存時の拡張子です。 現在は以下のように記述しています (問題なく動作はしてくれます) object[] mySave ={strFileName,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing}; objBook.GetType().InvokeMember("SaveAs", BindingFlags.InvokeMethod, null, objBook, mySave); 以前はこのようにしていました objBook.SaveAs(strFileName,      Excel.XlFileFormat.xlExcel8,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Excel.XlSaveAsAccessMode.xlNoChange,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing,      Type.Missing); 保存する拡張子をxlsに統一したいのですが、遅延にした場合のファイル形式の指定方法がわかりません Type.Missingにすると、実行環境にあるものに合わせた拡張子で保存されてしまい Excel2007を使用している環境ではxlsxのファイルを作ってしまいます。 Type exFormat = Type.GetTypeFromProgID("Excel.XlFileFormat.xlExcel8"); のような感じで使えるかとも思ったのですが、できませんでした。。 わかる方がいましたら、よろしくお願いします。 開発環境   Vista   VisualStudio2008   .NET Framework 3.5

  • tasoh
  • お礼率87% (65/74)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

Excel 2000/XP/2003には,xlExcel8 (=56) は存在せず,xlWorkbookNormal (=-4143) を使います。 遅延バインドするのであれば,整数値をそのまま付けばよいです。

tasoh
質問者

お礼

素早い回答ありがとうございます 拡張子の問題が解決しました! 数値での指定ができるとは驚きです。 本当にありがとうございます! あとは枠線・・・ 補足なのですが、枠線指定の部分は Type.GetTypeFromProgID("Excel.XlLineStyle.xlContinuous"); などの部分がどうやらnullとして返されてるようです。 そのあたりが解決すれば上手く引けそうな気がします・・・ ここらへんも数値で指定とかができるのでしょうか?

その他の回答 (1)

回答No.2

事前バインディング時に列挙型になっている物は,整数型として扱えます。 私が現在やっているプロジェクトでは, ・インターフェイス用のプロジェクト  ・ここにIApplicationやIWorkbookといった,バージョンに依存せず使うためのインターフェース  ・共通で使うための列挙型 (2007のPIAからリフレクションで取得) ・各バージョン用のプロジェクト  ・各バージョンのIAやPIAへの参照を持つ  ・インターフェイス用のプロジェクトのインターフェイスを実装。内部はほぼIA/PIAへの委譲のみ  ・列挙値は名前を使って変換  ・パラメータが必要数より多い場合は無視 ・全体をとりまとめるためのプロジェクト  ・バージョンチェックを遅延バインディングで実行  ・バージョンによって,各バージョン用のプロジェクトをリフレクションで実行時ロード という方法を使っています。 各バージョン用の物がコピペになるのが悲しいのですが,バージョンごとの差異も吸収できるので,実用にならない,ということはないと思います。 どちらかというと,それだけのバージョンのExcelを入手できるかにかかってきますが……。

tasoh
質問者

お礼

2度も回答ありがとうございます。 整数を調べて実装したら無事動くようになりました! 思わず万歳しそうになりましたw なるほど、そういうふうに分けて利用する方法もあるのですね 今度試してみて、部品化出来るようにしていけたらと思います。 でも、遅延バインディングを選択せずにExcelを扱う必要がある時っていうのはどういう時なのでしょうか? 今回のことで遅延万歳状態になりつつあるのですがw メリットやデメリットなんかも教えてもらえるとうれしいです。 Excelにもいろいろとバージョンがあるんですよね、まだ把握しきれていないので、今回の壁にぶつかったことで色々と目が覚めました。 少しずつ色々なことが出来るようになると本当にプログラミングは楽しいですね。 これからもがんばります。 ありがとうございました!

関連するQ&A

  • C# Wordファイルから文章データを取得

    いつもお世話になっております。 只今、Wordの中身をリッチテキストボックスに取得しようとしています。 取得したデータを他の形式に変更するので、中身を編集というのはしない予定です。 取り込むこと自体はできるようになりまして なんとかなるかなと思っていたのですが、動作を確認していると どうも大きなファイルだと上手くいかないのです。 十数ページなら何とかいけても、数十ページだとエラーが出ます。 そこで質問です。  1:考えられる原因にはどんなものがあるでしょうか     クリップボードを利用してるので、そこが怪しいですが     ほかにありましたらお願いします。  2:解決する方法にはどんなものがあるでしょうか?  3:この方法以外にWordのデータを取得する方法はあるでしょうか?   (クリップボードを利用する以外の方法) ソースは以下のように記述しました。 --------------------------------- Type wt = Type.GetTypeFromProgID("Word.Application"); Object wApp = Activator.CreateInstance(wt); try {     Object tmpDoc = wApp.GetType().InvokeMember("Documents", BindingFlags.GetProperty, null, wApp, null);     object[] tmpFile = {             fileName,             false,             true,             false,             Type.Missing,             Type.Missing,             true,             Type.Missing,             Type.Missing,             Type.Missing,             Type.Missing,             false,             true,             Type.Missing,             true,             Type.Missing            };     Object wDoc = tmpDoc.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, tmpDoc, tmpFile);     Object activeW = wDoc.GetType().InvokeMember("ActiveWindow", BindingFlags.GetProperty, null, wDoc, null);     Object activeWSelection = activeW.GetType().InvokeMember("Selection", BindingFlags.GetProperty, null, activeW, null);     activeWSelection.GetType().InvokeMember("WholeStory", BindingFlags.InvokeMethod, null, activeWSelection, null);     activeWSelection.GetType().InvokeMember("Copy", BindingFlags.InvokeMethod, null, activeWSelection, null);     //クリップボードの中身取得     IDataObject data = Clipboard.GetDataObject();     //リッチテキストボックス(rTextにデータを挿入)     rText.Rtf = data.GetData(DataFormats.Rtf).ToString(); } catch (Exception ex) {     MessageBox.Show(ex.ToString()); } finally {     Object apApp = wApp.GetType().InvokeMember("Application", BindingFlags.GetProperty, null, wApp, null);     apApp.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, apApp, new object[] { Type.Missing, Type.Missing, Type.Missing }); } --------------------------------- あちこち参考サイトを見て回っているのですが 捜し方が悪いのか、クリップボードを利用する方法以外が見つかりません。 わかる方がいましたら、よろしくお願いします。 開発環境:VisualStudio2008 実行環境:Vista Word:*.doc/*.docx

  • InvokeMemberメソッドとは何をするメソッドでしょうか?

    はじめまして、質問です。 C#のソースコードで、「Type.InvokeMember メソッド」というのを使っている箇所があるのですが、 これがいったい何をするメソッドなのかよく分かりません。 msdnのヘルプでは、 「指定したバインディング制約を使用し、指定した引数リストと照合して、指定したメンバを呼び出します。 」 と言っていますが、知識不足で理解できていません。 ネットで検索しても参考になりそうなものが引っかからない状況です。 実際に使用している箇所のソースコードは以下のような感じです。 private void axWebBrowser1_NavigateComplete2(object sender, AxSHDocVw.DWebBrowserEvents2_NavigateComplete2Event e) { Object o = e.pDisp; Object oDocument = null; oDocument = o.GetType().InvokeMember("Document",BindingFlags.GetProperty,null,o,null); o.GetType().InvokeMember("Application",BindingFlags.GetProperty,null,oDocument,null); 中略 } ご存知の方がいらっしゃいましたら宜しくお願い致します。 何か参考になるURLや、このように調べるべきだなどのアドバイスなどもありましたら、 ぜひお願い致します。

  • C#でのEXCEL出力に関して

    教えて下さい。 C#でEXCELシートにデータを出力していますが、その際に以下のような記述をした場合、 EXCELファイルは作成されるものの、そのファイルをダブルクリックで開こうとすると、 EXCELの枠だけ表示され、中身のシートが表示されない現象となってしまいます。 それらしきオブジェクトはすべて開放しているつもりですが、その事象を解決できません。 どこがおかしいか教えて頂きたいと思います。 記述に過不足あればご指摘下さい。 尚、環境は、WindowsXP Office2000-EXCEL です。 《記述内容》 ////////////////////////////////// //ここからエクセルシートへの転記// ////////////////////////////////// Excel.Application objExcel = null; Excel.Workbooks objBooks = null; Excel.Workbook objBook = null; Excel.Worksheet sheet = null; Excel.Range range1 = null; Excel.Range range2 = null; Excel.Range range3 = null; //ExcelのCOMオブジェクトの生成 objExcel = new Excel.Application(); //Excelを表示する設定 //objExcel.Visible = isVisible; //ワークブックの集合体取得 objBooks = objExcel.Workbooks; //ブックの新規作成 objBook = objBooks.Add(Missing.Value); //シートを取得 sheet = (Excel.Worksheet)objBook.Sheets.get_Item(1); //Rangeを取得 range1 = (Excel.Range)sheet.Cells[1, 1]; range2 = (Excel.Range)sheet.Cells[1, 2]; //文字列を設定 //ヘッダ書き込み range1.Value = "仕入先名"; range2.Value = "図面番号"; //エクセルシート側の行数カウント変数 int rcount = 2; //データテーブル側の行数カウント変数 int tcount = 0; for (tcount = 0; tcount < mst_cnt;tcount++ ) { range1 = (Excel.Range)sheet.Cells[rcount, 1]; range2 = (Excel.Range)sheet.Cells[rcount, 2]; range1.Value = 仕入先名[tcount]; range2.Value = 図面番号[tcount]; rcount++; } //エクセルシート削除 DeleteFile(@"c:\\" + h_no + ".xls"); //エクセルシート生成 objBook.SaveAs( "c:\\" + h_no + ".xls", Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, 0, Missing.Value, Missing.Value, Missing.Value, Missing.Value ); //COMオブジェクト解放 Marshal.ReleaseComObject(range1); Marshal.ReleaseComObject(range2); //COMオブジェクトの開放(必須) Marshal.ReleaseComObject(objBook); objBook = null; Marshal.ReleaseComObject(sheet); sheet = null; Marshal.ReleaseComObject(objBooks); objBooks = null; //System.Runtime.InteropServices.Marshal.ReleaseComObject(objExcel); objExcel.Quit(); Marshal.ReleaseComObject(objExcel); objExcel = null; //objExcel.Quit(); return; } よろしくお願いします。

  • C#にてエクセルの名前をつけて保存の方法

    お世話になります。 C#を勉強中ですが、既存エクセルの起動及び停止。又は新規エクセルの 起動はわかったのですが、処理後の名前をつけて保存方法がわかりません。 いろいろやってみたのですが***はコンテキスト内に存在しませんと エラーになります。どこが悪いのでしょうか教えてください。 Workbook.SaveAs("c:\\Lot\\AA\\51.xls", Type.Missing, Type.Missing, Excel.XlFileFormat.xlXMLSpreadsheet,Type.Missing,Type.Missing,false,false, Excel.XlSaveAsAccessMode.xlNoChange,Type.Missing,Type.Missing,Type.Missing); 上記のようにcドライブ直下のLotのフォルダーに保存を行いたいのですが書き方を変更すると、usingに足りないものがあると別のエラーが出ます。 併せてよろしくお願いします。

  • Excelのアクティブなセル情報

    C#でプログラミングをしています。 Excelで、太枠で選択されたセルのセル参照を表示させたいのですが出来ません。 --------- string t; Excel.Application oApplication = null; Excel.Range oRange = null; oApplication = new Excel.Application(); oRange = oApplication.ActiveCell; t = oRange.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing); MessageBox.Show(t); --------- oRangeがnullのままなのですがなぜでしょうか??

  • VB6における事前バインディングの記述方法について

    VB6.0で、ActiveXコンポーネントのインスタンス生成に関連する質問をさせていただきます。 まず前提として、VB6.0では、 ExcelのようなActiveXコンポーネントをコード上で生成する場合、下記の4通りの記述が可能です。 -------------------------------------------- '(1) 参照設定は要らない Dim hoge As Object Set hoge = CreateObject("Foo.Bar") '(2) 参照設定が必要 Dim hoge As Foo.Bar Set hoge = CreateObject("Foo.Bar") '(3) 参照設定が必要 Dim hoge As Object Set hoge = New Foo.Bar '(4) 参照設定が必要 Dim hoge As Foo.Bar Set hoge = New Foo.Bar --------------------------------------------- この中で遅延バインディング(実行時バインディング)は(1)のみで、 (2)~(4)は事前バインディングです。 ここで疑問なのですが、開発者が事前バインディングでコーディングを行う場合、 (4)以外の記述(つまり、(2)と(3)の記述方法)にメリットや必要性はあるのでしょうか。 (2)はコード補完が使えなくなりますし、 (3)はレジストリ経由のせいでパフォーマンスが低下するでしょうし、 デメリットしかないように思われます。 そうであれば、これらの記述方法は推奨されないものなのでは、と思ったしだいです。 回答、よろしくお願いします。

  • C#でのExcel操作について.(Rangeオブジェクトへの複数範囲設定)

    C#でExcelのグラフを作成させるプログラムを書いるのですが,Rangeオブジェクトへの離れたセルの複数範囲を指定したいのですが,いろいろ調べてみましたがどうしても解決できません. 調べた限りではVBではできるようですが,C#ではできないのでしょうか? Excel.ChartObjects chartObjects =(Excel.ChartObjects)oSheet.ChartObjects(Type.Missing); Excel.ChartObject chartObj = chartObjects.Add(100, 100, 700, 400); Excel.Chart chart = chartObj.Chart; Excel.Range chartRange = oSheet.get_Range("B1","B3"); /*↑の部分で("B1:B3,B5:B8,C5")のようなことをしたいです.RangeにAddメソッドのようなものがあればと思っているのですが無いみたいなので‥‥*/ chart.SetSourceData(chartRange,Excel.XlRowCol.xlColumns); Excel.SeriesCollection seriesCollection=(Excel.SeriesCollection)chart.SeriesCollection(Type.Missing); よろしくお願いします.

  • C#の動的キャスト

    いつもお世話になっています。 C#の動的キャストに関する質問です。 C#のメソッドにobjectの引数を渡して動的にキャストする場合 void Hoge(object obj) { Type t = Type.GetType(obj); objの型 obj2 = (objの型)Convert.ChangeType(obj, t); //(1) ................................. } のようにされています。 しかし多様性をもつobjcetを引数にする多くの場合は「objの型」は不定です。 逆に言えば「objの型」がわかっている場合はわざわざobjectを引数にする必要はないわけです。 そこで質問ですが、何とかType t から「objの型」を取得して(1)記法による動的キャストを行う方法はないでしょうか? GetMethod, GetPropertyでメソッド,プロパティを取得し、Invoke, GetValue, SetValueすることは可能ですが、できればドット記法(.)が使える (1) のような動的キャストを行いたいと考えています。 よろしくお願いします。

  • EXCELプロセスの正常終了に関して

    VB2008で、EXCELにデータを出力するプログラムを作成しています。 その際に、どうしてもタスクマネージャーにプロセスが残ってしまい、なんとかプロセスが残らない ように、様々なホームページから消す方法等を検索し、実際に試してみましたが、未だ残ったままと なってしまいます。 あるホームページには、下記のように"Cell"を使用するとプロセスが残ってしまうと記載が あった為に、それを削除して実行してみましたが、やはり消えないままです。 以下のサンプルプログラムで、何をどうしたらプロセスが正常に消えてくれるでしょうか。。。 教えて頂きたいと思います。 なかなかこのEXCELのプロセスの扱いは理解しにくく、直書きとなって申し訳ありません。 よろしくお願いします。 《サンプルプログラム》 '既存のEXCELファイルを開く Dim excelName As String = "C:\order.xls" '起動時の処理 Dim xlApp As New Excel.Application Dim xlBooks As Excel.Workbook xlApp = New Excel.Application() xlApp.Visible = True ' 確認のためExcelのウィンドウを表示する ' Excelファイルをオープンする xlBooks = DirectCast((xlApp.Workbooks.Open( _ excelName, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing, _ Type.Missing)), _ Excel.Workbook) Dim xlSheets As Excel.Sheets = xlBooks.Worksheets Dim xlSheet As Excel.Worksheet = xlSheets.Item(1) Dim x, y As Integer x = 0 y = 17 'データをEXCELファイルに書き出し Do While x < 1 xlSheet.Cells(10, 1).Value = "TEST" 'こちらの書き方も出来る x = x + 1 y = y + 1 Loop xlBooks.Close(Type.Missing, Type.Missing, Type.Missing) xlApp.Quit() ' COM オブジェクトの解放 System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks) ' Excel のプロセス終了 System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)

  • エクセル2010で2003形式でマクロ保存したい

    マクロ初心者ですので、よろしくお願いいたします。類似例が無いかと検索しましたが見つからないので質問いたします。 会社のパソコンがエクセル2003から2010に変更されました。しかし、XP環境でエクセル2003しか使えないソフトがあり、そのパソコンも残してあります。2010で作成したマクロブック(xlsm)が、2003でも使えるようファイル名を付けてエクセル2003(xls)で保存できるマクロを作成したのですが、うまくいきません。 2010で保存できた構文に、「m」を削除し、Excel8の構文を付加するのですが、構文「FileFormat:」がハイライトされ、コンパイルエラーと表示され、「名前付き引数がありません」となります。 ActiveWorkbook.SaveCopyAs Filename:=FPATH & "\" & book3 & ".xls", _ FileFormat:=xlExcel8  「ActiveWorkbook.SaveAs」では拡張子が合わないとなりますが、保存はできています。「ActiveWorkbook.SaveCopyAs」で名前付け保存したいのですが、上記のエラーとなります。 よろしくご回答をお願いいたします。

専門家に質問してみよう