3
\$\begingroup\$

Most of the VBA I write is to produce tabulated reports from spreadsheet data.

So, here is my attempt at creating a CLS_Data_Report class.


Properties:

a 2-dimensional Data Array

3 dictionaries to, respectively:

  • Map headers to column indexes

  • Map external (user-set) descriptions to data headers

  • Store number formatting for columns (by header)

And the PrintRange (for other visual formatting, e.g. row-colouring)


Key Methods:

  • Add Data to the Array (options for merging, overwriting, replacing)

  • Create a filtered report based on a single columns' values

  • Print the report to a worksheet (and set number formatting)


What I would especially like to know is, is this a good abstraction? (Is it too high, not high enough, is it trying to do too much, not enough?)

As always, any other feedback is greatly appreciated.


Properties and Class_Initialize

Option Explicit

Private pReportData As Variant '/ Data Array

Private pMapDescriptionsToHeaders As Scripting.Dictionary
Private pColumnIndexesOfHeaders As Scripting.Dictionary
Private pNumberFormatsOfHeaderColumns As Scripting.Dictionary

Private pPrintRange As Range

'/============================================================================================================================================================
Private Sub Class_Initialize()

    pReportData = Array()

    Set pMapDescriptionsToHeaders = New Scripting.Dictionary
    Set pNumberFormatsOfHeaderColumns = New Scripting.Dictionary
    Set pColumnIndexesOfHeaders = New Scripting.Dictionary

End Sub

Property Get/Set

'/============================================================================================================================================================
Public Property Get printRange() As Range
    Set printRange = pPrintRange
End Property
Public Property Set printRange(ByRef printRange As Range)
    Set pPrintRange = printRange
End Property

'/============================================================================================================================================================
Public Property Get reportData() As Variant
    reportData = pReportData
End Property
Public Property Set reportData(ByRef inputArray As Variant)
    pReportData = inputArray
End Property

'/============================================================================================================================================================
Public Property Get MapDescriptionsToHeaders() As Scripting.Dictionary
    Set MapDescriptionsToHeaders = pMapDescriptionsToHeaders
End Property
Public Property Set MapDescriptionsToHeaders(ByRef descriptions As Scripting.Dictionary)
    Set pMapDescriptionsToHeaders = MapDescriptionsToHeaders
End Property

'/============================================================================================================================================================
Public Property Get NumberFormatsOfHeaderColumns() As Scripting.Dictionary
    Set NumberFormatsOfHeaderColumns = pNumberFormatsOfHeaderColumns
End Property
Public Property Set NumberFormatsOfHeaderColumns(ByRef numberFormats As Scripting.Dictionary)
    Set pNumberFormatsOfHeaderColumns = numberFormats 
End Property

'/============================================================================================================================================================
Public Property Get ColumnIndexesOfHeaders() As Scripting.Dictionary
    Set ColumnIndexesOfHeaders = pColumnIndexesOfHeaders
End Property
Public Property Set ColumnIndexesOfHeaders(ByRef columnIndexes As Scripting.Dictionary)
    Set pColumnIndexesOfHeaders = columnIndexes 
End Property

Main Methods

'/============================================================================================================================================================
Public Sub AddDataToReport(ByRef inputArray As Variant, ByVal mergeArrays As Boolean, Optional ByVal unidHeader As Variant, Optional ByVal overrideValues As Boolean)
    If mergeArrays Then
        If IsMissing(unidHeader) Or IsMissing(overrideValues) Then PrintErrorMessage "Merge Arrays is specified but required arguments are not supplied"
    End If

    If ArrayIsAllocated(pReportData) Then
        WriteDataToArray inputArray, mergeArrays, unidHeader, overrideValues
    Else
        ReplaceDataArray inputArray
    End If
End Sub

