VBAにおけるOption Explicitの役割

このQ&Aのポイント
  • VBAでゲームを作る際に重要な役割を果たすOption Explicitについて解説します。
  • Option Explicitはプログラム中に宣言されていない変数を利用することを防ぎ、コンパイルエラーを防止する役割があります。
  • また、Option Explicitはプログラムの可読性を高め、変数の宣言漏れやスペルミスを見つけるのに役立ちます。
回答を見る
  • ベストアンサー

VBAにおける Option Explicitの役割

VBAにおける Option Explicitの役割 VBAでゲームを作ることを勉強している初心者です。 本に従ってもっとも基本的なスロットゲームをためしました。 プログラム本体の前にある下記のOption Explicitを省くとコンパイルエラーになります。 VBAにおける Option Explicitはプログラム本体中にあるどのキーがどのスロットを止めるなどの指示を 具体的記述なしに有効にするなどの役目があるのでしょうか。 Option Explicit Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Declare Function GetTickCount Lib "kernel32" () As Long 'Windows起動後経過時間取得API どなたか教えていただけると助かります。 よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Randomize
  • ベストアンサー率70% (38/54)
回答No.9

Wendy02さんの回答で出てきているのですが、勝手ながら今回の質問の内容に即して補足致します。 回答へのお礼の一部に 'Option Explicit 'Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long 'Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'Declare Function GetTickCount Lib "kernel32" () As Long 'Windows起動後経過時間取得API と言う風にかかれていますね。 Option ExplicitのほかにDeclareについても説明しなければいけませんね。 VBは基本的にコロン「:」を挟むかアンダースコア「_」単独を記述しない限りは1行でその命令は完結します。ですので、Option Explicitと次の行のDeclare Function・・・は別の構文になります。 さて、質問の内容に戻しましょう。 Daclareステートメントの意味はDLLなど外部にあるプロシージャーを使用するために「プロシージャ」を宣言するための構文です。 Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long の場合ですと、User32.dll内にあるGetAsyncKeyStateというプロシージャを使用するために、「User32.dll内にはGetAsyncKeyStateと言う命令があり、この命令を使用したいと思います。使用するためにはLong型の変数を1個値渡しで引数に渡さなければいけないので、その変数をvKeyと言う名前で宣言します。また、このプロシージャからはLong型の値が結果として帰ってきます。Visual Basicさん、よろしくお願いします。」といった感じでプロシージャを宣言しているのです。 ここで実際の構文を見てみましょう。 Option Explicitを省くとエラーになると言うことでしたよね。通常は皆さんが言うように逆がよく発生すのです。今回はどうしてエラーが発生したのでしょう。 これは私の推測ですが、Option Explicitを省いていない状態では変数の宣言は問題なく行えていたのかもしれません。では、なぜOption Explicitを省くとエラーが発生したのでしょう。 それは、Wendy02さんの回答でも出てきているのですが、その下にある Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long 以下の構文までもコメントアウトしてしまっているからです。 Declare構文は外部にあるプロシージャを呼び出すためのものです。外部にあると言うことはVisual BasicにはGetAsyncKeyStateに関する情報は何も無いのです。変数なのか関数なのかすらも分からない状態なのです。(だからDeclareステートメントを使ってVisual Basic側に使い方を教えているのです) ではここでエラーの起こった文を見てみると、 If GetAsyncKeyState(90) <> 0 Then と言う情報が何も知らされずにやってきました。Visual Basic側としては何も知らないので、GetAsyncKeyStateが何であるかを調べようとします。でも後ろにかっこ( )が付いているのでプロシージャであると解釈します。そしてこのプロシージャって何?と調べようとしますが、当然何も出てきません。変数と判断した場合は自動的に影で変数を作成しますが、プロシージャと判断した場合は何をするプロシージャかも分からないので「GetAsyncKeyStateってプロシージャは無いですよ?」とエラーを出すのです。これがコンパイルエラー「Sub または Function が定義されていません。」です。 ためしにDeclareの構文のコメントアウトを解除してOption Explicitの行のみコメントアウトしてみてください。おそらくそこでコンパイルエラーは発生しなくなると思います。 ちなみに、もしこれが If GetAsyncKeyState <> 0 Then と書いた場合は、GetAsyncKeyStateは変数であると解釈され、このIF式は必ず偽になりこのIFの内部は実行されなくなります。

