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

VBAの定数の使い方で、計算値を定数に入れることは可能ですか。

例えば、モジュール先頭に、

Option Explicit

Const TEISU_COUNT As Integer = Application.WorksheetFunction.CountA(Range("A1:IV1"))

と書き、その下に、

Sub TestTeisu()

  MsgBox TEISU_COUNT

  '↑定数式が必要です、のようなエラーが出ます。なぜでしょう?
  'エラー時、「.CountA」にスポットがあたります。
  'つまり、ここがダメということでしょうか?やはり、この点が動的だからでしょうか?

End Sub

と書いて、実行。
結果は、上述の通り、エラーとなります。

やはり、定数値には、固定的な数値(上記例では、Integer)や文字列を入れるべきなのでしょうか。

定数に入れることのできる値の注意事項について、
どなたかアドバイスして頂けますでしょうか。
宜しくお願い致します。

A 回答 (4件)

#2の回答者です。



本当は、変数と定数の区別のつかない段階で、混乱するので、余計な話は聞かないで進めていったほうがよいのですが、一応、お答えしておきます。

定数は、変動したり値やプロパティを取得するものには使えません。だから、本来、比較のしようがありません。

グローバル変数のメリットとしては、一定の環境で、再取得することなく使えることです。主に、Auto_Open で取得して、最後まで使うことが多いです。グローバルにしておけば、他のプロシージャにでも、使えます。再取得する必要がないので、当然、処理スピードは上がります。

メモリについては、このレベルでは気にするほどのものはありません。String 型ですと、文字数に比例しますが、数値型は、仮にLong 型でも、4 Byte しかありません。Integer型は、2 Byte ですが、事実上、32ビットパソコンでは、4 Byte =32ビット分を使用します。メモリについては心配はほぼないと思います。処理速度の違いですが、定数と変数の違い自体は比べようもありませんが、再取得は別として、変数が100個も使うならともかく、その差は検知できないはずです。

グローバル変数のデメリットは、実は、マクロ稼働中にエラーが発生して、グローバル変数の内容がなくなってしまう、という問題があります。そうすると、以下のようなチェックコードが必要になるということがあります。

If g_Count =0 Then
 Call RowCount
End If

'//
Public g_Count As Integer

Public Function RowCount()
 g_Count = Application.WorksheetFunction.CountA(Range("A1:IV1"))
End Function

普通は、こんなことは気にしなくてよいのですが、複雑な内容のマクロですと、必要になることがあります。また、なるべく、変数の名称は、プロシージャ内の変数とは区別がつくようにしてやることがコツです。こういうマクロは、1~2年レベルの経験では使わないと思います。

>ある固定的な値を入れる容器として、
>定数を使った場合でも、
>また、グローバル変数を使った場合でも動く

具体的な状況が思い浮かびません。どちらでも動くから、定数を使うというものでもないように思います。
前回も書いたように、消費税や数式の係数に対して用いるというのが、基本です。
    • good
    • 0
この回答へのお礼

詳細な補足をありがとうございます。

定数とグローバル変数は、同じ土俵で比べられるものではないようですね。
用途が似ているようで似ていない、全くフィールドの異なる概念であるように思いました。

よって、両者のどちらを使うかで迷う、ということはない、ということなのでしょうね。

>具体的な状況が思い浮かびません。

苦し紛れに、具体的な状況を挙げさせて頂くと、
たとえば、

>グローバル変数のメリットとしては、一定の環境で、再取得することなく使えること

とありましたが、
定数では、またげないスコープに対し、オールラウンドに、ある特定の値を使い回したい場合、
各スコープで、毎回、定数宣言をするよりかは、
どこか1箇所でグローバル変数宣言をして、その特定の値を使うようにしたほうが、
「その特定の値 に種類が50ほどある場合」なんかには、
コードが短くなり、メリットがあるのかなぁ、なんて思いましたが、いかがでしょう?

その場合、

Public Sub Global_Var_Dim()
  Public global_var01 as Single = 0.05
  Public global_var02 as Single = 1.05
  Public global_var03 as Single = 3.14
    :
    :
  Public global_var48 as Single = 1.41421356
  Public global_var49 as Single = 2.71828
  Public global_var50 as Single = 1.7320568
End Sub

こんなプロシージャを、どこか1箇所で実行するようにします。

一方、上記を定数で処理するとなると、
50個の特定の値を、各スコープで毎回、宣言することになりますよね。
これを私は冗長と考えたわけですが、何か見落としなどはありますでしょうか。


まだVBA初心者であるため、文法的に変なことを言っているかもしれません。
考え方の大枠として、こんなことはできないだろうか~?といった話として、
解釈頂けると助かります。

もしまたよろしければ教えて下さい。

お礼日時:2010/05/22 23:37

>定数では、またげないスコープに対し、オールラウンドに、ある特定の値を使い回したい場合、


>上記を定数で処理するとなると、50個の特定の値を、各スコープで毎回、宣言することになりますよね。

