Excel VBA can';不要打开工作簿

Excel VBA can';不要打开工作簿,excel,vba,Excel,Vba,第一:我使用的是Excel2007,但代码也必须适用于Excel2003 我的问题如下:我需要访问其他工作簿中的单元格,该工作簿可能已关闭。以下代码可以在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 fa

第一:我使用的是Excel2007,但代码也必须适用于Excel2003

我的问题如下:我需要访问其他工作簿中的单元格,该工作簿可能已关闭。以下代码可以在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
遗憾的是,在open语句之后,wbk什么都不是(我很想给出一个更好的错误消息,但不知道该怎么做;对于一个真正的IDE和一种有用的语言,我会给出什么:/)。绝对路径正确,并指向有效的excel xlsx文件

我还认为最好的方法是“缓存”工作簿,而不是每次调用函数时都打开/关闭它?有没有可能的问题(除了必须处理工作簿已经打开的情况)

单步执行时的图像:

若要从工作簿中获取数据,而不打开工作簿,可以使用ADO连接

要在Excel 2007中使用,请更改此

Microsoft.Jet.OLEDB.4.0

[]的

您不必“设置”单元格,它是工作簿类的一部分(据我所知)。只需使用以下命令

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

我可以重现这个问题。只有当我尝试将此代码粘贴到用户定义的函数中时,才会发生这种情况

我相信这是出于设计(该报价是针对XL 2003的,但同样的事情也发生在XL 2010上)

在自定义函数中使用VBA关键字

可以在自定义函数中使用的VBA关键字数小于可以在宏中使用的VBA关键字数。自定义函数只允许向工作表中的公式或其他VBA宏或函数中使用的表达式返回值。例如,自定义函数无法调整窗口大小、编辑单元格中的公式或更改单元格中文本的字体、颜色或图案选项。如果在函数过程中包含此类“操作”代码,函数将返回#值!错误


我发现的唯一解决方法是通过普通宏调用此类代码。类似于选择要应用它的单元格,然后在选择上循环等等。

我建议您在worbook\u open事件中打开调用工作簿时打开新工作簿

然后将新工作簿引用存储在全局变量中

然后,单元格调用的函数使用所述全局变量,而不是尝试打开新工作簿。这样你就绕过了限制


PS:当然要避免全局变量,某种容器比直接全局变量更好。

将例程放入工作簿模块中的单独宏中,并在保存代码之前从工作簿调用该宏的解决方法似乎已经奏效

我也遇到过类似的问题,但在我的例子中,这是一个“Workbooks.Open(filename)”命令,位于工作簿\u BeforeSave中嵌入的一个小例程的开头。VBA只是跳过代码行,就好像它不在那里一样,它甚至不报告Err.code或Err.Description

对我来说,唯一的线索是它是工作簿_BeforeSave例程的一部分,上面函数的限制似乎表明这可能是一个原因。因此,我进一步挖掘,以找到更多的细节

“工作簿保存前”似乎禁止Excel打开更多文件,我想这样做是有原因的,因为“文件”>“打开”选项在“文件”菜单中仍然可见,但无法单击。奇怪的是,“打开”工具栏图标/按钮仍然有效,因此虽然我可以从那里手动打开文件,但我想知道这是否是因为无法从VBA代码调用此操作,这就是他们允许的原因?

您可以使用此操作(类似于Bruno Leite的建议,但编写起来要简单得多):

由于UDF会被反复调用,您应该确保在退出函数之前执行excelApp.Quit(之前执行WB.close(False))操作,以避免在您的框上运行无数Excel实例


我对此进行了一些思考,并得出结论:在执行UDF时,您不能随意处理当前excel实例的工作簿。另一方面,打开第二个excel实例将不受干扰地完成此工作。

您可以使用以下代码以正确的方式检查错误:

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"
我知道这并不能回答这个问题(这就是为什么我也会出现在这个线程中,因为我无法打开文件,也无法理解为什么会这样)

干杯,
RV

您没有收到任何错误消息,
Open
语句什么也不返回?我试图重现你的问题,但没有成功。您必须给我们提供更多的细节和上下文。@Jean-FrançoisCorbett说“否”的错误消息是,excel只是继续执行。我看了一下,但找不到任何
GetLastError()
或类似的,并且
On Error Goto
没有指定任何异常对象?引用的内容基本上是整个函数,但我将其更改为完整函数,这可能会有所帮助。即时窗口中的“?Err.Number”和“?Err.Description”将获得有关运行时错误的信息。您需要为On error Goto提供错误处理程序。当你说“下一个语句失败”时,你的意思是你在那里遇到了运行时错误吗?如果是,什么?如果不是,单元格是否也等于零?您是否尝试过一个非常简单的路径,例如,指向我文档中的文件?@Douglancy我得到了一个
#值D:\test.xlsx
(所以权限肯定没有问题,也不会变得更简单)和我的用户文件夹。什么是即时窗口?我把“.Err.Description”作为一个watch表达式,但这显然不是你的意思,只是告诉我它是一个包含“.Err.Description”的字符串。好的,我只是在Open()语句后面加了一个
MsgBox Err.Description
Extended Properties=\"Excel 12.0;HDR=Yes;\
foo = wbk.Worksheets("Sheet1").Range("A1").Value
Dim excelApp As New Excel.Application
excelApp.Visible = False
Set WB = excelApp.Workbooks.Open(FileName, xlUpdateLinksNever, True)
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"