Google AI produced this little gem:
Function Macro Limitations:
- Direct Interaction: Function macros (UDFs - User Defined Functions) called directly from a worksheet cell are designed to return a value to that cell and generally have restrictions on interacting with the Excel application, such as opening new workbooks or manipulating other objects.
- Solution: If the goal is to open a workbook and perform actions, consider using a Sub procedure instead of a Function. Sub procedures are designed for actions and can freely interact with the Excel application object model. If the function's result is needed in a cell, the Sub can update the cell after opening the workbook.
I was almost able to work around the problem by putting the Open call into a private Sub that the function could call (see below). Unfortunately, this only worked when I manually entered the function using F8 in the debugger. When I called the function from a cell in a worksheet, the Open still failed.
Function xyz() As Long
Dim wb As Workbook
Dim x As Long
Dim str As String
x = Workbooks.Count
MyOpen ("D:\Finance\auto.xls")
'Set wb = Workbooks(x + 1)
If wb Is Nothing Then
Debug.Print "again"
xyz = -1
Else
Debug.Print wb.Name
Debug.Print wb.Sheets("summary").Range("C275").Value
xyz = 27
End If
End Function
Private Sub MyOpen(fname As String)
Dim wb As Workbook
Debug.Print fname
Set wb = Workbooks.Open(Filename:=fname, ReadOnly:=True)
If wb Is Nothing Then Debug.Print "oops!"
End Sub
However I was able to get it to work by creating a Sub that mimicked the action of a function (see below). Basically, you select the cell to contain the value and you then invoke the Sub (ALT-F8 or a shortcut key). The Sub manually stores the result in the selected cell.
Sub abc()
Dim Here As Range
Dim wb As Workbook
Set Here = Selection
Debug.Print Here.Address
Set wb = Workbooks.Open(Filename:="D:\Finance\auto.xls", ReadOnly:=True)
If wb Is Nothing Then
Debug.Print "oops"
Exit Sub
End If
Here.Value = wb.Sheets("summary").Range("C275").Value
Debug.Print Here.Value
End Sub
Finally, if other considerations dictate the use of a function, you could create a Sub to be run once at the beginning whose only job is to open the workbook. The function could then find the workbook by searching the Workbooks collection and extracting what it needs since the workbook is already open.