Excelのマクロで、どうにも理解できない結果に困っております。
If文による大小判定なのですが、同じ判定条件文なのに一枚のシートモジュールに書いたマクロと判定文を標準モジュールに書いてシートモジュールからコールした場合の判定結果が同じ結果になりません。
このような場合には、必ず何処かに単純なミスがあるのが通例ですが、今回は何度見直してもミスが発見できません。
少々分かり難い質問文になりましたが InputBox から入力した数値が指定した範囲にあるか否かの判定をするマクロです。
1.シートモジュール Sheet1 に書いたマクロ (正常動作)
Dim データ総数 As Long
Dim 除外データ数 As Variant
Dim 処理データ数 As Variant
Dim Alm As String
Sub 血圧色分けA()
データ総数 = 300 '仮にデータ総数を300と設定
N1: 除外データ数 = InputBox("除外するデータ数を入力してください" & vbCr & _
"データ範囲は0~" & データ総数 - 1 & "個です" & vbCr & _
"最新データから除外するデータ数より以前のデータを処理します", _
"血圧色分け", 0)
If 除外データ数 = "" Then
MsgBox ("処理をキャンセルします")
GoTo N3
ElseIf IsNumeric(除外データ数) = False Then
Alm = MsgBox("数字を入れてください", vbCritical)
GoTo N1
ElseIf 除外データ数 > データ総数 - 1 Or 0 > 除外データ数 Then
Alm = MsgBox("データ範囲は0~" & データ総数 - 1 & "個です", vbCritical)
GoTo N1
End If
N3: End Sub
2.判定文を標準モジュール Module1 に書いて引数付きでシートモジュール Sheet2 に書いたマクロから引数付きでコールする場合 (動作?)
<Sheet2のマクロ>
Dim データ総数 As Long
Dim 処理項目 As String
Dim 初期値 As Long
Dim キャンセル As Boolean
Dim 除外データ数 As Variant
- - - - - - - - -
Sub 血圧色分けB()
データ総数 = 300 '仮にデータ総数を300と設定
処理項目 = "除外データ数"
初期値 = 0
Call 除外データ数取得(除外データ数, データ総数, 処理項目, 初期値)
N3: End Sub
- - - - - - - - -
<Module1のマクロ>
Dim Alm As String
- - - - - - - - -
Sub 除外データ数取得(A, B, C, D)
'A = 除外データ数
'B = データ総数
'C = 処理項目
'D = 初期値
N1: A = InputBox(C & "を入力してください" & vbCr & _
"データ範囲は0~" & B - 1 & "です" & vbCr & _
"最新データから" & C & "より以前のデータを処理します", C, D)
If A = "" Then
MsgBox ("処理をキャンセルします")
GoTo N3
ElseIf IsNumeric(A) = False Then
Alm = MsgBox("数字を入れてください", vbCritical)
GoTo N1
ElseIf A > B - 1 Or 0 > A Then
Alm = MsgBox("データ範囲は0~" & B - 1 & "個です", vbCritical)
GoTo N1
' ElseIf 除外データ数 > データ総数 - 1 Or 0 > 除外データ数 Then
' Alm = MsgBox("データ範囲は0~" & データ総数 - 1 & "個です", vbCritical)
' GoTo N1
End If
N3: End Sub
No.2ベストアンサー
- 回答日時:
厳密に言えば、どちらも正しくありません。
Excelのお節介によって前者は意図したとおりに動き、後者は意図したとおりに動いていないだけです。
前者のマクロでは変数「初期値」はLongで宣言されていますが、後者の方では変数「B」は宣言されていないためVariant(Variant型数値)になっています。
InputBoxで入力された値はどちらもVariant型の変数に代入されていますが、InputBoxが返すのは文字列型ですので、中身は文字列(Variant型文字列)になっています。
前者は、Variant型文字列とLong型の変数を比較しています。
Excelは、比較相手がLong型なので、Variant型文字列を気を利かせて数値として扱います。
後者は、Variant型文字列と、Variant型数値を比較しています。
Excelは、なぜか解りませんが、Variant型文字列とVariant型数値を比較すると、必ずVariant型文字列の方が大きいと判断します。
比較をするときは型を合わせるようにしましょう。
Variantは便利ですが、思いがけないところではまる原因になりやすいです。
最少の修正で後者を前者と同じ動きにしたいのでしたら、以下の様に修正しましょう
Sub 除外データ数取得(A, B, C, D)
↓
Sub 除外データ数取得(A, B As Long, C, D)
>Excelは、なぜか解りませんが、Variant型文字列とVariant型数値を比較すると、必ずVariant型文字列>の方が大きいと判断します。
以前何かで読んだ記憶があるのを思い出しました。
忘れた頃にVBAをやるのですっかり抜けていました。
>Excelのお節介によって前者は意図したとおりに動き、後者は意図したとおりに動いていないだけです。
意図したとおりに動く方はVariant型文字列とLong型の変数を比較していて、意図したとおりに動かない方はVariant型文字列とVariant型数値を比較しているんですね。
はまってしまった理由のひとつは、エディター画面でデバッグする時、マウスカーソルを当てた時に表示される変数の値はLong型もVariant型数値も同じ整数で表示され、型の区別が付かないためだと思います。
見た目は全く同じものを判定しているのに結果が違う。ウー何故って感じでした。
問題の判定文のところではVariant型文字列に入っているのは整数のみなので CLng 等を使用して型を変換して比較するのが間違いのない方法でしょうか。
ElseIf CLng(A) > CLng(B) - 1 Or 0 > CLng(A) Then
Alm = MsgBox("データ範囲は0~" & B - 1 & "個です", vbCritical)
GoTo N1
すっきり解決しました。ありがとうございました。
No.1
- 回答日時:
インプットボックスの後に
Debug.Print TypeName(A), TypeName(B)
と入れて走らせてみると、原因がわかります。
答えを言ってしまうと・・変数AはがString型で見られていますね。
このInputBoxは文字列型で返してくるようです。
なので、数値としての大小を比べられていない状態ですね。
とりあえずの対策。
文字列型が返るなら、数値型に変換しちゃえ、ってことで、
ElseIf Val(A) > B - 1 Or 0 > Val(A) Then
Val関数で変換しちゃうと上手くいきそうですよ。
多少強引ですけどね^^;
>文字列型が返るなら、数値型に変換しちゃえ、ってことで、
ElseIf Val(A) > B - 1 Or 0 > Val(A) Then
Val関数は便利ですね。その他にも CLng とかで型変換すれば上手く行きそうです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
- その他(Microsoft Office) マクロVBAについて 1 2022/09/06 18:12
- Visual Basic(VBA) VBAが止まります。 3 2022/08/31 14:09
- Visual Basic(VBA) VBAでoutlook365が起動しません。 4 2022/08/25 13:31
- Excel(エクセル) VBAについて 3 2022/06/19 18:19
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Visual Basic(VBA) 【ご教示ください】VBAの記述方法がわかりません。 2 2022/08/12 21:28
- Visual Basic(VBA) Sub 分けてソートして貼り付ける() Dim srcSheet As Worksheet Dim 6 2023/08/04 19:57
- Visual Basic(VBA) 【前回の続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/16 16:44
このQ&Aを見た人はこんなQ&Aも見ています
-
プロが教える店舗&オフィスのセキュリティ対策術
中・小規模の店舗やオフィスのセキュリティセキュリティ対策について、プロにどう対策すべきか 何を注意すべきかを教えていただきました!
-
Excel VBA IF文がうまく動作しないわけがわかりません…
Visual Basic(VBA)
-
同じ文字列なのにfalseになってしまいます。
Excel(エクセル)
-
EXCEL VBA セルに既に入力されている文字に文字を追加する
Excel(エクセル)
-
-
4
VBA:同じ文字列データの比較がうまくいかない例
Excel(エクセル)
-
5
エクセルでエラーが出て困っています。
Excel(エクセル)
-
6
なぜこんな初歩的なVBAのIf文でエラーか発生して使えないのか、全く理解出来ません。誰か助けてくださ
Visual Basic(VBA)
-
7
DATE型変数を初期化する方法
Visual Basic(VBA)
-
8
あるセルの値を認識しないのですが、何が悪いのでしょうか?
Excel(エクセル)
-
9
エクセルVBAのIf,Then 構文でOr条件とAnd条件の結合方法?
Excel(エクセル)
-
10
Excel マクロ VBA プロシージャが大きすぎます のエラー対処方法
Visual Basic(VBA)
-
11
VBA シートのボタン名を変更したい
Visual Basic(VBA)
-
12
VBA 数式を残して値をクリアについて
Excel(エクセル)
-
13
findは動くがfindnextがマクロで動きません。記述は同じはずなのですが…
Visual Basic(VBA)
-
14
メッセージボックスに表示する文字を大きくしたい
Excel(エクセル)
-
15
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
-
16
エクセルVBAのIF文の否定の複数条件
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
教えて下さい
-
配列でデータが入っている要素...
-
Accessで該当データにフラグを...
-
【エクセル】測定時間がバラバ...
-
メモ帳(テキストデータ)をExc...
-
MSCommを用いたRS-232-Cデータ転送
-
S9タイプからXタイプにデータ...
-
EXCELVBAでSQLserverからデータ...
-
[C言語] コメント文字列を無視...
-
PLSQLで文字列置換
-
VBAを使ってOutlookメール本文...
-
fortranでフーリエ変換→パワー...
-
VBA 毎日取得するデータを順番...
-
カンマからスラッシュに
-
C# ソケット通信でデータ受信時...
-
HTMLでテキストボックスで...
-
PDOオブジェクトは使い回し可能?
-
Excelのマクロでワードのテキス...
-
Excelの関数で表示されているデ...
-
GETはできるがPOSTができない、...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
教えて下さい
-
配列でデータが入っている要素...
-
【エクセル】測定時間がバラバ...
-
メモ帳(テキストデータ)をExc...
-
VBA 空白セルを削除ではない方...
-
多量のSUMIF式を軽くしたい
-
Excelのマクロでワードのテキス...
-
エクセルで2つの時系列のデー...
-
この行は既に別のテーブルに属...
-
VBAを使ってOutlookメール本文...
-
シーケンサにパソコンからアク...
-
EXCELVBAでSQLserverからデータ...
-
ブレーカー落ちで壊れたりしな...
-
[C言語] コメント文字列を無視...
-
オープンチヤットでデータ削除...
-
モジュラス103の算出方法について
-
javaでDBからデータを取ってき...
-
カンマからスラッシュに
-
VBA 毎日取得するデータを順番...
-
Android携帯をUSBメモリ代わりに
おすすめ情報