I am taking a user input which consists of a from date and a to date. Those dates are compared against 4 cells in a row - a post date, pause date, resume date, and a close date. My goal with this code is to generate an array of rows with dates active within my date range.
Primary concern is if I followed the most effective logic for sorting and determining valid dates. Any comments on best practices would be appreciated.
Private Function DateRange() As Variant
Dim postcell As Range
Dim pausecell As Range
Dim unpausecell As Range
Dim closecell As Range
Dim arr_validRows() As Variant
Dim ws As Worksheet
Set ws = Sheets(1)
ReDim arr_validRows(0) As Variant
Dim z As Range
For Each z In ws.Range("D3:D" & ws.Cells(ws.Rows.Count, 2).End(xlUp).row)
Set postcell = z
Set pausecell = z.Offset(0, 1)
Set unpausecell = z.Offset(0, 2)
Set closecell = z.Offset(0, 3)
If Not closecell.Value = "?" Then
If CDate(postcell.Value) <= this.ToDate Then
If Not pausecell.Value = "" Then
If CDate(pausecell.Value) >= this.FromDate Then
ReDim Preserve arr_validRows(UBound(arr_validRows) + 1) As Variant
arr_validRows(UBound(arr_validRows)) = z.row
ElseIf CDate(pausecell.Value) < this.FromDate And CDate(unpausecell.Value) >= this.FromDate Then
ReDim Preserve arr_validRows(UBound(arr_validRows) + 1) As Variant
arr_validRows(UBound(arr_validRows)) = z.row
End If
Else
If CDate(closecell.Value) >= this.FromDate Then
ReDim Preserve arr_validRows(UBound(arr_validRows) + 1) As Variant
arr_validRows(UBound(arr_validRows)) = z.row
End If
End If
End If
End If
Next z
DateRange = arr_validRows
End Function
Below is the full class module that this function is contained in. The AddToReports()
sub is where the DateRange()
function is called.
Class: Report_Generator
Option Explicit
Private Type Reports
RequisitionNumber As String
FromDate As Date
ToDate As Date
JobTitle As String
JobLocation As String
JobCategory As String
RecruiterName As String
TSViews As Long
TSApplicants As Long
End Type
Private this As Reports
Public Property Let RequisitionNumber(ByVal inputValue As String)
this.RequisitionNumber = inputValue
End Property
Public Property Get RequisitionNumber() As String
RequisitionNumber = this.RequisitionNumber
End Property
Public Property Let JobTitle(ByVal inputValue As String)
this.JobTitle = inputValue
End Property
Public Property Get JobTitle() As String
JobTitle = this.JobTitle
End Property
Public Property Let JobLocation(ByVal inputValue As String)
this.JobLocation = inputValue
End Property
Public Property Get JobLocation() As String
JobLocation = this.JobLocation
End Property
Public Property Let JobCategory(ByVal inputValue As String)
this.JobCategory = inputValue
End Property
Public Property Get JobCategory() As String
JobCategory = this.JobCategory
End Property
Public Property Let RecruiterName(ByVal inputValue As String)
this.RecruiterName = inputValue
End Property
Public Property Get RecruiterName() As String
RecruiterName = this.RecruiterName
End Property
Public Property Get TSViews() As Long
TSViews = this.TSViews
End Property
Public Property Get TSApplicants() As Long
TSApplicants = this.TSApplicants
End Property
Public Property Get FromDate() As String
FromDate = this.FromDate
End Property
Public Property Let FromDate(ByVal inputValue As String)
this.FromDate = inputValue
End Property
Public Property Get ToDate() As String
ToDate = this.ToDate
End Property
Public Property Let ToDate(ByVal inputValue As String)
this.ToDate = inputValue
End Property
Private Function DateRange() As Variant
Dim postcell As Range
Dim pausecell As Range
Dim unpausecell As Range
Dim closecell As Range
Dim arr_validRows() As Variant
Dim ws As Worksheet
Set ws = Sheets(1)
ReDim arr_validRows(0) As Variant
Dim z As Range
For Each z In ws.Range("D3:D" & ws.Cells(ws.Rows.Count, 2).End(xlUp).row)
Set postcell = z
Set pausecell = z.Offset(0, 1)
Set unpausecell = z.Offset(0, 2)
Set closecell = z.Offset(0, 3)
If Not closecell.Value = "?" Then
If CDate(postcell.Value) <= this.ToDate Then
If Not pausecell.Value = "" Then
If CDate(pausecell.Value) >= this.FromDate Then
ReDim Preserve arr_validRows(UBound(arr_validRows) + 1) As Variant
arr_validRows(UBound(arr_validRows)) = z.row
ElseIf CDate(pausecell.Value) < this.FromDate And CDate(unpausecell.Value) >= this.FromDate Then
ReDim Preserve arr_validRows(UBound(arr_validRows) + 1) As Variant
arr_validRows(UBound(arr_validRows)) = z.row
End If
Else
If CDate(closecell.Value) >= this.FromDate Then
ReDim Preserve arr_validRows(UBound(arr_validRows) + 1) As Variant
arr_validRows(UBound(arr_validRows)) = z.row
End If
End If
End If
End If
Next z
DateRange = arr_validRows
End Function
Sub AddToReport(ByVal sheetname As String)
Dim ws As Worksheet
Dim newrow As Long
Set ws = Sheets(1)
Dim exists As Boolean
exists = False
Dim i As Integer
For i = 1 To Worksheets.Count
If Worksheets(i).Name = sheetname Then
exists = True
End If
Next i
If Not exists Then
Call CreateSheet(sheetname)
With ThisWorkbook.Worksheets(sheetname)
.Range("1:1").Value = ws.Range("2:2").Value
End With
End If
Dim array_rows() As Variant
array_rows = DateRange()
Dim z As Variant
Dim w As Integer
For z = 1 To UBound(array_rows)
If z <= UBound(array_rows) Then
With ThisWorkbook.Worksheets(sheetname)
newrow = .Cells(.Rows.Count, 2).End(xlUp).row + 1
.Range(newrow & ":" & newrow).Value = ws.Range(array_rows(z) & ":" & array_rows(z)).Value
End With
Else
Exit For
End If
Next z
End Sub
Sub TimeSeriesSummation()
'Still in progress
End Sub
Sub AdvancedFilters( _
ByVal reqnum_on As Boolean, _
ByVal jobcategory_on As Boolean, _
ByVal recruiter_on As Boolean, _
ByVal jobtitle_on As Boolean, _
ByVal joblocation_on As Boolean, _
ByVal sheetname As String)
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(sheetname)
With ws.Range("A:O")
ws.AutoFilterMode = False
If reqnum_on Then
'field 1
.AutoFilter field:=1, Criteria1:="<>" & this.RequisitionNumber
End If
If jobcategory_on Then
'field 13
.AutoFilter field:=13, Criteria1:="<>" & this.JobCategory
End If
If recruiter_on Then
'field 14
.AutoFilter field:=14, Criteria1:="<>" & this.RecruiterName
End If
If jobtitle_on Then
'field 2
.AutoFilter field:=2, Criteria1:="<>" & this.JobTitle
End If
If joblocation_on Then
'field 3
.AutoFilter field:=3, Criteria1:="<>" & this.JobLocation
End If
End With
If reqnum_on Or jobcategory_on Or recruiter_on Or jobtitle_on Or joblocation_on Then
ws.Range("B2:B" & ws.Cells(ws.Rows.Count, 2).End(xlUp).row).SpecialCells(xlCellTypeVisible).EntireRow.Delete
ws.AutoFilterMode = False
End If
End Sub
Private Sub CreateSheet(ByVal sheetname As String)
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets.Add(After:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = sheetname
End Sub
Sub Statistics(ByVal sheetname As String)
With ThisWorkbook.Worksheets(sheetname)
.Range("Q3").Value = "Descriptive Statistics"
.Range("Q4").Value = "Mean"
.Range("Q5").Value = "Median"
.Range("Q6").Value = "Std. Dev."
.Range("Q7").Value = "Variance"
.Range("R3").Value = "Total Days Active"
.Range("S3").Value = "Views"
.Range("T3").Value = "Applications"
.Range("U3").Value = "Views-To-Applications"
.Range("V3").Value = "Applications per Day"
.Range("R4").Value = "=AVERAGE(H$2:H$" & .Cells(.Rows.Count, 2).End(xlUp).row & ")"
.Range("R5").Value = "=MEDIAN(H$2:H$" & .Cells(.Rows.Count, 2).End(xlUp).row & ")"
.Range("R6").Value = "=STDEVP(H$2:H$" & .Cells(.Rows.Count, 2).End(xlUp).row & ")"
.Range("R7").Value = "=VARP(H$2:H$" & .Cells(.Rows.Count, 2).End(xlUp).row & ")"
Dim sourceRange As Range
Dim fillRange As Range
Set sourceRange = .Range("R4:R7")
Set fillRange = .Range("R4:V7")
Call sourceRange.AutoFill(fillRange)
.Range("R4:R7").NumberFormat = "0.00"
.Range("S4:S7").NumberFormat = "0.00"
.Range("T4:T7").NumberFormat = "0.00"
.Range("U4:U7").NumberFormat = "0.00%"
.Range("V4:V7").NumberFormat = "0.00"
End With
End Sub
Sub FormatColumns(ByVal sheetname As String)
With ThisWorkbook.Worksheets(sheetname)
.Range("H:H").NumberFormat = "0.00"
.Range("I:I").NumberFormat = "0"
.Range("J:J").NumberFormat = "0"
.Range("K:K").NumberFormat = "0.00%"
.Range("L:L").NumberFormat = "0.00"
.Columns("Q:W").EntireColumn.AutoFit
.Columns("A:N").EntireColumn.AutoFit
.Columns("E:G").EntireColumn.Hidden = True
End With
End Sub
And just to provide even further context, below is the sub that is called when the user form is submitted.
Private Sub GenerateReportButton_Click()
Application.ScreenUpdating = False
Call ReportGenerator
Application.ScreenUpdating = True
If TotalsButton.Value Then
Unload Me
End If
End Sub
Sub ReportGenerator()
Dim reqnum_on As Boolean
Dim jobtitle_on As Boolean
Dim joblocation_on As Boolean
Dim jobcategory_on As Boolean
Dim recruiter_on As Boolean
Dim sheetname As String
Dim Reports As Report_Generator
Set Reports = New Report_Generator
With Reports
.RequisitionNumber = ReqNumBox.Text
.FromDate = CDate(FromBox.Text)
.ToDate = CDate(ToBox.Text)
.JobTitle = (JobTitleBox.Text)
.JobLocation = JobLocationBox.Text
.JobCategory = JobCategoryComboBox.Text
.RecruiterName = RecruiterComboBox.Text
End With
reqnum_on = False
jobtitle_on = False
joblocation_on = False
jobcategory_on = False
recruiter_on = False
sheetname = Left(Format(Reports.FromDate, "mmm d") & " to " & Format(Reports.ToDate, "mmm d") & " ", 31)
If Not Reports.RequisitionNumber = "" Then
reqnum_on = True
sheetname = Left(sheetname & "RQ", 31)
End If
If Not Reports.JobTitle = "" Then
jobtitle_on = True
sheetname = Left(sheetname & "JT", 31)
End If
If Not Reports.JobLocation = "" Then
joblocation_on = True
sheetname = Left(sheetname & "JL", 31)
End If
If Not Reports.JobCategory = "" Then
jobcategory_on = True
sheetname = Left(sheetname & "JC", 31)
End If
If Not Reports.RecruiterName = "" Then
recruiter_on = True
sheetname = Left(sheetname & "RN", 31)
End If
Reports.AddToReport (sheetname)
Reports.AdvancedFilters reqnum_on, jobcategory_on, recruiter_on, jobtitle_on, joblocation_on, sheetname
Reports.Statistics (sheetname)
Reports.FormatColumns (sheetname)
End Sub