• ベストアンサー

Excel2000のVBAでわからないことがあります。

こんなものを作ってみました。 Sub 理想体重() Dim Sin As Long Dim Tai As Long Sin = InputBox("あなたの体重は?", "体重") Tai = InputBox("あなたの身長は?", "身長") If Tai >= Sin * Sin * 21 / 10000 + 3 Then MsgBox "太りすぎです" ElseIf Tai <= Sin * Sin * 21 / 10000 - 3 Then MsgBox ("痩せすぎです") Else MsgBox ("標準です") End If End Sub 結果はきちんと出てくるのですが、最初の変数宣言のところがわかりません。 最初は、Longではなく、Integerにしたのですが、オーバーフローのエラーが出たので、Longに変更したところ、きちんと出てくるようになりました。 しかし、なぜ、Integerではだめなのかがわかりません。私としては、Integerは32,767までの数字が入るのだから、身長や体重を入れたぐらいだと、オーバーフローにはならないのではないかと考えています。 きっと、根本的なものがわかっていないんだとは思うのですが、違いを教えていただければうれしいです。 よろしくお願いいたします。 (VBAを勉強したばかりです。)

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

  • ベストアンサー
  • ja7awu
  • ベストアンサー率62% (292/464)
回答No.8

#6ですが、ちょっと追加です。 > 私としては、Integerは32,767までの数字が入るのだから、身長や体重を入れたぐらいだと、 > オーバーフローにはならないのではないかと考えています。 まったくその通りです。 決しって入れ物が小さいのでは、ありません。 でもエラーになるのは、順番に演算している時点のエラーなのです。  Integer * Integer * Integer = Integer でエラーになっているのを (Sin)    (Sin)    (21)   Integer * Integer * Double = Double になるように1つでも大きなタイプのものを使って (この結果が、Integerになるようでは大変ですよね。)  If Tai >= Sin * Sin * 21# / 10000 + 3 Then のように 21 を Doubleにしてやると、演算されます。 (他に ! とか & #6のレス参照)

omusupa
質問者

お礼

再度の回答ありがとうございます。 ということは、変数宣言を Dim Sin As Long Dim Tai As Integer というふうに、両方をLongしなくても、片方をLongにすればよいということになりますか? (一応確認してみましたが、エラーは出ませんでした。) もし、間違えているようであれば、ご指摘いただけないでしょうか?よろしくお願いいたします。

その他の回答 (8)

  • ja7awu
  • ベストアンサー率62% (292/464)
回答No.9

> 両方をLongしなくても、片方をLongにすればよいということになりますか? > もし、間違えているようであれば、ご指摘いただけないでしょうか? その通りです。 間違っておりません。 普通は、 If Tai >= Sin ^ 2 * 21 / 10000 + 3 Then のように書きますが、 変数 Sin 自体は、Integerで大丈夫なのですが、これを計算するのに、 Integer用の¥980の電卓を使うものですから、桁数が足りなくてオーバーフローに なってしまう訳です。 それで、計算式の中にLog が入っていると、ちょっと桁の多い\1,980のLog 用の電卓で 計算されますので、エラーにならない。 ということだと思います。 #2のtinu2000さんが仰っている様に、計算する用紙が小さすぎて、答えを出せる状態 ではない ということと同じですね。 基本が大事です。デバックの方法を習得し、エラーの原因を突き止めることが上達に つながるものと思います。 ところで、この体重、InputBoxに入力する単位は、何ですか? 当方、痩せているのですが、「太りすぎ」と出ますが・・・? 適当に可也スリムな数値を入力しても、「太りすぎ」になってしまいます。 どっか、計算式、おかしくありません?

omusupa
質問者

お礼

本当にありがとうございます。最初はぜんぜんわからなくて、くじけそうになったのですが、やっと理解ができました。 ご指摘の件ですが、 Sin = InputBox("あなたの体重は?", "体重") Tai = InputBox("あなたの身長は?", "身長") Sinのところに体重を入れるInputBoxになってしまっています。正しくは Sin = InputBox("あなたの身長は?", "身長") Tai = InputBox("あなたの体重は?", "体重") です。スミマセン。

  • popesyu
  • ベストアンサー率36% (1782/4883)
回答No.7

