Reputation: 33
I am having a problem using a filtered range in VBA. If I use a macro to filter the range, then use another to call a Subtotal worksheet function to find a minimum values in the first column, I get the expected minimum for the filtered range; this is what I want. This is shown here:
Sub TestFilterTrans()
Call FilterTrans("111Wall")
End Sub
Sub TestMinDate()
MsgBox MinTransDate()
End Sub
Sub FilterTrans(Inv As String)
Range("TransLabels").Select
Selection.AutoFilter
ActiveSheet.Range("Trans").AutoFilter Field:=2, Criteria1:=Inv
End Sub
Function MinTransDate()
MinTransDate = Application.WorksheetFunction.Subtotal(5, Worksheets("Transactions").Range("TransDates"))
End Function
However, if, from the sheet, I call a function to first invoke the filter procedure, and then call a function to find the minimum, it selects the minimum over the whole range, as if unfiltered, shown here:
Function IncepDate(Inv As String)
Dim d As String
Call FilterTrans(Inv)
d = MinTransDate()
Call FilterOff
IncepDate = d
End Function
Can anyone tell me why the filter does not seem to work in the second case?
Upvotes: 3
Views: 3162
Reputation: 53663
A Function is not supposed to manipulate the worksheet object. There are several questions on that topic here, but the consensus is that calling subroutines from within worksheet functions to manipulate the worksheet object is a bad idea.
I stepped through some similar code to try and replicate this.
The code executes without error, but if you step through, you will see that the autofilter is never actually applied.
I am reasonably certain this is by design, although an error/warning message would be nice.
My previous comment on a similar question:
Cells reference not working in Excel VBA 2010 Function
It is not possible to manipulate worksheet cells from a UDF called from the worksheet.
More information here:
https://stackoverflow.com/a/15647054/1467082
And here:
http://www.excel-it.com/UDF.htm
generally, subroutines can manipulate the worksheet, and functions cannot.
The exception is that functions called from within a subroutine(sometimes) can, however this is probably a bad habit to use a function for anything other than returning values to the Subroutine.
And, plenty of documentation about this from Microsoft:
http://support.microsoft.com/kb/170787
A user-defined function called by a formula in a worksheet cell cannot change the environment of Microsoft Excel. This means that such a function cannot do any of the following:
- Insert, delete, or format cells on the spreadsheet.
- Change another cell's value.
- Move, rename, delete, or add sheets to a workbook.
- Change any of the environment options, such as calculation mode or screen views.
- Add names to a workbook.
- Set properties or execute most methods.
The purpose of user-defined functions is to allow the user to create a custom function that is not included in the functions that ship with Microsoft Excel. The functions included in Microsoft Excel also cannot change the environment. Functions can perform a calculation that returns either a value or text to the cell that they are entered in. Any environmental changes should be made through the use of a Visual Basic subroutine.
During calculation, Excel examines the precedents of the cell that contains a user-defined function. If not all precedents have been calculated so far during the calculation process, Excel eventually calls the user-defined function and passes a Null or Empty cell to the function. Excel then makes sure that enough calculation passes occur for all precedents to be calculated. During the final calculation pass, the user-defined function is passed the current values of the cells. This can cause the user-defined function to be called more frequently than expected, and with unexpected arguments. Therefore, the user-defined function may return unexpected values.
For correct calculation, all ranges that are used in the calculation should be passed to the function as arguments. If you do not pass the calculation ranges as arguments, instead of referring to the ranges within the VBA code of the function, Excel cannot account for them within the calculation engine. Therefore, Excel may not adequately calculate the workbook to make sure that all precedents are calculated before calculating the user-defined function.
Upvotes: 1