プロが教える店舗&オフィスのセキュリティ対策術

等しく「長いコーディング箇所」が何度も繰り返される場合のテクニック?!

例えば、
If var = 1 Then
  Range(color_position).Interior.ColorIndex = const_color_1
Elseif var = 2 Then
  Range(color_position).Interior.ColorIndex = const_color_2
Elseif var = 3 Then
  Range(color_position).Interior.ColorIndex = const_color_3
    :
    :
Elseif var = 20 Then
  Range(color_position).Interior.ColorIndex = const_color_20
End IF

なんて場合、
「Range(color_position).Interior.ColorIndex」の箇所が、何度も繰り返されるわけです。

そういう箇所が、至るところにある場合、ファイルサイズが大きくなり、
色々とデメリットがあるような気がしています。
(単純にファイルサイズが無駄に大きい、ファイルの保存に時間がかかる、などのデメリット。場合によっては、処理速度にも悪影響を及ぼす?!)

そこで、
Dim set_color As Object
Set set_color = Range(color_position).Interior.ColorIndex

のようにすれば(Withを使っても良いですが)、前述のコード例は、

If var = 1 Then
  set_color = const_color_1
Elseif var = 2 Then
  set_color = const_color_2
Elseif var = 3 Then
  set_color = const_color_3
    :
    :
Elseif var = 20 Then
  set_color = const_color_20
End IF

こんなにスッキリ♪
となりますが、こういう考え方で作業をするのは、
実際、価値があると言えますでしょうか?
むしろ、デメリットであったりするのでしょうか?
アドバイスを宜しくお願い致します。

A 回答 (4件)

あるセルの色を設定しているのですね。


こういう場合は Select Case を使う方がスマートですね
あと何度も使うなら関数にするとよいです。

Sub Color_Set(rng As Range, var As Integer)

 With rng.Interior
  Select Case var
   Case 1:
    .ColorIndex = const_color_1
   Case 2:
    .ColorIndex = const_color_2
       略
   Case 20:
    .ColorIndex = const_color_20
  End Select
 End With
End Sub

呼び出す部分はこうなります
Color_Set(Range(color_position), var)


また、1~20など続き番号なら配列変数を使うともっと簡略化できます。

Dim Color_data(1 To 20)

Color_data(1) = const_color_1
Color_data(2) = const_color_2
       略
Color_data(20) = const_color_20


こういう風に配列変数を初期化しておけば

Range(color_position).Interior.ColorIndex = Color_data(var)

これだけで済みます。
実際に動かした訳ではないので何かエラーが出たらすみません。
    • good
    • 0
この回答へのお礼

If文よりかは、Select Case文、または、配列変数を使った方法、
の方がスマート、さらに、関数化しておくと、使い回しに便利、
というお話でした。
ありがとうございます。
「コードの長さ」と「見た目のシンプルさ」で考えると、
配列の方法が良さそうに思えましたが、Select文に比べ、メモリ確保負担が高いと言えますでしょうか。
(気にするほどの差ではないのかもしれませんが。)

改善案をご提示頂き、ありがとうございます。
参考にさせて頂きます。

お礼日時:2010/05/25 08:14

複雑なら、IF 分岐でなく、Select Case を使うのですが、ただ、こういう場合は、私は、Select Case も使いません。



>Range(color_position).Interior.ColorIndex = const_color_1

この前の話ですと、Const は、Single 型だったはずですが、今回は、Long型ですね。Excel の場合に、Interior の色の表現力が低いので、果たして、20をフルに使えるかは分かりませんが、それはともかくとして、そういう場合、私は、配列変数を使います。凝った使い方なら、列挙型を使うと思います。

例えば、このようなスタイルになりますね。

Const COLORS As String = "1,3,4,5,6,7,8,9,10,11,12,13,14,15,16"
Public arColor() As Long

Sub Auto_Open()
Dim buf As Variant
Dim i As Long
 buf = Split(COLORS, ",")
 ReDim Preserve arColor(UBound(buf))
 For i = LBound(buf) To UBound(buf)
  arColor(i) = CLng(buf(i))
 Next
End Sub

Sub Test2()
Dim v As Integer
Const C_POS As String = "A1:A5" '普通はこのような書き方をしない、Rangeオブジェクトを取る
v = 3
If v > 0 And v < UBound(arColor)+2 Then
  Range(C_POS).Interior.ColorIndex = arColor(v-1)
End If
End Sub

(v-1) というスタイルは、配列を1を初期値にしないからですが、VBAは、こうした配列は、初期値を1からにする人が多いようです。私自身は、それをやっていると他の言語と共有性がなくなるのでしないだけです。

なお、VBAでは、color_position と「_(アンダーバー)」でつないだりすることは、ほとんどありません。倒産した、九天社の書籍のライターのコードには、そういう書き方をしていましたが、たぶん、違う分野のプログラマのようです。逆に、コンパイル型では、VBAの省略形はあまり好まれないのですが、経験的に、長い変数名などは、使わないようです。

なお、書法は、Excel大事典(下記URL)に出ていますが、若干、今風のではない書き方があります。Prefix は必要以上に乱用しないこととか、そのページで書かれている、型宣言文字は、リテラル値以外では間違いです。

