excel VBAで、
ユーザからの操作を待ち受け、操作に応じて外部アプリケーションを
起動し、外部アプリケーションウインドウのスクリーンショットを撮り、
保存するアプリを開発しています。
セルに保存したデータをパラメータとして外部アプリケーションに渡すために、
excel上での開発をしています。
当方、プログラミング歴は浅く、Cのポインタ、Javaのオブジェクト指向で頓挫し、
必要に迫られ、VBAとSwiftでコードを書きはじめた初心者です。
参考URL、同じような問題を解決した時の方法、前提知識の誤解の指摘等、皆様のお知恵を拝借いただけますと、幸いです。よろしくお願い致します。
<困ったこと>
・外部アプリケーションを起動し、スクリーンショット作成時に用いるwindowsAPIを
呼び出した時、オブジェクトが破棄されるため、処理が進まない
・オブジェクトの破棄は、UserFormを起動したタイミングでも起こっている模様
<知りたいこと>
・VBAコード全体でオブジェクト変数を保持するエレガントな方法を知りたい
・そもそも、VBAで外部アプリケーションとの連携をする際、
どのようなプログラム構造であるのが望ましいのか
(イベント駆動型のプログラムを書くときの作法 等)
<アプリケーションのイメージ>
UserFofmで作成したメニュー画面を表示
※マクロが入ったexcelファイルの起動時もしくは、別の起動用マクロからUserFormを表示。
ユーザ動作を待ち、UserFormに設置したコマンドボタンを押下した際、下記の処理を行う
コマンドボタン1(btnLaunch)押下時
別のアプリケーション(例えばIE)が起動する
コマンドボタン2(btnTakePicture)押下時
コマンドボタン1で起動したウインドウのスクリーンショットを撮る
※keybd_event(windowsAPI)を使用
コマンドボタン3(btnTerminate)押下時
VBAのコード全体が終了する
※コマンドボタン1で生成したアプリケーションのプロセスも正しく終了する
<アプリケーション全体の構造>
・メインのコードは標準モジュールmainに配置。
・mainモジュールから呼び出す関数は役割ごとに異なる標準モジュールに配置
・コマンドボタン押下時に起動するアプリケーションのオブジェクト変数は、
mainモジュールのグローバル変数として定義
<コード>
※細かい部分は省略しています
●mainモジュール
————————————————————————————
Option Explicit
'WindowsAPIの設定
'キーボード関係
Private Declare Sub keybd_event Lib "user32" _
(ByVal bVk As Byte, ByVal bScan As Byte, _
ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare Function GetKeyboardState Lib "user32" _
(pbKeyState As Byte) As Long
Const VK_NUMLOCK = &H90 '「NumLock」キー
Const KEYEVENTF_EXTENDEDKEY = &H1 'キーを押す
Const KEYEVENTF_KEYUP = &H2 'キーを放す
'Sleep関数
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
#End If
'ウインドウ制御関係
'cf. http://www.vba-ie.net/ie/foreground.html
Declare Function IsIconic Lib "user32.dll" (ByVal hWnd As Long) As Long
Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hWnd As Long) As Long
Declare Function ShowWindowAsync Lib "user32.dll" ( _
ByVal hWnd As Long, _
ByVal nCmdShow As Long _
) As Long
Const SW_RESTORE As Long = 9
'for event loop
Declare Function GetInputState Lib "user32.dll" () As Long
Public objIe As Object
Public menuKeyFlg As String
Public Sub init()
MainCtrl.Show
End Sub
Public Sub terminate()
Unload MainCtrl
‘その他、オブジェクトの破棄処理等
End Sub
Public Sub launch()
Set objIe = new_ie(***URL***)
ie_submit objIe
'無限ループにしておく
Do While True
If GetInputState() Then DoEvents
Sleep 500
Loop
End Sub
Public Sub takePicture(ByRef objIe As Object)
'ウィンドウが最小化されているかのチェック
If IsIconic(objIe.hWnd) Then
ShowWindowAsync objIe.hWnd, SW_RESTORE
End If
'IEを最前面に表示
SetForegroundWindow (objIe.hWnd)
'・ウインドウ全体のスナップショットを作成
‘ウインドウの表示イメージをクリップボードに保存
Call keystroke
Call saveClipBoard
End Sub
Private Sub keystroke()
' alt+PrtScreenを模擬し、クリップボードに保存
keybd_event VK_LMENU, 0&, fKEYDOWN, 0& 'Altキーを押す
keybd_event vbKeySnapshot, 0&, fKEYDOWN, 0&
keybd_event vbKeySnapshot, 0&, fKEYUP, 0&
keybd_event VK_LMENU, 0&, fKEYUP, 0& 'Altキーを離す
End Sub
Private Sub saveClipBoard()
クリップボードの中身を画像ファイルとして書き出す
**内容省略**
End Sub
●UserFormモジュール
————————————————————————————
Private Sub btnLaunch_Click()
call launch
End Sub
Private Sub btnTakePicture_Click()
call takePicture
End Sub
Private Sub btnTerminate_Click()
call terminate
End Sub
Private Sub UserForm_Initialize()
call init
End Sub
A 回答 (1件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
コードの詳細をよく読んでいないのですが……
> Public Sub takePicture(ByRef objIe As Object)
と引数objIeを必要とする定義にしているのに
> Private Sub btnTakePicture_Click()
> call takePicture
> End Sub
呼ぶ側で引数を与えていないのは変ですよね?
そもそもobjIeは、広域変数として宣言しているのでtakePictureの定義では引数は不要ではないでしょうか?
siffon9さん ご回答ありがとうございます。
仰るとおりですね。投稿した際に使ったコードが古いものでした。
Public Sub takePicture で定義しています。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Access(アクセス) Vba Userformを前面に出すについて 3 2022/04/15 12:29
- Excel(エクセル) 【マクロ】スクショ印刷がうまく動かない件 5 2022/12/06 17:37
- Excel(エクセル) 【VBA】 Alt+PrintScreenにてアクティブウィンドウのスクショを貼付する方法 4 2022/12/08 20:53
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る バッチからEXEの結果を受け取りたいのですが、 下記のバッ 1 2023/07/04 15:13
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る EXEの実行内容の結果によって、戻り値を0か1かで返したい 1 2023/07/04 16:40
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Excel(エクセル) エクセルVBAでオブジェクトが必要です 2 2022/09/10 16:37
- Visual Basic(VBA) EXCEL VBAにて動的にCheckBOXを複数作成し、同BOXにイベントを追加したい 1 2023/03/16 07:05
- Visual Basic(VBA) ユーザーフォーム「frm_基本❶」を立ち上げると新規で入力する行数を右下のNoとして表示しています。 1 2023/03/16 19:02
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
MFCアプリケーションでの終了コ...
-
Vba アプリケーションが立ち上...
-
コンソールアプリケーションの...
-
OSの”シャットダウン中”のステ...
-
実行時のコマンドプロンプトを...
-
フレームワーク「4.8.1」で、[S...
-
pccNTmon.exeとntrtscan.exeの違い
-
自分自身を更新するプログラム
-
イラストレーターCS4のシリアル...
-
excel VBAで、外部アプリケーシ...
-
Windowsプログラムのビジー状態...
-
Accessフォームからの外部アプ...
-
VB.NETでフォームアクティブの...
-
Shell関数の終了を調べる方法
-
httpd.pidって何ですか?
-
C#でGUI・CUIの判断する仕方を...
-
vb6.0からのタスクの終了
-
VBSで2バイト文字の送り方の質...
-
outlookが強制終了してしまう
-
vcxprojファイルの修正法???
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Vba アプリケーションが立ち上...
-
コンソールアプリケーションの...
-
フレームワーク「4.8.1」で、[S...
-
VBSでのSendKeysでの画面の最小化
-
実行時のコマンドプロンプトを...
-
イラストレーターCS4のシリアル...
-
Windowsプログラムのビジー状態...
-
VB.NETでMessageBoxを表示した...
-
Accessフォームからの外部アプ...
-
自分自身を更新するプログラム
-
初回接続の遅い原因について
-
vb6で異なるのプロジェクト間で...
-
Console Applicationをタスクト...
-
他アプリケーションの終了
-
MFCアプリケーションでの終了コ...
-
WSH(VBScript)でアプリケーショ...
-
VB.NETでフォームアクティブの...
-
VB6の強制終了について
-
現在起動中のアプリケーション...
-
VB6での二重起動(複数起動)の制...
おすすめ情報