- PR -

C++でEXCELファイルを読む方法

投稿者投稿内容
やす
常連さん
会議室デビュー日: 2005/12/07
投稿数: 20
投稿日時: 2007-01-09 13:41
ご返答ありがとうございます。

> MFCなのか、Win32 SDKなのか、C++/CLI(Windows Formアプリケーション)なのか
> どれなのでしょうか?

そうですね、肝心なことが抜けてました。
現在、ある計算ライブラリを作成しておりまして、その中でエクセルファイルから
データを取得する必要が出てまいりました。
ちなみに、このライブラリは、MFCを使わない、Win32コンソールアプリケーション
>DLLもしくはスタティックライブラリです。

MFCを使ってはいけないという制限はないので、もし簡単になるのであれば、MFCを
使ってもかまいません。

以上、よろしくお願いいたします。
Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2007-01-09 14:21
じゃんぬさんから適切なアドバイスがありますが、

RangePtrの値を_WorksheetPtrの変数から取得するときに

pSheet->Range["A1"];

のように取得するのと同様、A1の部分を任意の名前にするだけです。

Excel::RangePtr pRange = pSheet->Range["あ"];

みたいに。
やす
常連さん
会議室デビュー日: 2005/12/07
投稿数: 20
投稿日時: 2007-01-09 14:41
Blueさん、じゃんぬねっとさん、
ご回答ありがとうございます。
これで解決できそうです。

ところで、ついでにもう一つ教えて下さい。

先にふれましたように開発しているものはオブジェクトライブラリ
もしくはDLL形式で提供することになるのですが、こういったケースでは、
COMの初期化(CoUninitialize)終了(CoUninitialize)処理
というのは、これを利用するアプリケーション側でやってもらうもの
なのでしょうか?それともライブラリの初期化/終了関数の中でやるもの
なのでしょうか?




ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2007-01-09 16:53
自分の面倒は自分でみたほうがいいんじゃない?
ラッパークラスにしてコンストラクタとデストラクタを使うとか。
やす
常連さん
会議室デビュー日: 2005/12/07
投稿数: 20
投稿日時: 2007-01-09 19:01
言葉足らずでした。

今回作ったものは汎用のライブラリ/DLLとして提供するのですが、
これを利用するアプリはすでにCOMを使っているかどうかが分かり
ません。

もしアプリがすでにCOMの初期化処理を行っていると、ライブラリ側
でやる必要はないですし、COMを使っていないアプリであれば、ライ
ブラリ側で初期化しないといけません。

一般的なお作法として、このようなCOMの機能を使用するライブラリ
を提供する場合は、誰がどのようにCOMの初期化・終了をしてやれば
よいのでしょうか。

ライブラリの利用手引きに、ライブラリの関数を呼び出す前に、COM
の初期化を行ってくださいと書けばすむ話なのでしょうか。
やす
常連さん
会議室デビュー日: 2005/12/07
投稿数: 20
投稿日時: 2007-01-09 19:15
矢継ぎ早の質問ですいません。

おかげさまで、教えていただいたサンプルを参考にEXCELのデータを読めるようになりました。
ここで1つ困ったことがあります。
現在は以下のようにタイプライブラリを利用?しているのですが、EXCELのバージョンや
インストール先が決まっていない場合はどのようにすればよいのでしょうか?

ご教示のほどよろしくお願いいたします。

#import "C:\Program Files\Common Files\Microsoft Shared\Office11\MSO.DLL" no_namespace rename("DocumentProperties", "DocumentPropertiesXL") rename("RGB", "MSO_RBGXL")
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\Vbe6ext.olb" no_namespace
#import "C:\Program Files\Microsoft Office\Office11\EXCEL.EXE" rename("ReplaceText", "ReplaceTextXL") rename("CopyFile", "CopyFileXL") rename("DialogBox", "DialogBoxXL") rename("RGB", "RBGXL") rename("DocumentProperties", "DocumentPropertiesXL") exclude("IFont") exclude("IPicture") no_dual_interfaces
Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2007-01-10 00:51
引用:

やすさんの書き込み (2007-01-09 19:15) より:
EXCELのバージョンや
インストール先が決まっていない場合はどのようにすればよいのでしょうか?


かなり、根気が要る作業になります。
まず、#importを使う方法はまず使えません。
CLSIDFromProgID、CoCreateInstanceあたりを使って一つ一つプロパティからメソッドを割り当てていく方法になります。
それが面倒であれば、VB6とか遅延バインディングを使えるプログラム言語を使って
ActiveX DLLを作るとか。(わたしならそうするかも。(COMの初期化処理なんていらないし))

というか、一番最初のリンク先のスレッドに同様な質問&回答がありますけど。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2007-01-10 09:48
おはようございます。

引用:

やすさんの書き込み (2007-01-09 19:15) より:
現在は以下のようにタイプライブラリを利用?しているのですが、EXCELのバージョンや
インストール先が決まっていない場合はどのようにすればよいのでしょうか?



まずExcelのインストール先が決まっていない点ですが、
実行時に関しては「COMの位置透過性」から問題にはなりません。
(COMの実行モジュールのパスはレジストリに登録されているはずですから)

EXCELのバージョンが決まっていない点に関しては、
すでに#import指令に"no_dual_interfaces"を付けていらっしゃるようなので、
カスタムインターフェイス経由ではなく、IDispatchインターフェイスを使用するようになっています。
つまり一応「遅延バインディング」となっております。

問題はEXCELのバージョンによって、
 1.ディスパッチIDと呼ばれるIDが変更されている可能性があることと
 2.メソッド・プロパティの引数が変更されている可能性があることです。

2.の引数変更に関しては、一般的な対処の方法は難しいですが、
1.の、ディスパッチIDに関しては、IDispatch::GetIDsOfNamesを実行時に呼んでやれば
動的に取得することができます。

つまり何が言いたいかといいますと、
自動生成された「excel.tli」というソースファイルで
_com_dispatch_method関数呼び出しの第2引数を定数ではなく、
IDispatch::GetIDsOfNamesで取得したものを使用するほうがよいということです。


#私ならMFCのCOleDispatchDriverを使うと思います。
「TypeLibからのMFCクラス」でCOleDispatchDriver派生クラスが自動生成されます。
あとは、ディスパッチIDを動的に取得するように、ちょこちょこっと修正をします。


[ メッセージ編集済み 編集者: Tdnr_Sym 編集日時 2007-01-10 09:52 ]

スキルアップ/キャリアアップ(JOB@IT)