プロが教える店舗&オフィスのセキュリティ対策術

やりたいことはVBAからコマンドプロンプトにてBCP.EXEを呼び出してSQL文を実行することです。
コマンドプロンプトで直接打つと以下のようなコマンドになります。SQL文は長いので省略しました。
*************************
"c:\WINNT\system32\cmd.exe /k" "C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe " "SQL文"
*************************
これをVBAで以下のように記述しました。
//////////////////////////////////////////////////
stAppName = "c:\WINNT\system32\cmd.exe /k"
stAppName = stAppName & "C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe "
stAppName = stAppName & "SQL文"
Call Shell(stAppName, 1)
/////////////////////////////////////////////////

上のような記述だとコマンドプロンプトでは パスのダブクォテーションがなくなり
*************************
c:\WINNT\system32\cmd.exe /k C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe ”SQL文”
*************************
のように実行されBCP.exeのパスが通らず以下のエラーになります。
/////////////////////////////////////////////////
内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
/////////////////////////////////////////////////

どなたかVBAでコマンドのパスにダブルクォテーションをつける方法を教えてください。

A 回答 (6件)

 


> Const DQ = Chr(34)はコンパイルエラーになります。
> 使い方が間違っているのでしょうか?

間違えてます。
答えを書くのは簡単ですが、「なぜエラーになるのか」、
「何が原因なのか」考える習慣を付けないと、何度質問しても実力は身に付きません。

ヒントですが、エラーメッセージの文言に問題点が端的に表現されています。そして、エラーメッセージには、[OK]ボタンだけではなく、[ヘルプ]ボタンも付いています。
ひとことで言うと、「定数の値を変数で定義することはできない」ということです。
(関数の返値は動的に変化しますので、変数の一種です)


> Call Shell(stAppName, vbHide) を実行してみましたがAccessから”ファイルが見つかりません”というエラーが帰ってきます。

空白文字が含まれるパスはダブルクォートで括る必要があることは理解されているでしょうか?

キーボードの<Ctrl> + <G>キーを叩くとイミディエイトウィンドウが開きます。そこで、

?stAppName <Enter>

とタイプしてみてください。
ダブルクォートはなく、

c:\WINNT\system32\cmd.exe /k C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe DatabaseName.UserName.TableName -q -c (以下、略)

と表示されます。

で、すでにNo.1で述べたように(読んでおられないか、見落しているようですが)

