Excel VBA 質問スレッド No.143 (未解決)

変数について

投稿者 : koko     投稿日時 : 2020/12/05(Sat) 22:30:03     OS : Windows 10     EXCEL : Excel 2016
Dim max9 As Double

max9 = WorksheetFunction.Large(.Range(.Cells(30, KISO_3T), .Cells(370, KISO_3T)), 9)
count1 = 18

For i = 30 To 370 Step 20
If .Cells(i, KISO_3T) <> "" Then
If .Cells(i, KISO_3T) >= "max" & WorksheetFunction.Round(count1 / 2, 0) Then
.Cells(i, KISO_3T).Font.Bold = True
.Cells(i, KISO_3T).Interior.Color = RGB(255, 230, 255)
End If
End If
Next

上記コードの8行目は、 「"max" & WorksheetFunction.Round(count1 / 2, 0)」で「max9」を表示しているつもりですが、
実際には機能していません。

If max9 = "max" & WorksheetFunction.Round(count1 / 2, 0) Then
Debug.Print True
End If
とのコードには 「True」と返します。

また、「"max" & WorksheetFunction.Round(count1 / 2, 0)」の部分を「max9」と入れ替え、
「If .Cells(i, KISO_3T) >= max9 Then」とした場合は、意図した答えが返っております。
この違いがどこにあるのか戸惑っています。どなたかお分かりの方教えて下さい。
宜しくお願いします。

[返信 1] Re : 変数について
投稿者 : EUNO     投稿日時 : 2020/12/11(Fri) 11:20:04
結論だけ言うと、文字列結合されたmax9は、変数ではなく文字列として扱われているからです。

Sub test()
Dim max9 As Double
 max9 = 555
 MsgBox max9
 MsgBox "max" & 9
End Sub

[返信 2] Re : 変数について
投稿者 : ヘンリー     投稿日時 : 2020/12/11(Fri) 16:19:59
【結論】
「変数と変数の型」、或いは「型」という概念と、
文字列の並び替えの理解不足かな思われます。


【解説】
コンピュータ上では、数値の1と文字の"1"では、基本的に別の物になります。

例えば、以下の2つでは大小の比較が変わります。。
①1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22
"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22"

小さい順に並べると
①は1、2、3…22となりますが、
②は"1","10","11","12","13","14","15","16","17","18","19","2","20","21","22","3","4","5"
となります。
※文字列型は、VBAプログラミングでは""(ダブルクォーテーション)でくくる、
 というルールがあります。掲示板等への質問の時などでも、
 文字列とはっきりわかるようダブルコーテーションを付けるとわかりやすいです。