それと、
>ファイルサイズが大きくなり、色々とデメリットがあるような気がしています。
>(単純にファイルサイズが無駄に大きい、ファイルの保存に時間がかかる、などのデメリット。場合によっては、処理速度にも悪影響を及ぼす?!)

根本的な設計の問題以外で、あまりチューンしようとしても、同じ方式では、変数だとか定数とか、どのように方針を取っても、1秒・2秒の差を縮める程度にしか過ぎないと思います。少し、こだわりすぎのような気がします。別に、私のような配列変数にする必要もないですが、今の状態で、あまりスタイル自体に迷いが多すぎると、コーディング途中で頓挫してしてしまいます。何年かしていれば、いずれスタイルは決まってくるはずです。実務経験がないのか、一部の掲示板回答者のように、スタイルを持たない、VBAヘルプ以下のまったくの素のままのコードを書くのも問題でしょうけれども……。

参考URL:http://home.att.ne.jp/zeta/gen/excel/c04p15.htm
    • good
    • 0
この回答へのお礼

前回に引き続き、今回もありがとうございます。
毎回、質問本題以外の所でも鋭い指摘をして頂き、大変興味深く読ませて頂いております。
特に、今回は勉強になりました。

>私自身は、それをやっていると他の言語と共有性がなくなるのでしない

私も同感です。

>VBAでは、color_position と「_(アンダーバー)」でつないだりすることは、ほとんどありません。

PHP使用時に、これをやってまして、その習慣でVBAでも使っていますが、
VBAでは、やめた方が良いでしょうか。笑

>根本的な設計の問題以外で、あまりチューンしようとしても、同じ方式では、変数だとか定数とか、どのように方針を取っても、1秒・2秒の差を縮める程度にしか過ぎないと思います

なるほど、その程度の節約にしかならない話を私はしているわけですね。
ご指摘、助かります。
参考URLもじっくり読ませて頂きます。

また、コード例は、
私にはまだ少し難しいものでしたが、
こちらからも色々と学ばせて頂こうと思っています。

配列を使う方法でも、
こんな方法もあるんですね。

Const COLORS As String = "1,3,4,5,6,7,8,9,10,11,12,13,14,15,16"
buf = Split(COLORS, ",")

このあたりに光るモノを感じました。
ありがとうございます、またよろしくお願い致します。

お礼日時:2010/05/25 08:30

皆さん、サンプルに対しての改善例の話ばかりですが、本題を


「同じオブジェクトが繰り返し出てくる場合に、変数にセットしたりwithを使ったりすることのメリットは?」だとすると、

あります。

サンプルだと、どれか1つの分岐しか実行されないので、速度的なメリットはありません。プログラムファイルサイズが多少小さくなるけど誤差以下でしょう。
そのオブジェクトが複数回使われるのであれば多少の速度向上がありますが、これもそれを何万回も繰り返すのでない限り、誤差の範囲。

メリットが大きいのはプログラムを読むときです。
・全く同じ表記が何度も出てくる
・全く同じような表記が何度も出てくるが、実は一カ所だけ違っている
この2つは、ぱっと見では区別できません。注意深く見比べて「全部同じ表記だ」と判別しなくてはなりません。変数にセットしたりwithを使ったりすれば、見比べるのが楽になります。関数化するのも一つの方法ですね。
    • good
    • 0
この回答へのお礼

>本題を
>「 ~略~ のメリットは?」だとすると、
>あります

質問に対する直球回答を頂きました。ありがとうございます。
知りたかった本題を思い出しながら、読ませて頂きました。

>プログラムファイルサイズが多少小さくなるけど誤差以下
>これもそれを何万回も繰り返すのでない限り、誤差の範囲

まさに聞きたかったことです。はい。

>変数にセットしたりwithを使ったりすれば、見比べるのが楽になります。関数化するのも一つの方法

こちらのメリット、なるほどなと思いました。
機械にとって早いコードかどうか、という視点とは別に、
人間にとって早く、また、容易に保守できるかどうか、という視点も確かに重要ですよね。
大変勉強になりました、参考にさせて頂きます。

お礼日時:2010/05/25 09:07

変数が1から20の順番になっている時は配列を使用した方が良いと思う。



【例】
 color = Array(const_color_1, const_color_2, const_color_3, … ,const_color_20)
 Range(color_position).Interior.ColorIndex = color(var - 1)

メリットとしては
1.処理が早い(この程度ならあまり変わらないですが)
2.拡張性がある(21以上が増えても追加が楽)
3.プログラムステップ数が減る。

※特に2.3.はコーディング量が減り、テスト時間を減らすことができる。
 人間が関わる作業量を減らすことにより、バグ(人為ミス)が減ることが最大のメリットだと思う。
    • good
    • 0
この回答へのお礼

挙げて頂いた3つのメリットは、とても参考になりました。
特に3番目が気になりました。

プログラムステップとは、If文やSelect文を通過する際に行われる条件判断のことを指すのですよね?
私はそう解釈しましたが、間違っていたらすみません。

>人間が関わる作業量を減らすことにより、バグ(人為ミス)が減ることが最大のメリット

プログラムを組む際には、機械に優しいコードを、と私などは考えがちでしたが、
コードの保守管理をする人間に対する配慮も同じくらいに大事なんだなと、
本質問を通して痛感しました。

簡潔明瞭な回答をありがとうございます。

お礼日時:2010/05/26 02:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!