Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


4622 / 13646 ツリー ←次へ | 前へ→

【55549】select caseの空文字と0について VBA超超初心者さる 08/5/10(土) 23:13 質問[未読]
【55550】select caseの空文字と0について(訂正) VBA超超初心者さる 08/5/10(土) 23:20 質問[未読]
【55553】Re:select caseの空文字と0について(訂正) ひげくま 08/5/10(土) 23:30 発言[未読]
【55554】Re:select caseの空文字と0について(訂正) kanabun 08/5/10(土) 23:50 発言[未読]
【55555】Re:select caseの空文字と0について(訂正) VBA超超初心者さる 08/5/11(日) 0:16 質問[未読]
【55556】Re:select caseの空文字と0について(訂正) kanabun 08/5/11(日) 0:25 発言[未読]
【55557】Re:select caseの空文字と0について(訂正) VBA超超初心者さる 08/5/11(日) 1:09 質問[未読]
【55558】Re:select caseの空文字と0について(訂正) kanabun 08/5/11(日) 10:17 発言[未読]
【55559】Re:select caseの空文字と0について(訂正) VBWASURETA 08/5/11(日) 11:06 発言[未読]
【55560】Re:select caseの空文字と0について(訂正) kanabun 08/5/11(日) 11:23 発言[未読]
【55562】Re:select caseの空文字と0について(訂正) VBWASURETA 08/5/11(日) 11:50 発言[未読]
【55563】Re:select caseの空文字と0について(訂正) VBWASURETA 08/5/11(日) 12:21 発言[未読]
【55565】訂正Select Caseにはルールがあるようです VBWASURETA 08/5/11(日) 14:50 発言[未読]
【55566】Re:訂正Select Caseにはルールがあるようで... kanabun 08/5/11(日) 16:24 発言[未読]
【55567】Re:訂正Select Caseにはルールがあるようで... VBWASURETA 08/5/11(日) 17:02 発言[未読]
【55574】Re:訂正Select Caseにはルールがあるようで... VBA超超初心者さる 08/5/11(日) 21:01 お礼[未読]

【55549】select caseの空文字と0について
質問  VBA超超初心者さる  - 08/5/10(土) 23:13 -

引用なし
パスワード
   EXCEL VBAの超超初心者さるです。

本を数冊買って、EXCEL VBAの勉強を独学で始めました。
下記のselect caseの構文で空文字の条件をつけても
表示は「1以上」になってしまいます。

Sub test()
  Dim a As Variant
 
  a = InputBox("入力してね", "数字")
  
  Select Case (a)
    Case Is >= 1
      Range("a1") = "1以上"
    Case Is < 0
      Range("b1") = "負の数"
    Case 0
      Range("d1") = "0が入力されました"
    Case ""
      Range("c1") = "なにも入力されてません"
  End Select
End Sub

理由がどうしてもわからず、どなたかご教授願えませんでしょうか。

他の方の同じようなご質問も探してみたのですが、みつけられませんでした。

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

【55550】select caseの空文字と0について(訂正)
質問  VBA超超初心者さる  - 08/5/10(土) 23:20 -

引用なし
パスワード
   EXCEL VBAの超超初心者さるです。

先ほど投稿したコードに誤りがありました。
訂正後のコードです。

Sub test()
  Dim a As Variant
 
  a = InputBox("入力してね", "数字")
  
  Select Case a
    Case Is >= 1
      Range("a1") = "1以上"
    Case Is < 0
      Range("b1") = "負の数"
    Case 0
      Range("d1") = "0が入力されました"
    Case ""
      Range("c1") = "なにも入力されてません"
  End Select
End Sub

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

【55553】Re:select caseの空文字と0について(訂正)
発言  ひげくま  - 08/5/10(土) 23:30 -

引用なし
パスワード
   [F8]キーでステップ実行をしてみて、プログラムがどのように条件分岐されているのかを調べてみましょう。