定数も変数も、基本的にはスコープは同じです。またげないということはありませんが、そこまでのレベルが必要になるというのは、入門の方からすれば、遥か彼方のテクニックだと思います。

Public global_Var(49) As Single '注:VBAでは、Single 型は慣例的にDouble型にすることが多い
'私は、こういう場合は配列に確保します。
Private Sub Global_Var_Dim()
  global_var(0) = 0.05
  global_var(1) = 1.05
  global_var(2) = 3.14
  ・
  ・
  ・
  ・
  ・
End Sub

または、Long型の場合は、列挙型にすることが多いです。

しかし、実際問題として、あまり、公にしていないのですが、プロの作ったものは、この場合、アドイン(.xla)にして、シートにデータを置き、そこから取り出す書かたをする人が多いようです。秘匿性がないので、あまり格好良くないのですが、決め打ちでやってみると、取り出すことが可能です。Excel VBAというものは、そういうものだとするしかありません。それ以外の方法(暗号化)もあるようですが、私自身、それ以上のことはしたことがありません。そこまで必要とされないからです。
    • good
    • 0
この回答へのお礼

さらなる補足をありがとうございます。

>定数も変数も、基本的にはスコープは同じです。

あらら、では、私の挙げた例は適切ではありませんでしたね。苦笑
しかし、おかげさまで、
定数とグローバル変数の使い分けが少し分かったように思います。
ありがとうございます。

>シートにデータを置き、そこから取り出す書かたをする人が多いようです。

そういうテクニックもあるわけですね。

>'注:VBAでは、Single 型は慣例的にDouble型にすることが多い
>'私は、こういう場合は配列に確保します。

こちらも、勉強になりました。
メモリのことを気にして、できる限り、Doubleは使わずにSingleで確実に大丈夫な所はSingleで、
なんて私は考えていましたが、業界の慣例ではDoubleにすることが多いのですか~、始めて知りました。

それでは、定数をドッサリ使って、作業を再開したいと思います。
終始、丁寧に回答下さり、ありがとうございました。

お礼日時:2010/05/23 13:53

元のコードからすれば、以下のようにするのが自然だと思います。



'//
Option Explicit
Public g_Count As Integer '←Global 変数の場合は、標準モジュールに置きます。
'モジュールレベルなら、Private m_Count As Integer

Sub TestMacro1() '←Global変数を使っている場合は、同じモジュールでなくても可能
  g_Count = Application.WorksheetFunction.CountA(Range("A1:IV1"))
 MsgBox g_Count
End Sub


定数というのは、固定値ですから、変動しないことが条件です。
例えば、消費税として、Const RATE As Double = 0.05 など、定数(Constant)を使います。ワークシートの変動する条件の値を取る場合は、変数(Variable)です。
    • good
    • 0
この回答へのお礼

.CountAなどを用いて計算した値を使い回す際に使用する「データの入れ物」は、
定数ではなくグローバル変数が良さそうですね。

当初、私は、例えば、消費税のような定数で良いようなものまで、
グローバル変数に入れて、固定的なグローバル変数というような扱いで、
まるで定数のように使っていたのですが、
「定数」そのものの存在を、ごく最近知りましたので、
定数にできるものは全て定数にしてしまおうと考え、
今回のような疑問にぶち当たりました。

定数で問題ないものを、仮にグローバル変数に入れて使う場合に考えられるメリット、デメリットがあれば、
教えて頂けると嬉しいです。
(どなたでも結構ですので、心当たりのある方、お願い致します。)

定数の場合、コード中に値が変更されてしまわない、
というメリットがあるように思いますが、それを踏まえた上で、
ここで私が知りたいメリットとは、具体的には、「処理速度」の面のメリットです。
メモリの食い、なども気になります。

ある固定的な値を入れる容器として、
定数を使った場合でも、
また、グローバル変数を使った場合でも動く
という場合には、

やはり、グローバル変数ではなく、定数の方を使うべきなのでしょうか。

変なことを質問しているとは思いますが、
もしまた機会がございましたら、教えて下さい。

お礼日時:2010/05/22 20:30

>やはり、定数値には、固定的な数値(上記例では、Integer)や文字列を入れるべきなのでしょうか。



その通りです。

使えるのは、リテラル値、その他の定数、Isを除く算術演算子や論理演算子を組み合わせた式です。


シート関数の利用はもちろんシート内容も参照することはできませんし、VBAの関数も使うことはできません。

たとえば、

Const a As Single = 5.5 * 3
Sub Test()
MsgBox Int(a)
End Sub

は大丈夫ですが、

Const a As Single = Int(5.5 * 3)
Sub Test()
MsgBox a
End Sub

はだめです。
    • good
    • 1
この回答へのお礼

大変わかりやすい回答をありがとうございます。

>使えるのは、リテラル値、その他の定数、Isを除く算術演算子や論理演算子を組み合わせた式

上記に気をつけて、定数宣言をしていこうと思います。
分かりやすい具体例もありがとうございました。

お礼日時:2010/05/22 17:31

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

このQ&Aを見た人はこんなQ&Aも見ています