My project creates a report based on test results which are stored in database table associated with a JobNumber. The test results for a particular JobNumber may be all be from the same date or from a range of dates. I create a report to display results for a single JobNumber and this report contains a string to display this date or range in a readable way.
The following code would produce the date range string from the two classes outlined below and the two interfaces implied below:
With ReportRepository.Create("1234")
Debug.print .MonitoringDates
End With
The desired output of IReportRepository.MonitoringDates:
- "01 January 2022" - single date
- "01 - 02 January 2022" - date range in same month
- "01 January - 01 February 2022" - date range across different months
- "01 January 2022 - 01 January 2023" - date range across different years
The project uses Rubberduck SecureADODB - https://github.com/rubberduck-vba/examples/tree/master/SecureADODB
SecureDatabase class, Implements IDataAccessObject:
'@Folder "ProjectWriter.DataAccessObject"
Option Explicit
Implements IDataAccessObject
Private Type TSecureDatabase
SecureConnetion As IDbConnection
Command As IDbCommand
End Type
Private this As TSecureDatabase
Const ConnectionString As String = "<connection string here>"
Private Sub Class_Initialize()
Dim Mappings As ITypeMap
Set Mappings = AdoTypeMappings.Default
Dim Provider As IParameterProvider
Set Provider = AdoParameterProvider.Create(Mappings)
Dim BaseCommand As IDbCommandBase
Set BaseCommand = DbCommandBase.Create(Provider)
With DbConnection.Create(ConnectionString)
Set this.Command = DefaultDbCommand.Create(.Self, BaseCommand)
End With
End Sub
Private Function IDataAccessObject_MonitoringStartDate(ByVal JobNumber As String) As Date
AllErrors.GuardEmptyString JobNumber
IDataAccessObject_MonitoringStartDate = this.Command.GetSingleValue("SELECT MIN(SampleDate) FROM Results JOIN Jobs ON Results.JobID = Jobs.ID WHERE Jobs.JobNumber = ? LIMIT 1", JobNumber)
End Function
Private Function IDataAccessObject_MonitoringEndDate(ByVal JobNumber As String) As Date
AllErrors.GuardEmptyString JobNumber
IDataAccessObject_MonitoringEndDate = this.Command.GetSingleValue("SELECT MAX(SampleDate) FROM Results JOIN Jobs ON Results.JobID = Jobs.ID WHERE Jobs.JobNumber = ? LIMIT 1", JobNumber)
End Function
'other functions
ReportRepository class, Implements IReportRepository
'@Folder("ProjectWriter.Repository")
'@PredeclaredId
Option Explicit
Implements IReportRepository
Private Type TReportRepository
DataAccessObject As IDataAccessObject
MonitoringDates As String
'other members
End Type
Private this As TReportRepository
Public Property Get Self() As ReportRepository
Set Self = Me
End Property
Public Function Create(ByVal JobNumber As String) As IReportRepository
AllErrors.GuardEmptyString JobNumber
With New ReportRepository
.Initialise JobNumber
Set Create = .Self
End With
End Function
Public Sub Initialise(ByVal JobNumber As String)
this.JobNumber = JobNumber
Set this.DataAccessObject = New SecureDatabase
With this.DataAccessObject
this.MonitoringDates = MonitoringDates(.MonitoringStartDate(JobNumber), .MonitoringEndDate(JobNumber))
'initialisation of other members
End With
End Sub
Private Function MonitoringDates(ByVal StartDate As Date, ByVal EndDate As Date) As String
Dim StartMonth As String
StartMonth = VBA.Format$(StartDate, "mmmm")
Dim EndMonth As String
EndMonth = VBA.Format$(EndDate, "mmmm")
Dim StartYear As String
StartYear = VBA.Format$(StartDate, "yyyy")
Dim EndYear As String
EndYear = VBA.Format$(EndDate, "yyyy")
Dim Dates As String
Select Case True
Case EndDate = StartDate:
Dates = VBA.Format$(StartDate, "dd mmmm yyyy")
Case StartMonth = EndMonth And StartYear = EndYear
Dates = VBA.Format$(StartDate, "dd") & " - " & VBA.Format$(EndDate, "dd mmmm yyyy")
Case StartYear = EndYear
Dates = VBA.Format$(StartDate, "dd mmmm") & " - " & VBA.Format$(EndDate, "dd mmmm yyyy")
Case Else:
Dates = VBA.Format$(StartDate, "dd mmmm yyyy") & " - " & VBA.Format$(EndDate, "dd mmmm yyyy")
End Select
MonitoringDates = Dates
End Function
Private Property Get IReportRepository_MonitoringDates() As String
IReportRepository_MonitoringDates = this.MonitoringDates
End Property
'other properties
I invite your comments, particularly on:
- If I am using the SecureADODB correctly - I was thinking there may be a way to refactor what I am doing to include both the start and end date in a single transaction or query and whether this would be worthwhile.
- If there is a more efficient way of producing the date range string compared to the VBA select case.
- Any comments on the structure of the classes for what I appear to be doing. Or any other comments on how I can improve the way this code is written.
Sorry if I have missed anything that I should have included, this is my first code review post. Thanks in advance!