あと追加で。 Dim x As Long x = 35000 * 100 x = 3500 * 1000 この例では上はエラーになりませんが、下のはエラーになります。上のは32767以上なので仮Xの型が自動でLongになるからです。下の仮XはIntegerになってしまうのでオーバーフローします。この辺はVBの癖ということで丸覚えしましょう。ちなみにこんな知識は他の言語には何の役にもたちませんw

omusupa
質問者

お礼

>仮Xの型が自動でLongになるからです うーん・・わかってきたような・・・(?) 変数宣言の問題ではないということですか? Longということは、長整数型ですので、いっぱい入りますね(アバウトな言い方ですいません) なのにもかかわらず、 x = 3500 * 1000 がエラーになるということは、入れ物(変数)がいくら大きいものを使っていても、計算途中で、 3500(Integer)*1000(Integer)はInteger以下の結果にならないと、オーバーフローが出るということでしょうか?だから、long*IntegerだったらLong以下の結果を出せるということですか? お礼の箇所に書いてしまいましたが・・・すみません。回答ありがとうございます。

  • ja7awu
  • ベストアンサー率62% (292/464)
回答No.6

変数が Integerの場合、こんな感じで如何でしょうか。 If Tai >= Sin * Sin * 21& / 10000 + 3 Then ついでに次のコードを実行して確認してみると良いでしょう。 Sub GetType() Debug.Print VarType(21) ' ----> 1=Integer Debug.Print VarType(21&) ' ----> 3=Long Debug.Print VarType(21!) ' ----> 4=Single Debug.Print VarType(21#) ' ----> 5=Double End Sub

omusupa
質問者

お礼

上記の式で解決できます。 ありがとうございます。 Get Typeも確認してみました。(イミディエイトウィンドウで確認すればよいのですね。) でも、まだまだ勉強が足りないようです。

  • popesyu
  • ベストアンサー率36% (1782/4883)
回答No.5

4番です。 記述が分かりにくい、かつミスがあるということで再度書き直します。 --- ヘルプにありますが 数値計算で数値が内部的に整数型として処理されている場合に、計算結果が整数型の範囲を超えているとオーバーフローします。 エラーが出る例  Dim x As Long  x = 2000 * 365 エラーが出ない例  Dim x As Long  x = CLng(2000) * 365 今回の事例なら If Tai >= Clng(Sin) * Sin * 21 / 10000 + 3 Then で解決です。 VBは型変換がいい加減というか処理が自動化されすぎているため、自覚することが少ないのですが、上の例では2000は仮にInteger型のXという変数の中に入っているのです。で掛け算の計算途中でその仮Xがオーバーフローしています。

omusupa
質問者

お礼

実際に確認してみました。解決はしたのですが・・まったく理解ができず、くじけそうです。(苦笑)  Dim x As Long  x = 2000 * 365 は 長整数型の変数 x を宣言します 変数 x に 2000*365 に代入 という意味にどうしても考えてしまうのです。 長整数型は2147483647までの整数まで処理ができるのに、なぜ エラーが出るのかが・・・ もう少し勉強が必要ですね。 ありがとうございました。

  • popesyu
  • ベストアンサー率36% (1782/4883)
回答No.4

ヘルプにありますが 数値計算で数値が内部的に整数型として処理されている場合に、計算結果が整数型の範囲を超えているとオーバーフローします。 Dim x As Long x = 2000 * 365 計算途中がオーバーフローなのです。 この場合は計算途中も明示的に型を示す必要があります。 Dim x As Long x = CLng(2000) * 365 今回の事例なら If Tai >= Clmg(Sin) * Sin * 21 / 10000 + 3 Then で解決です。 VBは型変換がいい加減というか処理が自動化されすぎているため、自覚することが少ないのですが、上の例では2000は仮にInteger型のXという変数の中に入っているのです。で掛け算の結果そのXがオーバーフローしています。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

SINなどは三角関数と混同されるかも。 INPUTBOX関数は文字列を返すはずです。 VBでは数字と演算すると数値化してくれるかも知れないが、そう言う意識は必要では。VAL関数で数値化しておいたほうが良いのでは。

omusupa
質問者

お礼

>INPUTBOX関数は文字列を返すはずです。 まったく知りませんでした。 勉強になりました。ありがとうございました。

回答No.2