Public Sub WriteDataToArray(ByRef inputArray As Variant, ByVal mergeArrays As Boolean, Optional ByVal unidHeader As Variant, Optional ByVal overrideValues As Boolean)

    If mergeArrays Then
        Dim unidRows As Scripting.Dictionary
        Set unidRows = CreateDictOfUnidRowNumbers(inputArray, unidHeader)
    End If

    Dim targetArray As Variant
    targetArray = pReportData

    '/=========================================================================================================================
    Dim inputLB1 As Long, inputUB1 As Long
    Dim inputLB2 As Long, inputUB2 As Long
    AssignArrayBounds inputArray, inputLB1, inputUB1, inputLB2, inputUB2

    Dim inputHeaderRow As Variant
    inputHeaderRow = RowFrom2dArray(inputArray, inputLB1)

    '/=========================================================================================================================
    Dim targetLB1 As Long, targetUB1 As Long
    Dim targetLB2 As Long, targetUB2 As Long
    AssignArrayBounds targetArray, targetLB1, targetUB1, targetLB2, targetUB2

    Dim targetHeaderRow As Variant
    targetHeaderRow = RowFrom2dArray(targetArray, targetLB1)

    '/=========================================================================================================================
    Dim i As Long, j As Long, k As Long
    Dim ix As Long, iy As Long

    Dim inputHeader As Variant, targetHeader As Variant
    Dim inputCol As Long, targetCol As Long
    Dim inputRow As Long, targetRow As Long
    Dim inputValue As Variant

    If mergeArrays Then
        Dim unid As Variant, unidCol As Long
        unidCol = IndexIn1dArray(inputHeaderRow, unidHeader)
    End If

    Dim headerMatchFound As Boolean, addValue As Boolean

    '/ Add any missing headers
    For iy = inputLB2 To inputUB2
        inputCol = iy
        inputHeader = inputArray(inputLB1, inputCol)

        targetCol = targetLB2 - 1
        headerMatchFound = False
        For i = targetLB2 To targetUB2
            targetHeader = targetArray(targetLB1, i)
            If inputHeader = targetHeader Then
                headerMatchFound = True
                targetCol = i
                Exit For
            End If
        Next i

        If Not headerMatchFound Then
            targetUB2 = targetUB2 + 1
            ReDim Preserve targetArray(targetLB1 To targetUB1, targetLB2 To targetUB2)
            targetArray(targetLB1, targetUB2) = inputHeader
            SetColumnIndexOfHeader targetUB2, inputHeader
            targetCol = targetUB2
        End If

    Next iy

    Set ColumnIndexesOfHeaders = Me.ColumnIndexesFromHeadersInArray(targetArray)

    '/ Add Values
    targetHeaderRow = RowFrom2dArray(targetArray, targetLB1)
    targetArray = Transpose2dArray(targetArray)

    addValue = True
    For ix = inputLB1 + 1 To inputUB1
        inputRow = ix
        inputValue = inputArray(inputRow, inputCol)

        If mergeArrays Then

            unid = inputArray(ix, unidCol)
            If Not unidRows.Exists(unid) Then
                targetUB1 = targetUB1 + 1
                ReDim Preserve targetArray(targetLB2 To targetUB2, targetLB1 To targetUB1)
                targetRow = targetUB1
            Else
                targetRow = unidRows.item(unid)
            End If

            addValue = Not (IsEmptyNothingOrNull(inputValue) And overrideValues)
        Else
            addValue = True
            targetUB1 = targetUB1 + 1
            ReDim Preserve targetArray(targetLB2 To targetUB2, targetLB1 To targetUB1)
            targetRow = targetUB1
        End If

        If addValue Then
            For iy = inputLB2 To inputUB2
                inputCol = iy
                inputHeader = inputArray(inputLB1, inputCol)
                targetCol = ColumnIndexesOfHeaders.item(inputHeader)

                inputValue = inputArray(inputRow, inputCol)
                targetArray(targetCol, targetRow) = inputValue
            Next iy
        End If
    Next ix

    targetArray = Transpose2dArray(targetArray)
    pReportData = targetArray

End Sub

'/============================================================================================================================================================
Public Sub PrintToWorksheet(ByRef startCell As Range)

    Dim currentBook As Workbook, currentSheet As Worksheet
    Set currentBook = ActiveWorkbook
    Set currentSheet = ActiveSheet

    Dim printBook As Workbook, printSheet As Worksheet
    Set printSheet = startCell.Worksheet
    Set printBook = printSheet.Parent

    printBook.Activate
    printSheet.Activate

    Print2dArrayToSheet printBook, printSheet, pReportData, startCell

    Dim LB1 As Long, UB1 As Long
    Dim LB2 As Long, UB2 As Long
    AssignArrayBounds pReportData, LB1, UB1, LB2, UB2

    Dim firstCol As Long, lastCol As Long
    Dim firstRow As Long, lastRow As Long
    firstCol = startCell.Column
    firstRow = startCell.row
    lastCol = firstCol + (UB2 - LB2)
    lastRow = firstRow + (UB1 - LB1)

    Set printRange = printSheet.Range(startCell, Cells(lastRow, lastCol))

    Dim col As Long
    Dim columnRange As Range
    Dim header As Variant
    Dim formatString As String
    For col = firstCol To lastCol
        With printSheet
            header = .Cells(firstRow, firstCol)
            If NumberFormatsOfHeaderColumns.Exists(header) Then
                Set columnRange = .Range(Cells(firstRow, col), Cells(lastRow, col))
                formatString = NumberFormatsOfHeaderColumns.item(header)
                columnRange.NumberFormat = formatString
            End If
        End With
    Next col

    currentBook.Activate
    currentSheet.Activate

