出産前後の痔にはご注意!

VBAから複数のバッチファイルを実行する際に、1つの処理が終了するまで次の処理を待機させる方法について

こんにちは。VBA初心者です。

Shell関数を使って複数のバッチを連続して実行するプログラムを書きたいのですが、前のバッチ処理が終了する前に次のバッチが実行されてしまいエラーになってしまいます。

1つのバッチ処理が終了するまで、次の処理を待機させるようなことは可能でしょうか。

具体的には、B列に「test_01.txt」「test_02.txt」... といったファイル名が入力されていて、隣のA列に何らかの文字/記号があった場合は、指定されたバッチ(ファイル名.bat)が実行されるということをやりたいと考えています。

以下のようなプログラムを書いてみましたが、実行するバッチが複数になるとうまくいきせん。
どうしたら問題を回避できるか、ご教示いただけないでしょうか。
よろしくお願いします。

Sub バッチを実行()
i = 7 'リストの開始行
Const myPath As String = "D:\sample_batch\"
  Const endPath As String = ".bat"

 For i = 7 To 200 '7行目から200行目まで実行

If Cells(i, 1).Value <> "" Then
Shell (myPath & Cells(i, 2).Value & endPath)

End If
Next
End Sub

A 回答 (4件)

確かに。

。。andy_kunさんのおっしゃるように「"」の付け方が怪しかったですね。

バッチファイルまでのパスにスペースが無いならandy_kunさんの回答通りで。
ある(かもしれない)なら
 objWShell.Run """" & myPath & Cells(i, 2).Value & endPath & """", 1, True
で。

ただ、私の場合
 実行時エラー'91' オブジェクト変数または With ブロック変数が設定されていません。
じゃなくてオートメーションエラーになりましたが。。。

この回答への補足

ありがとうございます!

教えていただいた方法でとりあえずエラーは回避できました。

しかし、処理がループにならずに 1 回で終了してしまいます。

そこで、WScript.Shellを1回ごとに初期化する必要があるのかと思い、以下の例のように「objWShell = null」や「Set objWShell = Nothing」などを挿入してみたのですが、動作に変化がありません。

実行したプログラムの終了コードを参照するのに別途何かコードがいるのでしょうか。
(それとも、バッチの内容が他のエクセルシートとサーバの通信に関するもので、処理に時間がかかるのが原因か??? ※なぜ、一旦バッチを経由してエクセルシートの処理をするのか…というのは聞かないでください。ちょっと、事情があるのです)

Sub バッチを実行()

Dim objWShell
Set objWShell = CreateObject("WScript.Shell")
Dim i As Integer

i = 7 'リストの開始行
Const myPath As String = "D:\20101006_test\"
Const endPath As String = ".bat"

For i = 7 To 200 '7行目から200行目まで実行

If Cells(i, 1).Value <> "" Then
MsgBox (Cells(i, 2).Value & " をコンバートします。")
objWShell.Run myPath & Cells(i, 2).Value & endPath, 1, True
End If
Set objWShell = Nothing
Next

End Sub

補足日時:2010/10/07 18:14
    • good
    • 0
この回答へのお礼

マッチポンプですみません。

objWShell.Run myPath & Cells(i, 2).Value & endPath, 1, True

の次に

Workbooks("ブック名").Worksheets("シート名").Activate

を挿入して、アクティブなブック(シート)をVBAを実行している方に戻したらOKでした。

お礼日時:2010/10/07 19:11

こうかな?


objWShell.Run myPath & Cells(i, 2).Value & endPath, 1, True

"は不要だと思うけど
    • good
    • 0

objWShell.Run "myPath & Cells(i, 2).Value & endPath", 1, True


かな?

この回答への補足

早速のご回答ありがとうございます。

先程の補足で「.Run」抜けていることに気付き、ご指摘のようにしたのですが、

「実行時エラー'91' オブジェクト変数または With ブロック変数が設定されていません。」

となってしまいました。

どこがいけないのか、本当に途方に暮れています。。。
何かわかることがあれば、是非々々ご教示ください。

補足日時:2010/10/07 14:00
    • good
    • 0

Shell関数は非同期ですので、