きっと、自分が思っている流れとは違う流れになっていると思いますよ。

【55554】Re:select caseの空文字と0について(訂正)
発言  kanabun  - 08/5/10(土) 23:50 -

引用なし
パスワード
   Case 文というのは 上から順にCaseに合致するか調べていくわけだから、

>    Case ""
>      Range("c1") = "なにも入力されてません"

の判定を、一番最初にもって行ったら、どうでしょ

【55555】Re:select caseの空文字と0について(訂正)
質問  VBA超超初心者さる  - 08/5/11(日) 0:16 -

引用なし
パスワード
   ひげくまさん、kanabunさんありがとうございます。

確かに最初にcase ""の条件を持っていくと
うまくいきました!

ですが、なぜ最初に持っていかないと、「1以上」を
認識してしまうのか、わかりません。

どうしてそうなるのでしょうか?
そのようなルールがあるのでしょうか?

よろしくお願いします。

【55556】Re:select caseの空文字と0について(訂正)
発言  kanabun  - 08/5/11(日) 0:25 -

引用なし
パスワード
   >確かに最初にcase ""の条件を持っていくと
>うまくいきました!
>
>ですが、なぜ最初に持っていかないと、「1以上」を
>認識してしまうのか、わかりません。

テストしてみました。

 Dim a As Variant
 a = ""
 MsgBox a >= 1

 True が返ります。  "" は 1以上なんだそうです..

