OleContainerを利用してExcelを制御しようとしています。
http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/T_OleCont.htm
を参考にしてある程度、制御することはできました。
しかし、他の作業でExcelを起動させたまま
このプログラムを実行すると例外エラーになります。
どうも、ActiveWorkbook=nilになっているのが原因のようです。
Excelを起動させていてもエラーにならない方法はあるのでしょうか?
CreateOleObjectでやれば、うまくいくのですが、
この場合、Excelシートでの編集イベントが取れないため
TExcelApplicationを利用しようと思っています。
CreateOleObjectでExcelの変更イベントが取れれば
それでも良いのですが・・・
Oleでの取得です。
try
Excel := GetActiveOleObject('Excel.Application'); //動作中の場合
except
Excel := CreateOleObject('Excel.Application'); //起動させる
end;
Hotaさん早速の回答ありがとうございます。
try
Excel := GetActiveOleObject('Excel.Application'); //動作中の場合
except
Excel := CreateOleObject('Excel.Application'); //起動させる
end;
ここで言う、Excelは、Variant変数ですよね。
できれば、TExcelApplicationコンポーネントを利用したいのですが。
やはり、この方法しかないでしょうか?
この場合、OleContainerに埋め込まれている
Excelで値の変更などがあった場合、
編集フラグを立てるなどチェックすることが
できればよいのですが・・・
環境書くのを忘れてましたが、Delphi5です。
>しかし、他の作業でExcelを起動させたまま
>このプログラムを実行すると例外エラーになります。
私のところではエラーになりませんが...。
(WindowsXP + Delphi7 )
もし、既に起動しているExcel(エクセル)とは別に、OleContainerで表示している
Excel(エクセル)を別のもの(インスタンス)で制御するのであれば以下のようにします。
質問の意図するところと違っていたらゴメンなさい。
//OLEオブジェクトを表示可能状態にして表示
OleContainer1.Visible:=True;
OleContainer1.DoVerb(ovShow);
OleContainer1.SetFocus;
//既に起動中のエクセルとは別のエクセルとして制御する場合
//ConnectKindのデフォルト値はckRunningOrNew
ExcelApplication1.ConnectKind:=ckRunningInstance; //ここを明示的に指定
ExcelApplication1.Connect;
くどいようですが、解説しますと以下のことです。
ckRunningOrNew
既に起動中(Running)があればそれ、または(or)なければ新しいExcel(New)
ckRunningInstance
既に起動中のインスタンス(RunningInstance)、つまり今回の場合は
OleContainer1に起動しているエクセルのインスタンスのこと。
Mr.XRAYさん回答ありがとうございます。
一度、試してみます。
結果については、後日報告させて頂きます。
ExcelApplication1.ConnectKind:=ckRunningInstance;
を試してみました。
確かにエラーは出なくなりましたが、
作業中のExcelに遷移できなくなってしまいました。
しかも、OleContainerの終了時に作業中のExcelも
終了してしまいます。
OleContainer1のExcelはどの時点でExcelのインスタンスが
できあがっているのでしょうか?
どうも、OleContainerのインスタンスではなく、
作業中のExcelのインスタンスを使っているようなのですが・・・
Delphi7で出ないと言うことは、
WindowsXP+Delphi5の環境に問題があるのでしょうか?
自己レスです。
ServerコンポーネントをExcel97からExcel2000に入れ替えると
起動中のExcelがあってもエラーは出なくなりました。
やはり、環境の問題だったようです。
Excelを起動しておいてから、サンプルプログラムを実行すると
先に起動しておいたExcelの画面に遷移できません。
先にプログラムを動かしておいてExcelを別で起動したときは、
画面の切替が問題なくできるのですが・・・
同時に終了してしまう件は、
ExcelApplication1.ConnectKind:=ckNewInstance;
とすることで回避できました。
普通に起動したExcelとプログラムからOleContainerを使用したExcelで
画面の切替は、できないのでしょうか?
ちなみに、OleContainerが貼り付けてあるフォームは、
ShowModalで開いています。このあたりに原因があるのでしょうか?
失礼。
ExcelWorkbook1
ExcelWorksheet1
のConnectKindプロパティも変更する必要がありますね。
それでダメならお手上げです。
追加です。
>先に起動しておいたExcelの画面に遷移できません。
これは全く分かりませんね。サンプルのプログラム(たとえ、他のFormから
ShowModalで表示したとしても)の場合。他に何か操作していないんですよね。
Mr.XRAYさん回答ありがとうございます。
http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/T_OleCont.htm
をそのままコピーして試してみましたが、
やはり、Excelを起動してからプログラムを動かすと
プログラム実行中は、最初に起動していたExcelが
さわれません。画面は、後ろに見えているのですが・・・
ここから、もう一つExcelファイルを起動するとそちらは
Activeになります。何が違うのでしょうか・・・
起動時にExcelが立ち上がっていたらプログラムを
起動できなくするなど工夫する必要があるかもしれません。
まさかとは思いますが、
>http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/T_OleCont.htm
(1)このサンプルのフォルダ内のOleTest.xlsを義堂
(2)サンプルのExcel_OleContainer.exeを起動
なんてことはしていませんよね。
同じファイルは、起動していません。
こちらでは、以下の通りで再現します。
(1) [スタート]-[プログラム]からExcelを起動
(2)サンプルのExcel_OleContainer.exeを実行
このようにすると(1)で起動したExcelのシートが無くなってしまい
Excelアプリのみ起動した状態が後ろに残る。
さらに、(1)のExcelにカーソルが行かない。
しかも、Excel_OleContainer.exe終了時に(1)のExcelも
同時に終了してしまう。。。
やはり、環境の問題でしょうか???
それとも、OleContainerのプロパティの問題???
いろいろと調べてみましたが、どうも環境のようです。
Office2000のSP-1を当てない状態で試してみると
現象は、起きずに画面遷移も問題ありませんでした。
SP-1にあげてから試してみると動きがおかしくなりました。
私が試していたのはOfficeSP-3だったのでSP-3でも問題がある?
Delphiの問題ではなさそうなので
ここでは、解決とさせて頂きます。
Mr.XRAYさんのサンプルで
procedure TForm1.FormShow(Sender: TObject);
var
EFile: String;
begin
ExcelApplication1.Connect; //追加
ExcelApplication1.IgnoreRemoteRequests[0] := True; //追加
:
:
:
//ExcelApplication1.Connect; //コメント
SAKURAさん
>Excelアプリのみ起動した状態が後ろに残る。
>さらに、(1)のExcelにカーソルが行かない。
>しかも、Excel_OleContainer.exe終了時に(1)のExcelも
>同時に終了してしまう。。。
>う一つExcelファイルを起動するとそちらはActiveになります。何が違うのでしょうか・・・
上記の現象確認しました。Excelの設定、フォルダオプションをいろいろ変更
してみたら発生しました。ただ、何をどのように変えたかが...
そして、元に戻らなくなってしまいました(笑)。
当方 WindowsXP(SP2) + Delphi7 + Excel2000(SR-1)です。
ちなみに、ExcelはOffice2000インストール後、何も設定変更していません。
が、エクセル操作フォームとか、いろいろエクセルの操作をしていますので、
デフォルトがどのようになっているかも分かりません。
近日中に、ExcelまたはOfficeを再インストールして実験してみます。
これじゃダメ?さん
回答ありがとうございます。
試してみましたが、現象は、かわりませんでした。
Mr.XRAYさん
わざわざ検証ありがとうございます。
それに環境までおかしくなってしまうなんて・・・
申し訳ありません。。。
調べてみると、OLEのバージョンのような気がします。
こちらの環境では、SYSTEM32フォルダの
STDOLE2.TLBの日付だけ古いのが気になります。
OLEAUT32.DLL、OLEPRO32.DLLとか同じバージョンでないといけないとか。
また、下記のようにVariant型にしてExcelのCreateを
しないとうまくいくこともわかりました。
しかし、この場合、ExcelでScreenUpdatingが使えないなど弊害も・・・
//OLEオブジェクトを表示可能状態にして表示
OleContainer.Visible:=True;
OleContainer.DoVerb(ovShow);
OleContainer.SetFocus;
//OLEオブジェクトに接続<−※ここをやめてみた
//objExcel := OleContainer.OleObject.Application;
//objExcel := CreateOleObject( 'Excel.Application' );
//開いているブックをobjWorkBookに接続
objWorkBook := OleContainer.OleObjectInterface as _Workbook;
//シートを objWorkSheetに接続
objWorkSheet := objWorkBook.WorkSheets[1];
・
・
・
少しテストした結果を報告しておきます。
結果的には分かりませんので、ご了承下さい。
エクスプローラで、
[ツール][フォルダオプション][ファイルの種類]で
XLS Microsoft Excelワークシートを選択し、[詳細設定]
ここで[Open]の[編集]を開きます。実行アプリケーションの
"C:\Program Files\Microsoft Office\Office\EXCEL.EXE" /e %1
最後の /e %1 を削除したり、また元に戻したりしました。
これによって当然動作が変化しますが、元に戻しても何故か元と同じ動作に
なりません。なんか変です。
当方、Office の SR-1となっていますか、たしかSR-2まで適用した記憶が
あるのですが、失念。
これは根性据えて調べるしかありません。いつか調べるつもりではいます。
解決策でなくて申し訳ありません。以上報告まで。
>調べてみると、OLEのバージョンのような気がします。
OLEについても調べてみます。
>また、下記のようにVariant型にしてExcelのCreateを
>しないとうまくいくこともわかりました。
そうですね。OleContainerがExcelのインスタンスを生成するので、これが
正解でしょうね。ただ、そうするとExcelApplicationの方も...
と考えて、テストしてみたのですが... 変化なし...です。
ツイート | ![]() |