代わりに WScript.Shellオブジェクトの Runメソッドを使いましょう。

この回答への補足

ご回答ありがとうございます。

WScript.Shellというものがあるんですね。VBEのヘルプを見ても載っていませんでしたが、WEBで調べたら使い方が書いてありました。

そこで、プログラムを以下のように変更してみたのですが、実行すると「コンパイルエラー:Sub, Function, またはproperty が必要です。」となってしまいます。

どこがいけないのかご指摘いただけないでしょうか。
(正直に申し上げて、エラーの意味が分かりません)

Sub バッチを実行()

Dim objWShell
Set objWShell = CreateObject("WScript.Shell")
Dim i As Integer

i = 7 'リストの開始行
Const myPath As String = "D:\test_path\"
Const endPath As String = ".bat"

For i = 7 To 200 '7行目から200行目まで実行

If Cells(i, 1).Value <> "" Then
MsgBox (Cells(i, 2).Value & " をコンバートします。")
objWShell "myPath & Cells(i, 2).Value & endPath", 1, True

End If
Next
End Sub

補足日時:2010/10/07 12:30
    • good
    • 0
この回答へのお礼

スミマセン。補足では「.Run」が抜けていました。

objWShell.Run "myPath & Cells(i, 2).Value & endPath", 1, True

としたところ、「実行時エラー'91' オブジェクト変数または With ブロック変数が設定されていません。」となってしまいました。

謎です。。。

お礼日時:2010/10/07 12:48

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

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

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

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

QShell関数からバッチファイルを起動後に、バッチファイルが終了するまで待ちたい。

はじめまして。
掲題の通り、VB.netからshell関数を用いてバッチファイルを起動します。
その後、そのバッチファイルが終了してログファイルの出力を完了した後に、
ファイルを開いて確認したいのです。
thread.sleepなどで大体このくらいかなという時間を待ってみる、
などのやり方しか今は思いつかないのですが、
何か明確にバッチファイルの終了を受け取れる方法は無いものでしょうか。

どなたかご存知の方がいらっしゃいましたらご教授ください。

Aベストアンサー

Shell関数より Processクラスで実行したほうが簡単に待てますよ

Dim oPro as Process
oPro = Process.Start("..\..\a.bat")
oPro.WaitForExit()
MessageBox.Show("Hello")

といった具合です

QVBAで外部プログラムを非表示で実行するには

VBAとVBScriptを混同しているのかもしれませんがよく分からないので教えてください。

Excel2010のVBAから、外部プログラム(test.exe)をコマンドプロンプトを非表示の状態で実行して、外部プログラムの実行が終了するのを待ってから、次の処理をさせたいのですが、test1のプログラムでは(A)の部分でエラーになってしまいます。また、test2のプログラムでは正しく実行されるのですがコマンドプロンプトのウインドウを非表示にする方法がよく分かりません。

test1のプログラムでエラーをでなくする方法、または、test2のプログラムでコマンドプロンプトのウインドウを非表示にする方法がありましたら教えてください。

-------------------------------------------------------
Sub test1()
 Dim ws As Object
 Dim we As Object
 Dim command As String
 command = "C:\test.exe"
 Set ws = CreateObject("WScript.Shell")
 Set we = ws.Run("%ComSpec% /c " & command, 0, False) '<===(A)
 Set we = Nothing
 Set ws = Nothing
End Sub
-------------------------------------------------------
Sub test2()
 Dim ws As Object
 Dim we As Object
 Dim command As String
 command = "C:\test.exe"
 Set ws = CreateObject("WScript.Shell")
 Set we = ws.exec("%ComSpec% /c " & command)
 Do Until we.Status
  DoEvents
 Loop
 Set we = Nothing
 Set ws = Nothing
End Sub
-------------------------------------------------------

VBAとVBScriptを混同しているのかもしれませんがよく分からないので教えてください。

Excel2010のVBAから、外部プログラム(test.exe)をコマンドプロンプトを非表示の状態で実行して、外部プログラムの実行が終了するのを待ってから、次の処理をさせたいのですが、test1のプログラムでは(A)の部分でエラーになってしまいます。また、test2のプログラムでは正しく実行されるのですがコマンドプロンプトのウインドウを非表示にする方法がよく分かりません。