End Sub

Auxilary Methods

'/============================================================================================================================================================
Public Sub SetDescriptionOfHeader(ByVal description As String, ByVal header As Variant)
    pMapDescriptionsToHeaders.item(description) = header
End Sub

Public Function GetHeaderFromDescription(ByVal description As String) As Variant
    If IsObject(pMapDescriptionsToHeaders.item(description)) Then
        Set GetHeaderFromDescription = pMapDescriptionsToHeaders.item(description)
    Else
        GetHeaderFromDescription = pMapDescriptionsToHeaders.item(description)
    End If
End Function

'/============================================================================================================================================================
Public Sub SetColumnIndexOfHeader(ByVal colIndex As Long, ByVal header As Variant)
    pColumnIndexesOfHeaders.item(header) = colIndex
End Sub
Public Function GetColumnIndexOfHeader(ByVal header As Variant)
    GetColumnFormattingOfHeader = pColumnIndexesOfHeaders.item(header)
End Function

'/============================================================================================================================================================
Public Sub SetColumnFormattingOfHeader(ByVal header As Variant, ByVal formatString As String)
    pColumnIndexesOfHeaders.item(header) = formatString
End Sub
Public Function GetColumnFormattingOfHeader(ByVal header As Variant) As String
    GetColumnFormattingOfHeader = pColumnIndexesOfHeaders.item(header)
End Function

'/============================================================================================================================================================
Public Function ColumnIndexesFromHeadersInArray(ByRef inputArray As Variant) As Scripting.Dictionary
    Dim dict As Scripting.Dictionary
    Set dict = New Scripting.Dictionary

    Dim ixHeaderRow As Long, LB2 As Long, UB2 As Long
    AssignArrayBounds inputArray, LB1:=ixHeaderRow, LB2:=LB2, UB2:=UB2

    Dim header As Variant, columnIndex As Long
    Dim iy As Long

    For iy = LB2 To UB2
        columnIndex = iy
        header = inputArray(ixHeaderRow, iy)
        dict.item(header) = columnIndex
    Next iy

    Set ColumnIndexesFromHeadersInArray = dict
End Function

'/============================================================================================================================================================
Public Function CreateDictOfUnidRowNumbers(ByRef inputArray As Variant, ByVal unidHeader As Variant) As Scripting.Dictionary
    Dim dict As Scripting.Dictionary
    Set dict = New Scripting.Dictionary

    Dim LB1 As Long, UB1 As Long
    AssignArrayBounds inputArray, LB1, UB1

    Dim ixUnidColumn As Long
    ixUnidColumn = pColumnIndexesOfHeaders.item(unidHeader)

    Dim unid As Variant, row As Long

    For row = LB1 To UB1
        unid = inputArray(row, ixUnidColumn)
        If dict.Exists(unid) Then
            '/ TODO: Error Handling
            Stop
        Else
            dict.item(unid) = row
        End If
    Next row

    Set CreateDictOfUnidRowNumbers = dict
End Function

'/============================================================================================================================================================
Public Sub ReplaceDataArray(ByRef inputArray As Variant)
    Erase pReportData
    pReportData = inputArray

    Set pColumnIndexesOfHeaders = ColumnIndexesFromHeadersInArray(pReportData)
End Sub

'/============================================================================================================================================================
Public Function GetFilteredReport(ByRef sourceReport As CLS_Data_Report, ByVal columnHeader As Variant, ByVal operator As ComparisonOperator, ByVal comparisonValue As Variant, ByVal keepOrRemoveOnTrue As KeepOrRemove) As CLS_Data_Report
    Dim filteredReport As CLS_Data_Report
    Set filteredReport = sourceReport.CloneProperties(sourceReport)

    Dim filterColumn As Long
    filterColumn = pColumnIndexesOfHeaders.item(columnHeader)

    Dim dataArray As Variant

    dataArray = filteredReport.reportData

    dataArray = KeepOrRemoveArrayRowsWhereComparisonIsTrue(dataArray, filterColumn, operator, comparisonValue, hasHeaders:=True, keepOrRemoveOnTrue:=keepOrRemoveOnTrue)

    filteredReport.ReplaceDataArray dataArray

    Set GetFilteredReport = filteredReport
