こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

VBA 変数を使うべき?

VBA 変数を使うべき?
VBAを独学で勉強中のものです。
エクセルVBAでデータが入っている行数分処理を行いたい場合などに
------------------------------------------------
lastRow = cells(rows.count,1).end(xlup).row
for i = 1 to lastRow
・・・
next i
------------------------------------------------
などと最終行を変数に代入して使う場合と

------------------------------------------------
for i = 1 to cells(rows.count,1).end(xlup).row
・・・
next i
------------------------------------------------
などと直接for文の中で指定する場合とでは結果は同じと思うのですが
結果以外の部分で見た場合どちらで行うほうがいいのでしょうか?

投稿日時 - 2010-01-14 09:34:49

QNo.5591951

暇なときに回答ください

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

私個人的には、今まで1回しか使わないものであれば変数を使わずに済ませてきました。
でも#2のtodo36さんはじめ、可読性やデバッグし易さの事も考慮すると変数を使ったほうが良いという意見も納得するものがあります。
考えてみれば
Dim r As Range
For Each r In ws.Range("A1", ws.Cells(ws.Rows.Count, 1).End(xlUp)).Offset(, 1)
なんて長ったらしくなる場合は改行するのもなんなのでRange型変数に入れてたりもしてたし。(矛盾...orz)
ケースバイケース&質問者さんのコーディングスタイル次第、という事で良いんじゃないでしょうか。


ところで余談ですが、VBAのFor...Nextステートメントではループ処理の度に counter の最終値を評価するわけではないようです。
確かFor Each...Next ステートメントも同じだったと思います。

Sub test()
  Dim i As Long

  Sheets.Add
  Cells(10, 1).Value = 1
  Debug.Print Cells(Rows.Count, 1).End(xlUp).Row
  For i = 1 To Cells(Rows.Count, 1).End(xlUp).Row
    'こんな処理はあり得ないけどテストなので。
    Rows(i).Insert 'Delete
    Debug.Print i, Cells(Rows.Count, 1).End(xlUp).Row
  Next
End Sub

投稿日時 - 2010-01-14 19:24:02

ANo.6

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.7

#4 の内容の訂正:
#ここら辺は、Microsoft サポートあたりでも、決まりはありませんから、これをプログラミング・ルールとはできません。

必ずしも、今回のケースに当てはまるとは言いませんが。
'-------------------------------------------
以下は、マイクロソフトのAccess のヘルプですが、こんな文面があります。
http://office.microsoft.com/ja-jp/access/HP051868231041.aspx
データ アクセス オブジェクトやそのプロパティを何度も参照する場合は、識別子を使うのではなく、オブジェクト変数を作成し、その変数を参照してください。
'-------------------------------------------
私は、個人的には、こういう原則論というのは、こだわりますね。人にどうこう言うべき問題ではなくて、原則論をないがしろにすると、自分のスタイルを維持できませんし、ミスが増えてしまいます。

End プロパティというのは、一種のファイルサイズのような物理的な範囲を示すものだと思います。一見、Ctrl + ↑ みたいな動的な作業を連想するので、メソッドのように思われがちですが。

スクリプト言語だと考えると、文字数が少なければ良いと考えるようですが、それは今の時代の議論には合わないし、VBAは、スクリプト言語としての要素は、デバッグ時は別として、実行時にはあまり多くはありません。

それに、可読性というのは、あるレベルの人たちには、結構議論の的になるようです。本来、決まりきったものがあるわけではありませんから、VBAのみに専門性や他の言語のルールなんていうものを持ち出しても、本来はお話にはなりません。しかし、私自身、それを借りて書いています。

end-uさんのご指摘は、的を得ていますが、こちらも、こういうコードを考えてみました。これを見る限りは、呼び出しは、1回限りです。それに、スクリプト言語なら、MsgBox が出るはずです。

ただし、この種のループは、失敗しているかは、エラーが出るわけではありませんから、変数を置かない場合、ウォッチ式を置かない分からないと思います。

Sub test2()
  Dim i As Long
  Dim j As Long
  'Sheets.Add
  Cells(2, 1).Value = 1
  For i = 1 To Cells(Rows.Count, 1).End(xlUp).Row
    Cells(i + 1, 1).Value = i
    j = j + 1
    If j > 10 Then MsgBox "この部分がでるか?"
  Next i
End Sub

投稿日時 - 2010-01-14 22:01:42

ANo.5

既に皆様書かれてますが、ご参考までに。
(VBAの話でもありませんが・・・)

プログラミング基礎編

* for (int i = 0; i < list.getLength(); i++) {}の潜在的パフォーマンスボトルネック
list.getLength()がlist.getLength()回評価されてしまう。具体例としては、JREに標準で付属するDOMのライブラリの NodeListの実装はlist.getLength()内で非常に重い処理をしているため、これが原因で劇的にパフォーマンスが劣化することがある。
(まあ「getLength()」で重い処理するなよ、という話もありますが)

この問題を回避するためのイディオムとしては、
for (int i = 0, length = list.getLength(); i < length; i++) {}
といったものがあり、IBM developerWorksなどプログラマー向けのメディアでは、この書き方に統一しているものもある。