test1のプログラムでエラーをでなくする方法、または、te...続きを読む

Aベストアンサー

Runメソッドを何処で調べましたか?
詳しくはこちらを見てください。
http://msdn.microsoft.com/ja-jp/library/cc364421.aspx

先ず、Aで失敗する理由ですが、Runメソッドの戻り値は何型ですか?
説明を見れば分かると思いますが、整数です。オブジェクトでは
ありません。従って、戻り値の型が違うし、Set文を使うのもオカシイ

次に、プログラムの終了を待つなら、Runメソッドの第3引数は
省略するか、Trueを指定すべきです。

test2のExecメソッドはオブジェクトを返しますが、この中には
標準入出力やエラー出力用の出し入れ口があり、人に代わって
データを送り込んだり、出力結果を見て、処理を変更するなどを
行う場合に使いますので、今回の仕様では使いません。
尚、DoEventsでグルグル回る処理は絶対にすべきではありません。
必ずSleepを入れるべきだし、DoEventsの使用そのものを避ける
べきだからです。この文がどのような効果をもたらすかを理解しており、
それを制御できるだけの技術があれば別ですが・・・

Runメソッドを何処で調べましたか?
詳しくはこちらを見てください。
http://msdn.microsoft.com/ja-jp/library/cc364421.aspx

先ず、Aで失敗する理由ですが、Runメソッドの戻り値は何型ですか?
説明を見れば分かると思いますが、整数です。オブジェクトでは
ありません。従って、戻り値の型が違うし、Set文を使うのもオカシイ

次に、プログラムの終了を待つなら、Runメソッドの第3引数は
省略するか、Trueを指定すべきです。

test2のExecメソッドはオブジェクトを返しますが、この中には
標準入出力やエラー...続きを読む

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

QVBからBATファイルを起動して戻り値の取得方法

VBからBATファイルを起動して戻り値(エラーコード)を
もらうにはどうすれば良いのでしょうか?
WshShellという関数を使用することは、何となく分かるのですが
宜しければサンプルを教えていただけないでしょうか?

Aベストアンサー

>WScript.CreateObjectの
>ところで"オブジェクトが必要です"となってしまいます。

VBのときは、CreateObjectですね。

QExcel VBAにて2つの処理を同時実行可能?

是非お力をお貸し下さい。
よろしくお願いします。
Windows XP
Excel2003 (VB6.0)

メイン処理が非常に時間がかかるため、フォームを表示させ
文字(Label)を点滅させて「動いている(ハングアップしていない)」ことを
使用者に伝えようとしています。

--- Form1内のコード(メイン) ---
Sub Main()

Form2.Show vbModeless

[ ~メイン処理~ ]

End Sub

--- Form2内のコード ---
Sub UserForm_Initialize()

Call Blink

End Sub

--- 標準モジュール内のコード ---
Sub Blink()

If Form2.Label1.Visible = True Then
Form2.Label1.Visible = False
Else
Form2.Label1.Visible = True
End If

Form2.Repaint

DoEvents

Application.OnTime Now + TimeValue("00:00:01"), "Blink"

End Sub


これを実行すると、メイン処理が終了した後にForm2内の文字が
点滅します。

実現したいのは「使用者が動いていることを(ハングアップしていない
ことを)確認出来る」という点です。

どうぞ よろしくお願いします。

是非お力をお貸し下さい。
よろしくお願いします。
Windows XP
Excel2003 (VB6.0)

メイン処理が非常に時間がかかるため、フォームを表示させ
文字(Label)を点滅させて「動いている(ハングアップしていない)」ことを
使用者に伝えようとしています。

--- Form1内のコード(メイン) ---
Sub Main()

Form2.Show vbModeless

[ ~メイン処理~ ]

End Sub

--- Form2内のコード ---
Sub UserForm_Initialize()

Call Blink

End Sub

--- 標準モジュール内のコード ---
Sub Blink()

If Form2.L...続きを読む

Aベストアンサー