sakura54
質問者

お礼

Randmize様 >Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long 私にとって火星語と同じだった上記の意味を丁寧に教えていただいて感激しました。 >ためしにDeclareの構文のコメントアウトを解除してOption Explicitの行のみコメントアウトしてみてください。おそらくそこでコンパイルエラーは発生しなくなると思います。 仰るとおりでした。 貴重な知識を与えてくださってありがとうございました。

その他の回答 (8)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.8

Option Explicit と Declare Funciton/Sub を混同して、それら全部に、コメントブロック('---)をしたからエラーが出たという話だったはずです。 >下記のキー判定の最初の1行のGetAsyncKeyStateの部分がコンパイルエラーで色が変わります。 そうでないと、ここがコンパイルエラーにはなりません。 まあ、本来は、Public Declare ~とか、Private Declare ~ とか書いたほうが分かりやすいようですが。 ReelF() は、配列変数ですよね。それは、どこかに変数の宣言を置いているということだと思いますし、ご質問範疇にはどこにも触れていないと思います。 だから、ReeIFは、例えば、Dim ReeIF(5) As Boolean などと、どこかに宣言しているはずです。

sakura54
質問者

お礼

Wendy02様  再度のご回答感謝いたします。 >ReelF() は、配列変数ですよね。それは、どこかに変数の宣言を置いているということだと思いますし、ご質問範疇にはどこにも触れていないと思います。 仰る通りプログラム最初の一連の宣言の中で次のように宣言されています。知識がないためプログラムのどの部分を見ていただかなければならないのかを判断できず大変失礼いたしました。 Dim ReelF(1 To 3) As Boolean 'リールの状態 いろいろ教えていただいてありがとうございました。

  • fujiponxx
  • ベストアンサー率32% (186/580)
回答No.7

まず、標準モジュールを追加して、 そこに以下の文を書きます。 ------------ Option Explicit Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Declare Function GetTickCount Lib "kernel32" () As Long 'Windows起動後経過時間取得API ------------ 他の文は別に標準モジュールでも シートに書いてもいいですが、 SUBかFUNCTIONのプロシージャ内に書きます。 ------------ Sub test()     'シートのコードに書いて、名前をTESTにしました。 'キー入力判定 If GetAsyncKeyState(90) <> 0 Then ReelF(1) = False  '<---そうするとここでエラーになります。            '   ReelF(1)が定義されていないからです。 End If If GetAsyncKeyState(88) <> 0 Then ReelF(2) = False End If If GetAsyncKeyState(67) <> 0 Then ReelF(3) = False End If End Sub ------------

sakura54
質問者

お礼

fujiponxx様  お忙しい中、何回もご回答感謝いたします。 >まず、標準モジュールを追加して、 そこに以下の文を書きます。 ------------ Option Explicit Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Declare Function GetTickCount Lib "kernel32" () As Long 'Windows起動後経過時間取得API 知識がないため間違っているかもしれませんが上記の文を書く場所が問題だと解釈しました。 ありがとうございました。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

#5様から改めて返事は付くと思いますが、 'Option Explicit 'Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long ' ・ ' ・ 外部関数や外部プロシージャと同じことですから、Win32 APIにコメントブロックはしてはいけませんね。Option Explicit と、Win32 APIは、まったく別です。 ちなみに、大村あつし氏の『Excel VBAでラクラクAPIプログラミング』は、PDFで復刻版が出ているようです。軒並み、Win32 APIのVB6系の書籍が廃版になりましたが、探せば、まだ古本などは見つかるはずです。.Net FrameWork の移行も進んではいるようですが、Office VBAでは範囲が限られているようです。

sakura54
質問者

お礼

Wendy2様 >外部関数や外部プロシージャと同じことですから、Win32 APIにコメントブロックはしてはいけませんね。Option Explicit と、Win32 APIは、まったく別です。 このような基本的かつ重要なことも知らないということはWendy2様が仰るように基本的勉強が必要なのですが、その場合使う本によって結果が大きく異なってきます。 >ちなみに、大村あつし氏の『Excel VBAでラクラクAPIプログラミング』は、PDFで復刻版が出ているようです。軒並み、Win32 APIのVB6系の書籍が廃版になりましたが、探せば、まだ古本などは見つかるはずです。.Net FrameWork の移行も進んではいるようですが、Office VBAでは範囲が限られているようです。 本についても貴重なご助言感謝いたします。 自分のレベルにあったものを探したいと思います。 ありがとうございました。

  • fujiponxx
  • ベストアンサー率32% (186/580)
回答No.5

まず、VBAで、コンパイルとかいてますが、 開発環境から確認する必要があります。 なにをつかってプログラミングしてますか? VBAといえば自分は、EXCELで書きますけど。 コンパイルしないで実行する事はできますか? その場合は、エラーになりますか? エラーになる場合は、どの行でなるかはわかりますか? エラー表示の内容は?

sakura54
質問者

お礼

fujiponxx様  たびたびのご回答感謝いたします。 私の使用しているソフトはExcel2007です。 下記のように宣言の部分を無効にすると 'Option Explicit 'Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long 'Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'Declare Function GetTickCount Lib "kernel32" () As Long 'Windows起動後経過時間取得API 下記のキー判定の最初の1行のGetAsyncKeyStateの部分がコンパイルエラーで色が変わります。 'キー入力判定 If GetAsyncKeyState(90) <> 0 Then ReelF(1) = False End If If GetAsyncKeyState(88) <> 0 Then ReelF(2) = False End If If GetAsyncKeyState(67) <> 0 Then ReelF(3) = False End If 何回もご迷惑をおかけします。 よろしくおねがいいたします。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

>Option Explicitの役割 もう少し、基礎的なことを学んだほうがよいと思いますね。 Option Explicit は、データ型の宣言を強制するものです。しかし、 >Option Explicitを省くとコンパイルエラーになります。 私も、どんなエラーが出ているかは分かりませんが、ふつうは、そんなことはありえません。 Option Explicit を入れて変化する場合は、「変数が定義されていません」と出るだけです。 ただ、私としては、Option Explicit を入れるのは入れる目的がはっきりしている人だけで、入れる目的が分からない人には、あまり入れても意味があるとは思えません。私は、初心者にも教えた経験でも、ふつうVBAのテキストでも、ある程度上達するまでは、入れなくてもよいと教えています。それでつまずいていたら、いつまでも、先に進めません。それで安易に、エラートラップ(On Error Goto ~)などを教える人もいますが、そういう安直な方法は、覚えなくてはならない部分を、台なしにしてしまいます。 変数でも、Byte 型や Currency 型を使いこなせるならともかく、そういうケースは、長くやっていないと出会いません。これらは、変数を宣言しないと、思ったようには使えません。(具体例は省きます) 一般的には、綴りを間違えないようにとは言いますが、最初の内は、変数は、複雑なものは使わないことですね。そうでなくても、長い名前の変数を使う人がいますが、読みにくくてしょうがないです。自分でも入れづらいと思います。それに、変数にはインテリセンスがありませんから、入力しにくいです。 ただ、他の方も触れていますが、ある程度の長さの変数を使うなら、Option Explicit といっしょに、キャメル形式(camel = ラクダ)という書き方、つまり、大文字・小文字を混ぜた変数で名付けます。そうすると、実際に書く時に、小文字で書けば、変化しないので、間違いが分かるわけです。プロシージャは、パスカル形式(Pascal, 先頭が大文字)、定数は、全部大文字(先頭に小文字で後は大文字も可)というような、プログラマの暗黙の約束がありますが、それは、別にあまり細かいことを言ってもしょうがありません。(ただし、ある程度の基本的な約束を守れない人は、何年もコードを書いていたとしても、少し長いコードを書かせればスパゲッティコードになるのは目に見えています。まともなコードが書けるはずがありません。) それと、 >GetAsyncKeyState(90) >( )の中の数字はキーごとにあらかじめ決まっている数字なのでしょうか。 90とかは、Win32 APIの定数ではなく、VB側の組込み定数で、本来、VB系では、組込み定数を使うのが良いとされます。 90   vbKeyZ '(&H5A) ←定数宣言は、本来16進で書きます。 88   vbKeyX '(&H58) 67   vbKeyC '(&H43) 38   vbKeyUp '(&H26) 113  vbKeyF2 ' (&H71) 私は、ひとつのブックで、何千行というコードを書きますが、直接、変数の宣言をしなくてエラーになるのではなくて、Win32 API関数でも、サブルーチン・Sub プロシージャやFunction プロシージャの場合は、ByVal になっていればだいたい通りますが、そうでないと、強制的に変数の宣言をあわせなくてはなりません。特に、Win32 APIは、間違えると、ハングすることがありますから、とても厄介です。しかし、私は、コーディングする場合、基本的な変数は入れておいて、Option Exlicit を、コメントブロックしておき、必要に応じて、変数を加えていくという書き方をしています。そして、最後にOption のブロックを外して、変数の宣言抜けをチェックします。そうしないと、VBAでは、先頭で変数を宣言するという決まりがありますから、途中で宣言していたら、コーディングの流れを見失ってしまいます。 なお、変数を宣言されていなければ、新しい変数のデータ型は、Variant 型で、値はEmpty です。

sakura54
質問者

お礼

Wendy02様  このように専門知識をお持ちの方から詳しいご説明を頂くことができて ほんとうに光栄に思います。私の知識がないためせっかくのご説明が理解 できない点も多いのですが、 >90とかは、Win32 APIの定数ではなく、VB側の組込み定数で、本来、VB系では、組込み定数を使うのが良いとされます。 90   vbKeyZ '(&H5A) ←定数宣言は、本来16進で書きます。 88   vbKeyX '(&H58) 67   vbKeyC '(&H43) 38   vbKeyUp '(&H26) 113  vbKeyF2 ' (&H71) この点を教えていただいただけでも私としては大変ありがたいです。 Wendy02様がおっしゃるようにもっと基本的な勉強からする必要が あることを実感しました。 ありがとうございました。

  • fujiponxx
  • ベストアンサー率32% (186/580)
回答No.3

Option Explicitを書いた状態で普通に動くのに、 Option Explicitを消したからって、エラーにはならないと思います。 別の所にエラーの原因があると思われます。

sakura54
質問者

お礼

fujiponxx様  再度のご回答感謝いたします。 >Option Explicitを書いた状態で普通に動くのに、 Option Explicitを消したからって、エラーにはならないと思います。 Randomize様のご回答を見ても仰る通りだと思います。 しかし、ではどの部分にミスがあるかということになると、 画面だけ自分で作って、プログラムは本についているCDからコピー したのでこの時点で私はお手上げです。 User32.dllやkernel32が何を意味するのかも分かりません。 また、プログラム中にリールを停止するキー判定として If GetAsyncKeyState(90) <> 0 Then ReelF(1) = False End If If GetAsyncKeyState(88) <> 0 Then ReelF(2) = False End If If GetAsyncKeyState(67) <> 0 Then ReelF(3) = False End If '上方向のキーが押されたらゲーム終了 If GetAsyncKeyState(38) <> 0 Then GameFlag = False End If とあるのですが( )の中の数字はキーごとにあらかじめ決まっている数字なのでしょうか。 お忙しいところ長々と書いて申し訳ありませんでした。 もし教えていただけたら大変助かります。 よろしくお願いいたします。

  • Randomize
  • ベストアンサー率70% (38/54)
回答No.2

回答内容からずれて記述を開始しますが、ずばり、今後ステップアップを少しでも考えているのであればOption Explicitは必ず記述してください。 Option Explicitは変数・APIによる関数・Sub/Functionプロシージャーなどなどすべての項目でDimなりDeclareなり何らかの形で宣言しなければエラーとしてコンパイルを完了させなくするためのものです。 この1文を削った場合は、何も宣言せずに For I=1 to 10 なんて文を書けばIは変数であると認識され自動的にIと言う変数が「影で」生成されます。VBは手軽に組める言語と言う面があるのでそういった親切機能がついているのです。しかし、この親切機能には大きな罠が潜んでいます。 「VB(VBAならなおさら)は手軽に組める言語である」という安易な理由でこの1文を削ることは非常によろしくないです。この1文を削ったときに良く現れるミスの1例を紹介します。 If PressBottonID=BottonRight Then と言うコードがあったとします。このコードを打ち込むときにタイプミスをしてしまい If PressBottomID=BottonRight Then と書いてしまったとします。 スロットと言うことで、右リールのストップボタンの押下判定をイメージしてみました。仮に目的のボタンのIDすなわちBottonRightは113が記入されていると仮定します。(数字はでたらめに入れてます) もしPressBottonIDが想定しているボタンである113番であったならばこの構文はTrueになりIF文の中が処理されることになります。 しかし、間違えた文の方でかつOption Explicitが宣言されていない場合はPressButtomIDという知らない文字が現れたときにVBはこれを新しい変数とみなして新しくPressButtomIDという変数を作成してしまいます。さらにVBは変数の初期化も自動でするので、PressButtomIDは0が入ることになります。 この状態でIF文を考えると、何のボタンを押しても比べられるのは押したボタンによって変化するPressButttonIDではなくて、何を入力しても常に0しかならない(その場で始めて生成されるから常に0にしかなりません)PressButtomIDが比較されてしまいます。 このことが何を示すかと言うと、どのボタンを押しても右リールのストップボタンを押したと判定されないと言うバグが発生することを意味します。さらに、大量に文字が並ぶ中、mとnの違いだけであるという探すのが困難なバグを生んでしまうことになります。しかもこのバグの一番厄介な点は、「一見動作はするけれど何か動きがおかしい」ことです。この手の物はどこでバグが起こっているかをすぐには把握しにくいのが通常です。 Option Explicitを宣言すると言うのは、こういったタイプミスなどによって知らない単語が出てきたときに、変数とみなして変数を作成するのではなく、これ見かけない文字だけど間違っていませんか?とコンパイルエラーを起こさせるための転ばぬ先の杖のようなものです。 プログラムが大型化・複雑化するほどこの問題は色濃く表れ、Option Explicitで変数の宣言を強制することの重要さを痛感すると思います。 なお、変数の宣言を強制した場合、先ほどの構文の右辺の式ButtonRightも宣言しないといけなくなります。 Const ButtonRight As Long = 113 '右リールストップボタンのキーコード と言う風にです。 もしくは、あまりお勧めはできないですが、 If PressButtonID = 113 Then '右リールストップボタンの押下判定 と言う風に直書きするかです。 なお、VBで出てくる文字は大文字小文字を識別しません。また、宣言されている文字を正しく入力されると宣言したときの大文字/小文字の字遣いに変換されます。これを逆に利用して宣言する時は大文字小文字混じった宣言をし、プログラム記述時はすべて小文字で入力すると、大文字に変換されない単語は何かしらのタイプミスが起こっていることになります。Option Explicitと合わせて利用すると作成効率が少し上がりますのでお試しあれ。

sakura54
質問者

お礼

Raudomize様  このような詳しいご説明を頂いて感激しております。 私の知識がないため、十分理解できない部分もありますが、ていねいなご説明で >Option Explicitを宣言すると言うのは、こういったタイプミスなどによって知らない単語が出てきたときに、変数とみなして変数を作成するのではなく、これ見かけない文字だけど間違っていません か?とコンパイルエラーを起こさせるための転ばぬ先の杖のようなものです。 この部分については理解できました。 ご助言頂いたようにOption Explicitはかならずつけるようにします。 ありがとうございました。

  • fujiponxx
  • ベストアンサー率32% (186/580)
回答No.1

どのキーがどのスロットを止めるとかいうのは、意味が不明ですが・・。 リンクの説明通り、変数名の宣言を強制するものです。 >宣言されていない変数名を使用すると、コンパイル時にエラーが発生します。 という事だと思います。

参考URL:
http://msdn.microsoft.com/ja-jp/library/y9341s4f(VS.80).aspx
sakura54
質問者

お礼

fujiponxx様  さっそくのご回答感謝いたします。 >どのキーがどのスロットを止めるとかいうのは、意味が不明ですが・・。 自分しか分からないことを書いて大変失礼しました。 これはスロットのリールが3つの部分に分かれていてたとえばその3つが 777とそろえば”大当たり”です。 リールの3つの部分を静止させるキーがたとえばzキーをおすとリールの 一番左の部分が静止するなどと割り当てられえているということです。 fujiponxx様のご回答とご紹介いただいた参考URLから判断するとこの Option Explicitを省略するとプログラム本体中のdimで宣言された変数が 変数として機能しなくなると解釈してよろしいのでしょうか。 たびたび恐れ入りますが教えていただければ幸いです。

関連するQ&A

  • VBAでGetAsynckeyStatekのエラー

    初めて質問します。なので、情報が少なかったらすみません。 windows7 64bit Excel2010でVBAにトライしています。 その中で「GetAsynckeyState」関数を使用して、キーボードの入力を判定したく、 コードを書いたところ「GetAsynckeyStateはUser32.dll 内に見つかりません」という エラーが発生しました。 下記がそのコードです。使用できるようにしたいのですがどうしたらいいでしょうか。ご教授お願いします =================== Option Explicit Private Declare Function GetAsynckeyState Lib "user32.dll" (ByVal vKey As Long) As Long Sub test() If GetAsynckeyState(38) <> 0 Then Range("B1") = "●" Else Range("B1") = "" End If End Sub ====================

  • VBAでのカーソル移動とマウスクリック

    業務上の単純作業の自動化のため、VBAから他のアプリケーションを操作することが目的です。 以前、ブラウザ上での作業の時に使用した、下記2つのAPIでは今回はマウスカーソルが指定した座標に動いてくれません、、、 Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal Y As Long) As Long Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) この2つのAPI以外で、カーソル移動とマウスクリックを実現する方法は何かありますでしょうか? 色々な方法を教えていただけるとVBAの勉強にもなり幸いです。 ' // 標準モジュール Option Explicit Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal Y As Long) As Long Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long) Private Type POINTAPI     x As Long     y As Long End Type Private Sub クリックテスト() Call SetCursorPos(216, 421) Sleep 400 Call mouse_event(&H2, 0, 0, 0, 0) Call mouse_event(&H4, 0, 0, 0, 0) End Sub

  • Excel VBAでアプリのウィンドウ名取得

    WindowsXP, Excel2007で、ExcelからIE8にキーコードを送りたいです。 ネットで拾った以下のコードにより、 Option Explicit Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" _ (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Public Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Function activate_win(win_name As String) As Long Dim hwindow As Long hwindow = FindWindow(vbNullString, win_name) If hwindow <> 0 Then SetForegroundWindow hwindow activate_win = hwindow End Function Call activate_win("ウィンドウ名") Sendkeys "ABC", True のような形で、メモ帳での動作は確認したのですが、 IEだとウィンドウがアクティブになってくれません。 おそらくウィンドウタイトルを間違えているのだと思われますが、 全角半角などを変えてみたりしても、どう見比べてみても間違いがわかりません。 見た目ではわからない、似た文字だが違うということではないかと思っています。 そこで、開いているアプリのウィンドウ名すべてをメモ帳に書き出すような (あるいは任意のアプリにペーストできるようにするような)コードはないでしょうか? よろしくお願いします

  • ExcelVBAでのkernel32(64bit)

    今までExcel2000のVBAから、以下のようなコードを使ってC++で作ったコマンドプロンプトで動くプログラムを動かすプログラムを作っていましたが、これを64bitのWindows7上で動いているExcel2010で使おうとしたらメッセージが出ました。いろいろ調べてみたところ、たぶんDeclareにPtrSafeを付ければ良いようなのですが、その際、他のコードはそのままで良いのでしょうか。特に、コード中のLongはそのままで良いのか気になるのですが...。ちなみに、下記コードの条件コンパイルはネットで調べて見よう見まねで付けたもので、Excel2000のときには付けていないものでした。ご存じの方がいらっしゃいましたらご教授ください。 '------------------------------------------------------------------------------ ' Win32 API関数・定数の宣言 '------------------------------------------------------------------------------ #If VBA7 And Win64 Then '64bit Declare PtrSafe Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _   ByVal dwMilliseconds As Long) As Long Declare PtrSafe Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _   ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long #Else '32bit Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _   ByVal dwMilliseconds As Long) As Long Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _   ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long #End If Private Const PROCESS_ALL_ACCESS As Long = &H1F0FFF Private Const INFINITE As Long = &HFFFF '------------------------------------------------------------------------------ ' Run '------------------------------------------------------------------------------ Public Sub Run(ByVal project_name As String)   Dim program As String   Dim task_id As Long   Dim h_proc As Variant   program = mdlFunc.ProgramPath() & mdlFunc.ProgramOption(project_name) 'プログラム名   task_id = Shell(program, vbHide)   h_proc = OpenProcess(PROCESS_ALL_ACCESS, False, task_id)   If OpenProcess(PROCESS_ALL_ACCESS, False, task_id) <> vbNull Then     Call WaitForSingleObject(h_proc, INFINITE)     CloseHandle h_proc   End If End Sub

  • VBA 「何時間何分何秒」にするにはどうすればいい

    Declare Function GetTickCount Lib "KERNEL32" () As Long Sub Sample() Debug.Print GetTickCount & "ミリ秒" End Sub これで取得される値を 「何時間何分何秒」にするにはどうすればいいでしょうか? Format(GetTickCount, "hh:mm:ss") にするとなぜかオーバーフローしてしまいました。

  • オーバーフローしちゃった・・・

    http://www.excellenceweb.net/vba/api/what_windows_api.html をさんこうに、PC起動からの時間を取得しつつ、○○時間○○分という形で返したいのですが Option Explicit Declare Function GetTickCount Lib "kernel32.dll" () As Long Sub TEST1() Dim Tickcount As Long Tickcount = GetTickCount() Tickcount = Format(Tickcount, "hh:mm") Debug.Print "PC起動から " & Tickcount & " ミリ秒経過しています" End Sub これを実行すると、オーバーフローしました。になってしまいます。 どこがおかしいのでしょうか?

  • VBAでSetTextColorがうまくいかない

    EXCELのVBAでユーザーフォームを使ったグラフィック表示のプログラムを 作っているのですが、SetTextColorでテキスト色の設定をしようと してもうまくいきません。何故か設定しようとする色の値が無視されて 「1304008」が設定されてしまいます。(GetTextColorで確認) そしてそれ以降何を設定してもこの状態のままです。 何か考えられることがありますでしょうか。 下にそのプログラムを示します。 ちなみにSetBKColorやAngleArcなど他のグラフィック命令は問題なく 動いていてSetTextColorだけがうまくいってない状態です。 '------------------------------------------------- ' ユーザーフォーム用プログラム '------------------------------------------------- Private Declare Function GetActiveWindow Lib "user32" () As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpszClass As String, _ ByVal lpszWindow As String) As Long Private Declare Function GetDC Lib "user32" ( _ ByVal hWnd As Long) As Long Private Declare Function ReleaseDC Lib "user32" ( _ ByVal hWnd As Long, _ ByVal hdc As Long) As Long Private Declare Function SetTextColor Lib "gdi32" _ (ByVal hdc As Long, crColor As Long) As Long Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" _ (ByVal hdc&, ByVal x&, _ ByVal y&, ByVal lpString$, ByVal nCount&) As Long Dim hWnd As Long Dim hdc As Long Public Sub UserForm_Activate() DoEvents hWnd = FindWindowEx(GetActiveWindow, 0, "F3 Server 60000000", "") hdc = GetDC(hWnd) ret = SetTextColor(hdc, RGB(255, 0, 0)) ret = TextOut(hdc, 0, 0, "abc", 3) Call ReleaseDC(hWnd, hdc) End Sub '-------------------------------------------------

  • vbaで鳴らした音楽を止めたい

    vbaのAPIで音楽を鳴らした後、 曲が終わる前に、vbaで終了させたいのですが Option Compare Database Option Explicit Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" _ (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _ ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long Sub test() Dim mySoundFile As String Dim rc As Long mySoundFile = "C:\tset.mp3" rc = mciSendString("Close " & mySoundFile, "", 0, 0) End Sub これを実行してもエラーにもならないし音楽も鳴り止まないのですが どこがまちがってますか? "C:\tset.mp3"で音楽を再生したので、 "C:\tset.mp3"は存在します。

  • Excel2003VBAでクリップボードにあるビットマップの操作について

    Excel2003VBAにおいてクリップボードにあるビットマップの画像の任意の1pxの色を、 ペイントのスポイトツールのように取得するマクロを作成したいのですが GetPixelという関数で画像の任意1pxの色を取得できる所までは調べられたのですが、 それをクリップボードの画像で使用することができませんでした。 以下は、GetPixel関数を試してみた時のソースになります。 '------------------------------------------------------------------ Option Explicit Declare Function GetDesktopWindow Lib "user32" () As Long Declare Function GetWindowDC Lib "user32" (ByVal hwnd As Long) As Long Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal Y As Long) As Long Sub ピクセル色獲得() Dim hwnd As Long Dim hdc As Long hwnd = GetDesktopWindow() hdc = GetWindowDC(hwnd) Debug.Print Hex(GetPixel(hdc, 100, 200)) End Sub '------------------------------------------------------------------ 上記ソースで任意1pxの色を取得できたため クリップボードの画像の色を取得するマクロを下記のように作成しました。 '--------------------------------------------------------------- Option Explicit Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal Y As Long) As Long Sub クリップボードピクセル色獲得() Dim CB As Variant Dim i As Long CB = Application.ClipboardFormats Debug.Print Hex(GetPixel(CB, 100, 200)) End Sub '--------------------------------------------------------------- 型が一致しません と言われ動きません。 以上です、よろしくお願いいたします。

  • 64ビットエクセルでのAPI宣言/PtrSafe

    エクセルのInputboxで、入力された文字列を自動的にアスタリスクで隠すようにする方法を探し http://okwave.jp/qa/q2371878.html の回答No1のコードがまさに最適なコードで、これまで非常に助かっていました。 ところが、64bitのエクセルでは動かないことがわかりました。 表示されたエラーメッセージの言葉から調べて、PtrSafeという言葉を入れなければならないようなのでAPI宣言を以下のようにしてみました。 #If VBA7 And Win64 Then '64ビット版 Private Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _ (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long Private Declare PtrSafe Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" _ (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _ ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long #Else '32ビット版 Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _ (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" _ (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _ ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long #End If ところが、回答No1のコードで Sub Report_Open() を実行すると Public Function InputBoxDK(Prompt, Optional Title, Optional Default, Optional XPos, _ Optional YPos, Optional HelpFile, Optional Context) As String のところがハイライトされてエラーになります。 どう直せば良いのでしょうか? 全文のコードを乗せると字数制限に引っかかりますので、申し訳ありませんが宣言以外の部分は http://okwave.jp/qa/q2371878.html の回答No1のコードを見てくださいますようお願いします。

専門家に質問してみよう