こんばんは。 たぶん、 If Tai >= Sin * Sin * 21 / 10000 + 3 Then の所でエラーが出たと思います。 コンピューターは計算をいっぺんにするのではなく、 一つ一つ順番に計算をします、 ちょうど、人間が紙を使って計算して行くようにです。 計算の相手が小さければ小さい作業用の紙を用意し、 大きければ大きい作業用の紙を用意します。 ここでは、Tai と Sin の大きさを見て紙の大きさを決めています。 Integer と指定したら、Integerの紙を用意します。 例えば、身長を170Cmと入れると、 170*170*21 の計算結果(=606900)をIntegerの紙に書いて置こうとして、オーバーフローになります。 たぶん。

omusupa
質問者

お礼

回答ありがとうございます。 もう少し勉強が必要なようです。 >例えば、身長を170Cmと入れると、170*170*21 の計算結果(=606900)・・・ という表現はわかるのですが、 >Integerの紙に・・ というのがなぜInteferの紙に書かれてしまうのかが、理解ができないのです(勉強不足です) この170*170*21の結果を何かの変数に代入するのであれば、理解ができるのですが、論理式を作って比較しているだけなのに・・と考えてしまうのです。 変数の考え方がそもそも違うのですね。勉強しなおします。丁寧に教えていただいてありがとうございました。

  • pppc88
  • ベストアンサー率43% (40/93)
回答No.1

ご投稿のマクロを試していませんが、怪しいところが2つあります。 1.変数名に"sin"はこのましくありません。 三角関数サインの予約関数で同じ関数名があるためです。 2.式的に変数sinを2乗しているところがあります。 √32768≒181なので、単純に約182以上で演算上オーバーフローになります。

omusupa
質問者

お礼

アドバイスありがとうございます。 Sinという変数名はよくありませんね。よくわかりました。 しかし、他の名前に変えてみましたが、解消はされませんでした。 でも、変数名を変えたときに、SINの引数が・・・などのエラーが出ていましたので、名前がよくなかったのも理解できます。 ありがとうございます。

