質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.06%

定数として使っていたものを、同効果の変数に変更したい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 643

kujiraSE

score 6

前提

エクセルVBAで作成した入出庫管理システムがあります。

集計表出力先フォルダのパスや駐車スペース数などの、システム(ファイル)起動時からずっと不変の設定値15個ほどを、定数の宣言と初期化のために作ったモジュールにPublic Const として定数で書いてあります。

Public Const syutsuryokuPath = "C:\xxx"
Public Const carSpace = 5

このシステムを別の倉庫でも使うことになりました。
別の倉庫では定数に設定したい値が違うのですが、できれば、別倉庫用に定数部分の値を書き換えた別ファイル(.xlsm)を作成するのではなく、同じファイルをコピーして使用することで、使用倉庫の増加での混乱を避け将来的な改修もスムーズになるようにしたいのです。

定数は、倉庫IDだけ 

Public Const SoukoID = 1


のように、ひとつだけにして、各倉庫に配布する際にこのIDだけ書き直せばよいだけにしておいて、

Select Case SoukoID 
  Case 1
      syutsuryokuPath = "C:\xxx"
      carSpace = 5
  Case 2
      syutsuryokuPath = "C:\xxx\abc"
      carSpace = 10
  Case 3
      syutsuryokuPath = "Z:\"
      carSpace = 3

のように、これまで定数で設定していた各価を使用する倉庫ごとにすべて書いておけば楽なのではないか、と思っています。

実現したいこと

・Case文で値を設定(初期化)する形にしたい
・これまで定数で設定していたのと同じく、その値はどのモジュールのどのプロシージャからも使用できるようにしたい
・また、その値はシステム起動(当xlsmファイルを開く)直後から終了まで不変のまま使用できるようにしたい

この条件を満たす最適な方法が知りたいです。

定数のように値を持ちたいけれど、初期化するときだけ条件分岐でやりたい」というのは、それほどめずらしくない希望だと思うのですが、一般的にはどういう方法が採られているのか知りたいです。

私の最初のアイデアは、

  '第 1倉庫用
      Public Const syutsuryokuPath = "C:\xxx"
      Public Const carSpace = 5
  '第 2倉庫用
      Public Const syutsuryokuPath = "C:\xxx\abc"
      Public Const carSpace = 10
  '第 3倉庫用
      Public Const syutsuryokuPath = "Z:\"
      Public Const carSpace = 3


と書いておき、配布する際に別倉庫の部分をコメントアウトする、という方法です。
しかし、もっとスマートで一般的な方法があるかと思います。

よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

Functionにするとかでもいいかな。
標準モジュールに下記のように記述します。

Option Explicit
Public Const SoukoID = 3

Public Function syutsuryokuPath() As String
    Dim aryPath
    aryPath = Array("C:\xxx", "C:\xxx\abc", "Z:\")

    syutsuryokuPath = aryPath(SoukoID - 1)
End Function

Public Function carSpace() As Long
    Dim arySpace
    arySpace = Array(5, 10, 3)

    carSpace = arySpace(SoukoID - 1)
End Function

使用例

Public Sub Test()
    MsgBox "集計表出力先フォルダは、'" & syutsuryokuPath & "'" & vbCrLf & _
           "駐車スペース数は、" & carSpace
End Sub

変数と同じように使えます。

メリットとしては、記述場所が標準モジュール1か所ですむということです。

補足

標準モジュールのグローバル変数は、ブックが開いている間でも消える時があるらしい。

たとえば、
Excel VBA を学ぶなら moug モーグ | 即効テクニック | モジュールレベル変数の値が消えるとき

ExcelのVBA。public変数の値が消える -VBAについて。Excelの2003や2007- Visual Basic(VBA) | 教えて!goo

excel/vba/public変数 -excel VBAで下記のようなコードを書きました。- その他(Microsoft Office) | 教えて!goo

MSの昔の公式ドキュメント(現在は削除されて見れないので、WEBアーカイブに残されたものです。)
[VBA] Public 宣言された変数の有効期間

このなかに、下記のような文言があります。

Public 変数がアプリケーション終了時まで有効であることを期待する VBA マクロの実装は、推奨されません。

削除されたドキュメントなので現在は改善されているかも知れませんが。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/10 10:37

    ご回答ありがとうございました。
    まさか、Publicで初期化した変数が信用できないとは考えたこともありませんでした。
    functionにすれば、その都度値を取得するので「ちゃんと保持し続けていてくれるかな」と心配する必要がなくなるということですね。
    勉強になりました。ありがとうございました。

    キャンセル

+2

あなたのリクエスト通りにするとなると以下のようになります。
1.標準モジュールに以下のマクロを追加します。

Option Explicit

Public Const SoukoID = 3
Public syutsuryokuPath  As String
Public carSpace   As Long

2.ThisWorkBookに以下のマクロを追加します。

Option Explicit

Private Sub Workbook_Open()
    Select Case SoukoID
    Case 1
        syutsuryokuPath = "C:\xxx"
        carSpace = 5
    Case 2
        syutsuryokuPath = "C:\xxx\abc"
        carSpace = 10
    Case 3
        syutsuryokuPath = "Z:\"
        carSpace = 3
    End Select
End Sub


これで、このマクロが登録されたブックをオープンすると、
Public Const SoukoID = 3 が適用された状態になります。
syutsuryokuPath は "Z:\" が設定されています。
carSpace は 3 が設定されています。

標準モジュール
ThisworkBook

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/10 10:31

    ご回答ありがとうございました。
    画像までご用意いただき、丁寧に教えていただけたことにとても感謝しております。

    キャンセル

+1

私が作るなら

  • syutsuryokuPathとcarSpaceを変数化する
  • 設定用のシートを作っておき、初期化時にセルから値を読み込む。

と作ります。で、ファイルによってセルへの入力値を変えます。
こうしておけばVBAを書き換える必要がなくなります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/10 10:31

    ご回答ありがとうございました。
    その方法は私も考えていました。同じことを考える人がいるのを知っただけでも安心です。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る