エクセルVBAで、絶対パスは記述が面倒で、相対パスのほうが使いやすいという方も多いです。
今回はツリー上の全階層絶対パスを変数化できる、VBAの部品化コードです。
こんにちは、じゅんぱ店長(@junpa33)です。
エクセルVBAのコード組み立ての上で、ファイルの存在場所、ディレクトリ指定は非常に重要です。
普通は、汎用性の高い「相対パス」で指定されることが多いのではないでしょうか。
今回は、記述が面倒くさい、融通の利きにくい「絶対パス」を『変数化させよう』という内容です。
コンテンツ
ツリー上の全階層の各パスを変数化したい
エクセルVBAのコード組み立ての中では、
「ファイルを開く」や「ファイルを保存する」などの操作を行わせることも多いです。
その中でいつも必要なのが「どこにあるファイル?」「どこに保存するの?」という指示です。
それを指示しないと、エラーストップしたり、おかしな結果になったりと散々な目に遭うことになります。
その「どこに」に対応するものが「相対パス」や「絶対パス」です。
そして、利便性の高い相対パスを使えば
VBAの入ったエクセルファイルを、どこのフォルダに保存しても、
そのエクセルファイルからの相対パスを参照して、
ディレクトリについてのエラーを回避することが出来ます。
ただ、
幾ら相対パスが、保存場所の自由度が大きいといっても(移動幅が大きければ)、
カレントディレクトリ(エクセルファイルの存在位置)から上の階層に3つとか
下の階層に2つ4つとかとなれば、頭が大混乱でコード組み立てに無理ゲーなことも多くあります。
そこで、
配列変数を使って、予め絶対パスで、ディレクトリツリーで最下層のフォルダまでのパスを指定すれば、
ルートディレクトリからの経路上にある各階層ごとに、そこの階層フォルダの絶対パスをあらかじめ変数化してしまうことが出来ます。
つまり、指定したい階層の絶対パスを、ルートからの長文の記述の代わりに「変数名を記述するだけで処理できる。」ということになります。
利用用途についていえば、
作成しているエクセルVBAプログラムに入れ込む、ひとつのプログラムパーツとしての利用を想定しています。
絶対パスでのディレクトリ指定を行っていますので、
移動利用可能なエクセルVBAプログラムにはどちらかと言えば向いていませんが、
(絶対パスを変数化していますので、その都度の設定作業で対応できますが、)
エクセルVBAプログラムをPCへ導入した後は余り移動させない場合には良いと思います。
ツリー最下層までのフルパス入力で全階層のパスを変数化
アプローチの考え方はいろいろあるかと思います。今回は
絶対パスで各階層を表示する記号「¥」をキーワードにします。
- まず「一文字入力用の配列変数」を使って絶対パスのすべての文字を一文字ずつ代入していきます。
- 配列変数に「¥」記号を代入した時点で、一階層の区切りとします。
- その時までに代入処理をした配列変数の値(文字)を再結合し文字列化します。
- 階層別の絶対パス用の配列変数にこの再結合した文字列を代入します。
- この「絶対パス用の配列変数」を取り出して、ディレクトリ指定に使っていきます。
絶対パス変数化の全コード
Option Explicit
'絶対パスを配列変数化します
Dim AbsPath() As String
Sub 絶対パス取り出し()
Dim OrigPath As String
Dim Fullleng As Long
'絶対パスの一文字ずつ配列変数に代入します
Dim Lett() As String
Dim t, n, s As Long
'インプットボックスで絶対パスを入力します
OrigPath = InputBox("最下層までの絶対パスを入力", _
Title:="絶対パス入力")
If OrigPath = "" Then Exit Sub
'入力した絶対パスの文字列長を取得します
Fullleng = Len(OrigPath)
'配列変数を再定義します
ReDim Lett(1 To Fullleng)
ReDim AbsPath(Fullleng)
n = 0
For t = 1 To Fullleng
'絶対パスの文字を一つずつ配列変数に代入します
Lett(t) = Mid(OrigPath, t, 1)
'「\」記号があった時階層が変わるコードを仕込みます
If Lett(t) = "\" Then
'「\」記号が出た時それまでの文字を再結合します。
'半角スペースが混ざりますので、すべて削除します
'AbsPath(n) = Replace(Join(Lett), " ", "")
AbsPath(n) = Join(Lett, "")
'カウンターnを1つ増やします
n = n + 1
'「\」記号が出た時の回数(t回)をsとして保存します
s = t
End If
Next t
'最下層を別に設定します
AbsPath(n) = AbsPath(n - 1) & Right(OrigPath, Fullleng - s) & "\"
'これで配列変数AbsPathに各層の絶対パスが代入されました
MsgBox "階層は " & n & " 階層になりました"
'---- ここから結果の解説用(使用時には不要) ----
MsgBox "絶対パスを変数化しました" & vbCrLf & _
"第0階層: " & AbsPath(0) & vbCrLf & _
"第1階層: " & AbsPath(1) & vbCrLf & _
"第2階層: " & AbsPath(2) & vbCrLf & _
"第3階層: " & AbsPath(3) & vbCrLf & _
"第4階層: " & AbsPath(4) & vbCrLf & _
"第5階層: " & AbsPath(5) & vbCrLf & _
"第6階層: " & AbsPath(6) & vbCrLf & _
"第7階層: " & AbsPath(7) & vbCrLf & _
"第8階層: " & AbsPath(8)
'---- 実際の使用TEST用(使用時には不要) ----
'---- 「'」シングルクォーテーションを外します----
'Workbooks.Add
'ActiveWorkbook.SaveAs AbsPath(n) & "test.xlsx"
End Sub
コード実行すると・・・
インプットボックスから、階層別に変数化したい絶対パスを入力します。
変数化した階層数をメッセージ表示します。
変数化した各階層の絶対パスはこのようになっています。
絶対パスの変数名はこのようにセットされています
- AbsPath(0) = C:\
- AbsPath(1) = C:\Users\
- AbsPath(2) = C:\Users\Public\
- AbsPath(3) = C:\Users\Public\AAAAA\
- AbsPath(4) = C:\Users\Public\AAAAA\BBBBB\
- AbsPath(5) = C:\Users\Public\AAAAA\BBBBB\CCCCC\
- AbsPath(6) = C:\Users\Public\AAAAA\BBBBB\CCCCC\DDDDD\
- AbsPath(7) = C:\Users\Public\AAAAA\BBBBB\CCCCC\DDDDD\EEEEE\
- AbsPath(8) = C:\Users\Public\AAAAA\BBBBB\CCCCC\DDDDD\EEEEE\FFFFF\
絶対パス変数化コードの活用例
活用時の条件として、本体のプロシージャー(埋め込まれるプロシージャー側)が記述されているモジュールと同じモジュールにこの「絶対パス取り出し」コードが記述されていることが必要です。
本体プロシージャーのあるモジュールの頭に、必ず次のコードを配置します。
Option Explicit
'絶対パスを配列変数化します
'モジュール内で有効な変数設定です
Dim AbsPath() As String
例えば、「利用テスト」プロシージャーにこの「絶対パス取り出し」コードを埋め込んでみます。
エクセルBOOKを「test.xlsx」名で新規作成します。
今回の保存場所は、先ほど設定した第5階層「AbsPath(8)」に保存します。
絶対パスの配列変数を読み込みできなかった時のために、エラー回避のコードを記述しておきます。
Sub 利用テスト()
Call 絶対パス取り出し
Workbooks.Add
On Error Resume Next
ActiveWorkbook.SaveAs AbsPath(5) & "test.xlsx"
End Sub
実行結果は、第5階層の「CCCCC」フォルダの中に「test.xlsx」が作成されています。
「絶対パス取り出し」コード 利用時のカスタムポイント
コード進行上、使い勝手のいいように「絶対パス取り出し」を修正してください。
不要部分は削除したり、修正したり、コメント化したりしてください。
「絶対パス取り出し」コードを動かす度に毎回、インプットボックスに絶対パスを入力しないといけません。
'インプットボックスで絶対パスを入力します
OrigPath = InputBox("最下層までの絶対パスを入力", _
Title:="絶対パス入力")
If OrigPath = "" Then Exit Sub
絶対パス入力の変更がない場合は、直接VBAコードに記述しておくと楽です。
OrigPath = "C:\Users\Public\AAAAA\BBBBB\CCCCC\DDDDD\EEEEE\FFFFF"
Worksheets上に絶対パス入力のセルを準備し、「絶対パス取り出し」コード作動時にそのセルを参照させるようにするコードに改修します。
例えばSheet1のB2セルに絶対パスを記述するとします。
OrigPath = Worksheets("Sheet1").Range("B2").Value
VBAコードの進行をストップするだけの、値を返さないMsgBoxも削除して問題ありません。
MsgBox "階層は " & n & " 階層になりました"
絶対パスの全階層を変数化するVBA まとめ
こういった「絶対パス取り出し」コードなどの汎用性のあるプロシージャーをいくつか準備していれば、
一つのプロジェクトの中で、これらを積み上げていくことが出来ます。
実際上、一度PCにプログラムを入れてしまえば、そうは頻繁にそのプログラムを移動させることもないでしょう。
そういった意味では、VBAコード中で面倒な「パスの指定」も、相対パス中心でなくても絶対パスが簡単に使えればそちらの方がいいということも言えます。
今回は、「パスの指定」にもこういった方法もあるということを説明させていただきました。
エクセルVBAをはじめからしっかり勉強するための方向付けとなる記事を書いています。
エクセルVBAを独習するのに参考書は欠かせません。 参考書選びは自分に合った「相棒」にできるものを選んでいきたいです。
エクセルVBAの独習でおすすめ参考書を7冊選ぶ。良書との出会いは大切です今回の記事はここまでです。 最後までご覧いただき有難うございました。
<記事内容についての告知>
VBAコードの記述記事においては、その記述には細心の注意をしたつもりですが、掲載のVBAコードは動作を保証するものではりません。 あくまでVBAの情報の一例として掲載しています。 掲載のVBAコードのご使用は、自己責任でご判断ください。 万一データ破損等の損害が発生しても当方では責任は負いません。
アンケートでポイ活しよう!!
アンケートに答えれば答えるほど ”使える” ポイントがたまります。