単純に、HTMLファイルを表示するとかいうのではだめでしょうか?VBAに影響を与えることなくブラウザ側が勝手にやってくれるので、負荷は少ないように思うのですが。
的を外した回答でしたらすみません。

QExcelのセルの内容をコマンドプロンプトで実行

Excel VBA初心者です。
Excelのセルに記入されている文字列をコマンドプロンプトで実行する方法を教えて下さい。

具体的には、

A1 → d:
A2 → cd hogehoge
A3 → dir

とセルにそれぞれ記入されていたとして、フォームから作成したボタンを押下すると
A1~A3が順番にコマンドプロンプトで実行(貼り付け)されるマクロの作り方が知りたいです。

ロジックは以下のようにしたいと考えています。

セルA1に値 →ない→ 「値がありません」というエラーのポップアップか何かを表示。
↓ある
セルA1に記入された文字列をコマンドプロンプトで実行

セルA2に値 →ない→exit
↓ある
セルA2に記入された文字列をコマンドプロンプトで実行

セルA3に値 →ない→exit
↓ある
以下ループ

わかりにくいかもしれませんが、よろしくお願い致します。

Aベストアンサー

目的が分からないのですが、思いつきで作成してみました。
セルの情報からバッチファイルを生成して実行するコードです。
XPSP3、XL2000で試しています。ご参考まで。
Sub test()
Dim targetRange As Range
Dim FSO As Object
Dim i As Long
Dim myTextFile As Object
Dim batFilePath As String

Set FSO = CreateObject("Scripting.FileSystemObject")
’バッチファイルをテンポラリフォルダーに作成して実行します
batFilePath = FSO.GetSpecialFolder(2) & "\temp.bat"
Set myTextFile = FSO.CreateTextFile(batFilePath)
With ActiveSheet
Set targetRange = .Range(.Range("A1"), .Range("A" & .Rows.Count).End(xlUp))
End With
With myTextFile
For i = 1 To targetRange.Cells.Count
If i = targetRange.Cells.Count Then
'コマンドプロンプトを開いたままにする
.writeline "cmd /k " & targetRange.Cells(i)
Else
.writeline targetRange.Cells(i)
End If
Next i
.Close
End With
Set FSO = Nothing
CreateObject("WScript.Shell").Run "CMD.EXE /C " & batFilePath, , True
End Sub

おまけで、DOSコマンドの実行結果をVBAで取得したい時は、下記が参考になると思います。
http://www.f3.dion.ne.jp/~element/msaccess/AcTipsGetDosResult.html

目的が分からないのですが、思いつきで作成してみました。
セルの情報からバッチファイルを生成して実行するコードです。
XPSP3、XL2000で試しています。ご参考まで。
Sub test()
Dim targetRange As Range
Dim FSO As Object
Dim i As Long
Dim myTextFile As Object
Dim batFilePath As String

Set FSO = CreateObject("Scripting.FileSystemObject")
’バッチファイルをテンポラリフォルダーに作成して実行します
batFilePath = FSO.GetSpecialFolder(2) & "\temp.bat"
Set myTextFile = FSO...続きを読む

QEXCEL VBAで計算値を四捨五入、切り上げ、切捨てする方法

ネットで探してみたのですが、計算結果を四捨五入して特定のセルを
返すにはどうしたらいいのでしょうか?

Sub hokangosa()

Dim ZPS As Double
Dim ZPOS As Double
Dim DMN As Double
MsgBox (" >>> 補間誤差自動計算 <<< ")
MsgBox (" >>> 初期値入力します <<< ")
ZPS = InputBox(">>> ステップを入力してください<<<")
ZPOS = Sheet1.Cells(22, 4).Value
DMN = ZPOS / ZPS
Sheet1.Cells(23, 6).Value = DMN
End Sub

ここでDMNの値を四捨五入したいです。

またこれとは別に切上げ、切捨ても教えていただけるとありがたいです。

Aベストアンサー

DMN = Application.WorksheetFunction.Round(ZPOS / ZPS, 0)
で、四捨五入
DMN = Application.RoundDown(ZPOS / ZPS, 0)
で切り捨て
DMN = Application.RoundUp(ZPOS / ZPS, 0)
で切り上げです。

