简体   繁体   中英

Excel VBA can't open Workbook

First: I'm using Excel 2007, but the code has to work for Excel 2003 as well.

My problem is the following: I need to access cells in a different workbook, which may be closed. The following code can be found all around the web:

Function Foo()
    Dim cell As Range
    Dim wbk As Workbook
    Set wbk = Workbooks.Open("correct absolute path")
    ' wbk is Nothing here so the next statement fails.
    Set cell = wbk.Worksheets("Sheet1").Range("A1")
    Foo = cell.Value
    wbk.Close
End Function

sadly, wbk is Nothing after the open statement (I'd love to give a better error message, but no idea how I'd do that; what I'd give for a real IDE and an useful language :/). The absolute path is correct and points to a valid excel xlsx file.

Also I assume the best way to do this, is to "cache" the workbook and not open/close it every time the function is called? Any possible problems with that (apart from having to handle the situation when the workbook is already open obviously)?

Image while stepping through: 调试信息

I can reproduce this problem. It only happens to me when I attempt to paste this code into a user-defined function.

I believe this is by design (the quote is for XL 2003, but the same thing happens to me on XL 2010)

Using VBA keywords in custom functions

The number of VBA keywords you can use in custom functions is smaller than the number you can use in macros. Custom functions are not allowed to do anything other than return a value to a formula in a worksheet or to an expression used in another VBA macro or function. For example, custom functions cannot resize windows, edit a formula in a cell, or change the font, color, or pattern options for the text in a cell. If you include "action" code of this kind in a function procedure, the function returns the #VALUE! error.

http://office.microsoft.com/en-us/excel-help/creating-custom-functions-HA001111701.aspx

The only workaround I've found is to call this kind of code via a normal macro. Something like selecting the cells to apply it to, then looping over Selection or the like.

You can use this (similar to what Bruno Leite proposed, but much simpler to write):

Dim excelApp As New Excel.Application
excelApp.Visible = False
Set WB = excelApp.Workbooks.Open(FileName, xlUpdateLinksNever, True)

As UDFs are called repeatedly, you should make sure to do an excelApp.Quit before exiting the function (and a WB.close(False) before) to avoid having countless Excel instances running on your box.

I spent some thoughts on it and came to the conclusion that you cannot mess around with the workbooks of the current instance of excel while executing a UDF. On the other hand, opening a second instance of excel will do the job without interference.

The workaround of putting my routine into a separate macro in the workbook module, and calling that macro from the Workbook_BeforeSave code, seems to have done the trick.

I've had a similar issue, but in my case it's a "Workbooks.Open(filename)" command at the start of a small routine embedded in Workbook_BeforeSave. VBA just skips right over the line of code as if it weren't there, it doesn't even report an Err.Code or Err.Description.

The only clue for me was that it's part of the Workbook_BeforeSave routine, and the limits with Functions above seem to indicate that could be a possible cause. So I dug around further to find more details.

It seems that Workbook_BeforeSave disables Excel from opening more files, and I guess there's a good reason for doing that, since the File > Open option is still visible in the File menu, but it can't be clicked. Strangely, the Open toolbar icon/button still works, and so whilst I can manually open the file from there, I wonder if it's because it's impossible to call this action from VBA code and that's why they allowed it?

To get data from Workbook without is open, you can use this , with ADO connection.

To use in Excel 2007 change this

Microsoft.Jet.OLEDB.4.0

to

Provider=Microsoft.ACE.OLEDB.12.0

and

Extended Properties=\"Excel 8.0;HDR=Yes;\

to

Extended Properties=\"Excel 12.0;HDR=Yes;\

[]'s

You can check the error in a proper way by using the following code:

filelocation = c:\whatever\file.xlsx

On Error GoTo Handler 'this is key as if the next row returns an error while opening the file it will jump to the Handler down there.
Set wkb2 = Workbooks.Open(filelocation, ReadOnly)

Handler:
MsgBox "File " & filelocation & " does not exist or cannot be reached, please review and try again"

I know that this does not answer the question (that's why I also landed in this thread, as I cannot open the file and can't understand why is that so)

Cheers, RV

You don't have to "Set" a cell, It's part of the workbook class (as far as I know). Just use the following...

foo = wbk.Worksheets("Sheet1").Range("A1").Value

I would suggest that you open you the new workbook upon opening the calling workbook, in the worbook_open event.

You then store the new workbook reference in a global variable.

Then the function called by your cell uses the said global variable instead of trying to open a new workbook. This way you go around the limitations.

PS : Of course global variable are to be avoided, some sort of container would be better than a direct global variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM