9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

VBAでは、デストラクタを活用しよう

Last updated at Posted at 2019-03-16

VBAとデストラクタ

VBA (Visual Basic for applications)は、多くの現場でインストール済みの開発環境というのが魅力ですが、なにぶん20世紀の言語なだけに使いづらいところも多いです。
そのうちの一つとして、例外処理があります。
try catch どころか finally がないことに苦心します。

そんな VBA ですが、オブジェクト指向が流行り始めた時期に乗ってクラスがあり、そこにデストラクタがあることに救いがあります。
Sub Class_Terminate がそれですね。
また VBA は、参照カウント方式でこれを呼び出す仕様となっています。
つまり、デストラクタを呼び出すタイミングをプログラマが制御できるわけです。

Application のプロパティでの例

ごたくを並べすぎました。
つまり、「この処理をしたら、それに対応する処理を終了するまでにしておく」ということをこれで実装できるわけです。
具体的には、Application のプロパティの一時変更などに向いています。

まずは、Application.Cursor と Application.Calculation を実例にあげて見ていきましょう。

ApplicationTemporaryMode
Private mResumeCalculation As Boolean
Private mOrgValCalculation As XlCalculation

Private mResumeCursor As Boolean
Private mOrgValCursor As XlMousePointer

Public Property Let TemporaryCalculation(ByVal NewVal As XlCalculation)
    If Not mResumeCalculation Then
        mOrgValCalculation = Application.Calculation
    End If
    mResumeCalculation = True
    Application.Calculation = NewVal
End Property

Public Property Let TemporaryCursor(ByVal NewVal As XlMousePointer)
    If Not mResumeCursor Then
        mOrgValCursor = Application.Cursor
    End If
    mResumeCursor = True
    Application.Cursor = NewVal
End Property

Private Sub Class_Initialize()
    mResumeCalculation = False
    mResumeCursor = False
End Sub

Private Sub Class_Terminate()
    Call ResumeAll
End Sub

Private Sub ResumeAll()
    If mResumeCalculation Then
        Application.Calculation = mOrgValCalculation
    End If
    If mResumeCursor Then
        Application.Cursor = mOrgValCursor
    End If
End Sub

プロパティを初めて変えた時だけ変更前の値のバックアップを取っておいて、デストラクタでその値に戻すわけです。

プロシージャ単位で使うなら冒頭で宣言すればあとは何も書かなくてもそのプロシージャの終了時に戻してくれます。

ThroughProcedure
Sub SampleProc
    Dim AppTempMode As New ApplicationTemporaryMode
    AppTempMode.TemporaryCursor = xlWait
    
    '(一時変更している間に実行する処理)
End Sub

プロシージャの途中での一時利用なら、With New でも使えば手軽です。

InnerProcedure
    With New ApplicationTemporaryMode
        .TemporaryCursor = xlWait
        .TemporaryCalculation = xlCalculationManual
        
        '(一時変更している間に実行する処理)
    End With 

プロパティをいくつ変更しようが、End With一つで戻りますからね。

応用範囲

これでうれしいのは、エラーで中断しようがExit Subしようが、このブロックを抜けたときに必ず実行されるということです。
そういう対応漏れは、自他ともによく見かけますからね。

ここでは

  • Application.Cursor
  • Application.Calculation
    だけを取り上げましたが、Applicationのプロパティだけでも他に
  • Application.DisplayAlerts
  • Application.ScreenUpdating
  • Application.Visible
    など、一時変更したいプロパティは色々あるので、割とよく使えるのではないでしょうか。
    一時変更するものとしては他に
  • Application.Selection
  • ブックの一時的なオープン
    などもありますが、これらはもう少し面倒なことがあるので、また別の機会に。
9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?