Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10全般 : Excel 2016)
開いているブックの取得で得られる結果が安定しません。
投稿日時: 21/11/17 20:26:16
投稿者: うちょ

表題の件でお世話になります。
よろしくお願いいたします。
 
開いているブックの取得で得られる結果が安定しません。
以下、コードです。
 
事前に「エクセルの起動確認」を実装しています。ここについては割愛させていただきます。
On Error Resume Next
Set ex = GetObject(, "Excel.Application")
 
For Each bk In ex.Workbooks
 
MsgBox bk.Name
 
Next
On Error GoTo 0
 
 
 
具体的には「業務用システム」で吐き出さされたブックを捕捉することを目的としています。
このブックは特定のボタンを押すとシステムから吐き出された内容を表示し、未保存の状態で画面に出現します。
ほかの作業中のブックがデスクトップに存在しない場合「かなり高い確率で」捕捉できるのですが、まれに捕捉できないことがあります。
また、ほかに作業中のブックがすでに立ち上がっている状態で「業務用システム」からブックを作成するとほぼ完全に捕捉できません。
いろいろと条件を変えて試したのですが、ほかの作業中のブックがデスクトップに存在しない場合「かなり高い確率で」捕捉できるのですが、失敗することもある。と言うこと以外何も解決できていません。
 
最終的にはきちんと捕捉することが目的なのですが、問題の切り分け方法等、何かヒントなどあればご教示いただきたく思います。
 
自宅からの投稿のためコードはかなり端折っています事をお許しください。
 
 
 

回答
投稿日時: 21/11/17 22:49:03
投稿者: よろずや

特定のブックを捕捉したいなら、"Excel.Application"ではなく
ブック名を指定しなければいけません。
 
ブック名の指定が不可なら、APIでWindowとかTaskとかを全件取得して、
その中から探すという大変面倒なことになります。
 
多分、「未保存の状態」というのが取得を難しくしていると思います。
 
「業務用システム」が完成していて仕様の変更ができないとなると、
APIゴリゴリになると思いますよ。

回答
投稿日時: 21/11/17 23:30:57
投稿者: WinArrow
投稿者のウェブサイトに移動

今回実施するマクロブックは、
「業務用システム」で吐き出す前に、起動しているのですか?
単純に考えると、
「業務用システム」側で、仮の形でもよいが保存してしまえば、簡単ではないかと思います。
未保存の状態であるならば、
「業務用システム」で、本マクロブックを起動して、引数の吐き出したブック名をわたすという方法もありかと思います。

投稿日時: 21/11/17 23:33:22
投稿者: うちょ

よろずや様。早速のご回答ありがとうございます。
 
>"Excel.Application"ではなく
後出しとなり大変心苦しいのですが、最終的にはVBSとして完成させたいと思いこのような記述をしている次第です。
デバッグが楽な事もあり実際はMSワードのVBAにて動作確認を行っているのが現状です。
板違いで不適切な投稿であれば一旦クローズとさせていただきますが、可能であればもう少しお付き合いいただく事は可能でしょうか?
 
>多分、「未保存の状態」というのが取得を難しくしていると思います。
やはりそうでしたか・・・。根拠はないのですが何となくそんな気はしていたところです。
 
>業務用システム」が完成していて仕様の変更が
はい、仰るようにすでに完成済みでこのような件に関してはサポート対象外ということもあり、手がかりが掴めずこちらに救いを求めた次第です。
 
となるとご提案いただいた
>APIでWindowとかTaskとかを全件取得して
 
こちらについても勉強を開始したいと思いますが、何かきっかけとなるヒント等ございますでしょうか?
 

投稿日時: 21/11/17 23:49:28
投稿者: うちょ

 WinArrow様。ありがとうございます。
 
>「業務用システム」で吐き出す前に、起動しているのですか?
この件に関してはよろずや様へのレスに書き込んだ通りです。
 
最終的にはVBS化することをゴールと考えています。
↑ご質問の答えになっていますでしょうか?
 
>仮の形でもよいが保存してしまえば
諸般の事情により「未保存の状態」で進めたいと考えています。
 
>業務用システム」で、本マクロブックを起動して
これについてもう少し調べてみます。
 
蛇足ですが、私の拙い記憶を辿ると・・・。
恐ろしく何世代も前の古いバージョンのエクセルであれば、マクロの保存時に「別のブックに保存し」未保存のブックから別のブックのマクロを指定して動かす。というような事も可能であったような記憶があるのですが、仕様の変更?、または私の大きな勘違い?
どちらにしてももう少し調べてみます。
 
差支えなければ暫くお付き合いいただければ幸いです。
 
 
 

回答
投稿日時: 21/11/18 21:17:48
投稿者: MMYS

うちょ さんの引用:

また、ほかに作業中のブックがすでに立ち上がっている状態で「業務用システム」からブックを作成するとほぼ完全に捕捉できません。

当然の結果だと思います。
 
 
まず、GetObject と CreateObject の違いは理解していますか。
 
CreateObjectは新規のインスタンスを作成して、そのインスタンスを返します。
一方、GetObjectは既存のインスタンスを探して、そのインスタンスを返します。
 
 
Excelは複数起動している可能性があり、GetObjecではどのExcelインスタンスを取得するか分かりません。
うちょさんが、欲しいExcelインスタンスは「業務用システム」が生成したExcelインスタンスですよね。
 
 
「業務用システム」は、おそらくCreateObjectで新規のExcelインスタンスを生成しているはずです。Excelを起動してない状態で「業務用システム」を動かした場合、Excelインスタンスはゼロです。
この状態で出力するとExcelインスタンスは1個のみ存在。この時GetObjectは、その「業務用システム」が作成したExcelインスタンスを取得できます。(1個しかないので)
 
一方、Excelを起動済みの場合、「業務用システム」は新しく生成したExcelインスタンスを生成しますから、メモリ上には複数のExcelインスタンスが存在します。
 
この場合、下記の記載の通り、GetObjectは最初に見つかったExcelインスタンスを返しますから、うちょさんが提示したコードでは期待した動作はしないと思います。
 
 
https://docs.microsoft.com/ja-jp/office/troubleshoot/office-suite-issues/getobject-createobject-behavior
> 複数のインスタンスが実行されているMicrosoft Excel GetObject は、最初に起動されたインスタンスに接続します。
 
 

投稿日時: 21/11/18 21:26:04
投稿者: うちょ

お世話になります。
 
当初の目的は「業務用システム」で吐き出さされたブックを捕捉する事でした。
業務ではそのブックを「決まったパスとファイル名で保存する」のですが、ユーザーによっては必ずしも一定の手順を踏むことが困難な者も存在することから、何とかこの部分を「標準化する」のが目的でした。
 
ご教示いただいた
>APIでWindowとかTaskとかを全件取得して
についても少し調べてみたのですが、現在の私のスキルでは解決できるはずも無く・・・。
しかし、今後役立つこともあろうかと思いますので少しづつ勉強したいと思います。
 
 
最終的には
>「業務用システム」で、本マクロブックを起動して
ご提示いただいたヒントからソースコードをアドイン化して対応することとしました。
 
ご回答頂き大変感謝しております。
ありがとうございました。