ジメジメする梅雨のお悩み、一挙解決! >>

エクセルVBAから他のアプリを終了するマクロを書きたいのですが、途中で行き詰ってます。

Sub test()
Dim h As Long
h = FindWindow(vbNullString, "タイトル")
Call SendMessage(h, 0, 0, "ALT+{F4}")
End Sub


FindWindowでハンドルを取得してALT+F4を送ればいいじゃないかと思ってますが
ALT+F4の送り方がわかりません。どなたか教えてください。
また、ほかに良い方法があれば併せてご提案くださると幸甚です。

よろしくお願いします。

--
エクセル2003

このQ&Aに関連する最新のQ&A

A 回答 (1件)

そこまでできているのなら下記のように変更して見て下さい。


VB6.0 用のコードをそのまま転記していますがご理解頂けるかと。

Private Sub hwndAcquire()
'ハンドル取得及び終了処理のサブプロシージャ
  Dim hwnd As Long
  Dim ret As Long
  If Len(strClassName) Then
    'クラス名を与えてハンドルを取得
    '起動中ならハンドルが返り、起動していなければ 0 が返る
    hwnd = FindWindow(strClassName, vbNullString)
  ElseIf Len(strCaptionName) Then
    'キャプション名を与えてハンドルを取得する場合
    'strCaptionName = "Microsoft Excel - Book1"  '電卓の場合  "電卓"
    hwnd = FindWindow(vbNullString, strCaptionName)
  End If
  '指定のハンドルに終了のメッセージを送る
  ret = SendMessage(hwnd, WM_CLOSE, 0&, 0&)
End Sub
    • good
    • 4
この回答へのお礼

おっしゃ。新年一発目の疑問が解決しました。
ありがとうございました。

お礼日時:2012/01/02 22:13

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q【Excel VBA】マクロでExcel自体を終了させたい

環境:WindowsXP、Excel2003

マクロでエクセルを終了(ブックを閉じて、アプリケーション自体も終了)させたいのですが、以下のコードではアプリケーションが閉じてくれません。

ThisWorkbook.Close
ExcObj.Quit
Application.Quit

どこか悪いところはありますでしょうか?

よろしくお願いします。

Aベストアンサー

普通に考えれば質問者のコードで上手くいきそうですが
hana-hana3さんの回答にもあるようにThisWorkBook.Closeでコード終了となりますので
Application.QuitをThisWorkBook.Closeの前にもってこないといけません。
Application.Quitはそれがあるプロシージャのコードが全て終わるまで
その実行を保留するちょと特別動作をします。

'-------------------------------------
 Application.Quit
 ThisWorkbook.Close
'-------------------------------------
 
 

QVB6.0 SHELLで起動したプログラムを終了さしたいのですが

(1)メインプログラムから電卓を実行します。
 Shell("C:\WINNT\system32\CALC.EXE", 1)
(2)メインプログラムで電卓を終了させるにわ、どうすればいいのですか
 教えてください。

Aベストアンサー

(今会社なのですが、、、)サンプルありました。奥深く眠ってました。
Microsoftの終了方法と、定数が違いますが、こちらでも終了ができます。


コメントを見たら、処理の流れがわかると思いますが、処理の流れを記します。

Shellで電卓を起動します。Shell関数は起動したアプリのプロセスIDを返します。
次に Call EnumWindows(AddressOf EnumWinProc, 0&)を実行します。
これはたった一文で、FOR文/DO~LOOP文を使用してませんが、EnumWinProc関数内を何度も実行します。実行回数はWindowsに存在するハンドルの数だけ実行されます。
そしてその関数内で電卓のプロセスと同じハンドルを探し、電卓に終了の命令を送ってます。



EnumWinProc内を詳しく説明します。
GetParentが'0'ゼロの時、未処理としています。