引数で、対象桁を変更できます。

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
'-------------------------------------
 
 

Qバッチファイルでエクセルのマクロを動かしたい

最近になってバッチファイルを知りました。バッチファイルを使ってエクセルファイルの中に書かれたマクロを動かしたいと思っています。
過去ログの検索をし、マクロが書かれたエクセルを起動させるところまではわかりました。
しかしその先がわかりません。わからない内容は次の二つです。
1)エクセル起動時マクロを有効にするかどうか聞いてきます。自動的に有効で起動させるにはどうしたらいいでしょうか。
2)Macro1という名前のものが001.xlsの中に既に作ってあったとして、これを作動させるにはどのようにしたらいいのでしょうか。
環境はwin xp sp2 office2000です。
過去ログを参考にし、下記記述で001.xlsを開くところまではわかりました。この後をどうすればいいか、よろしくお教えください。
"C:\Program Files\Microsoft Office\Office\excel.exe" "c:\My Documents\001.xls"

Aベストアンサー

こんにちは。

Perl 自体は、また別というか、Wscript.Run で呼び出してもよいと思いますが、
WScript でも、Perl の複雑な処理にはかないませんが、正規表現も持っていますから、多少は似たようなマネが出来ます。

バッチプログラムと違うのは、まず、フォルダを探すことが可能だということと、フォルダを選択する、ダイアログが使えるということです。

個別のファイルのファイルの移動なら、

Const myPATH ="C:\My Documents\

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile =objFS.GetFile(myPATH & "Test.txt")
objFile.Move "C:\"

個別のファイルのファイルの削除なら、

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile =objFS.GetFile(myPATH & "Test.txt")
objFile.Delete

----------------------------------------------
ワイルドカードも使うようでしたら、
Const myPATH ="C:\My Documents\


Set objFS = CreateObject("Scripting.FileSystemObject")
objFS.MoveFile myPATH &"*.txt", "C:\"

ですし、ファイルの削除なら、

Set objFS = CreateObject("Scripting.FileSystemObject")
objFS.DeleteFile myPATH &"*.txt"

ということになります。

---------------------------------------------
なお、余談ですがVBAの技術は、今はもう停滞したままですが、総じて、テキスト・スクリプト側は、日進月歩、Win XP になってからは、1年ごとに、まるで違う技術が導入されているのです。歯が立たないかもしれませんが、どんな風になっているかは、知っておいたほうがよいかもしれません。昔は、コンパイラーを使った、実行ファイルしたが、今は、テキスト・スクリプトで、ツールを出しています。それは、Office 2007 も同じですね。そして、今は、スクリプトで、.Net FrameWork まで使ってしまおうというのだから、時代は変わっているのです。(知っている人には、間が抜けた発言ですが。)

参考サイト:
ヘイ! スクリプティング ガイ
http://www.microsoft.com/japan/technet/scriptcenter/learnit.mspx

こんにちは。

Perl 自体は、また別というか、Wscript.Run で呼び出してもよいと思いますが、
WScript でも、Perl の複雑な処理にはかないませんが、正規表現も持っていますから、多少は似たようなマネが出来ます。

バッチプログラムと違うのは、まず、フォルダを探すことが可能だということと、フォルダを選択する、ダイアログが使えるということです。

個別のファイルのファイルの移動なら、

Const myPATH ="C:\My Documents\

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objF...続きを読む

Q複数のバッチを同時並行で起動したい

環境:Windows2003Server
バッチファイルの中に複数のバッチファイルを呼んでいるのですが、同時並行で実行することは可能でしょうか?
サーバにCPUが4つあるのですが一回の実行ではタスクが分散されず1CPUで負荷がかかってしまって対応方法を考えています。複数のバッチに分けてから同時に実行した場合はタスクも複数になる為、処理が分散されるのではないかと思っているのですが・・・。

どなたかアドバイスお願い致します。

Aベストアンサー

start C:\xxx\yyy.bat
とやると別のコマンドプロンプトが開いてそこで実行されますので、並行に処理が進みます。

1つのウィンドウでやるのはCMD.EXEが1つしか動いていない以上無理です。


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

人気Q&Aランキング