stAppName = Environ("ComSpec") & " /C ""C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe"" """ & SQL文字列 & """"

としてから、

?stAppName <Enter>

とタイプすると、今度は、

C:\WINNT\system32\cmd.exe /k "C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe" DatabaseName.UserName.TableName -q -c (以下、略)

と、必要な箇所にダブルクォートが付加されて表示されます。

ダブルクォートは通常の文字と違い、文字列の開始と終端を表現する「メタ文字」(制御文字)なので、文字列の内部でダブルクォートを記述するには、「エスケープ」(=通常の文字と同列に扱う)という処理が必要です。
文字列内でダブルクォートを2つ重ねると、終端ではなく、「文字列の一部」として扱うことができます。(シングルクォートでも同様で、SQL文の中で、文字の一つとして扱うには、「''」と記述します)

ちなみに、

C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe

の部分はフルパスで記述しなくとも、

bcp

だけで実行できるはずです。
と言うか、フルパスで記述すると、

(1) インストールされているドライブやフォルダ名が開発環境と違う場合のことも考慮する必要がある。
    ↓
(2) 実行環境でbcp.exeのフルパスを取得する処理を書く必要がある。
    ↓
(3) レジストリを読む必要がある。(API必須)

となって、コードが増大します。

「C:\WINNT\system32\cmd.exe」についても、上記(2)とおなじ理由で感心しません。

Environ("ComSpec")

とすれば、OSがどこにインストールされていても、コードを変更することなくプログラムが動作します。


ついでに・・・。

インポート処理なら、bcp を使用するより、BULK INSERT を使用した方が高速に処理できる旨、SQL Server (2000)の Books On Line に記載されていますが、ご存じでしょうか?
 

この回答への補足

すみませんでした、もう回答を書いたところにまた回答を書かないのでは・・・と卑怯な思いをしてしまい
新しく質問を開設しました。
確かに自分っていろいろ甘いなと反省しています。ぜんぜんわからないことを短時間でやろうとしてなんでもかんでも聞いちゃっていますね。
でも目的を達成するために、叱りながらも教えてくれる方に甘えたいと思います。

問題(1) Const DQ = Chr(34)
今まで私が使っていた言語はパッケージソフトについているVasicScriptという偏った言語でこのような使い方ができました。ですので"Chr(34)"はひとつのコード(定数)と思ってました。
これでVBAとVBSriptがいろいろ違うとよく認識できました。

問題(2)空白文字が含まれるパスについて
>で、すでにNo.1で述べたように(読んでおられないか、見落しているようですが
さすがにそれは見落としてません、教えていただいたとおりにやってダブルクォートがつくのを検証しました。 そのダブルクォートがついているコマンドをコマンドプロンプトに移して実行成功しました。だけどAccessから実行するとエラーメッセになります。
焦てる割にはちゃんと説明してなくてごめんなさい。

今現在やっていることは Accessのフォームからパラメータが入力されたらそのパラメタをもってMSDEのテーブルから条件にあうデータを選択してエクスポートする(CSV)ことです。
ここまで書いてみたらやっぱり自分がいけないと思います。なにひとつわかってないということがよく認識できました。明日会社に行って勉強します。
ご指導とご勧告に感謝します。

補足日時:2003/04/20 01:59
    • good
    • 0
この回答へのお礼

丁寧なご指導ありがとうございます。
ファイルが見つからない理由がわからず(もしかして実行文の長さと関係してるとか?)、takntさんのアドバイスとおりバッチファイルを作って実行させることに成功しました。

>C:\Program Files\Microsoft SQL Server\80\Tools\Binn\bcp.exe

の部分はフルパスで記述しなくとも、

bcp
だけで実行できるはずです。
について疑問ですが

BCPが環境変数に設定されてないとパスなしでは実行できないのではないでしょうか?

お礼日時:2003/04/21 20:06

定数なら、関数が使えないのは当たり前


dim DQ as string
DQ=chr(34)
だろ

定数なら
Const DQ = """"

VBの本を1から○×△※
と言っておこう
    • good
    • 0

chr(34)

この回答への補足

Const DQ = Chr(34)はコンパイルエラーになります。
使い方が間違っているのでしょうか?

補足日時:2003/04/19 21:26
    • good
    • 0

BATファイルを作成し、BATファイルに記述し、


実行させるという手もあります。

VBで そのBATファイルの編集をするか
パラメタで渡してあげればいいでしょう。
    • good
    • 1

 


No.1の補足です。

/k よりは/c の方がよいでしょう。

> Call Shell(stAppName, 1)
  ↓
Call Shell(stAppName, vbHide)

プロンプトを表示する必要はないと思いますので、/Cを指定した上で、vbHideで実行した方がよいでしょう。
 

この回答への補足

早速のアドバイスありがとうございます。
教えていただいたとおりやったら要望のコマンドができて
Call Shell(stAppName, vbHide) を実行してみましたがAccessから”ファイルが見つかりません”というエラーが帰ってきます。”stAppName”をそのままコマンドプロンプトに打ち込んだら実行されるのですが・・・

stAppName = "CMD.exeパス" & "BCP.exeパス" & "SQL文"
Call Shell(stAppName, vbHide)
このコマンドはクリックイベントプロシージャとしてコマンドボタンに登録されています。
これでコマンドプロンプトを起動し、そこからさらにBCP.exeを起動するつもりですが・・・
なにかアドバイスはございますでしょうか?

補足日時:2003/04/19 21:24
    • good
    • 0

 


> stAppName = "c:\WINNT\system32\cmd.exe /k"
  ↓
stAppName = "%ComSpec% /k"

> stAppName = stAppName & "SQL文"
  ↓
stAppName = stAppName & """" & SQL文 & """"
    • good
    • 0

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