なんでかな〜〜 (^^

【55557】Re:select caseの空文字と0について(訂正)
質問  VBA超超初心者さる  - 08/5/11(日) 1:09 -

引用なし
パスワード
   kanabunさん、ありがとうございます。

""が1以上というのが、どうしてもナゾです。

どなたかこの理由をご存知の方がおられましたら
ぜひ教えてください。

とても気になります。

よろしくお願いします。

【55558】Re:select caseの空文字と0について(訂正)
発言  kanabun  - 08/5/11(日) 10:17 -

引用なし
パスワード
   ▼VBA超超初心者さる さん:
> Dim a As Variant
> a = ""
> MsgBox a >= 1

なぜ a >= 1 が True なのか分かりませんが、
もともと↑のような異なるデータ型での比較演算はしません。

なぜ、
>>    Case ""
>>      Range("c1") = "なにも入力されてません"
>の判定を、一番最初にもって行ったら、どうでしょ
と提案したかというと、

もともとInputBox関数からの戻り値は ヘルプにあるように、
文字列型 (String) の値だからです。
あなたが InputBox関数で 1 とか入力しても、
戻り値は 1(数値) ではなく 文字列の "1" なのです。
ですから、
-------------------------
 Dim a As String '変数a のデータ型を String型で宣言する
 a = ""
 MsgBox a >= 1
-------------------------
を実行すれば、a >= 1 のところで「型が一致しません」と叱られる
でしょう?
そういうわけで、
InputBoxの戻り値により条件分岐しようとするばあいには
(1)●まず、何らかの入力があったか? をチェックします。
(2)入力された文字列が「数値に変換可能か」を調べるのは
 その次となります。
(3) IsNumeric(戻り値)が真のときだけ 戻り値を数値に変換して
  数値が >=1 か =0 か マイナスか でCase文の分岐をする
ことになります。

なお、
InputBoxのダイアログで[キャンセル]ボタンを押して
入力がCancelされたことを判断するには
If StrPtr(a) = 0& Then Exit Sub
のように、InputBox実行直後に判断します。
(StrPtr という関数は文字列変数のメモリ上のアドレス
 を返す関数で、StrPtr(a) の戻り値がゼロということは
 アドレスがない、変数a がメモリのどこにも格納されて
 いないことを意味します)

【55559】Re:select caseの空文字と0について(訂正)
発言  VBWASURETA  - 08/5/11(日) 11:06 -

引用なし
パスワード
   皆さんおはようございます。

C言語している方でしたらよくわかるのですが、
VBAの自動型変換(キャスト)は正しくできない場合があります。

Select CaseはCで言うswitch Caseと同じだったと思うので
確か内部的に数値変換していたと思います・・・(憶測ですが)
ということは、

>    Case Is >= 1
>      Range("a1") = "1以上"
>    Case Is < 0
>      Range("b1") = "負の数"
>    Case 0
>      Range("d1") = "0が入力されました"

のいずれしか通らない条件ということになるのだと思います。
なので、最後の Case ""を先頭に持っていくことで条件として通る
ということでしょうね多分ですが^^;;

【55560】Re:select caseの空文字と0について(訂正)
発言  kanabun  - 08/5/11(日) 11:23 -

引用なし
パスワード
   ▼VBWASURETA さん:
>Select CaseはCで言うswitch Caseと同じだったと思うので
>確か内部的に数値変換していたと思います・・・(憶測ですが)

>のいずれしか通らない条件ということになるのだと思います。

VB(A)の Select Case は 数値だけではありませんよ。
Dim s As String
s = "あ"
Select Case s
  Case "あ"
  Case "い"
  Case ""
End Select
とか、

Dim a As VAriant
a = ""
Select Case True
  Case a = ""
  Case a >= 1  'ここに来たとき 型キャストされます 
End Select

とかは、ふつうの構文です。

【55562】Re:select caseの空文字と0について(訂正)
発言  VBWASURETA  - 08/5/11(日) 11:50 -

引用なし
パスワード
   ▼kanabun さん:
こんにちは。


C言語の場合は数値特定ですが。
VBAのSelect caseは数値だけではないのはわかりますよ?
ただCaseではVBA内部の話で("")は数値に置き換えられて
VBAでは("")は1以上の存在にあるということではないですか?という話です。

Caseの根を追いかけたわけではないですが仕組み的にC言語と近いのではないかな?
ということでした。(C言語の場合、Case 1 To 10とかは出来ませんけどね^^;)

【55563】Re:select caseの空文字と0について(訂正)
発言  VBWASURETA  - 08/5/11(日) 12:21 -

引用なし
パスワード
   すみません、もう少し補足を追加します。

何故C言語を例にしたかと言いますと、
C言語は文字列同士の比較が出来ないからです。
C言語で文字列同士を比較する場合、
数値型(16進、10進)の変換が必要となるからです。


で、VBAはその部分についてはエンドユーザが意識せずに
比較できると思いますが、恐らく文字列の比較は原理が
同じでVBA独自が数値変換して比較していると思います。

なので、Select Caseの文字列のCase比較もVBA自身が数値に変換して
比較していると思いますよ?という話です。

確証がないので確かとは言い切れません。

【55565】訂正Select Caseにはルールがあるようです
発言  VBWASURETA  - 08/5/11(日) 14:50 -

引用なし
パスワード
   こんにちは。

ちょっと気になったので文字コードで調べていたら
Select Caseにはルールがあるようです。

//park7.wakwak.com/~efc21/cgi-bin/exqalounge.cgi?print+200606/06060146.txt

Caseと比較となる型は同じでなければならないそうで、
文字コードで比較しているわけではないようです。
なので、文字と数値を比較すると常に文字が大きいと判断します。
型が一致しない場合はSelect Caseは使用しない方が良さそうです。

因みに

Sub test()
  Dim a As Variant
 
  a = InputBox("入力してね", "数字")
 
  Select Case a
    Case 1 To 100
      Range("a1") = "1〜100の間です"
    Case Is > 65535
      Range("a1") = "65535以上"
    Case Is < 0
      Range("b1") = "負の数"
    Case 0
      Range("d1") = "0が入力されました"
    Case ""
      Range("c1") = "なにも入力されてません"
  End Select
End Sub

とやってみたところ、「"65535以上"」となりました。

【55566】Re:訂正Select Caseにはルールがあるよう...
発言  kanabun  - 08/5/11(日) 16:24 -

引用なし
パスワード
   > とやってみたところ、「"65535以上"」となりました。

何度も申し上げますように、
InputBox関数が返す値のデータ型はString型です。
で、混乱の一端は
InputBox関数の戻り値を Variant型の変数で受け取っていることに
あるような気がします。
Variant型変数は 「InputBoxメソッド」の戻り値のように
時には文字列であったり、時にはFalse(Boolean型)であったり、
場合によっては配列であったりするときには
必要不可欠な変数型なのですが、今回の例のように
自動型キャストが行われて「エラーにならず」
不可解な処理をすることがあります。
(例1) ----------------------------------- 既報
 Dim a As Variant
 a = ""
 MsgBox a >= 1 '【True】となります

(例2) -----------------------------------
 Dim a As Variant
 a = ""
 MsgBox a >= "1" '【False】となります

そうかと思えば、自動型変換して 0 = 0 となりそうな
ものが、そうならないこともあります。
(例3) -----------------------------------
 Dim a As Variant
 a = ""
 MsgBox a = Val(a) '【False】が返る

で、
私からのコメントはすでに申し上げたとおり、
InputBox関数は文字列を返すのだから、受け取る変数を
Dim a As String と文字列型で宣言して、
もし a が "" (vbNullString) だったら
  「入力がありません」
何らかの文字列が返されたら、
  数値化できるかどうか IsNumeric で判断して
  数値化可能だったら
   Select Case Val(a) '▼数値に変換する
     Case >= 1 : MsgBox 「1以上」
     Case 0   : MsgBox 「0 です」
     Case Is < 0: MsgBox 「負値です」
   End Select
と、分岐すればいいと思います。
Dim a As String と文字列型で宣言してあれば、
a が "" のとき、
  a >= 1
を実行すれば、「型が一致しません」とはっきりエラーになるので、
  「どうして "" は1以上なのか?」...と
悩まなくて済みますので (^^

【55567】Re:訂正Select Caseにはルールがあるよう...
発言  VBWASURETA  - 08/5/11(日) 17:02 -

引用なし
パスワード
   ▼kanabun さん:

InputBoxの戻り値がString型であるのはわかってます。
書いている事はString型とかそいう事ではないです。
String型であればString型でなければ正しい比較の結果が
得られませんということです。結果は書いた通り
文字と数値をSelect Caseで比較すると常に数値より文字が大きいです。
試しにInputBox関数へ「"="」等の文字を入れればわかりますよ。

> 自動型キャストが行われて「エラーにならず」
> 不可解な処理をすることがあります。
これについては
「VBAの自動型変換(キャスト)は正しくできない場合があります。」
で書いたと思いますが^^;

> 数値化できるかどうか IsNumeric で判断して
> 数値化可能だったら
についてはkanabunさんが既に記載されていましたので、
触れませんでした。

なので、事前チェックもない状態でSelect Case内部で
変換する処理にはSelect Caseは避けるべきなのかもしれません。
と「""」が1以上原因について書きたかっただけなので
Select Caseの使い方とかについて書いたわけではないです^^;;

【55574】Re:訂正Select Caseにはルールがあるよう...
お礼  VBA超超初心者さる  - 08/5/11(日) 21:01 -

引用なし
パスワード
   kanabun さん、VBWASURETA さん、本当にありがとうございました。

今仕事から帰り、全部回答を読ませていただきました。

データ型をVariantに設定したのがそもそもの間違いであったことと
間違いであるVariant型にした場合に、なぜ""が1以上と表示するかは
文字が数値よりも大きいと判断されるからであるということがすごく
よくわかりました。

すごく納得できました。

すでに1行目でつまずいている「さる」ですが、誰にも
聞けず、参考書をめくっても載っていないへんなご質問に
丁寧に解説していただいて、本当に感謝しています。

これにこりず、今後ともどうぞ、どうぞよろしくお願いします。

4622 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free