関連するQ&A

  • Excel VBAで検索(Win2000 Excel2000)

    現在、下記のようなコードを書いています。データテーブルの縦と横の検索値を探してその列数と行数を返したいのですが、下記の Sub検索1 と Sub検索2 を1つのSubで実行させるにはどうしたらよいのでしょうか?よろしくお願い致します。 ----------------------------------------- Sub 検索1() Worksheets("Data").Activate Dim x As Integer For x = 3 To 22 If Cells(2, x).Value >= 12 Then MsgBox x Exit Sub End If Next MsgBox "見つかりません" End Sub --------------------------------------------- Sub 検索2() Worksheets("Data").Activate Dim i As Integer For i = 4 To 42 If Cells(i, 2).Value = "A" Then MsgBox i Exit Sub End If Next MsgBox "見つかりません" End Sub

  • ExcelVBAでの変数を用いたべき乗の計算

    以下のコードを実行すると止まってしまいます。#1も同義です。エラーメッセージは、「実行時エラー'6': オーバーフローしました。」と表示されます。最初は変数prAをIntegerで定義していたので、Longにすれば解決するはずの問題と思ったのですが、解決しません。なぜこれではうまくいかないのか教えて下さい。バグでしょうか?回避して#1の行を#2や#3のようにかくとエラーは出ずに実行できました。よろしくご教示下さい。 Sub problem() '身長を定義する Dim prH As Integer '体重を定義する Dim prW As Integer '標準体重を定義する Dim prA As Integer '肥満度を定義する Dim prB As Integer prH = InputBox("身長[単位:cm]を入力してください。") 'prW = InputBox("体重[単位:kg]を入力してください。") prA = prH * prH * 2 * 22 / 10000 MsgBox (prA) End Sub '#1 'prA = prH * prH * 22 / 10000 '#2 'prA = prH / 100 * prH / 100 * 22 '#3 prA = prH ^ 2 * 22 / 10000

  • ■Excel VBA グローバルな書き方■

    Sub 跳ね返る() Dim time1 As Integer, time As Integer Dim X As Integer, Y As Integer Dim hyouji As String, yoko As String, tate As String hyouji = "●" X = 1 Y = 1 yoko = "右" tate = "上" Do Cells(X, Y).Value = hyouji '★ For time1 = 0 To 1000 For time2 = 0 To 1000 Next Next Cells(X, Y).Value = hyouji For time1 = 0 To 1000 For time2 = 0 To 1000 Next Next          '★ If yoko = "右" Then Y = Y + 1 Else Y = Y - 1 End If If Y = 30 Then yoko = "左" ElseIf Y = 1 Then yoko = "右" End If If tate = "上" Then X = X + 1 Else X = X - 1 End If If X = 20 Then tate = "下" ElseIf X = 1 Then tate = "上" End If Loop End Sub ************************************ 上記のプログラムを Dim a() EndSub Dim b() EndSub Dim c() endSub Sub main() a b c EndSub のような、mainを動かせばabcも動く グローバルな(ローカルでもいいのですが) プログラムにするにはどうしたらいいですか? ★印から★印までの間の動作が同じような動作で 二つあるので、それを一つにまとめ 尚且つ、表示と時間稼ぎと表示削除の 3つの動作を分けた形にしたいです。 質問が下手で申し訳ありません…;;

  • [と”の意味を教えてください。

    http://okwave.jp/qa/q5945112.html を参考に、 Sub test1() Dim i As Integer i = 2 If i Like "[1-3]" Then MsgBox i & "です" End If End Sub Sub test2() Dim i As Integer i = 2 If i Like "[1-5]" Then MsgBox i & "です" End If End Sub Sub test3() Dim i As Integer i = 2 If i Like "[1-10]" Then MsgBox i & "です" End If End Sub を作ったのですが、 test3はうまく行きません。 意味としては、 iが "[1-10]"の中の数字の間のどれかであれば、 MsgBox i & "です" を表示させたいです。 でも上記のマクロを実行させた結果、 "[1-10]"の中で計算が行われてるのではないかと思います。 だから、test3は、1-10=-9 という事になり、msgboxが反応しないのではないかと思っています。 でもそうすると、test2だって "[1-5]"は、-4になって、i=2とは違う値なのに なぜMsgBoxが反応してしまうのかわかりません。 でもそもそも[と”の意味が分からないのでそこから教えていただけませんか? “の意味、は二つで挟んで文字列にすると思っています。

  • ●Excel VBA 配列●教えて下さい

    a~tの文字が順々に文字を追っていくプログラムにしたいと思い 配列を使用したのですが…プログラムが稼動しません、 下記のプログラムでは何が足りないのでしょうか わかる方いたら教えて下さい; 配列の使い方についてアドバイスがあれば そちらも教えていただきたいです…。 '――ここから―― Dim time1 As Integer, time2 As Integer, n As String Dim X As Integer, Y As Integer Dim yoko As String, tate As String Dim suuji (19) As String Sub 描画() Cells(X, Y).Value = suuji End Sub Sub 削除() Cells(X, Y).Value = "" End Sub Sub 待機() For time1 = 0 To 1000 For time2 = 0 To 1000 Next Next End Sub Sub 座標移動() If yoko = "右" Then Y = Y + 1 Else Y = Y - 1 End If If Y = 30 Then yoko = "左" ElseIf Y = 1 Then yoko = "右" End If If tate = "上" Then X = X + 1 Else X = X - 1 End If If X = 20 Then tate = "下" ElseIf X = 1 Then tate = "上" End If End Sub Sub main() suuji (0) = a suuji (1) = b suuji (2) = c suuji (3) = d suuji (4) = e suuji (5) = f suuji (6) = g suuji (7) = h suuji (8) = i suuji (9) = j suuji (10) = k suuji (11) = l suuji (12) = m suuji (13) = n suuji (14) = o suuji (15) = p suuji (16) = q suuji (17) = r suuji (18) = s suuji (19) = t For n = 0 To 19 Cells(X,Y).Value = suuji (n) Next X = 1 Y = 1 yoko = "右" tate = "上" Do 描画 待機 削除 待機 座標移動 Loop End Sub '――ここまでです―― 何度も同じような質問をさせてもらってすみません;

  • VBEについて

    例えば Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range) '***** 特定セルを選択するとイベントを実行する ***** Dim tate As Long Dim yoko As Long Dim 数量 As Long Dim 判定 As Integer tate = ActiveCell.Row yoko = ActiveCell.Column If yoko = 2 Then On Error GoTo skip01 数量 = InputBox("数量を入力してください。") 判定 = MsgBox("数量 = " & 数量 & " で間違いありませんか?", vbYesNo + vbInformation) If 判定 = vbYes Then Cells(tate, 2) = Cells(tate, 2) + 数量 End If End If skip01: End Sub ですが、上記コードでは2行目のみの物になりますが、例えば7と8行目にしたいときなどはどうすればいいのでしょうか?素人質問ですが宜しくお願い致します。

  • VBAについて

    こんばんは、VBA初心者で勉強をはじめたばかりで、自分で例題を作り調べながら途中まで作成しましたが、行き詰ったのでご教授をお願いします。ECXEL2000を使用しています。 ○やりたいこと。 ・INPUTBOXを表示させ、年齢を入力してもらう。 ・年齢が、18~64歳までならA2セルに入力年齢を表示させる。     17以下は「就職前」、65歳以上は「退職済」とBOXで表示させ、セルには表示させない。 ・A2セルに入力したら、A3セルをセレクトする。 ・INPUTBOXを表示させ、再度年齢入力をしてもらい、既にA2セルに年齢が入力済みであれば、A3に表示する。これをA10セルまで行えるようにする(その都度マクロの実行で実施) ○作成したマクロです。・・・やりたいことがすべて記述できていません。 Sub 年齢入力() 'INPUTBOXに入力される年齢の変数   Dim r As Integer 'データの最終行を代入する変数 Dim k As Long r = InputBox("年齢入力") k = Rows.Count Range("a2").Select If 17 < r And r < 65 Then MsgBox ("入力します") Range("a2") = r ElseIf r >= 65 Then MsgBox ("退職済") ElseIf r <= 17 Then MsgBox ("就職前") End If Cells(k, 1).End(xlUp).Offset(1).Select End Sub 以上のマクロのどこを変更すれば、私のやりたいことができるようになりますでしょうか?よろしくお願いします。

  • キャンセルボタンをクリックしたかどうかを取得したい

    InputBoxでもしキャンセルボタンが押されたら・・・ってどうやればいいですか? Sub あああ() Dim a As String a = InputBox("文字を入れてください。") MsgBox a End Sub をした時に、キャンセルボタンをクリックしたかどうかを取得したいのですが、どうすればいいんですか? a = InputBox("文字を入れてください。") の次に Cancel = True をいれても vbCancel = True をいれてもエラーになります。 Sub あああ() Dim a As String a = InputBox("文字を入れてください。") If a = "" Then MsgBox "キャンセルが押されました" End If End Sub これだとOKでもキャンセルでもメッセージが表示されます。

  • vba 初心者

    Dim a As Integer Dim inbox As String Dim Localpath As Variant Dim c As Range, myFadd As String Dim flag As Variant Dim MyShell As Object Dim Mysh As String Dim newHour As Variant Dim newMinute As Variant Dim newSecond As Variant Dim waitTime As Variant Localpath = ThisWorkbook.Path a = 1 inbox = InputBox("番号") Do If inbox = Empty Then Exit Sub End If If inbox = Cells(a, 1) Then MsgBox ("あります") Exit Do Else a = a + 1 ElseIf Cells(a, 1) <> inbox Then MsgBox ("ない") End If Loop Set MyShell = CreateObject("WScript.Shell") MyShell.Run ("AcroRd32.exe /n") MyShell.Run ("AcroRd32.exe /p") & Localpath & "\" & Myfile & ".pdf" newHour = Hour(Now()) newMinute = Minute(Now()) newSecond = Second(Now()) + 10 waitTime = TimeSerial(newHour, newMinute, newSecond) Application.Wait waitTime Application.SendKeys "{Enter}", True '次の使用例は、10 秒を過ぎるとメッセージを表示します。 If Application.Wait(Now + TimeValue("0:00:10")) Then MsgBox "時間が過ぎました。" End If End Sub ExcelからPDFファイルを検索して印刷したいのですが、 見よう見まねで作ってみたもののエラーが出てしまってよく分かりません。 指摘できるところご指導よろしくお願いします。

  • VBAコード実行を中止する方法は?(1プロシージャだけでなく)

    Exit Subは子だけしか中止できないのですね。 子でエラー起きたら、親もその他もまとめて中止することはできないのでしょうか? Sub 子()   Dim i As Integer   For i = 0 To 5     If 3 < i Then       '' ここで親も終了したい     End If     MsgBox i   Next End Sub Sub 親()   子   MsgBox "エラーならここまで来ないで" End Sub

専門家に質問してみよう