Search code examples
vbaexcelrangesubtraction

Excel range subtraction, overlooking errors in some cells possible?


I am having trouble figuring out how to subtract two ranges from each other, some cells in range H:H have "#N/A" while in range D:D there are no errors. I know in Excel it's a simple "=H2-D2" and drag that down but I'm in the process of recording a Macro and wanted to automate the subtraction as well. So far this is what I have:

Dim quantity1, quantity2, rIntersect, Qdiff, x  As Range

Set quantity1 = Range("D:D")
Set quantity2 = Range("H:H")

Set rIntersect = Intersect(quantity1, quantity2)

For Each x In quantity1
If Intersect(rIntersect, x) Is Nothing Then
    If Qdiff Is Nothing Then
        Set Qdiff = x
    Else
        Set Qdiff = Application.Union(Qdiff, x)
    End If
End If
Next x

Range("J2").Select
Dim lastRowJ As Long
lastRowJ = Range("A" & Rows.Count).End(xlUp).Row
Range("J2").AutoFill Destination:=Range("J2:J" & lastRowJ)

Solution

  • Place this procedure in a standard code module:

    Public Sub Subtract()
        [j2:j99] = [h2:h99-d2:d99]
    End Sub
    

    If you like how that works, I'm happy to embellish it so that it is not hard-coded for 98 rows only. Let me know.

    UPDATE

    Here is a version that will deal with any number of rows. It keys off of column D. So if there are 567 numbers in column D, then you will get 567 corresponding (subtracted) results in column J.

    This assumes that the data start in row 2, and that there are no blank cells until the numbers in column D end.

    If you are going to call this from the Macro Dialog then you should keep it Public. If on the other hand you are going to call it from another procedure in the same module, then you can make it Private.

    Here is the enhanced solution:

    Public Sub Subtract()
        Dim k&
        Const F = "iferror(h2:h[]-d2:d[],0)"
        k = [count(d:d)]
        [j2].Resize(k) = Evaluate(Replace(F, "[]", k + 1))
    End Sub
    

    Note that the routine now handles the errors and places a ZERO value in column J when the corresponding value in column H is an error. If you would prefer to have something other than a ZERO (like a blank for instance) when there are errors in column H, just let me know and I'll update to whatever you want.

    UPDATE 2

    Here is how to handle displaying blanks instead of zeroes:

    Public Sub Subtract()
        Dim k&
        Const F = "iferror(if(h2:h[]-d2:d[]=0,"""",h2:h[]-d2:d[]),0)"
        k = [count(d:d)]
        [k2].Resize(k) = Evaluate(Replace(F, "[]", k + 1))
    End Sub