0

say I have 2 add-ins A and B - both use VB functions from a shared add-in C (i.e. A and B have a reference to the VB Project C).

C will log some messages to a file (e.g. C.Log) when errors are detected. I want that C logs to A.log when the functions are called from A and to B.log when the functions are called from B.

the naive approach to set a global variable in C with the log-file name will not work, because the variable is a Singleton, so the last project to set the variable (A, or B) will win.

How can this easily be done in VBA?

Community
  • 1
  • 1
TmTron
  • 17,012
  • 10
  • 94
  • 142

1 Answers1

0

okay - so here's the solution I came up with (quite some code, but seems to work fine):

I have a logging project with a logging interface ILog (Instancing PublicNotCreatable) like this:

Public Sub Error(sLogMessage As String)
end sub
Public Sub Warning(sLogMessage As String)
end sub
' etc.

and of course an implementing class CLog that just writes the messages to a log-file.
and a public function so that the callers can get a new instance of the logger:

Public Function New_Log(ByVal logFilePathAndName) As ILog
    Set New_CLog = New CLog
    New_CLog.Initialise logFilePathAndName
End Function

then the project C must have all it's code in a class/or classes that get an ILog instance in their initialisation. For example CSharedClass could look like so:

Private Log as ILog ' note: the var is intentionally NOT called moLog

Public Sub Initialise(oLogger as ILog)
    Set Log = oLogger
End Sub

' other functions in this class that want to log just use this:
Public Sub SomeProcedure()
    Log.Error("error text")
End Sub

also this project must have one public function to let the callers create an instance, like this:

Public Sub New_SharedClass(oLogger as ILog) as CSharedClass ' NOTE: you may want to use an interface instead
    Set New_SharedClass = New CSharedClass
    New_SharedClass.Initialise oLogger
End Sub

Then projects A and B could use the logging like this:

Private moLog as ILog

Public Function Log() as ILog
    ' log-file name is of course different for Proejct B
    If moLog is Nothing then Set moLog = New_Log("ProjectA.log")
    Set Log = moLog
End Function

all other procedures in project A/B can now write log-messages like this (same as in the shared project)

Log.Error("Error text")

when project A/B wants to use the shared project, it can do it like so

Private moSharedClass as CSharedClass 

Public Function SharedClass() as CSharedClass    
    If moSharedClass is Nothing then Set moSharedClass = New_SharedClass(Log)
    Set SharedClass = moSharedClass
End Function

Now any code in project A/B that wants to call a proc on the shared class can simply do this:

SharedClass.SomeProcedure()

and the log messages written in SomeProcedure will end up in the correct log-file

Note: I decided to break some of my own naming rules, so that all projects can use the same code for logging (which has the benefit that I can just move procedures from projects A/B to the shared project or vice versa)

TmTron
  • 17,012
  • 10
  • 94
  • 142