
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も見ています
-
VBA:同じ文字列データの比較がうまくいかない例
Excel(エクセル)
-
同じ文字列なのにfalseになってしまいます。
Excel(エクセル)
-
Excel 大小比較演算子による「文字」の比較結果
Excel(エクセル)
-
-
4
エクセルVBAで、条件に一致するセルへ移動
Excel(エクセル)
-
5
VBAのプログラムで、DIAG = 1# / A(L, L) や R(
その他(プログラミング・Web制作)
-
6
イミディエイトウインドウの最高表示数は199行?
Excel(エクセル)
-
7
【VBA】特定の値が入った行をコピーして別シートに貼り付ける方法をおしえていただきたいです。
Excel(エクセル)
-
8
VBA シートをコピーする際に Copyメソッドは失敗しましたのエラーが出てしまいます
Visual Basic(VBA)
-
9
Vba初心者です。下記のコード助けてください Loopに対するDoがありませんと表示されます Sub
オープンソース
-
10
【VBA】特定列に文字が入っていたらそのセル行をコピーしてマスターブックの同じ行に貼り付けたい
その他(Microsoft Office)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
教えて下さい
-
二分探索の平均探索回数
-
【VBA】データを入力後に,同一...
-
Fortran カンマを含む数値デー...
-
Data(加算名詞、不可算名詞)に...
-
【エクセル】測定時間がバラバ...
-
カンマからスラッシュに
-
ビットシフトについて
-
VBA 空白セルを削除ではない方...
-
ユーザーフォームのテキストボ...
-
パースとはなんですか?
-
C# でDataTableの更新を高速化...
-
アクセス2000で画像データ...
-
多量のSUMIF式を軽くしたい
-
特定のデータの抽出方法を教え...
-
Excel VBAでのオートフィルター...
-
C#にてDropDownListの値を動的...
-
配列でデータが入っている要素...
-
winsock のrecvデータの終わり...
-
C#でデータのファイル保存と保...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
教えて下さい
-
【エクセル】測定時間がバラバ...
-
多量のSUMIF式を軽くしたい
-
配列でデータが入っている要素...
-
メモ帳(テキストデータ)をExc...
-
ユーザーフォームのテキストボ...
-
特定のデータの抽出方法を教え...
-
二分探索の平均探索回数
-
EXCELVBAでSQLserverからデータ...
-
Accessで該当データにフラグを...
-
VBA 空白セルを削除ではない方...
-
この行は既に別のテーブルに属...
-
Excel VBAでのオートフィルター...
-
[C言語] コメント文字列を無視...
-
エクセルで2つの時系列のデー...
-
アクセス2000で画像データ...
-
CString型の文字列連結について
-
カンマからスラッシュに
-
VBにおいてフォーム間の変数の...
-
<VB>String→Object
おすすめ情報