但し、プログラミング言語によって「暗黙の型変換」というものがあそうです。
VBAでは、「数値に変換できる場合、数値に変換する」となるようです。
私も最近、ある掲示板で教えて頂きました(汗
(この回答をする為に色々サンプルを作成していて、納得できない事に当たったため
とある掲示板で尋ねたところ、この様に教えて頂きました)

教えて頂いたことの内容は、
「VBAでは、一方が数値型で、片方が文字列型の場合、
両側が Double型へと暗黙の型変換されてから比較される仕様です。
しかし、文字列側を数値に変換できないようなケースは、
Double型への暗黙の型変換(CDbl)ができない為に、エラーを返すようになっている。」
という事です。
※CDblが分からなければ、ネットで検索してみて下さい。

コンピュータを扱う時は、Excelであろうと、VBAであろうと、他言語であろうと、
「型」について、強く意識しなければなりません。

これは私の意見ですが、VBAを始めたばかりの時は、
Integer型とLong型を、意識的に分けて使うなど、
型を意識するよう心掛るようにすると、慣れてくると思います。

「max9」という変数はDouble型です。つまり倍精度浮動小数点型となります。
一方、"max" & WorksheetFunction.Round(count1 / 2, 0)は、
文字列演算子(&)を使用していますので、"max9"という文字列型になります。
Cells(i, KISO_3T)が、文字列型"max"と数値を組み合わせた値であれば、
文字列型と文字列型を比較しているので、エラーは出ませんが、
人間の感覚の大小と、コンピュータ上での大小は変わります。

例えば文字列型"max9"と文字列型"max10"を比べると
コンピュータは"max10"の方が小さいと判断します。

>If max9 = "max" & WorksheetFunction.Round(count1 / 2, 0) Then
>Debug.Print True
>End If
とありますが、ここで疑問です。
変数「max9」の値は、文字列型になる事はありません。
一方で "max" & WorksheetFunction.Round(count1 / 2, 0)は文字型です。
この場合、Trueを返さず、型が一致しません、というエラーが出ると思うのですが…

理由は、「文字列型"max"と数値の9を文字列結合した物」
つまり、文字列型"max9"は、浮動小数点型に変換できないからです。
例えば、文字の"m"をDouble型(数値)に変換するといくつになる?
「わかりません。」→エラーとなります。

If "max9" = "max" & WorksheetFunction.Round(count1 / 2, 0)
なら等しいと判断すると思います。
文字型と文字型を比較しているからです。


>「If .Cells(i, KISO_3T) >= max9 Then」
で意図した答えが返ってくる理由は、
「max9」という変数がDouble型であるのと、.Cells(i, KISO_3T)の値が、数値型(Doubleなど)、
或いは、Double型に暗黙の変換ができるもの、とを比較しているからだと思います。


以上、説明が長くなりましたが、
おそらく、この内容をご理解して頂ければ、解決する思います。

[返信 3] Re : 変数について
投稿者 : EUNO     投稿日時 : 2020/12/12(Sat) 02:26:21
これ、型の問題ではないと思いますけど、いかがでしょうか。
(いきなり失礼ですみません)
変数名に数字や文字列が混在してややこしいので、シンプルにstring型の変数で考えてみましょう。

Sub test()
Dim myMax As String

myMax = "aaa" '変数myMaxに文字列aaaを代入
MsgBox myMax 'aaa と表示される(myMaxは変数なので当たり前)
MsgBox "my" & "Max" 'myMax と表示される(myMaxは変数として扱われていない)

Dim A As String
A = "my" & "Max"
MsgBox A 'myMax と表示される(変数として扱われていない。
            'もし変数として扱われるならaaaと表示されるはず)
End Sub


「文字列を結合してできた文字列をそのまま宣言済の変数として扱うことができるか」
という問題で、答えは「できない」ということだと思います。

[返信 4] Re : 変数について
投稿者 : ヘンリー     投稿日時 : 2020/12/14(Mon) 10:15:34
>「"max" & WorksheetFunction.Round(count1 / 2, 0)」の部分を「max9」と入れ替え、
>「If .Cells(i, KISO_3T) >= max9 Then」とした場合は、意図した答えが返っております。

この文章から、「文字列と倍精度浮動小数点を入れ替える」という
型の違いを意識できていないのかな?と推測したのです。

再度、何回か読み直したところ、確かにEUNO様のおっしゃる通り、
型の問題とは、ずれていたかもしれません。

VB5.0、6.0を少しやっていた頃に、私は、
VBの掲示板で教えて頂いた通りの事しか頭にありませんでした。

例えば、変数名には、文字型であれば、接頭語として「str」を付ける
などです。

例)
Dim strMax As String
Dim dblMax As Double

そして、比較する際には、必ず型を合わせるという事です。

If CDbl(strMax) = dblMax Then

というようにです。

これらをする事で、変数の接頭語から数値比較しているか、文字列比較しているかを
明確にできる、とVBの掲示板で教わりました。

その為、この回答をする際に、テストプログラムを作っていて、
String型で宣言した物が、暗黙の変換によって数値比較されている事を知らず、
今回改めてVBの掲示板に質問をさせて頂き、暗黙の型変換を知ったので、
この様な回答させて頂きました。

私の勉強不足により、EUNO様には、改めてご指摘して頂き、ありがとうございます。
又、質問者koko様には、誤解を与えてしまった事、誠に申し訳ございませんでした。

なお一層の努力をいたします。今後ともよろしくお願いいたします。

[返信 5] Re : 変数について
投稿者 : EUNO     投稿日時 : 2020/12/14(Mon) 20:08:11
いえ、こちらこそ通りがかりでコメントすみません。
私の理解不足の可能性もありますのでその場合はご容赦ください。
質問者さんから、解釈についてコメントいただけると助かります。

変数の先頭に型名を付けるハンガリアン記法は賛否ありますね。

当掲示板について
返信入力フォーム
お 名 前  :
内  容   :
ステータス  : この質問を解決済みにする

認証コード  :
        キャプチャ画像


( 処理日時 : 2021-01-27 13:58:10 )

Page
Top