End Function

'/==============================================================================
Public Function CloneProperties(ByRef sourceReport As CLS_Data_Report) As CLS_Data_Report
    Dim clonedReport As CLS_Data_Report
    Set clonedReport = New CLS_Data_Report

    Set clonedReport.printRange = sourceReport.printRange
    Set clonedReport.reportData = sourceReport.reportData
    Set clonedReport.MapDescriptionsToHeaders = sourceReport.MapDescriptionsToHeaders
    Set clonedReport.ColumnIndexesOfHeaders = sourceReport.ColumnIndexesOfHeaders
    Set clonedReport.NumberFormatsOfHeaderColumns = sourceReport.NumberFormatsOfHeaderColumns

    Set CloneProperties = clonedReport
End Function

Used Methods from my "Standard Methods" Module

Option Explicit

Public Enum ComparisonOperator
    NotEqualTo = 0
    LessThan = 1
    LessThanOrEqualTo = 2
    EqualTo = 3
    GreaterThanOrEqualTo = 4
    GreaterThan = 5
End Enum

Public Enum KeepOrRemove
    Remove = 0
    Keep = 1
End Enum

Public Function GetWorkbook(ByVal wbFilename As String, Optional ByVal wbFilePath As String) As Workbook

    Dim wbIsOpen As Boolean
    wbIsOpen = IsWorkbookOpen(wbFilename)

    If wbIsOpen Then
        Set GetWorkbook = Workbooks(wbFilename)
    Else
        If Len(wbFilePath) = 0 Then PrintErrorMessage "Workbook (" & wbFilename & ") is not open, and no filepath was supplied", stopExecution:=True
        Set GetWorkbook = Workbooks.Open(wbFilePath & wbFilename)
    End If

End Function

