首先:我使用的是Excel 2007,但代码也必须适用于Excel 2003。
我的问题如下:我需要访问可能已关闭的其他工作簿中的单元格。可以在网络上找到以下代码:
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
遗憾的是,wbk在开放声明之后是没有的(我想提供更好的错误信息,但不知道我是怎么做的;我为真正的IDE和有用的语言提供了什么:/) 。绝对路径是正确的,并指向有效的excel xlsx文件。
另外我假设最好的方法是“缓存”工作簿,而不是每次调用函数时都打开/关闭它?任何可能的问题(除了必须处理工作簿已经打开的情况)?
单步执行时的图像:答案 0 :(得分:6)
我可以重现这个问题。当我尝试将此代码粘贴到用户定义的函数中时,它才会发生在我身上。
我相信这是设计的(引用是针对XL 2003的,但XL 2010上的情况也是如此)
在自定义函数中使用VBA关键字
您可以在自定义函数中使用的VBA关键字数量小于您可以在宏中使用的数量。除了将值返回到工作表中的公式或另一个VBA宏或函数中使用的表达式之外,不允许自定义函数执行任何操作。例如,自定义函数无法调整窗口大小,编辑单元格中的公式或更改单元格中文本的字体,颜色或图案选项。如果在函数过程中包含此类“动作”代码,则该函数返回#VALUE!错误。
http://office.microsoft.com/en-us/excel-help/creating-custom-functions-HA001111701.aspx
我发现的唯一解决方法是通过普通的宏调用这种代码。比如选择要应用它的单元格,然后循环选择等等。
答案 1 :(得分:2)
你可以使用它(类似于Bruno Leite提出的,但编写起来要简单得多):
Dim excelApp As New Excel.Application
excelApp.Visible = False
Set WB = excelApp.Workbooks.Open(FileName, xlUpdateLinksNever, True)
由于重复调用UDF,您应该确保在退出函数之前执行excelApp.Quit(以及之前的WB.close(False)),以避免在您的盒子上运行无数的Excel实例。
我对它有一些想法并得出结论,在执行UDF时你不能乱用当前excel实例的工作簿。另一方面,打开excel的第二个实例将不受干扰地完成工作。
答案 2 :(得分:1)
要在没有打开的情况下从Workbook获取数据,您可以使用this和ADO连接。
要在Excel 2007中使用,请更改此
Microsoft.Jet.OLEDB.4.0
到
Provider=Microsoft.ACE.OLEDB.12.0
和
Extended Properties=\"Excel 8.0;HDR=Yes;\
到
Extended Properties=\"Excel 12.0;HDR=Yes;\
[]的
答案 3 :(得分:1)
将我的例程放入工作簿模块中的单独宏并从Workbook_BeforeSave代码调用该宏的解决方法似乎已经成功了。
我遇到了类似的问题,但在我的情况下,它是在Workbook_BeforeSave中嵌入的小例程开始时的“Workbooks.Open(filename)”命令。 VBA只是跳过代码行,好像它不存在一样,它甚至没有报告Err.Code或Err.Description。
对我而言唯一的线索就是它是Workbook_BeforeSave例程的一部分,而上面函数的限制似乎表明这可能是一个可能的原因。所以我进一步挖掘以找到更多细节。
似乎Workbook_BeforeSave禁止Excel打开更多文件,我猜这是有充分理由这样做的,因为文件> “文件”菜单中仍然显示“打开”选项,但无法单击该选项。奇怪的是,打开工具栏图标/按钮仍然有效,所以虽然我可以从那里手动打开文件,但我想知道是不是因为从VBA代码中调用此操作是不可能的,这就是为什么他们允许它?
答案 4 :(得分:0)
您不必“设置”一个单元格,它是工作簿类的一部分(据我所知)。只需使用以下内容......
foo = wbk.Worksheets("Sheet1").Range("A1").Value
答案 5 :(得分:0)
我建议您在worbook_open事件中打开调用工作簿时打开新工作簿。
然后,将新工作簿引用存储在全局变量中。
然后,您的单元格调用的函数使用所述全局变量,而不是尝试打开新的工作簿。这样你可以绕过限制。
PS:当然要避免使用全局变量,某种容器会比直接全局变量更好。
答案 6 :(得分:0)
您可以使用以下代码以正确的方式检查错误:
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