【发布时间】:2015-05-15 21:27:26
【问题描述】:
我正在寻找一种从任意工作簿返回值的方法(该工作簿在运行 UDF 时也不会打开),根据 UDF 中的计算定义。
伪代码:
Start by calling =someFunc(currentCell) in any cell
Function someFunc(adr As Range)
region_eval = "C" & Range(adr).Row ' where column C contains string entries, all of which have a corresponding sub-dir (see fileReference).
networkLocation = ActiveWorkbook.Path
networkPath = networkLocation & "\Locations\"
fileReference = networkPath & region_eval & "\ProductList.xlsx"
Workbook.Open fileReference readonly
Perform index/match call against some sheet in this workbook
someFunc = returned value
Close workbook and end function
这是期望的行为。
返回所需值的逻辑是可以的,我已经在一个更简单的公式中尝试过,并且在一个依赖于手动打开文件的 UDF 中:
INDEX(locationlist_$A$5000, MATCH(masterlist_A1, locationlist_$B$5000))
经过数小时的努力,我发现在设计用于处理非手动打开的工作簿的 UDF 中不能直接使用此功能,而且这是 Microsoft 方面的意图。但我也发现有一种可能的解决方法!
参考:
1.https://stackoverflow.com/a/27844592/4604845
2.http://numbermonger.com/2012/02/11/excel-pull-function-creating-dynamic-links-to-closed-workbooks/
这些解决方案需要硬编码的文件路径,这违背了我的预期用途。
有没有人知道如何通过任意文件路径(例如,包含在与调用 UDF 的单元格相邻的单元格中)实现上述两个链接中的任何一个中所实现的目标?
注意:我尝试在 sub 中进行繁重的工作,只需将 sub 作为 UDF 中的第一行调用,将结果设置为全局 var,并在 sub 完成后将 UDF 返回值设置为相同的 var ,但要么我崩溃并严重烧毁,要么 Excel 识破了我的诡计并否认了它。
编辑:
这是 sub/func 组合。
Option Explicit
Public networkLocation As String, networkPath As String, fileReference As String, c_formula As String
Public sheet_src As Worksheet, sheet As Worksheet, wb_src As Workbook, wb As Workbook
Public region_eval As String, sheetName_src As String, sheetName As String, regionPath As String, fileName As String
Sub findProductStatus(adr As Range)
networkLocation = ActiveWorkbook.Path
networkPath = networkLocation & "\Locations\"
sheetName_src = "Sheet1"
sheetName = "Sheet1"
Set wb_src = ThisWorkbook
Set sheet_src = wb_src.Sheets(sheetName_src)
region_eval = Range("I" & adr.Row)
regionPath = networkPath & region_eval
'fileReference = regionPath & "\ProductList.xlsx"
fileName = "ProductList.xlsx"
ChDir regionPath
Workbooks.Open fileName:=fileName, ReadOnly:=True
'Set wb = Workbooks.Open(fileName:=ThisWorkbook.Path & "\Locations\Test\ProductList.xlsx", ReadOnly:=True)
Set wb = Workbooks("ProductList.xlsx")
Set sheet = wb.Sheets(sheetName)
c_formula = Application.WorksheetFunction.Index(sheet.Range("$K$2:$K$5000"), Application.WorksheetFunction.Match(sheet_src.Range("A" & adr.Row), sheet.Range("$A$2:$A$5000"), 0))
End Sub
Function getProductStatus(adr As Range) As String
Call findCourseStatus(adr)
getCourseStatus = c_formula
wb.Close
End Function
我还没有针对打开的文件测试 sub/func 组合,但是当所有代码都在函数中并且手动打开有问题的文件时,它可以完美运行。单步执行代码并使用 Debug.Print,我看到即使“Workbooks.Open ...”通过没有任何明显的错误,工作簿实际上并没有被打开,因此,当我们尝试使用工作簿对象时设置工作表,函数/子终止。
【问题讨论】:
-
我找到了this 的建议,但如果可能的话,我宁愿避免它!
-
我建议发布您尝试过的
sub()的代码。有人可能会发现错误,或者至少有一些东西可以开始工作。 -
阅读你的第二个链接,有一个Morefunc add-in的引用(二级主机,好像原来的已经不见了)。如果Gary's answer 不适合您,那可能值得研究。 (我正在为它添加书签以供以后查看...)
-
This approach 允许摆脱 UDF 限制,并通过 UDF 从已关闭的工作簿中获取值。
-
IMO 您最多应该在每个工作表计算事件中打开一个工作簿。考虑通过第一次 UDF 调用打开工作簿,将打开的工作簿保存在全局或静态变量中,并在计算事件结束时关闭。否则,您可能会因 UDF 单元的数量而变慢。