参考URL:http://blog.livedoor.jp/lalha/archives/50254720.html

投稿日時 - 2010-01-14 15:32:51

ANo.4

こんにちは。

質問内容の場合は、変数を置いた方がよいような気がしますね。

Cells(Rows.Count,1).End(xlUp).Row は、これ自体は、プロパティですから、そんなには差はないとは思いますが、変数を置かないと、デバック時にミスっているのか、わかりにくいです。

>ループ中に行数が変わるような処理

列を動かしていくコードのことです。そうしたら、基本的には、その部分に、1 が立つ可能性があるのですから、変数を置いた方がよいと思いますよ。すでに、インクリメンタルの i という変数が立っているのですから、その手間とミスの可能性を考えたら、そういうことは、言うまでもないと思います。

ここら辺は、Microsoft サポートあたりでも、決まりはありませんから、これをプログラミング・ルールとはできません。

ただ、プログラミングの上達の要のひとつに、可能性のあるエラーやトラブルを予測するということがあります。その点は、そのつど、どうすればよいかは、ご自分で考えていただくしかありません。

投稿日時 - 2010-01-14 14:25:17

ANo.3

どちらも A列の途中に空白がない場合の例だと思います。
両者の決定的な違いは、
最初のサンプルはループ処理の前に最終行番号を決定してますが、次のサンプルはループ処理の度に毎回、最終行番号を取得してるって点ですね。
ループの中で最終行番号が変化するなら後者。しないなら前者。
また、最終行番号を入れた変数のスコープ内で (たぶんプロシージャ内だと思いますが) もう一度使いまわすなら前者ってところかな。

最後に 「好きにして構わんと思う」 とだけ言わせてください。。。

投稿日時 - 2010-01-14 12:44:26

お礼

>最初のサンプルはループ処理の前に最終行番号を決定してますが、次のサンプルはループ処理の度に毎回、>最終行番号を取得してるって点ですね。
なるほど!そう言われてみるとそうかもしれません。これはちょっと実験してみます。
ループ中に行数が変わるような処理は遭遇したことがないので考えてもみませんでした。
ループの中で行数が増えていく場合、減っていく場合と実験してみます。

>最後に 「好きにして構わんと思う」 とだけ言わせてください。。。
独学なので今まで好きにやってきましたが、ちょっと他の人の意見も聞いてみたくなりまして。
できればいいプログラムをかけるようになりたいので。
色々な意見が聞けて大変参考になりましたので質問してよかったと思っています。

投稿日時 - 2010-01-14 13:20:43

ANo.2

読みやすい
デバッグしやすい
改造しやすい
再利用しやすい
のが前者

パフォーマンス的には大差なし

よって前者を強く支持する

投稿日時 - 2010-01-14 12:37:43

お礼

なるほどです。
たしかに何回もcells(row.count,1).end(xlup).rowの値を使うような場合は、変数を使っておけば変更も楽だしミスが出にくいと思いました。
例えば"本当はcells(row.count,1).end(xlup).rowから-1しなければいけなった!"ってときも1箇所の修正ですみますね。
大変参考になりました。
使い分けずに変数を利用するようにしたほうがいいかもしれませんね。

投稿日時 - 2010-01-14 13:08:09

ANo.1

どちらでも大きな違いは無いと思います。

用意した変数(LastRow)を何箇所でも使う場合は、変数を使ったほうが計算時間の短縮になるでしょうね。

逆に、このForループ1箇所だけで使うなら、行数を減らすために、変数を使わないのも良いでしょうね。
スクロールをせずに一画面で見られる情報(コード)が多いほうが良いですからねぇ。

会社で使う場合は、他の人が見ても解りやすいほうが良いので、その工夫も必要です。
その意味では、LastRowという変数を使ったほうが解りやすいかもしれません。
ただ、解りやすいコメントを書いておけば、LastRowという変数を使わなくても済みますね。

計算時間と、読みやすさを、天秤にかけて、どっちが良いかを判断すると良いでしょうね。

投稿日時 - 2010-01-14 12:28:25

お礼

>用意した変数(LastRow)を何箇所でも使う場合は、変数を使ったほうが計算時間の短縮になるでしょうね。
なるほどです。たしかに毎回計算させるのは効率が悪るそうですね。

>他の人が見ても解りやすいほうが良いので、その工夫も必要です。
>その意味では、LastRowという変数を使ったほうが解りやすいかもしれません。
見やすさの点で私も影響してくると思っていますが、自分としては逆にlastRowとかの変数名じゃなくて
cells(row.count,1).end(xlup).rowとなっていたほうが見やすいかもしれないと思ったりしています。
変数名だった場合、その変数に何が入っているかを追わないといけないですが、変数を使ってなければその場で(for文を見れば)何をやっているかわかると思うので。
でも確かに何回も使う場合は変数を使ったほうがいいと思いましたので、使い分けたいと思います。
ありがとうございました。

投稿日時 - 2010-01-14 12:58:23

あなたにオススメの質問