これは何を意味するかというと、フォームだけでなく、フォームの中に存在するボタン、リストボックス、ラベル、それぞれのコントロールにハンドルが存在します。
しかしフォームとその中のコントロールには親子の関係があります。
GetParent(子のハンドル)の時 → '0以外'の数値を返します。基本的にフォーム(親)のハンドルのを返します。
GetParent(フォームのハンドル)の時 → '0'を返します。親が存在しないためです。

電卓にも多くのボタンが存在してます。そのボタンのハンドルはチェックする必要がないのでGoto文で未処理にさせています。必要なのは電卓本体が必要で、GetParentで0を返すものが、チェックの候補となるわけです。

あとは電卓のプロセスと比較し、一致するハンドルを取得するだけです。



Option Explicit

' ウィンドウのプロセスIDとスレッドIDを取得する関数の宣言
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" _
  (ByVal hwnd As Long, lpdwProcessId As Long) As Long

'親ハンドルを取得する関数の宣言
Private Declare Function GetParent Lib "user32" _
  (ByVal hwnd As Long) As Long

'ウィンドウを列挙する関数の宣言
Public Declare Function EnumWindows Lib "user32" _
  (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

'ウィンドウにメッセージ定数を送る関数の宣言
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
  (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long

Public Const WM_CLOSE = &H10

'見つかったウィンドウハンドル
Private FindWinWnd As Long
'探すべきプロセス
Private FindPrs   As Long


Sub Main()
  Dim lngSts As Long

  '初期化を行う
  FindWinWnd = 0
  FindPrs = 0

  'とりあえず電卓を起動と同時に、電卓のプロセスを得る
  FindPrs = Shell("Calc.exe")
  
  'プロセス=0のとき起動失敗
  If FindPrs = 0 Then
    MsgBox "電卓の起動失敗"
    GoTo PGMEND
  End If
  
  'Windowsに存在する全部のハンドルから、電卓のプロセスの一緒のハンドルを探す
  Call EnumWindows(AddressOf EnumWinProc, 0&)
  
  '電卓を終了します。
  If (FindWinWnd <> 0&) Then
    MsgBox "電卓が見つかりませた。終了します。"
    Call SendMessage(FindWinWnd, WM_CLOSE, 0&, 0&)
  Else
    MsgBox "電卓が見つかりませんでした。"
  End If
  
PGMEND:
End Sub

'Windowsの全ハンドルを得ることができる関数
'内部処理は、
'(1)指定のプロセスを探す
'(2)見つかったプロセスのハンドルを記憶
Public Function EnumWinProc(ByVal hwnd As Long, lParam As Long) As Boolean
  Dim lngTrd As Long 'スレッド
  Dim lngPrs As Long 'プロセス
  
  'Trueの間は、Windowsに存在するハンドルを最後まで取得しようとする
  EnumWinProc = True
  
  '子ウィンドウは未処理
  If Not (GetParent(ByVal hwnd) = 0) Then GoTo PGMEND
  
  'スレッドとプロセスを取得する
  lngTrd = GetWindowThreadProcessId(hwnd, lngPrs)
  
  '同じプロセスだとしたら
  If lngPrs = FindPrs Then
    '取得してきたハンドルを記憶
    FindWinWnd = hwnd
    'これ以上のハンドルは取得しないでもいいので、Falseをセット
    EnumWinProc = False
  End If
  
PGMEND:
End Function

(今会社なのですが、、、)サンプルありました。奥深く眠ってました。
Microsoftの終了方法と、定数が違いますが、こちらでも終了ができます。


コメントを見たら、処理の流れがわかると思いますが、処理の流れを記します。

Shellで電卓を起動します。Shell関数は起動したアプリのプロセスIDを返します。
次に Call EnumWindows(AddressOf EnumWinProc, 0&)を実行します。
これはたった一文で、FOR文/DO~LOOP文を使用してませんが、EnumWinProc関数内を何度も実行します。実行回数はWindowsに存在する...続きを読む

Q外部プロセスを終了したい!!

こんにちは。
ご多忙の中、申し訳ありませんが皆さんの知恵をお貸しください。

私はVBは初心者中の初心者なのですが、
あるアプリケーションからEXEをキックし(このEXEは永久ループ)、
ある程度の処理をしたら、キックしたEXEを終了させたいと考えております。

基本的にキックされたEXEがウェイトして自らおちるのではなく、キックした
アプリから落としたいと考えています。

簡単に言えば、UNIXでいうKILLコマンドのような関数はありますかと
言うことです。(プロセスIDを使用して・・・)

ご存知の方がいらっしゃいましたら、教えてください。
宜しくお願い致します。m(_ _)m

Aベストアンサー

サンプルをどうぞ。
http://www.microsoft.com/JAPAN/support/kb/articles/JP129/7/97.asp
しかし、強制終了するはあまりよくないと思います。
WM_CLOSEメッセージを投げる方法をお勧めします。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=157242

QEXCEL VBAから他アプリケーションを操作することは可能ですか?

こんばんは。

VBAの本を購入し勉強していますが、VBAと他アプリケーションとの連携について記載が少なく(txtやcsvファイル操作)、どこまで出来るんだろうという不安があり質問しました。

(1)EXCEL VBAから他アプリケーションを起動し、設定操作、命令を送り操作することは可能でしょうか?
イメージとしては他アプリに一方的に命令を送り操作できれば良しです。(アプリ側からのリターン要求はしません。)

(2)第2の質問です。
VBAで他アプリを起動した状態で人が操作している感覚でマウスを操作できますか?(利用方法:他アプリの●ボタンを押したい!!)
目の前にソフトがあるのに触る操作は出来ないものでしょうか?
いろいろ調べて見ましたが、この様な事例はありません。
駄目元ですが、こんな操作を知っていましたら教えてください。
こんな操作ができればいいな~

Aベストアンサー

#2,4 です。

> EXCEL2000内の特定のセルに規定値外のデータが入力された場合に
> UWSCを起動して...

UWSC のスクリプトが完成しているとすれば、起動オプション付きで
バッチ処理すれば良いでしょう。実行タイミングは、シートまたは
ThisWorkbook の Change イベントが使えます。

例)シートモジュール

Private Const EXE_PATHNAME As String = "C:\Program Files\uwsc\uwsc.exe"
Private Const DQ      As String = """"

Private Sub Worksheet_Change(ByVal Target As Range)

  Dim rChange   As Range
  Dim sCommand  As String
  Dim sScriptFile As String

  ' // 実行する UWSC スクリプト
  sScriptFile = "C:\sample.uws"
  ' // UWSC の起動オプションは UWSC のヘルプを参照
  sCommand = DQ & EXE_PATHNAME & DQ & " " & _
        DQ & sScriptFile & DQ
  
  ' // 変更されたのが単一セルかつ A 列でなければ終了
  If Target.Cells.Count > 1 Then Exit Sub
  Set rChange = Intersect(Target, Columns("A"))
  If rChange Is Nothing Then
    Exit Sub
  End If
  
  ' // さらに値が TEST だった場合のみ実行
  If rChange.Value = "TEST" Then
    Shell sCommand, vbNormalFocus
  End If

End Sub

#2,4 です。

> EXCEL2000内の特定のセルに規定値外のデータが入力された場合に
> UWSCを起動して...

UWSC のスクリプトが完成しているとすれば、起動オプション付きで
バッチ処理すれば良いでしょう。実行タイミングは、シートまたは
ThisWorkbook の Change イベントが使えます。

例)シートモジュール

Private Const EXE_PATHNAME As String = "C:\Program Files\uwsc\uwsc.exe"
Private Const DQ      As String = """"

Private Sub Worksheet_Change(ByVal Target As Range)

  ...続きを読む

QVBAで既に開いている別アプリケーションのオブジェクトを得る

 VBAで別のアプリケーションにアクセスするには、CreateObject関数を使ってアプリケーションのオブジェクトを作るようにすると思います。例えば、ワード文書にアクセスするなら次の構文になると思います。
  Set appWord = CreateObject("Word.Application")
  appWord.Visible = True
 しかしこれだと新しいワード文書を作ったり、既存のワードファイルを開いて扱うことしかできません。GetObject関数を用いても同様のようです。既に別ウィンドウで開いているワード文書があって、そこへアクセスするにはどうしたらよいのでしょうか。
 また、同じアプリで複数のファイルを開いている場合には、どうやって目的のファイルへのオブジェクトを得るのでしょうか。(ファイル名などを参照して判断?)

Aベストアンサー

Internet Explorerで開いているWindowを取得することはできますよ。

そのためには、まず開いているWindowを順番に取得し、それがInternet Explorerならばそれをオブジェクトに代入し、ひとつもIEウィンドウが存在しない場合は新規作成(CreateObject)すればいいのです。
Windowを取得するにはShell.Applicationというのを使います。

Dim ObjIE As Object
Dim ObjShell As Object
Dim ObjWindow As Object
Dim WinExist As Boolean

WinExist = False
Set ObjShell = CreateObject("Shell.Application")
For Each ObjWindow In ObjShell.Windows
If TypeName(ObjWindow.Document) = "HTMLDocument" Then
 WinExist = True
 Set ObjIE = ObjWindow
End If
Next
Set ObjShell = Nothing

If Not WinExist = True Then
Set ObjIE = CreateObject("InternetExplorer.Application")
End If

ObjIE.Navigate "http://nantokakantoka.html"
ObjIE.Visible = True


というような感じです。
Wordの場合はわからなくてすみません。
独学なのでもっといい方法があるかもしれないですが。

Internet Explorerで開いているWindowを取得することはできますよ。

そのためには、まず開いているWindowを順番に取得し、それがInternet Explorerならばそれをオブジェクトに代入し、ひとつもIEウィンドウが存在しない場合は新規作成(CreateObject)すればいいのです。
Windowを取得するにはShell.Applicationというのを使います。

Dim ObjIE As Object
Dim ObjShell As Object
Dim ObjWindow As Object
Dim WinExist As Boolean

WinExist = False
Set ObjShell = CreateObject("Shell.Applicatio...続きを読む

QEXCEL VBA で他のアプリケーションを開く方法について

EXCEL VBAで他のアプリケーションを開く方法について教えていただきたいことがあります。
現在開いているエクセルのブックと同じフォルダにある、"AAA"という名称のsqc形式のファイル(EAST社のSkyLink Ver9.0のコマンドファイルです)をVBAで開く。
SHELL関数で開くと思っていたのですが、

Sub Test()
Dim MyPath As String, MyTask As Double
MyPath = ActiveWorkbook.Path & "\"
MyTask = Shell(MyPath & "AAA.sqc")
SendKeys "%FO", True
End Sub
とすると
「プロシージャの呼び出し、または引数が不正です」
というメッセージが出てしまいます。
如何せんSHELL関数を使うのが初めてでして、色々調べても
どうしても解決策にたどり着きません。
どうぞよろしくお願いいたします。

Aベストアンサー

こんにちは。

>SHELL関数で開くと思っていたのですが、

たぶん、読み違えたのだと思います。Shell でファイルを開くというのは、全部で3つの種類があります。それぞれ使い方が違います。ご質問に書かれているShell は、Excelの内部から呼び出す、つまり、Excelの配下からの呼び出しですから、ファイル名を指定しても、それを起動するソフトは分かりません。

一旦、Excelから降りてあげないといけないのですが、しかし、その方法が、通常2つの種類あります。ひとつは、Win OSからと、コマンドラインからと二種類あります。(厳密には、Win32APIなど、後二つあります。)

使いやすい方法は以下の方法ですが、拡張子が登録していることと、OS によって、その挙動が変わるはです。若干、エキスプローラからクリックしたものとは違うようです。

'-------------------------------------------

Sub TestSehll_1()
  Dim objSh As Object
  Dim myPath As String
  Dim fn As String
  '-------------------------------------------
  fn = "AAA.sqc"
  myPath = ActiveWorkbook.Path & "\" & fn
  '-------------------------------------------
  If Dir(fn) = "" Then
    MsgBox "ファイルがありません。", 48
    Exit Sub
  End If
  With CreateObject("Shell.Application")
    .ShellExecute myPath
  End With
  ''SendKeys "%FO", True 'これは、どうかな?
End Sub

なお、SkyLink というソフトの仕様を読んでみないけれども、検索すると、そのソフト名と同時に、Excel マクロという名前が出てきます。もしも、オートメーションを想定したソフトである場合は、このように外部から動かそうとはせずに、もっと確実な方法があるかもしれません。

こんにちは。

>SHELL関数で開くと思っていたのですが、

たぶん、読み違えたのだと思います。Shell でファイルを開くというのは、全部で3つの種類があります。それぞれ使い方が違います。ご質問に書かれているShell は、Excelの内部から呼び出す、つまり、Excelの配下からの呼び出しですから、ファイル名を指定しても、それを起動するソフトは分かりません。

一旦、Excelから降りてあげないといけないのですが、しかし、その方法が、通常2つの種類あります。ひとつは、Win OSからと、コマンドラインからと...続きを読む

Qエクセル マクロで指定フォルダを開く

エクセルにて
指定フォルダを開く、マクロがあれば教えて頂けないでしょうか。
よろしくお願いいたします。

Aベストアンサー

こんにちは。

こういうものですか?
開くフォルダを変えたいときは targ に与えるパスを変更します。

Sub OpenFolders()
Dim targ As String
targ = "C:\"
Shell "C:\Windows\Explorer.exe " & targ, vbNormalFocus
End Sub

QPDFファイルを開き、印刷し、閉じるマクロ

Excel 2003 VBAにて、
PDFファイルを開き、印刷し、閉じるマクロを作りたいと思っています。

Dim AA, AAA

AA = "C:\Program Files\Adobe\Reader 11.0\Reader\AcroRd32.exe C:\Scan\20131101160734050_001.pdf"
AAA = Shell(AA, vbNormalFocus)

にて、PDFファイルを開くことは出来ました。
このPDFファイルを、「印刷し、閉じる」ためには、
このPDFファイルを指定する必要があると思いますが、
その構文が判りません。
知っている方、教えて下さい。

Aベストアンサー

#3です。
WShell.Execを使うと閉じる事ができる様ですが、色々と気難しくて苦労しました。
まず、なぜかAdobe Reader/Acrobatのフルパスを与えないと、ファイルがみつからないとゴネます。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub test()
printPdf2 GetDesktopPath & "\test.pdf", "DocuWorks Printer", "DocuWorks Printer Driver"
' printPdf2 GetDesktopPath & "\test.pdf"
End Sub

Sub printPdf2(pdfDocument As String, Optional printerName As Variant, Optional printerDriver As Variant)
Dim cmdLine As String
Dim WShell As Object
Dim oExec As Object
'ここは調整の必要がありそう
Const waitTime As Long = 1000
'Windows7 Home 64bitの場合です
Const pgmFullPath As String = "C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe"

Set WShell = CreateObject("WScript.Shell")
If IsMissing(printerName) Or IsMissing(printerDriver) Then
cmdLine = "pgmFullPath /n /s /o /h /t ""pdfFullPath"""
cmdLine = Replace(cmdLine, "pgmFullPath", pgmFullPath)
cmdLine = Replace(cmdLine, "pdfFullPath", pdfDocument)
Else
cmdLine = "pgmFullPath /n /s /o /h /t ""pdfFullPath"" ""printerName"" ""printerDriver"""
cmdLine = Replace(cmdLine, "pgmFullPath", pgmFullPath)
cmdLine = Replace(cmdLine, "pdfFullPath", pdfDocument)
cmdLine = Replace(cmdLine, "printerName", printerName)
cmdLine = Replace(cmdLine, "printeDriver", printerDriver)
End If
Debug.Print cmdLine
Set oExec = WShell.exec(cmdLine)
Sleep waitTime
'Windows7Home/64bit環境ではここで実行時エラーが出るので無理矢理先に進めていますが
'Adobe Readerは閉じられる様です
On Error Resume Next
oExec.Terminate
Set WShell = Nothing
End Sub

Private Function GetDesktopPath() As String
Dim wScriptHost As Object, strInitDir As String
Set wScriptHost = CreateObject("Wscript.Shell")
GetDesktopPath = wScriptHost.SpecialFolders("Desktop")
Set wScriptHost = Nothing
End Function

Terminateで原因不明のエラーが出るのでWebを漁っいて下記をみつけました。64bit環境でエラーが出るのはこれも関係しているのでしょうか?少々無理をしている様なので、ご使用時はご注意下さい。
Terminate メソッドは最後の手段としてのみ使用します。これは、アプリケーションによっては適切にクリーンアップできない場合があるためです。通常は、プロセスを途中で中断せず、プロセス自身で実行を終了させるようにします。Terminate メソッドは WM_CLOSE メッセージを使ってプロセスを終了しようとします。これで終了できない場合は、通常のシャットダウン手順を実行せずに、プロセスを強制終了します。
http://msdn.microsoft.com/ja-jp/library/cc364387.aspx

#3です。
WShell.Execを使うと閉じる事ができる様ですが、色々と気難しくて苦労しました。
まず、なぜかAdobe Reader/Acrobatのフルパスを与えないと、ファイルがみつからないとゴネます。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub test()
printPdf2 GetDesktopPath & "\test.pdf", "DocuWorks Printer", "DocuWorks Printer Driver"
' printPdf2 GetDesktopPath & "\test.pdf"
End Sub

Sub printPdf2(pdfDocument As String, Optional printerName As Variant, Optional prin...続きを読む

QEXCEL VBA で現在開いているブックのファイル名を取得する方法

EXCEL2003 VBAで業務を簡素化するために、現在開いているブックのファイル名を取得する方法が分かりません。
作業手順をマクロを使って処理していますが、オリジナルのワークブックをファイル名を変えて保存し、以後、このワークブックを読み込んで使用しています。
このときのVBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり、以後の業務に使用できません。
常にファイル名を取得出来るVBAをどなたか、教えて下さい。

Aベストアンサー

>現在開いているブックのファイル名
 ちょっと曖昧な表現かなぁという気もいたしますが、VBAが書いてあるブックのブック名は
ThisWorkbook.Name
で、現在 "アクティブにして" 操作対象になっているブックの名前は
ActiveWorkbook.Name
ですね。

 しかし、
>VBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり
というような文脈からすると、
ThisWorkbook.Name
の方ですかね。

QEXCELファイルのカレントフォルダを取得するには?

EXCELファイルのカレントフォルダを取得するには?

C:\経理\予算.xls

D:\2005年度\予算.xls

EXCEL97ファイルがあります。

VBAで
  カレントフォルダ名
(C:\経理\,D:\2005年度\)
を取得する事は可能でしょうか?

CURDIRでは上手い方法が見つかりませんでした。

Aベストアンサー

こんばんは。
Excel97 でも、同じですね。以下で試してみてください。

Sub test()
'このブックのパス
a = ThisWorkbook.Path
'アクティブブックのパス
b = ActiveWorkbook.Path
'Excelで設定されたデフォルトパス
c = Application.DefaultFilePath
'カレントディレクトリ
d = CurDir
MsgBox "このブックのパス   : " & a & Chr(13) & _
   "アクティブブックのパス: " & b & Chr(13) & _
   "デフォルトパス    : " & c & Chr(13) & _
   "カレントディレクトリ : " & d & Chr(13)
End Sub


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報