Origin - [http://www.bolterauer.de/consulting/dev/vbatools/vba_logging/VBALogging.html]
Author - Christian Bolterauer - csinfo@bolterauer.de
##Contents
Introduction Examples Download source files Setting Log Levels Installing the Logging Framework Running the Unit Tests
##Introduction
This VBA Logging framework is especially designed for VBA Applications. It provides feature specific to VBA development that include:
direct replacement of 'Debug.Print txt' with 'Logging.log (txt)' direct Logging with 'logpoint information' logging to a Logbuffer - with the option to create a Trace file of the Log full Log4VBA style logging. Different to logging frameworks like log4J it is not necessary to instantiate a 'Logger' Object prior to log a message: A simple procedure call is sufficient. If preferred the VBA Logging Framework also provides the sophisticated approach creating a Logger Object instance with the class name (comparable to log4J). Both approaches can be combined. Please refer to the Examples and the Unit Tests for more details.
##Examples:
Replacing Debug.Print
After installing the Logging Module "Debug.Print" statements can be replaced as:
instead of
Debug.Print txtuse
Logging.log(txt)
Note: It is not necessary to initialize a Logger! The Resulting 'printout' will be the same as Debug.Print but with the option to log to a file or the Logbuffer.
A more usefull Logging statement is a call like
Logging.logINFO ("myinfotxt..")
or adding Logpoint Information
Logging.logINFO "This is my message ..", "MySubOrFunction"
wich will give a result like
(28.08.2008 10:53:20) INFO: myinfotxt.. (28.08.2008 10:53:20)[MySubOrFunction]-INFO: This is my message ..
These messiges will be logged only if 'LOG_LEVEL = INFO' or finer.
##Log4VBA style logging:
Dim myLogger AsObject'globally define' initialize Logger and set Module Name for example 'VBALogger'Set myLogger = Logging.getNewLogger(Application.VBE.ActiveVBProject.name) ' log ALL to Console, Buffer, FileCallmyLogger.setLoggigParams(Logging.lgALL, True, True, True) ' log a message in Sub 'MySubOrFunction'
myLogger.logINFO "This is my message ..", "MySubOrFunction" Result:
(28.08.200810:53:20)[VBALogger::MySubOrFunction]-INFO: This is my message ..###Setting Log Levels: Log Levels can be set at startup time using vba_log.properties : The properties file must be located in the same directory as the VBA Module containing the LOGGER Class (and the Logging Module). When the Logger Class is initialized it will look for settings in the 'vba_log.properties' file. Here an Example:
-- settings for VBA logging --
LOG_LEVEL:
DISABLED BASIC 'like Debug.Print FATAL WARN INFO FINE FINER FINEST ALL
LOG_LEVEL = info LOG_TO_CONSOLE = True LOG_TO_BUFFER = True LOG_TO_FILE = True Default LOG_FILE_PATH is the same place as VBA project file containing the Logger Modul LOG_FILE_PATH=C:\vba_logger.log
Log Levels can also be set or changed inside VBA code using the method:
Call Logging.setLoggigParams(Logging.lgBASIC, True, True, False)
##Installing the Logging Framework
There are two options installing the VBA Logging Framework: Importing the source moduls into your VBA Projects Installation as a xla library
###Importing the source modules
Use your VBA IDE (e.g. Excel (or Word) ->Macros->'Visual Basic Editor') select your VBA Project and use 'Import file..' to import the src files into your project:
Logging.bas Logger.cls Logbuffer.cls Unit Tests (Optional)
I personally recomend to import the modul files directly into your project. Importing the modules does not create any dependancies and your project is 'redistributable'.
###Installation as a XLA library
To install the 'Logging.xla', copy Logging.xla into the MS Office Macros directory** (e.g. 'C:\Programme\Microsoft Office\Office\Makro') Note that you have to create a Reference to the 'Logging.xla' file to call the Logger from your VBA Project.
To add a Reference to a libray you ususally need to run a method like the following example:
PublicSubaddLoggerReference()
On ErrorGoTo Errhandler:
Dim location AsStringDim RefFile AsStringDim path
RefFile = "Logging.xla"
location = getParentFolder(Application.VBE.ActiveVBProject.Filename)
path = location & "\" & RefFile
'add the reference
Debug.Print"Adding Reference: " & path
Application.VBE.ActiveVBProject.References.AddFromFile path
Exit Sub
Errhandler:
Debug.Print Err.Description
End SubYour only have to run adding reference code once for your VBA Project: The VBA Project will remember the reference. **The exact location is dependent on your Office Version and MS Windows Enviroment.
##Running the Unit Tests
To run the Unit Test:
Import TestLogging.bas Run the test calling the Macro 'Test'
##Disclaimer:
The following development tool is free to use and change 'As Is' with no guarantee from the author(s). The tools come directly from our own development, so they my not fit 100% but hopefully provide a basis to build on.
###TestLogging.bas:
Attribute VB_Name = "TestLogging"'''''' Basic test macro to test Logger Class using Logging''''define 'myLogger' as 'Object' (not 'Logger') to ensure that'this test Class works in VBAProjects that reference 'Logging.xla''since Public Class Moduls may not be exposed as Type between VBAProjectsDim myLogger AsObjectSubTest()
Logging.setModulName (Application.VBE.ActiveVBProject.name)
Logging.logINFO ("***Starting Logger test..")
CallprintLogLevels
Logging.log ("***Testing LogLevels..")
CallLogging.setLoggigParams(Logging.lgALL, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgFINEST, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgFINER, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgFINE, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgINFO, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgWARN, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgFATAL, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgBASIC, True, True, True)
CallprintLogLevels
Logging.log ("***Now Turn logging off ..")
CallLogging.setLoggigParams(Logging.lgDISABLED, True, True, True)
CallprintLogLevelsCallLogging.setLoggigParams(Logging.lgALL, True, True, True)
CallLogging.log("***Testing logging with 'logpoint' entry ..")
CallprintLogLevelsWithLogPointCallLogging.setLoggigParams(Logging.lgALL, True, False, False)
Logging.log ("***Testing logBuffer ..")
Logging.log "----Printing Logging.getLogBuffer to Console only ----"
Logging.log Logging.getLogBuffer
CallLogging.setLoggigParams(Logging.lgALL, True, True, True)
Logging.setModulName ("")
CallTestLoggerInstance
Logging.log ("***Testing writing logBuffer to Tracefile ..")
Logging.writeLogBufferToTraceFile
Logging.log ("***Testing done.***")
End SubPrivateSubprintLogLevels()
Logging.log ("-LogBasic = like Debug.Print-")
Logging.logINFO ("-logINFO-")
Logging.logWARN ("-logWARN-")
Logging.logFATAL ("-logFATAL-")
Logging.logFINE ("-logFINE-")
Logging.logFINER ("-logFINER-")
Logging.logFINEST ("-logFINEST-")
End SubPrivateSubprintLogLevelsWithLogPoint()
Logging.log ("-LogBasic = like Debug.Print-")
Logging.logINFO "-logINFO-", "printLogLevelsWithLogPoint"
Logging.logWARN "-logWARN-", "printLogLevelsWithLogPoint"
Logging.logFATAL "-logFATAL-", "printLogLevelsWithLogPoint"
Logging.logFINE "-logFINE-", "printLogLevelsWithLogPoint"
Logging.logFINER "-logFINER-", "printLogLevelsWithLogPoint"
Logging.logFINEST "-logFINEST-", "printLogLevelsWithLogPoint"End SubSubTestLoggerInstance()
Set myLogger = Logging.getNewLogger(Application.VBE.ActiveVBProject.name)
CallmyLogger.setLoggigParams(Logging.lgALL, True, True, True)
myLogger.logBASIC "***Starting TestLoggerInstance test.."
myLogger.logBASIC "-LogBasic = like Debug.Print-", "TestLoggerInstance"
myLogger.logINFO "-logINFO-", "TestLoggerInstance"
myLogger.logWARN "-logWARN-", "TestLoggerInstance"
myLogger.logFATAL "-logFATAL-", "TestLoggerInstance"
myLogger.logFINE "-logFINE-", "TestLoggerInstance"
myLogger.logFINER "-logFINER-", "TestLoggerInstance"
myLogger.logFINEST "-logFINEST-", "TestLoggerInstance"'call a subCallMySubOrFunctionCallmyLogger.setLoggigParams(Logging.lgALL, True, False, False)
myLogger.logBASIC "*** printing the TestLoggerInstance buffer to Console.."
myLogger.logBASIC myLogger.getLogBuffer
End SubSubMySubOrFunction()
myLogger.logINFO "This is my message ..", "MySubOrFunction"' log a message in Sub 'MySubOrFunction'End Sub###Logging.bas:
Attribute VB_Name = "Logging"''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Contents: Logging Modul for VBA - uses 'LOGGER' Class'''''' Comments: Facade for Logger, with static reference to a Logger instance''' The Static Logger allows to write log statments to a logbuffer''' that can be read for example inside Errorhandling'''''' Example: Replacing Debug.Print:''' if you use the Logging Module no initialization needs to be done:''' instead 'Debug.Print txt' use: 'Logging.log (txt)''''''' Example: Log4VBA sytle logging:'''''' Dim myLogger As Object 'globaly define'''''' Set myLogger = Logging.getNewLogger(Application.VBE.ActiveVBProject.name) ' initalize Logger and set Module Name for example 'VBALogger'''' Call myLogger.setLoggigParams(Logging.lgALL, True, True, True) ' log ALL to Console, Buffer, File'''''' myLogger.logINFO "This is my message ..", "MySubOrFunction" ' log a message in Sub 'MySubOrFunction''''''' Result:''' (28.08.2008 10:53:20)[VBALogger::MySubOrFunction]-INFO: This is my message ..'''''' Changing Settings:'''''' The bestway to change Loglevels and the settings logging to console, buffer, or logfile''' is by changing the settings via properties file "vba_log.properties"''' With this version the properties file is expected in the same directory as the Module''' containing the LOGGER Class (and the Logging Module)''' Example:''' ---------------------------------------------''' #''' # -- settings for VBA logging --''' #''' # LOG_LEVEL:''' #''' # DISABLED''' # BASIC 'like Debug.Print''' # FATAL''' # WARN''' # INFO''' # FINE''' # FINER''' # FINEST''' # ALL''' #''' LOG_LEVEL = info''' LOG_TO_CONSOLE = True''' LOG_TO_BUFFER = True''' LOG_TO_FILE = True''' # Default LOG_FILE_PATH is the same place as Project File containing the Logger Modul''' #LOG_FILE_PATH=C:\vba_logger.log''' -----------------------------------------'''''' Settings can be changed using vba code with the setLoggigParams(..) procedure''' example:''' Call Logging.setLoggigParams(Logging.lgBASIC, True, True, False)'''''' Example use for LogBuffer:''' If (Err) Then Logging.writeLogBufferToTraceFile''''''''' Date Developer Action''' --------------------------------------------------------------------------''' 28/08/08 Christian Bolterauer Created''''''Option Explicit' global to allow access to Logger Class instance via Logging ModulePublic defaultLogger AsLogger'copy of levels from Logger Class to expose levels via the Logging Module'Note that the enum 'LogLEVEL' is only visable within the VBAProject that contains the Logger Class.'The Const variables are visable to every Modul where Logging can be accessedPublicConst lgDISABLED = LogLEVEL.DISABLED
PublicConst lgBASIC = LogLEVEL.BASIC
PublicConst lgFATAL = LogLEVEL.FATAL
PublicConst lgWARN = LogLEVEL.WARN
PublicConst lgINFO = LogLEVEL.INFO
PublicConst lgFINE = LogLEVEL.FINE
PublicConst lgFINER = LogLEVEL.FINER
PublicConst lgFINEST = LogLEVEL.FINEST
PublicConst lgALL = LogLEVEL.ALL
'setter for prime logparametersSubsetLoggigParams(myloglevel AsInteger, toConsole AsBoolean, toBuffer AsBoolean, toLogFile AsBoolean)
If (myloglevel = LogLEVEL.DISABLED) Then Debug.Print"Logging is disabled."'Important: initilaze logger by calling log() before setting params
log ("Logging with logLevel=" & defaultLogger.getLogLevelName(myloglevel) & " ToConsole=" & toConsole & " ToBuffer=" & toBuffer & " ToLogFile=" & toLogFile)
CalldefaultLogger.setLoggigParams(myloglevel, toConsole, toBuffer, toLogFile)
'Inital LogfilePath set here'Call defaultLogger.setLogFile(Application.ActiveWorkbook.path & "\vba_logger.log")End Sub'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Static defaultLogger instance'' The live time of this logger instance is as long as the application runs' This allows to write log messages to a buffer that can be processed even if modules are changed'' The defaultLogger is initialized the first time when any of the following log statements is called'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''PrivateSubthislog(msg AsString, myloglevel AsLogLEVEL, Optional slogpoint AsString)
Static mydefaultLogger AsNew Logger 'singelton'- if static value is not set assume start of vba session and delete the log file -If (defaultLogger IsNothing) ThenCallmydefaultLogger.deleteLogFileEnd IfCallmydefaultLogger.log(msg, myloglevel, slogpoint)
Set defaultLogger = mydefaultLogger 'refence to static objectEnd SubPublicSublog(sLogText AsString, Optional slogpoint AsString)
Callthislog(sLogText, LogLEVEL.BASIC, slogpoint)
End SubPublicSublogINFO(sLogText AsString, Optional slogpoint AsString)
Callthislog(sLogText, LogLEVEL.INFO, slogpoint)
End SubPublicSublogWARN(sLogText AsString, Optional slogpoint AsString)
Callthislog(sLogText, LogLEVEL.WARN, slogpoint)
End SubPublicSublogFATAL(sLogText AsString, Optional slogpoint AsString)
Callthislog(sLogText, LogLEVEL.FATAL, slogpoint)
End SubPublicSublogFINE(sLogText AsString, Optional slogpoint AsString)
Callthislog(sLogText, LogLEVEL.FINE, slogpoint)
End SubPublicSublogFINER(sLogText AsString, Optional slogpoint AsString)
Callthislog(sLogText, LogLEVEL.FINER, slogpoint)
End SubPublicSublogFINEST(sLogText AsString, Optional slogpoint AsString)
Callthislog(sLogText, LogLEVEL.FINEST, slogpoint)
End SubFunctiongetLogBuffer()
If (defaultLogger IsNothing) Then'initilize defaultLogger calling ..Callthislog("Retrieving LogBuffer..", LogLEVEL.FINE)
End If
getLogBuffer = defaultLogger.getLogBuffer
End Function'set setModulName: ensures that defaultLogger is initalized before value is setPublicSubsetModulName(myModulName AsString)
If (defaultLogger IsNothing) Then'initilize defaultLogger calling ..Callthislog("Setting ModulName to " & myModulName, LogLEVEL.FINE)
End If
defaultLogger.ModulName = myModulName
End SubPublicSubwriteLogBufferToTraceFile(Optional myfilePath AsString)
If (defaultLogger IsNothing) Then'initilize defaultLogger calling ..Callthislog("Writing LogBuffer to TraceFile ..", LogLEVEL.FINE)
End If
defaultLogger.writeLogBufferToTraceFile (myfilePath)
End Sub'*******************************************************************************************'* MODULE: getNewLogger'*'* PURPOSE: Return a logger object with the defaults set.'* The Log Buffer of the new Logger created by this factory method is set'* to defaultLogger.strLogbuffer so that all log entries of a session can be traced'*'* PARAMETERS: sModulName - the VBA Module that will be used as an identifier within the log file.'*******************************************************************************************PublicStaticFunctiongetNewLogger(sModulName AsString) AsLoggerDim myLogger AsNew Logger
myLogger.ModulName = sModulName
'set the logBuffer to defaultLogger Logbuffer so that all log entries of a session can be tracedSet myLogger.cLogbuffer = defaultLogger.cLogbuffer
Set getNewLogger = myLogger
End Function###Logger.cls:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1'TrueENDAttribute VB_Name = "Logger"Attribute VB_GlobalNameSpace = FalseAttribute VB_Creatable = FalseAttribute VB_PredeclaredId = FalseAttribute VB_Exposed = FalseOption Explicit''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' CLASS_MODULE: VBA Logger - allows 'log4VBA' style Logging in VBA''' - please see the 'Logging' Module for Usage: the Logging Module''' automatically creates a 'Logger' instance and provides additional''' Features'''''' - use Macro 'Test' from 'TestLogging' for testing and as an example'''''' Date Developer Action''' --------------------------------------------------------------------------''' 28/08/08 Christian Bolterauer Created'''Public cLogbuffer AsLogbufferPublic iLogLevel AsIntegerPublic bUseLogPrefix AsBooleanPublic bConsole AsBooleanPublic bBuffer AsBooleanPublic bToLogFile AsBooleanPublic LogFilePath AsStringPublic TraceFilePath AsStringPublic bDelLogFileAtSetup AsBooleanPublic PropsFileName AsString'ModulNamePublic ModulName AsString'Define log levelsPublicEnum LogLEVEL
DISABLED = 0
BASIC = 1'like Debug.Print
FATAL = 2
WARN = 3
INFO = 4
FINE = 5
FINER = 6
FINEST = 7
ALL = 8End Enum' The defaultsConst DEFAULT_LOG_LEVEL% = LogLEVEL.INFO
Const DEFAULT_LOG_Console = TrueConst DEFAULT_LOG_Buffer = FalseConst DEFAULT_LOG_FILE = FalseConst DEFAULT_PROPSFILE_NAME = "vba_log.properties"''Class KonstructorPrivateSubClass_Initialize()
On ErrorGoTo Errhandler:
Dim localpath AsStringSet cLogbuffer = New Logbuffer
bUseLogPrefix = True
bDelLogFileAtSetup = True'default
ModulName = ""'set default location of props file to directory of this Logger and add default name
localpath = getParentFolder(Application.VBE.ActiveVBProject.Filename) 'set path to location of file containing this Logger
PropsFileName = localpath & "\" & DEFAULT_PROPSFILE_NAME
'make sure defaults are setCallsetLoggigParams(DEFAULT_LOG_LEVEL, DEFAULT_LOG_Console, DEFAULT_LOG_Buffer, DEFAULT_LOG_FILE)
'set default log file path
LogFilePath = localpath & "\" & "vba_logger.log"
TraceFilePath = localpath & "\" & "vba_trace.log"'check if params can be set from a properties file and overwrite defaults if availableCallgetLogParamsFromFile'set log fileCallsetLogFile(LogFilePath, False)
Exit Sub
Errhandler:
Debug.Print"Error in Logger.Class_Initialize & "; " & Err.Number & "; " & Err.Description"End Sub'set logging parametersPublicSubsetLoggigParams(level AsInteger, toConsole AsBoolean, toBuffer AsBoolean, toLogFile AsBoolean, Optional deleteExistingLogFile)
Dim delLogfile AsBoolean
iLogLevel = level
bConsole = toConsole
bBuffer = toBuffer
bToLogFile = toLogFile
If IsMissing(deleteExistingLogFile) Then
delLogfile = FalseElse
delLogfile = deleteExistingLogFile
End If' delete currently set Logfile if setIf (delLogfile) Then deleteLogFile
End Sub'The main log procedurePublicSublog(sLogText AsString, level AsLogLEVEL, Optional slogpoint AsString)
If (Me.iLogLevel > LogLEVEL.DISABLED And Me.iLogLevel >= level) ThenIf IsMissing(slogpoint) ThenCallWriteLog(sLogText, level, "")
ElseCallWriteLog(sLogText, level, slogpoint)
End IfEnd IfEnd SubPublicSublogBASIC(sLogText AsString, Optional slogpoint AsString)
CallMe.log(sLogText, LogLEVEL.BASIC, slogpoint)
End SubPublicSublogINFO(sLogText AsString, Optional slogpoint AsString)
CallMe.log(sLogText, LogLEVEL.INFO, slogpoint)
End SubPublicSublogWARN(sLogText AsString, Optional slogpoint AsString)
CallMe.log(sLogText, LogLEVEL.WARN, slogpoint)
End SubPublicSublogFATAL(sLogText AsString, Optional slogpoint AsString)
CallMe.log(sLogText, LogLEVEL.FATAL, slogpoint)
End SubPublicSublogFINE(sLogText AsString, Optional slogpoint AsString)
CallMe.log(sLogText, LogLEVEL.FINE, slogpoint)
End SubPublicSublogFINER(sLogText AsString, Optional slogpoint AsString)
CallMe.log(sLogText, LogLEVEL.FINER, slogpoint)
End SubPublicSublogFINEST(sLogText AsString, Optional slogpoint AsString)
CallMe.log(sLogText, LogLEVEL.FINEST, slogpoint)
End SubPrivateSubWriteLog(sLogText, level AsLogLEVEL, slogpoint AsString)
Dim LogMessage AsStringDim sDateTime AsStringDim sLogPrefix AsString
LogMessage = getLogPrefix(level, slogpoint) & sLogText
' write to consoleIf Me.bConsole Then Debug.Print (LogMessage)
' write to BufferIf Me.bBuffer Then cLogbuffer.addline (LogMessage)
' write to fileIf Me.bToLogFile Then writeToLogFile (LogMessage)
End Sub' get LogLevelName for Integer valuePublicFunctiongetLogLevelName(level AsInteger)
Dim myLevelName AsStringSelect Case level
Case LogLEVEL.DISABLED:
myLevelName = "DISABLED"Case LogLEVEL.BASIC:
myLevelName = "BASIC"Case LogLEVEL.INFO:
myLevelName = "INFO:"Case LogLEVEL.WARN:
myLevelName = "WARN:"Case LogLEVEL.FATAL:
myLevelName = "FATAL:"Case LogLEVEL.FINE:
myLevelName = "FINE:"Case LogLEVEL.FINER:
myLevelName = "FINER:"Case LogLEVEL.FINEST:
myLevelName = "FINEST:"Case LogLEVEL.ALL:
myLevelName = "ALL:"Case Else
myLevelName = "Level is not defined:"End Select
getLogLevelName = myLevelName
End FunctionPrivateFunctiongetLogPrefix(level AsLogLEVEL, logpoint AsString)
Dim sDateTime AsStringDim myLevelPrefix AsStringDim mySubModul AsStringDim iLevel AsIntegerIfNot (bUseLogPrefix) Or level = LogLEVEL.BASIC Then'when level = LogLEVEL.BASIC no prefix to simulate Debug.Print
getLogPrefix = ""Exit FunctionEnd If
iLevel = level ' to Integer
myLevelPrefix = getLogLevelName(iLevel)
If (Len(Me.ModulName) > 0And Len(logpoint) > 0) Then
mySubModul = "[" & Me.ModulName & "::" & logpoint & "]"ElseIf (Len(logpoint) > 0) Then
mySubModul = "[" & logpoint & "]"ElseIf (Len(Me.ModulName) > 0) Then
mySubModul = "[" & Me.ModulName & "]"Else
mySubModul = ""End If
sDateTime = CStr(Now())
'ToDo provide different output styles ..'getLogPrefix = myLevelPrefix & " (" & sDateTime & ") - "
getLogPrefix = "(" & sDateTime & ")" & mySubModul & "-" & myLevelPrefix & " "End FunctionPrivateSubwriteToLogFile(logmsg AsString)
On ErrorGoTo Errhandler:
If Len(Me.LogFilePath) = 0Then
Debug.Print"Error: Log file path is empty."Exit SubEnd IfDim FileNum AsInteger
FileNum = FreeFile ' next file numberOpen Me.LogFilePath For Append As #FileNum ' creates the file if it doesn't existPrint #FileNum, logmsg ' write information at the end of the text fileClose #FileNum ' close the fileExit Sub
Errhandler:
Debug.Print"Error writing to Logfile: " & Me.LogFilePath & " " & Err.Number & " " & Err.Description
End SubPublicSubwriteLogBufferToTraceFile(Optional myfilePath AsString)
On ErrorGoTo Errhandler:
Dim mytracefile AsStringIf Len(myfilePath) = 0Then
mytracefile = Me.TraceFilePath
Else
mytracefile = myfilePath
End IfIf Len(mytracefile) = 0Then
Me.logFATAL "Error: Trace file path is empty."Exit SubEnd If'write to trace file
Me.cLogbuffer.writeLogBufferToTraceFile (mytracefile)
Exit Sub
Errhandler:
Debug.Print"Error writing to Tracefile: " & mytracefile & " " & Err.Number & " " & Err.Description
End SubPrivateSubreadPropertiesFile(path AsString)
On ErrorGoTo Errhandler:
Dim txtline AsStringDim para() AsStringDim mymsg AsStringIf Len(path) = 0ThenGoTo Errhandler
Open path For Input As #1' open fileDo WhileNot EOF(1) ' Loop until end of fileLine Input #1, txtline ' read line'Debug.Print txtline 'test
para = readParameter(txtline)
If Len(para(0)) = 0Then'continueElseIf ("LOG_LEVEL" = UCase(para(0))) ThenCallsetLogLevel(para(1))
ElseIf ("LOG_TO_CONSOLE" = UCase(para(0))) Then
bConsole = valIsTrue(para(1))
ElseIf ("LOG_TO_BUFFER" = UCase(para(0))) Then
bBuffer = valIsTrue(para(1))
ElseIf ("LOG_TO_FILE" = UCase(para(0))) Then
bToLogFile = valIsTrue(para(1))
ElseIf ("LOG_FILE_PATH" = UCase(para(0))) Then
Me.LogFilePath = para(1)
End IfLoopClose #1'show settings
mymsg = "Logging with logLevel=" & getLogLevelName(iLogLevel) & " toConsole=" & bConsole & " toBuffer=" & bBuffer & " toLogFile=" & bToLogFile
Calllog(mymsg, LogLEVEL.BASIC)
Exit Sub
Errhandler:
Debug.Print"Error reading Properties File: " & path & " " & Err.Number & " " & Err.Description
End Sub'delete log file currently setPublicSubdeleteLogFile()
On ErrorGoTo Errhandler:
If (FileExists(Me.LogFilePath)) Then
Kill (Me.LogFilePath)
End IfExit Sub
Errhandler:
Debug.Print"Error deleting Logfile " & Me.LogFilePath & " " & Err.Number & " " & Err.Description
End Sub'set logfilepath'- will delete an existing log file if bDelLogFileAtSetup is set to truePublicSubsetLogFile(filePath AsString, delExitingFile AsBoolean)
On ErrorGoTo Errhandler:
Me.LogFilePath = filePath
'delete if set to trueIf (delExitingFile) ThenCalldeleteLogFileIf (bToLogFile) Then Debug.Print"Logfile set to: " & LogFilePath
Exit Sub
Errhandler:
Debug.Print"Error setLogFile " & LogFilePath & " " & Err.Number & " " & Err.Description
End SubPublicFunctiongetLogParamsFromFile()
On ErrorGoTo Errhandler:
If (FileExists(PropsFileName)) Then
Debug.Print"Reading: " & PropsFileName
'read and set parameter from properties file
readPropertiesFile (PropsFileName)
getLogParamsFromFile = TrueExit FunctionEnd If
getLogParamsFromFile = FalseExit Function
Errhandler:
Debug.Print"Error getLogParamsFromFile " & PropsFileName & " " & Err.Number & " " & Err.Description
getLogParamsFromFile = FalseEnd FunctionPrivateSubsetLogLevel(level AsString)
Dim mylevel
mylevel = UCase(level)
Select Case mylevel
Case"DISABLED":
iLogLevel = LogLEVEL.DISABLED
Case"BASIC":
iLogLevel = LogLEVEL.BASIC
Case"INFO":
iLogLevel = LogLEVEL.INFO
Case"WARN":
iLogLevel = LogLEVEL.WARN
Case"FATAL":
iLogLevel = LogLEVEL.FATAL
Case"FINE":
iLogLevel = LogLEVEL.FINE
Case"FINER":
iLogLevel = LogLEVEL.FINER
Case"FINEST":
iLogLevel = LogLEVEL.FINEST
Case"ALL":
iLogLevel = LogLEVEL.ALL
End SelectEnd SubPublicFunctiongetLogBuffer() AsString
getLogBuffer = cLogbuffer.strLogbuffer
End Function'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Utils''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''-- extract full path of parent folder of file mypathPublicFunctiongetParentFolder(mypath AsString) AsStringDim pos AsIntegerDim fullpath AsString
pos = InStrRev(mypath, "\")
If (pos <> 0) Then
getParentFolder = Left(mypath, pos - 1)
Exit FunctionEnd If
getParentFolder = ""End Function'-- Check File Exists --PublicFunctionFileExists(path AsString) AsBoolean
FileExists = (Dir(path) <> "")
End Function'-- isNothing --FunctioncheckIsNothing(obj AsObject)
If (obj IsNothing) Then
checkIsNothing = TrueElse
checkIsNothing = FalseEnd IfEnd Function'-- parameters ---FunctionreadParameter(line AsString) AsString()
Dim txtarr() AsStringDim proparray(2) AsString
txtarr = VBA.Split(line, "=")
If (UBound(txtarr) > 0) Then
proparray(0) = VBA.Trim(txtarr(0))
proparray(1) = VBA.Trim(txtarr(1))
readParameter = proparray
Else
readParameter = proparray
End IfEnd Function'-- check text coded boolean value (if read from text file) --FunctionvalIsTrue(boolval AsString) AsBooleanIf ("TRUE" = VBA.UCase(boolval)) Then
valIsTrue = TrueExit FunctionEnd If
valIsTrue = FalseEnd Function###Logbuffer.cls:
rel=
VERSION 1.0 CLASS
BEGIN
MultiUse = -1'TrueENDAttribute VB_Name = "Logbuffer"Attribute VB_GlobalNameSpace = FalseAttribute VB_Creatable = FalseAttribute VB_PredeclaredId = FalseAttribute VB_Exposed = FalseOption Explicit''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' CLASS_MODULE: VBA Logbuffer - allows a Reference e.g. the 'Set' Method on a String Property'''''' - see the 'Logging' Module for Usage: the Logging Module''' automatically creates a 'Logger' instance and provides additional''' Features'''''' - use Macro 'Test' from 'TestLogging' for testing and as an example'''''' Date Developer Action''' --------------------------------------------------------------------------''' 28/08/08 Christian Bolterauer Created'''Public strLogbuffer AsStringPrivateSubClass_Initialize()
strLogbuffer = ""End SubPublicSubaddline(logmsg AsString)
If (Len(strLogbuffer) > 0) Then
strLogbuffer = strLogbuffer & vbLf & logmsg
Else
strLogbuffer = logmsg 'avoid empty line when strLogbuffer=""End IfEnd SubPublicSubwriteLogBufferToTraceFile(myfilePath AsString)
On ErrorGoTo Errhandler:
Dim lines() AsStringDim line AsVariantIf Len(myfilePath) = 0Then
Debug.Print"Error: Trace file path is empty."Exit SubEnd IfDim FileNum AsInteger
FileNum = FreeFile ' next file numberOpen myfilePath For Output As #FileNum ' creates the file if it doesn't exist
lines = VBA.Split(Me.strLogbuffer, VBA.vbLf)
For Each line In lines
Print #FileNum, line ' write Logbuffer to text fileNext line
Close #FileNum ' close the fileExit Sub
Errhandler:
Debug.Print"Error writing to Tracefile: " & myfilePath & " " & Err.Number & " " & Err.Description
End Sub