Home » excel » vba – Cleaning Excel of #NA values

vba – Cleaning Excel of #NA values

Posted by: admin May 14, 2020 Leave a comment

Questions:

I am trying to clean a very large file of #NA Values and 0 (zero values) and I am using the following code. The objective is to reduce the file size by removing these values which are obviously not needed and to improve the file performance. It is a 50 MB file and has become unwieldy

Sub cleanna()
Dim i As Integer
Dim j As Integer


i = 7
Do While i < 1200
j = 1
Do While j < 5100
**If (Cells(i, j) = 0 Or IsError(Cells(i, j))) Then**
   Cells(i, j).Select
   Selection.ClearContents
   j = j + 1
Else
   j = j + 1
End If
Loop
i = i + 1
Loop

ActiveWorkbook.Save

End Sub

I am getting a Type Mismatch error 13 at some cells and at the line in Bold. Not sure why. Any clues? Please help. Thanks in advance.

How to&Answers:

As Taosique pointed out, the problem arises from the cells with an error being evaluated and checked for 0. Therefore, best make sure it does not have an error and then check if it’s zero.

Here’s the code I’d use for that:

Sub DeleteErrorsAndBlanks()
    Dim rngToCheck As Range
    Dim rng As Range

    'Speed up the calculation
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    Set rngToCheck = ActiveSheet.UsedRange

    'Delete all errors
    rngToCheck.SpecialCells(xlCellTypeFormulas, xlErrors).ClearContents
    rngToCheck.SpecialCells(xlCellTypeConstants, xlErrors).ClearContents

    'Delete all zeros
    For Each rng In rngToCheck
        If rng.Value = 0 Then rng.ClearContents
    Next

    'Reset application
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

End Sub

Answer:

That is because #N/A will throw an error when compared to Integer. And you don’t have to select the cell to clear its contents. Try this:

If IsError(Cells(i, j) Then
  Cells(i, j).ClearContents
Else
  If Cells(i, j) = 0 Then
    Cells(i, j).ClearContents
  End If
End If

Answer:

This is difficult to do robustly since VBA evaluates both sides of the or even if the first one is true. Also it’s not sufficient to check IsError since there are other errors like #NUM and #VALUE which you should not be catching in your True case.

What I would do is build two robust functions and reword your if to

If isZero(Cells(i, j)) Or isNA(Cells(i, j)) Then

The functions are:

Private Function isZero(ByVal rng As Excel.Range) As Boolean

    On Error GoTo error:
    If rng.Value = 0 Then
        isZero = True
        Exit Function
    End If

    'follow through to error is intentional
error:
    isZero = False

End Function


Private Function isNA(ByVal rng As Excel.Range) As Boolean

    On Error GoTo error:
    If VarType(rng.Value) = vbError Then
        If rng.Value = CVErr(xlErrNA) Then
            isNA = True
            Exit Function
        End If
    End If

    'follow through to error is intentional
error:
    isNA = False

End Function

Note the xlErrNA value which isolates the error type to #N/A.