- ベストアンサー
記録マクロは分かるのにDim(変数)が入ると分からない
マクロ初心者です。記録マクロで色んなファイルを作り、活用は出来ているのですが、データーの増減、条件判定などが入ってくると必ず、Dim〇〇の記述が入ってきます。 記録マクロのコード記述を読んで大体は読めるのですが、Dimになるとサッパリ分からなくなります。 私にはこのDimが変数、代入と言うことは分かるのですが、では『具体的にこうなんだ、こうなるんだ』ということが理解できません。変数宣言を強制していません。 過去のこのカテの類似質問を拝見しましたが、今一、理屈が分かっておりません。 変数型マクロのサンプル例でこの辺を詳しく解説しているサイトをご存知でないでしょうか? VBA構文と日本語記述解説を対比して解説してあると分かり易いと思うのですが、書籍も探しています。 ご存知の方、教えていただけないでしょうか?
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。 ご質問の趣旨は、変数型の宣言ということと解釈してよろしいですか?回答されている中には、変数の有無を述べた方もいるようですから。 1960ken様は、もう、かなりVBAは、経験されている方のはずですから、「変数の型の宣言」の必要性を考えるのは、上達してきた証拠でしょうね。私も、少し考え直してみました。僭越かもしれませんが、1960ken様のVBAに対するアプローチの仕方に少し問題があるかもしれません。 最初に、「変数宣言を強制(Option Explicit)」は、コーディングの際に入力ミスを減らすという目的だけです。間違えれば、エラーが出るか、目的の値が取れないだけです。本来、変数を宣言するというのは、使用中のメモリを減らすことにあります。 次に、「変数の型の宣言」(Dimステートメントなど)が本当に必要になるのは、中級から上級に掛けてで、ここの掲示板に出で来るコード10のうち9までは、変数の型の宣言は必要がありません。Basic系の言語は、あまり変数型をとやかく言っても、「自動キャスト」がありますから、いわばルール無用の世界です。何でもあり、なんです。 (「自動キャスト」というのは、データから自動的に適当な型に割り振ってしまう機能) しょせん、ある程度上達してくると、みなさん、どうでも良くなります。型の宣言の必要性は、もう少し上のクラスの話です。しかし、変数自体が分からないのでしたら、自分でお金を払った初級レベルのExcelマクロの本を読んでみるしかありません。 とはいえ、多くの人が、日付文字列を平気で、Date型の変数に入れたり、文字列を、そのまま平気でRangeの引数にしてみたり、まあ、危なっかしいことを見せられるのが常です。そのレベルでは、逆に、「型の宣言」などしないほうがよいかもしれません。ひどい例では、プロパティ名を変数名にする人間がいますが、そんなことをしたら、ひとつのプロジェクト全体に影響してしまいます。 VBAには、VBにはない、独特の特徴があります。 しかし、そういうことを言ったところで、PC自体のスペックがあがるにつれ、問題が表面化しなくなり、「コードが通れば、文句あるか! 」と、逆切れされるのがオチで、しょせん、こういうのは、他人がどうこういうことではないかもしれません。ただし、基本が分かっていない人は、必ずミスします。(以下にある「VBA コードを最適化する」を参照) 初級のVBAですと、大雑把に言って、Long型とString型とObject型(Object型は、固有の変数型 例、Worksheet, WorkBookなどなら、なお良い)の三つでほとんどをカバーします。初級レベルのコードでは、単に格好付けだけで、何の意味もありません。 一応、簡単な割り振りの仕方を教えておきます。 例えば、Dim A とだけ入れて、As ○○を入れない変数が、ローカルウィンドウの中で、Variant/Range としたら、それは、As Range に割り振っておけばよいのです。Variant/Doubleと出たら、As Doubleとしておけばよいです。(注意:オブジェクト型すべてを、そのように割り振りはできないこともあります。) 書籍では、『かんたんプログラミンシリーズ Excel VBA 基礎編』(技術評論者)の第9章、「変数を理解しよう」に説明があります。(私の持っている本は、Excel 2002用です)。それ以上に詳しい説明は、井川はるき さんの『Excel VBAプロの技』(ナツメ社)の第1章に出てきますが、文章が冗長なので、多少読みにくい点があります。 後者は、一通りVBAがすべて分かっている人向けです。 本を読んだら、実際に、自分の指で、VB Editor画面に文字を入れてみて、それを、F8を押して、ステップインで動かしてみるのが一番です。語学学習と同じで、機械仕掛けで翻訳した英文が、正しいとは言えません。それを覚えたところで役に立ちません。基本文法を学び、その構文に自分の言葉を入れて応用してみるしか手がないと思います。ある程度のレベルになると、その人のコードで性格さえ判ります。 サイトというなら、MSDNライブラリを読んでみる価値はあると思います。一般サイトは、しょせん、どこかを書き写しているのがほとんどです。この内容は、現行VBAの原則です。 「VBA コードを最適化する」 http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/modcore/html/deconoptimizingvbacode.asp ○変数の宣言が必要とされる代表的なサンプル '(初級では出てきません) ''「なぜ、Currency型でなければならないか?」 '浮動小数点丸めに対しては、以下のような変数で防ぎます。 'ただし、数値リテラル値を直接入れるのは実務上はありません。 'これは、時間の計算、小数点が発生する演算、循環小数などに用いられます。 '実務では、金銭上の計算を用いるときに使われます。 'なお、必ずしも、「浮動小数点丸め誤差」が発生するわけではありません。 Sub BadSample1() Dim ret As Double ret = 0.5 - 0.4 - 0.1 MsgBox ret 'CStr(ret) End Sub '--------------------------------------------- Sub Sample2() Dim ret As Currency ret = 0.5 - 0.4 - 0.1 MsgBox ret 'CStr(ret) End Sub '--------------------------------------------- 'または、 Sub Sample2a() Dim ret As Double ret = 0.5 - 0.4 - 0.1@ 'Currency型 MsgBox ret 'CStr(ret) End Sub 'データ型の精度の違うものの比較 ''「なぜ、違うと出るのか?」 Sub Sample3() Dim a As Double Dim b As Currency Dim c As Double Dim msg As String a = 49.8 - 12.1 b = 49.8 - 12.1 'Currency型 c = b '型を低精度にキャストしてしまったミス If a <> c Then msg = "違う " & a - c Else msg = "同じ" End If MsgBox msg End Sub これは、隣接しているから分かりますが、離れてしたり、加筆していったりすると、分からなくなります。数値を比較する時や、他の型にキャストする時は、明示的に行う場合は除いて、自動キャストした場合、別の値に変わっていることがあります。(浮動小数点丸め誤差といいますが、小数点以下が入った数値の演算は、約半分ぐらいが、発生することがあります。上記の数値の組合せは、浮動小数点丸め誤差が発生します。) (「明示的」というのは、VBAなどで良く使われる言葉で、意図して行うこと<->「暗黙的」) Mod 演算子など、Long型以上の精度を出力しない場合は、Long型以上の精度を持ったデータ型を用いても、精度は上がりません。求める値が何か、ということが、ここでは読み取れません。 Sub Sample4() Dim a As Currency a = (49.8 - 12.1) Mod 4 MsgBox a '実際は、Currency型の精度は出ていない End Sub Sub Sample5() '修正例(私案) Dim a As Currency Dim b As Long Dim c As Long Dim d As Double a = 49.8 - 12.1 '浮動小数点誤差が発生する組合せ b = CLng(Fix(a * 10)) '小数点固定法 c = b Mod 40 d = c / 10 MsgBox d 'CStr(d) 'Long型に戻すのも可 End Sub 上級では、Win32 API関数やBinaryコードを扱う場合に、どうしても、決められた変数(型)が必要になります。内容は割愛します。コードは、この板で実際にあった話を元にして作ったもので、十分に検証したつもりですが、私個人、この問題を明確に割り切れているわけではありません。一種の原則的なルールとして覚えていくほうが無難です。
その他の回答 (7)
- Wendy02
- ベストアンサー率57% (3570/6232)
他の方に対するコメントを読んでみました。 私なりに、「Office VBAの勉強の仕方」 を書いておきます。 私自身いつまでここに書けるか分かりませんので、これで私の回答は終わりにしておきます。 >単純な記録絶対参照方式の固定マクロと変数型(データー増減変動の場合の)DIMの入るマクロの記述がどこが違うのか? そのレベルでしたら、改めて書きますが、DIMなんて入れる必要はありませんね。記録マクロと、記述式のマクロコードとは、絶対的に違う部分があります。それは、抽象的な言い方になりますが、記述式のものは、作者の「意思」「思惑」がこめられるからです。 変数は必要ですが、前にも書いたように、プロパティ名や予約語となりうるような名称(例:Database, Criteria, Value, Sum など)を使わなければよいだけです。 語学と同じで、"How are you!" "Fine, Thank you, and you." 方式ではダメなのです。私たちは、もう大人ですから、理屈で覚えるしかありません。まず、基本文型・基本文法を一通り習って、出来れば、上級文法まで習って、実務に応用するのが一番即戦力があり、やっていて楽しいです。 大村あつし著『かんたんプログラミング Excel VBA』(技術評論社) 基礎編 〇〇フォルダの××ファイルを開く 基7-2 ○○シートを選択 基7-8 そのシートのセル〇〇を選択(データー範囲は増減変動する) 基8-9 この大村さんの書籍は、三部作(演習編は除きます)ですが、かなりてんこ盛りな内容で、これで、ほとんどの基礎が終わります。ちょっと内容が詰め込みすぎですが、よほど興味がなければ、ほかの書籍を買わずにすみます。『応用編』の一部に初級ではないものがありますが、ほとんどは基礎です。ただ、その上は、極端に難しくなります。ほとんどの人は、基礎レベルで終わります。 実用の段階に入っている人でも、その基礎さえ終えていない人がほとんどです。それでも、まったく困らないわけです。まして、その上のレベルに足を踏み入れる人は、会社で特別な仕事についている人かめぐまれた環境にいる人です。 基礎を覚えるコツとしては、本は、文字の一字一句を覚えようとしないことです。もう大人になると、文字の記憶はできないような気がします。それから、ワークシートの操作は、一旦忘れたほうが良いです。 「なんとなく」を大事にして、入力して、その過程をイメージで覚えることです。細かいことを気にしないほうがよいです。これを出来事(イベント)記憶とかいうそうです。簡単に言うと、自分で作ってみたものが、「出来た!」「出来ない(~_~;)」という感情を持って、身体を使って覚えるわけです。本を読んだりWebサイトを読んだだけで覚えるわけはありません。 習ったら、すぐに使ってみることです。そうすると、自分の中で「なんとなく」の問題解決のパターンが作られます。上記の三部作で、だいたい、3ヶ月で一通り済ましてしまいます。分からなかったり、面倒だなって思ったら、基礎編を除いて飛ばして、後でフィードバックして良いです。3年も経って、あの意味は、こんな意味だったのか、と思い出して本を開いてもよいです。 >『わざわざ手間暇かけてコーディングしなくても記録で事足りる』と楽な方に行ってしまい、学習を疎かになりがちです。 一旦、記録マクロで済ませることを忘れなければ、とても、本格的には覚えられません。別物だと思ったほうがよいです。 VBAというかプログラミング言語というのは、パフォーマンス/学習 の効率があまりよくありません。覚えたものが、即効即戦力というわけにはいかないのです。根気良く覚えるためには、強い動機も必要です。 ただ、すべての人が、VBAが出来なくてもよいと思います。上手に掲示板を利用していくのも方法かもしれません。聞く人がいれば、教える人のバランスで成り立っているのがQ&A掲示板ですから。
- imogasi
- ベストアンサー率27% (4737/17069)
#4です。 お礼の部分で >記録から、変数を使った、相対化することになれていないだけだ まさにその通りです。記録でも相対参照ではあまりしないです ーーー 私の言った「相対化」は「相対参照」の「相対」ではありません。 「どんな場合にも対応できる」といった意味で、変数を使うことと 密接不可分のものです。 実行前の別の場所で、具体的な番地や値やその他をセットすることです。2段構えと言いましょうか。 あまりやらない例でしょうが Sub test01() fmt = "0000" ActiveSheet.Cells(1, "B").NumberFormat = "@" ActiveSheet.Cells(1, "B") = Format(Range("a1"), fmt) End Sub のようにして ActiveSheet.Cells(1, "B") = Format(Range("a1"), "0000") としないことで、違った利用が開けてきます。 そういうのを相対化と言ってます。 しかし、こういう置き換え的方法が全てできるとは限りませんので注意が必要です。
- zap35
- ベストアンサー率44% (1383/3079)
変数の概念がつかみにくいのでしょうか? 変数は他の回答者さまも書いているように、計算途中結果や状態を一時保存、あるいは待避するために使用します。 絶対に変数を使用しないとならない例として次のようなものがあります 「マクロが開始してから終了するまでの経過時間を表示する」 時刻はVBAでは Time で取得できますが、Timeの値は刻々変わりますから、経過時間を計算させようとすると 開始時の時刻(Time)を変数に待避しておいて、終了時の時刻(Time)から待避した開始時刻を減算する 必要があります。この例は変数を使用しないと実現できません。 また繰り返し処理で For idxSheet = 1 To 5 Worksheets(idxSheet).Visible = True Next idxSheet のような例でも、一時的に使用する変数が必要になります。(idxSheetが変数です) 次に変数を使用することによりプログラムを見やすく書くことができます。 Activesheet.Autofilter.Filters.count Activesheet.Range(curADDRESS).Interior.colorindex などの記述が長い項目が、マクロ中に何回も出現するとき、毎度書かなければならないのは大変ですし、コードも見にくくなります。見にくいプログラムはデバッグも大変です。 こんな時は FilterCount = Activesheet.Autofilter.Filters.count などと、一旦変数に値を格納して、二回目以降は変数名を書く方が、見やすく、分かりやすいマクロになります。 最後に長いマクロは絶対に Option Explicitを記述したほうがデバッグが楽です。このオプションがないと変数名を1文字間違って記述しても、エラーになりません。でも動かすとVBAインタープリタは別の変数と認識して、セットしたつもりの値がNULLになっているようなことがあるからです。 ですから面倒でも「DIM 変数名 As 型」で使用する変数を明示的に定義しておく方がよいのです。変数の型は結構やっかいですが、難しければ「DIM 変数名」だけでも構いません。(この場合はバリアント型という万能の型が割り当てられます)
お礼
回答有難うございました。 >変数の概念がつかみにくいのでしょうか? はい、その通りです。 説明いただいたのですが、難しくて飲み込めませんでした。 具体例を見つけて検証してみます。頭がこんがらがっている状態です。 サンプル例を吟味して繰り返し、理屈を覚えるしかなさそうです。エキスパートの方のように簡単に進まないのが今の私の現状です。
- imogasi
- ベストアンサー率27% (4737/17069)
例えば、マクロの記録モードにして、ファイルー印刷設定ー印刷範囲の設定の操作をします。するとマクロは Sub Macro1() ActiveSheet.PageSetup.PrintArea = "$A$1:$D$11" End Sub になります。しかし "$A$1:$D$11"はその場合に限った範囲しか指定できていません。 これを 変数PrtAreaを作って・使って Sub Macro1() ActiveSheet.PageSetup.PrintArea = PrtArea End Sub とすれば、PrintAreaという変数の中身が示す範囲で設定できるようになります。 そのとき、VBではDim宣言はなくても良いが、普通は >Dim〇〇の記述が入ってきます(宣言します) 。 Sub Macro1() Dim PrtArea ActiveSheet.PageSetup.PrintArea = PrtArea End Sub です。それとPrtAreagaの中身が文字列か、整数かなどを指定します。 この場合文字列を指定するので(これはエクセルVBAの知識から来ます) Sub Macro1() Dim PrtArea as String ActiveSheet.PageSetup.PrintArea = PrtArea End Sub しかしこれでは、 ActiveSheet.PageSetup.PrintArea = PrtArea を実行するときにPrintAreaの中身が指定できていませんのでエラーになります。 そこで Sub Macro1() Dim PrtArea As String PrtArea = InputBox("印刷範囲") ActiveSheet.PageSetup.PrintArea = PrtArea End Sub とします。 実行すると、印刷範囲を聞いてくるので $A$10:$D$20 のように入力します。これはエクセルのVBAの知識を持っていて 文字列でよい 絶対番地でよい(A1:D11でもよいよう) を知っていうからできることでVBAコーディングの知識では無い。 >今一、理屈が分かっておりません 理屈ではなくて、「決め」なんです。そうではなくて、マクロの 記録から、変数を使った、相対化することになれていないだけだと思います。 プログラムの勉強をマクロの記録から入る副作用とでも言いましょうか。しかしDimだけで大騒ぎする人はいないと思います。普通スラーと 前に行くと思いますが、人それぞれ、どうしてもそこに立ち止まる箇所というのが出てきます。質問とは別ですが、既習のプログラム言語 に存在しない構想(概念)があったりすると。 DimはDimentionから着ていると思うが、配列の次元の次元で、DosBasic->VBでは変数使用宣言になっちゃった。 Javaでは変数宣言は厳格ですが、Dimに当たるものはない。 Dec(Declaratin)などの方が(VBではダメだが)ふさわしいと思う。 ーーー 上記の変数化の説明を色々なマクロの記録に応用すれば、大変 レパートリが広がるものと思います。 普通はプレイバックするような実行でなく、一部を利用者が変えて パターンは同じ操作を実行させたいものですから。
お礼
imogasiさん、いつもながらの回答有難うございました。ご教導いただいた解説は非常に分かり易いのですが、 >プログラムの勉強をマクロの記録から入る副作用になっています。 私の作ったファイルは全て絶対参照の$A$10:$D$20 ように範囲が限定されてしまっています。 >記録から、変数を使った、相対化することになれていないだけだ まさにその通りです。記録でも相対参照ではあまりしないです。 そのため自由度が聞かず、手動修正している現状です。基本から記述式のマクロ(VBA)を覚えようとするのですが、『わざわざ手間暇かけてコーディングしなくても記録で事足りる』と楽な方に行ってしまい、学習を疎かになりがちです。 独学で参考書等をみてやろうとはするのですが、覚えることが多すぎて途中で挫折するの繰り返しです。 人のスキルにも高低がありますが、私は覚えるのに時間が掛かる方です。 どうすればこの辺の内容を理解できるのか困っています。 例えば日本語記述で 〇〇フォルダの××ファイルを開く ○○シートを選択 そのシートのセル〇〇を選択(データー範囲は増減変動する) のようなプロセスがあり、これをVBAモジュールに自動的に変換、コーディングしてくれたらいいのになぁと思います。 要は同じ処理をする場合でも、単純な記録絶対参照方式の固定マクロと変数型(データー増減変動の場合の)DIMの入るマクロの記述がどこが違うのか?ここの記述が違いますよ。と言うのがわかればもっと理解できるかもと思います。 その違いの部分はどこなのか?と言うことが私にはは把握できておりません。 プリントエリアの例で説明下さりましたが、何となく『子言うことなのかなぁ』位にしか理解できませんでした。 レベルが低くて申し訳ありませんでした。有難うございました。
- NCU
- ベストアンサー率10% (32/318)
モジュールの先頭に option explicit と書いておけば、後はエラーがでないようにするだけです。 それ以上のものではないと思います。
お礼
回答有難うございました。 option explicitの意味が分かっておりません。 NCUさんが言われるような簡単なものと私には思えないのですが、理解に困っています。
- papayuka
- ベストアンサー率45% (1388/3066)
私も独学なので厳密な説明は出来ませんが、ようするに変数は値を保持しておく入れ物(うつわ)です。 パソコンには型と言うのがあって、同じ 10 でも 数値か文字かで異なります。 下記を実行すると、同じ処理をしているようですが i と s では違うことがわかります。 整数型の i に10を代入して、 i+i とすると 20 文字列型の s に10を代入して、 s+s とすると 1010 Sub Test() Dim i As Integer '変数 i は 整数型を保持する器である事を宣言 Dim s As String '変数 s は 文字列型を保持する器である事を宣言 i = 10 ' i に 10 を代入 s = 10 ' s に 10 を代入 MsgBox "i の現在の内容は " & i MsgBox "s の現在の内容は " & s i = i + i ' i(10) に i(10) を足して i に代入 s = s + s ' s(10) に s(10) を足して s に代入 MsgBox "i の現在の内容は " & i MsgBox "s の現在の内容は " & s End Sub ざっと見渡せるくらいのプログラムならVBAでは宣言無しでも動きますし、型キャストもうるさくないのでナーバスになる必要は無いと思いますが、、
お礼
回答有難うございました。説明して戴いたことは『こういうことなのかな?』程度には理解できたのですが、数学の方程式のような感じがして、今一、頭に入っておりません。 子供の頃から、方程式や式の展開や数学を大の苦手にしていたもので頭で整理が付かないのです。 >ナーバスになる必要は無いと思いますが、、 と言われますが、非常にナーバスになっていてそこから前に進めていません。 同じようなファイルをマクロ記録で作ったものと変数型で作成したものとの比較で『ここの記述が違う』と言うのが分かれば理解できると思うのですが。 記録から入っていったので応用が効きません。困ったものです。
- misatoanna
- ベストアンサー率58% (528/896)
このあたりが参考になるでしょうか。 http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/sak3vb.htm の中の 入門編2 - 変数とは、変数タイプ、変数宣言、定数宣言、アスキーコード http://www.voicechatjapan.com/excelvba/index.html の中の 第4章コード の 宣言と変数と定数
お礼
回答有難うございました。 紹介いただいたHPを見たのですが、私の理解力が乏しくて難しくて意味が理解できませんでした。 やはりよく知っている方にマンツーマンで一から説明してもらわないと無理なような気がします。
お礼
Wendy02さん、お礼が遅れ、申し訳ありませんでした。大村さんの著書を購入し、今、少しずっ読んでいます。 焦らず、時間掛けて覚えたいと思います。奥が深いのでVBAは本当に難しいです。 記録を忘れてトライしてみます。有難うございました。