どの言語にも定番のコードというのがあります。Excel-VBAでは
Application.ScreenUpdating = False
などは、皆さん何回も書いていると思います。
はたらきたくないという思いに関しては誰にも負ける気がしない私は、この何回も同じことを書くという行為が嫌で何とかできないかと試行錯誤してきました。対処法として「コードをメモ帳などにストックしておいて、そこからコピペする」や「IMEに単語登録しておいて変換で呼び出す」など、いろいろやり方はありますが、私がたどり着いたひとつの答えがクラスを使って機能を定義しておくという方法です。
手始めに(個人的には)最も使用頻度が多い「ThisWorkbook」をクラスを使っていろいろやります。
クラスモジュールでThisWorkbookを改造する
ThisWorkbookはApplicationオブジェクトが持つプロパティです。現在マクロが実行されているブックをあらわします。
- ThisWorkbook.Save でブックが保存されます。
- ThisWorkbook.Path でブックまでのパスが文字列で取得できます。
このように「今作業しているブック」を示すThisWorkbookは非常に使い勝手がよく、それだけ登場する機会も増えます。
話はそれますが「今作業しているブック」を ActiveWorkbookで「今作業しているシート」をActiveSheetで参照しましょうみたいに説明されていたり、サンプルコードでさらっと使われていたりすることがありますが、このやり方はオススメしません。
あえてユーザーが選択しているブック、シートに対して処理をするからこうしているんだよ、とわかって使っている場合意外はActiveなんちゃらでオブジェクトを指定するのは危険です。
理由をわかりやすく解説しているサイトを以前見たのですがブックマークし忘れました。要は「ユーザーの操作によってその時々で対象が変わる」というのがActiveなんちゃらですよ、つまり、VBAのあずかり知らぬところで操作対象が変更される可能性がある、ということを知っておきましょう。かくいう私もこれで何回も無関係なシートにデータを書き込んでしまったことがあります。
さて、ThisWorkbookですが、オブジェクトブラウザーで確認すると次のようになっています。
正体はWorkbookオブジェクトだというのがわかります。Applicationオブジェクトが現在作業中のブックのWorkbookオブジェクトをこのプロパティへ格納しているということでしょう。先のSaveメソッドもPathプロパティもWorkbookオブジェクトが持っているそれです。
オブジェクトの詳細がわかったところで、クラスモジュールを使って、このThisWorkbookに追加の機能を持たせていきます。
どうやるかというと、いわゆるラッパークラスを作ります。お約束なので言っておきますが、チェケラッチョの方のラッパーではありません。ラッパーはWrapperで包み込むという意味です。ThisWorkbookがクラスに包まれているイメージです。
このクラスにメソッドとして Application.ScreenUpdating = False など汎用的に使う機能を全部突っ込んでしまいます。こうすることで、クラスのメソッドを呼ぶだけで、必要な処理を一度に実行できます。
もう一つラッパークラスの利点があります。ていうか、こちらの方がラッパーにした主たる理由です。
ThisWorkbookを使うということは、作業中のブック自体へ何かしら操作をしたいということに他なりません。よって、重要になってくるのが、ファイルパス、ファイル名といった情報です。これらは標準で備わっているプロパティから取得できるのですが、不満点があります。それがプロパティ名がわかりにくいことです。
次はブックの絶対パスを示すプロパティです。
ThisWorkbook.FullName
えっ?Pathじゃないのって思いません?私は思いました。
現に「Pathってカレントフォルダーのパスまでしか取れないのかよ、めんどくせーなー」と思いながら
ThisWorkbook.Path & “\” & ThisWorkbook.Name
とつなげて絶対パスを作ってました。FullNameの存在は最近知りました。
このように自分が思っている名前とかけ離れたプロパティ名で望みのパラメータが提供されていることがあります。当然、覚えられません。だったら自分の思っている名前に変更してしまえば良いのです。ラッパークラスを使うことでこれが可能です。
こうして必要な機能、条件をリストアップしたら、僕の考えたThisWorkbookあらため
ThisWorkbookExクラスとして定義します。
Private Base_ As Workbook
Private IsSilent_ As Boolean
Property Get FullPath() As String
FullPath = Base.FullName
End Property
Property Get FileName() As String
FileName = Base.Name
End Property
Property Get FileNameNoExtension() As String
FileNameNoExtension = Left(Base.Name, InStrRev(Base.Name, ".") - 1)
End Property
Property Get FileExtension() As String
FileExtension = Right(Base.Name, InStrRev(Base.Name, ".") - 1)
End Property
Property Get CurrentDirPath() As String
CurrentDirPath = Base.Path
End Property
Property Get IsSilent() As Boolean
IsSilent = IsSilent_
End Property
Property Get Base() As Workbook
Set Base = Base_
End Property
Sub Silent()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
IsSilent_ = True
End Sub
Sub UnSilent()
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
IsSilent_ = False
End Sub
Sub Save()
Base.Save
End Sub
Private Sub Class_Initialize()
Set Base_ = ThisWorkbook
End Sub
Private Sub Class_Terminate()
If IsSilent_ Then
Call UnSilent
End If
End Sub
次のように使います。
Sub test()
Dim ThisWorkbookEx As ThisWorkbookEx
Set ThisWorkbookEx = New ThisWorkbookEx
Debug.Print ThisWorkbookEx.FileName
Debug.Print ThisWorkbookEx.FileNameNoExtension
Debug.Print ThisWorkbookEx.FileExtension
Debug.Print ThisWorkbookEx.FullPath
Debug.Print ThisWorkbookEx.CurrentDirPath
Debug.Print ThisWorkbookEx.Base.path
End Sub
C:\expy\test.xlsm にファイルが存在している環境での実行結果は次の通りです。※環境により¥マークがバックスラッシュになります。
test.xlsm
test
xlsm
C:\expy\test.xlsm
C:\expy
C:\expy
解説
ThisWorkbookExクラスはThisWorkbookを内包しています。
コンストラクタ(Class_Initialize)でThisWorkbookを自身のプロパティとして格納します。
Private Sub Class_Initialize()
Set Base_ = ThisWorkbook
End Sub
これによりThisWorkbookEx.BaseプロパティからThisWorkbookが持つすべての機能を利用できます。
ThisWorkbookEx.Base.Path
このコードは以下と同義です。
ThisWorkbook.Path
BaseプロパティからThisWorkbookのプロパティをgetter(Property Get) を経由して返すことで好きな名前でパラメーターを取得したり、加工した後で取得したりできるようにしています。
プロパティは次の通りです。
名称 | 型 | 説明 |
---|---|---|
FullPath | String | 絶対パス |
FileName | String | ファイル名 |
FileNameNoExtension | String | 拡張子なしファイル名 |
FileExtension | String | 拡張子 |
CurrentDirPath | String | カレントフォルダーのパス |
IsSilent | Boolean | サイレントモードのフラグ |
Base | Workbook | ThisWorkbookへの参照 |
メソッドとして
- 画面更新の停止
- 再計算の停止
- 確認ダイアログの抑止
のVBA実行前の3点セットを全部設定するSilentを実装しています。Silentメソッドによって各種抑止が有効になっているかどうかをIsSilentプロパティとして保持します。
Sub Silent()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
IsSilent_ = True
End Sub
Sub UnSilent()
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
IsSilent_ = False
End Sub
Private Sub Class_Terminate()
If IsSilent_ Then
Call UnSilent
End If
End Sub
SilentメソッドでFalseへ変更されたApplicationのプロパティはThisWorkbookExクラスのインスタンスが破棄されるときにデストラクタ(Class_Terminate)によってTrueに戻されます。よって通常はプロシージャを抜けるとTrueが設定されます。またUnSilentメソッドにより明示的にTrueを設定することもできます。
Sub test1()
Dim wbex As ThisWorkbookEx
Set wbex = New ThisWorkbookEx
wbex.Silent
wbex.Base.Worksheets(1).Delete
End Sub
Sub test2()
ThisWorkbook.Worksheets(1).Delete
End Sub
このコードでは、test1プロシージャでは警告なくシートが削除されます。続けて実行したtest2プロシージャでは削除前に警告ダイアログが表示されます。
Saveメソッドはそのまま、BaseのSaveメソッドをコールしているだけです。ブックの上書き保存が実行されます。よく使うので入れときました。
使用方法
1.このページ下部のボタンでzipファイルをダウンロードして展開します。クラスファイルが入っています。
2.VBEにクラスファイルをドラッグ&ドロップします。
クラスモジュールにThisWorkbookExクラスが追加されます。
3.プロシージャでクラスをインスタンス化してご利用ください。
ダウンロード
プロパティ名の変更や、メソッドを追加して自分の使いやすいようにどんどん改造しましょう。ただしあまり具象的な処理を入れないようにしてください。具象化すればするほど、そのファイルでは便利になりますが他のファイルへ使えなくなります。
おわり。