Public Function IsWorkbookOpen(ByVal wbFilename As String) As Boolean
'/ Credit to @Mat's Mug [http://codereview.stackexchange.com/users/23788/mats-mug] for suggesting improvements here [http://codereview.stackexchange.com/questions/114156/get-workbook-methods]

    On Error GoTo CleanFail:
    IsWorkbookOpen = Not Workbooks(wbFilename) Is Nothing

CleanExit:
    Exit Function
CleanFail:
    Err.Clear
    Resume CleanExit

End Function

Public Sub AssignArrayBounds(ByRef Arr As Variant, _
    Optional ByRef LB1 As Variant, Optional ByRef UB1 As Variant, _
    Optional ByRef LB2 As Variant, Optional ByRef UB2 As Variant, _
    Optional ByRef LB3 As Variant, Optional ByRef UB3 As Variant, _
    Optional ByRef LB4 As Variant, Optional ByRef UB4 As Variant, _
    Optional ByRef LB5 As Variant, Optional ByRef UB5 As Variant)

    If Not IsMissing(LB1) Then LB1 = LBound(Arr, 1)
    If Not IsMissing(UB1) Then UB1 = UBound(Arr, 1)

    If Not IsMissing(LB2) Then LB2 = LBound(Arr, 2)
    If Not IsMissing(UB2) Then UB2 = UBound(Arr, 2)

    If Not IsMissing(LB3) Then LB3 = LBound(Arr, 3)
    If Not IsMissing(UB3) Then UB3 = UBound(Arr, 3)

    If Not IsMissing(LB4) Then LB4 = LBound(Arr, 4)
    If Not IsMissing(UB4) Then UB4 = UBound(Arr, 4)

    If Not IsMissing(LB5) Then LB5 = LBound(Arr, 5)
    If Not IsMissing(UB5) Then UB5 = UBound(Arr, 5)

End Sub

Public Function Transpose2dArray(ByRef sourceArray As Variant) As Variant

    Dim LB1 As Long, UB1 As Long
    Dim LB2 As Long, UB2 As Long
    Dim i As Long, j As Long

    AssignArrayBounds sourceArray, LB1, UB1, LB2, UB2

    Dim transposedArray() As Variant
    ReDim transposedArray(LB2 To UB2, LB1 To UB1)

    For i = LB1 To UB1
        For j = LB2 To UB2
            transposedArray(j, i) = sourceArray(i, j)
        Next j
    Next i

    Transpose2dArray = transposedArray

End Function

Public Function RowFrom2dArray(ByRef sourceArray As Variant, ByVal rowIndex As Long) As Variant

    Dim LB2 As Long, UB2 As Long
    Dim i As Long

    Dim rowArray As Variant
    rowArray = Array()

    AssignArrayBounds sourceArray, LB2:=LB2, UB2:=UB2
    ReDim rowArray(LB2 To UB2)

    For i = LB2 To UB2
        rowArray(i) = sourceArray(rowIndex, i)
    Next i

    RowFrom2dArray = rowArray

End Function

Public Function IndexIn1dArray(ByRef sourceArray As Variant, ByVal searchItem As Variant, Optional ByVal nthMatch As Long = 1) As Variant

    Dim ix As Long, i As Long
    Dim matchesFound As Boolean, matchCounter As Long

    Dim LB1 As Long, UB1 As Long
    AssignArrayBounds sourceArray, LB1, UB1

    matchCounter = 0
    i = LB1
    Do Until matchCounter = nthMatch Or i > UB1
        If sourceArray(i) = searchItem Then
            matchCounter = matchCounter + 1
            ix = i
        End If
        i = i + 1
    Loop

    matchesFound = (matchCounter = nthMatch)
    If matchesFound Then
        IndexIn1dArray = ix
    Else
        IndexIn1dArray = CVErr(xlErrValue)
    End If

End Function

Public Sub CloseWorkbook(ByRef wbTarget As Workbook)

    Application.DisplayAlerts = False
        wbTarget.Close
    Application.DisplayAlerts = True

End Sub

Public Function Remove2DArrayRows(ByRef sourceArray As Variant, ByRef rowListArray As Variant) As Variant

    Dim targetArray As Variant
    targetArray = Array()

    Dim LB1 As Long, UB1 As Long
    Dim LB2 As Long, UB2 As Long
    AssignArrayBounds sourceArray, LB1, UB1, LB2, UB2
    ReDim targetArray(LB2 To UB2, LB1 To LB1)

    rowListArray = SortArrayList(rowListArray, sortAscending:=True)

    Dim row As Long, col As Long
    Dim copyCounter As Long, ixListArray As Long
    copyCounter = 0
    ixListArray = LBound(rowListArray)

    For row = LB1 To UB1
        If row = rowListArray(ixListArray) Then
            ixListArray = ixListArray + 1
            If ixListArray > UBound(rowListArray) Then ixListArray = UBound(rowListArray)
        Else
            ReDim Preserve targetArray(LB2 To UB2, LB1 To LB1 + copyCounter)
            For col = LB2 To UB2
                targetArray(col, LB1 + copyCounter) = sourceArray(row, col)
            Next col

            copyCounter = copyCounter + 1
        End If
    Next row

    targetArray = Transpose2dArray(targetArray)
    Remove2DArrayRows = targetArray

End Function

Public Function KeepOrRemoveArrayRowsWhereComparisonIsTrue(ByRef sourceArray As Variant, ByVal colIndex As Long, ByVal operator As ComparisonOperator, ByVal comparisonValue As Variant, ByVal hasHeaders As Boolean, ByVal keepOrRemoveOnTrue As KeepOrRemove) As Variant

    Dim LB1 As Long, UB1 As Long
    AssignArrayBounds sourceArray, LB1, UB1

    Dim rowsToBeRemoved As Variant, removeCounter As Long
    rowsToBeRemoved = Array()
    ReDim rowsToBeRemoved(1 To 1)

    Dim ix As Long, startRow As Long
    If hasHeaders Then startRow = LB1 + 1 Else startRow = LB1

    Dim sourceValue As Variant

    Select Case keepOrRemoveOnTrue

        Case Is = KeepOrRemove.Keep
            removeCounter = 0
            For ix = startRow To UB1
                sourceValue = sourceArray(ix, colIndex)
                    If Not ComparisonIsTrue(sourceValue, operator, comparisonValue) Then
                        removeCounter = removeCounter + 1
                        ReDim Preserve rowsToBeRemoved(1 To removeCounter)
                        rowsToBeRemoved(removeCounter) = ix
                    End If
            Next ix

        Case Is = KeepOrRemove.Remove
            removeCounter = 0
            For ix = startRow To UB1
                sourceValue = sourceArray(ix, colIndex)
                    If ComparisonIsTrue(sourceValue, operator, comparisonValue) Then
                        removeCounter = removeCounter + 1
                        ReDim Preserve rowsToBeRemoved(1 To removeCounter)
                        rowsToBeRemoved(removeCounter) = ix
                    End If
            Next ix

    End Select

    sourceArray = Remove2DArrayRows(sourceArray, rowsToBeRemoved)

    KeepOrRemoveArrayRowsWhereComparisonIsTrue = sourceArray

End Function

Public Function ComparisonIsTrue(ByVal sourceValue As Variant, ByVal operator As ComparisonOperator, ByVal comparisonValue As Variant) As Boolean

    Dim isTrue As Boolean

    Select Case operator

        Case ComparisonOperator.NotEqualTo
        isTrue = (sourceValue <> comparisonValue)

        Case ComparisonOperator.LessThan
        isTrue = (sourceValue < comparisonValue)

        Case ComparisonOperator.LessThanOrEqualTo
        isTrue = (sourceValue <= comparisonValue)

        Case ComparisonOperator.EqualTo
        isTrue = (sourceValue = comparisonValue)

        Case ComparisonOperator.GreaterThanOrEqualTo
        isTrue = (sourceValue >= comparisonValue)

        Case ComparisonOperator.GreaterThan
        isTrue = (sourceValue > comparisonValue)

        Case Else
        '/ Error Handling
        Stop

    End Select

    ComparisonIsTrue = isTrue

End Function

Public Function ArrayIsAllocated(inputArray As Variant) As Boolean

    On Error Resume Next
    ArrayIsAllocated = IsArray(inputArray) And Not IsError(LBound(inputArray, 1)) And LBound(inputArray, 1) <= UBound(inputArray, 1)
    On Error GoTo 0

End Function
\$\endgroup\$
5
\$\begingroup\$

Just a quick shot at

Public Property Get MapDescriptionsToHeaders() As Scripting.Dictionary
    Set MapDescriptionsToHeaders = pMapDescriptionsToHeaders
End Property
Public Property Set MapDescriptionsToHeaders(ByRef descriptions As Scripting.Dictionary)
    Set pMapDescriptionsToHeaders = MapDescriptionsToHeaders
End Property  

you aren't assigning the descriptions As Scripting.Dictionary but you are calling the getter out of the setter which seems to be some copy&pasta bug.

\$\endgroup\$
  • \$\begingroup\$ Be aware, you have some more of these. \$\endgroup\$ – Heslacher Feb 1 '16 at 13:34
  • \$\begingroup\$ Damnit. I could've sworn I fixed those. \$\endgroup\$ – Kaz Feb 1 '16 at 13:40
  • 1
    \$\begingroup\$ A sane language wouldn't allow a Getter to not return anything. ++ \$\endgroup\$ – RubberDuck Feb 2 '16 at 10:06
2
\$\begingroup\$

This only works by sheer luck.

Public Sub AddDataToReport(ByRef inputArray As Variant, ByVal mergeArrays As Boolean, Optional ByVal unidHeader As Variant, Optional ByVal overrideValues As Boolean)
    If mergeArrays Then
        If IsMissing(unidHeader) Or IsMissing(overrideValues) Then 

I made the same mistake once upon a time. The problem is that the IsMissing() function only works for Variant types. Asking if a simple value type is missing just doesn't make sense, because they have default values.

This MVCE should highlight what I'm talking about.

Private Sub TestIsMissing(Optional bool As Boolean)
If IsMissing(bool) Then
    MsgBox "Was Missing!"
Else
    MsgBox bool
End If
End Sub

Private Sub test()
    TestIsMissing True
    TestIsMissing False
    TestIsMissing
End Sub

In short, the second half of this expression will always return False.

If IsMissing(unidHeader) Or IsMissing(overrideValues) Then

So, I believe you could remove the second half, but it's possible that it's actually a bug and you need to think harder about what it is that you're trying to check.

\$\endgroup\$
  • 1
    \$\begingroup\$ You're right, I knew about IsMissing() only applying to variants but must've forgotten it for the second argument. I guess this is why I should write Unit Tests ^^ \$\endgroup\$ – Kaz Feb 2 '16 at 11:41
  • \$\begingroup\$ You know, there's a tool for that. =;)- \$\endgroup\$ – RubberDuck Feb 2 '16 at 12:33
  • \$\begingroup\$ I know, but the code inspections bury me in 500 lines of "multiple declarations on one line" so it's easy to miss stuff (and yes, I've told it to ignore thiose, but to no avail) \$\endgroup\$ – Kaz Feb 2 '16 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.