2017年10月10日

【Access】エラーログ処理をクラス化する


以前、エラーログ出力の方法を書きましたが、こういうログ処理というのはクラスにまとめてしまうと使い勝手がよくなります。

LogClass

今回、VBEでクラスモジュールを追加し、名前をLogClassとしました。

プロパティでログファイルの最大サイズやローテーション世代数を設定出来るようにしています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
'定数
Private Const MAX_FILE_SIZE As Long = 4096            'ログファイルサイズ(KB)
Private Const LOG_FILE_NAME As String = "error"       'ログファイル名
Private Const LOG_FILE_EXT As String = "log"          '拡張子名
Private Const LOG_FOLDER As String = "Log"            'フォルダ名
Private Const ROTATE_NUM As Integer = 3               'ログローテーション世代数
 
'メンバ変数
Private mMaxFileSize As Long                            '最大ログファイルサイズ(KB)
Private mLogFileName As String                          'ログファイル名
Private mLogFileExt  As String                          '拡張子名
Private mLogFolderName As String                        'ログフォルダ名
Private mLogRotateNum As Integer                        'ログローテーション世代数
 
'Win32API
Private Declare Sub GetLocalTime Lib "kernel32" (lpSystem As SYSTEMTIME)
 
'構造体
Private Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek  As Integer
    wDay  As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type
 
'プロパティ
Public Property Let MaxFileSize(ByVal Value As Long)
    mMaxFileSize = Value
End Property
 
Public Property Let LogFileName(ByVal Value As String)
    mLogFileName = Value
End Property
 
Public Property Let LogFileExt(ByVal Value As String)
    mLogFileExt = Value
End Property
 
Public Property Let LogFolderName(ByVal Value As String)
    mLogFolderName = Value
End Property
 
Public Property Let LogRotateNum(ByVal Value As Integer)
    mLogRotateNum = Value
End Property
 
'クラス初期化処理
Private Sub Class_Initialize()
 
    'デフォルト値を設定
    mMaxFileSize = MAX_FILE_SIZE
    mLogFileName = LOG_FILE_NAME
    mLogFileExt = LOG_FILE_EXT
    mLogFolderName = LOG_FOLDER
    mLogRotateNum = ROTATE_NUM
 
End Sub
 
'エラーログ作成
Public Sub MakeErrorLog(ByRef errObj As ErrObject, _
                        ByVal procName As String)
 
    Dim errNumber        As Long
    Dim errDescription   As String
    Dim messageLog       As String
     
    'エラー情報を保管
    errNumber = errObj.Number
    errDescription = errObj.Description
     
    'エラーを消去
    errObj.Clear
     
    messageLog = "【エラー番号】" & errNumber & _
              " 【詳細】" & errDescription & _
              " 【発生場所】" & procName
     
    '書き込み
    Call WriteLog(messageLog)
     
    'メッセージボックス表示
    MsgBox errNumber & Space(2) & errDescription, vbCritical, "エラー"
 
End Sub
 
'ログ出力
Private Sub WriteLog(ByVal message As String)
On Error GoTo ErrorTrap
 
    Dim ts, fso         As FileSystemObject
    Dim projectPath     As String
    Dim logFolder       As String
    Dim logFile         As String
    Dim LogFileName     As String
    Dim sysLocalTime    As SYSTEMTIME
     
     
    '現在時刻を取得
    GetLocalTime sysLocalTime
     
    'ログファイル名
    LogFileName = "error.log"
     
    'プロジェクトパスを取得
    projectPath = CurrentProject.Path
     
    'ログ格納フォルダ
    logFolder = projectPath & "\" & mLogFolderName
     
    'FileSystemObjectオブジェクトを作成する
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    'ログ格納フォルダの確認(なければ作成)
    If fso.FolderExists(logFolder) = False Then
        'フォルダを作成する
        Call fso.CreateFolder(logFolder)
    End If
     
    'ログファイルフルパス名
    logFile = logFolder & "\" & LogFileName
     
    'ログローテート
    Call LogRotate(logFile)
     
    'ファイルオープン
    Set ts = fso.OpenTextFile(logFile, ForAppending, True)
 
    '書き込み
    Call ts.WriteLine("[" & sysLocalTime.wYear & "/" & _
                        Format(sysLocalTime.wMonth, "00") & "/" & _
                        Format(sysLocalTime.wDay, "00") & " " & _
                        Format(sysLocalTime.wHour, "00") & ":" & _
                        Format(sysLocalTime.wMinute, "00") & ":" & _
                        Format(sysLocalTime.wSecond, "00") & "." & _
                        Format(sysLocalTime.wMilliseconds, "000") & "] " & message)
                       
    'ファイルクローズ
    ts.Close
     
    Set ts = Nothing
    Set fso = Nothing
     
Exit Sub
ErrorTrap:
    MsgBox Err.Number & Space(2) & Err.Description, vbCritical, "エラー"
End Sub
 
'ログローテート
Private Sub LogRotate(ByVal fileName As String)
On Error GoTo Err_Trap
 
    Dim fso        As FileSystemObject
    Dim i          As Integer
    Dim r          As Integer
    Dim folderPath As String
    Dim srcFile    As String
    Dim destFile   As String
    Dim oldestFile As String
    Dim checkFile  As String
    Dim fileSize   As Long
 
    'FileSystemObjectオブジェクトを作成する
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    'ファイルが存在するかチェック
    If fso.FileExists(fileName) = False Then
        Exit Sub
    End If
 
    'ファイルサイズを取得する
    fileSize = fso.GetFile(fileName).Size
 
    'ファイルサイズをチェック
    If fileSize < mMaxFileSize * 1024 Then
        '最大サイズを超えてなければ処理を抜ける
        Exit Sub
    End If
 
    'フォルダパスを取得
    folderPath = fso.GetParentFolderName(fileName)
 
    '最古ファイルパス
    oldestFile = folderPath & "\" & mLogFileName & mLogRotateNum & "." & mLogFileExt
 
    '最古ファイルが存在すれば削除
    If fso.FileExists(oldestFile) Then
        Call fso.DeleteFile(oldestFile)
        r = mLogRotateNum - 1
    Else
        'ローテーション世代数を調べる
        For r = (mLogRotateNum - 1) To 0 Step -1
            If r = 0 Then
                checkFile = folderPath & "\" & mLogFileName & "." & mLogFileExt
            Else
                checkFile = folderPath & "\" & mLogFileName & r & "." & mLogFileExt
            End If
 
            If fso.FileExists(checkFile) Then
                Exit For
            End If
        Next
    End If
 
    'ファイル名をローテーションする
    For i = r To 0 Step -1
        If i = 0 Then
            srcFile = folderPath & "\" & mLogFileName & "." & mLogFileExt
        Else
            srcFile = folderPath & "\" & mLogFileName & i & "." & mLogFileExt
        End If
 
        destFile = folderPath & "\" & mLogFileName & i + 1 & "." & mLogFileExt
 
        If fso.FileExists(srcFile) Then
            'ファイル名変更
            Call fso.MoveFile(srcFile, destFile)
        End If
    Next
 
Exit_Trap:
 
    Set fso = Nothing
 
Exit Sub
Err_Trap:
    MsgBox Err.Number & Space(2) & Err.Description, vbCritical, "エラー"
    Resume Exit_Trap
End Sub


使用例

下記にLogClassの使用例を示します。
まず、LogClassの変数を宣言したあと、SetステートメントのNewキーワードでLogClassオブジェクトのインスタンスを作成します。
インスタンスを作成したら、各プロパティの値を設定しています。このプロパティを設定しなかった場合は、コンストラクタで設定した初期値が使われます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Public Sub LogClassTest()
On Error GoTo Err_Trap
  
    Dim log As LogClass
    Set log = New LogClass
     
    'ログクラスプロパティ設定
    log.MaxFileSize = 4096
    log.LogFileName = "error"
    log.LogFileExt = "log"
    log.LogFolderName = "Log"
    log.LogRotateNum = 3
     
    Dim a As Long
     
    a = 30 / 0
 
    MsgBox "a = " & a
 
Exit Sub
Err_Trap:
    Call log.MakeErrorLog(Err, "LogClassTest")
End Sub






スポンサーリンク



Follow Me on Pinterest
Clip to Evernote