Excel 公式中看不到变量

Excel Formula can't see variable in it

我有:
1.) 字典

Set DictN= CreateObject("Scripting.Dictionary")
arr = Sheet3.Range("D27", "H107").Value
For i = 1 To UBound(arr)
    DictN.Item(arr (i, 1)) = CStr(arr (i, 5))
Next

2.) Public ThisWorkbook 中的函数 returns 来自字典的值。

Public Function DictV(Dict As Object, Key As String)
    If InStr(1, Key, " flash") > 0 Then Key= Left(Key, InStr(1, Key, " flash") - 1)
    DictV = Dict(Key)
End Function

3.) 非常糟糕的代码,其中一部分似乎不起作用

With Sheet2
        .Range("AD2:AD" & NumR).FormulaR1C1 = "=Test.xls!DictV(" & DictN & ",RC14)"
        .Range("AD2:AD" & NumR) = .Range("AD2:AD" & NumR).Value
End With

我得到的:
1.) 公式 returns 不正确的值,我猜是因为它在我的 udf.
中看不到变量 有什么建议可以纠正吗?
这对我也没有帮助。
更新:
现在我得到 运行 时间错误“405”,因为它不会变得更糟

很难说您的代码更正可能从哪里开始,但很容易同意您指定为错误的部分已被正确诊断。这是它的一个稍微好一点的版本。

Dim WsSource As Worksheet
Dim Cell As Range

Set WsSource = Workbooks("Test.xls").Sheets(DictV(DictN, Key))
For Each Cell In Sheet2.Range("AD2", "AD" & NMR)
    Cell.Value = ws.Cells([Row], [Column]).Value
Next Cell

不要屏住呼吸。不行,但比原来更能暴露缺点

首先,我建议不要创建工作sheet公式来获取数据,然后将公式转换为数据。数据可以直接写入单元格。

所以,我创建了对象 WsSource。我希望我正确理解了您的意图:sheet 名称将从字典中提取。你应该自己测试 DictV(DictN, Key) 并让它工作,因为这是篮子里的坏苹果。函数 DictV 需要字典 DictN 和一个键。

  1. DictN 可以是一个函数,由 DictV 调用,也可以是一个 public 变量。它不能是范围限制在某处代码(子或函数)的某些未定义部分的变量。你必须让它可用。我指出,如果它是一个函数,它可以被 DictV 调用,如果它是一个 public 变量,它对 DictV 可用。所以为什么参数?
  2. 您似乎已将密钥识别为 "RC14"。我不熟悉 RC 表示法,现在不想学习。您可以将单元格指定为 Cell.
  3. 的偏移量

到目前为止,您已经指定了要从中导入值的工作簿和作业sheet。单元格、行和列未定义。您的代码似乎没有暗示您的意图。

我已经努力让代码更加透明,希望能帮助你补上遗漏,让它发挥作用。

Option ExplicitDim 语句开始。后者在 RAM 中分配一个地址,基本上是一个 "house" 数字,并将其与名称相关联。名称更容易识别,但 VBA 会将您提供的名称翻译成数字,因为这是它在 RAM 中查找内容的方式。 Dim语句用于"declare"一个变量。

如果您省略声明,VBA 将创建您命名的变量,始终作为 Variants。 Option Explicit 选项禁止自动声明,这是一件好事,可以避免你过早变得大胆。

通过您用来声明变量的方法,您可以确定它的 "scope" 或 "visibility"。在过程中声明的任何内容仅在该过程中可见。模块级别的声明,而不是任何过程内的声明,在声明它们的模块中是可见的,如果它们被声明为 Public,它们将在项目的任何地方可见。这里有一些例子。

Sub CreateDict()

    Dim DictN As Object
    Dim Arr As Variant
    Dim i As Long

    Set DictN = CreateObject("Scripting.Dictionary")
    Arr = Sheet3.Range("D27", "H107").Value
    For i = 1 To UBound(Arr)
        DictN.Item(Arr(i, 1)) = CStr(Arr(i, 5))
    Next
End Sub

如您所见,变量 DictN 是在 sub 中声明的。它仅对该子程序中的代码可见,对其他地方不可见。在下一个示例中,同名变量在过程外部声明(最好在模块顶部)。

    Dim DictN As Object

Sub SetDict()

    Dim Arr As Variant
    Dim i As Long

    Set DictN = CreateObject("Scripting.Dictionary")
    Arr = Sheet3.Range("D27", "H107").Value
    For i = 1 To UBound(Arr)
        DictN.Item(Arr(i, 1)) = CStr(Arr(i, 5))
    Next
End Sub

观察变量没有在子程序中声明。它已经存在,因为它是在模块的顶部声明的,而 sub 只是使用它。 DictN 在声明它的整个模块中可用,但在其他模块中不可用。过程 SetDict 分配给它的值即使在 sub 具有 运行 之后仍保留在字典(对象)中。其实sub就是用来加载的

在下一个示例中,字典是从函数返回的。

Private Function Dict() As Object

    Dim Fun As Object                   ' Function return value
    Dim Arr() As Variant
    Dim i As Long

    Set Fun = CreateObject("Scripting.Dictionary")
    Arr = Sheet3.Range("D27", "H107").Value

    For i = 1 To UBound(Arr)
        Fun.Item(Arr(i, 1)) = CStr(Arr(i, 5))
    Next

    Set Dict = Fun
End Function

该函数是 Private,这意味着它在它所在的模块中是可见的。如果你想从其他模块调用它,你必须将它声明为 Public。实际上 VBA 的默认值是 Public。因此,如果您省略 Private 这个词,默认情况下它将是 public。

只要模块级变量 DictN 存在,您就可以在模块的任何位置编写类似 MyString = DictN(Key) 的代码。您还可以编写 MyString = Dict(Key) 之类的代码,也可以在模块中存在函数 Dict 的任何位置。不同之处在于,该函数将在每次调用时创建字典,而变量 DictN 很可能被加载一次,然后被重新使用。

请注意,如果您在同一模块中有示例 1 和示例 2,则代码将无法编译,因为对象 DictN 在过程级别和模块级别均已声明。您只能使用一个名称一次。 (请记住,某些名称由 VBA 本身使用。)

您的代码(在没有声明的情况下提供给我们)似乎具有我的示例 #1 的结构。 DictN 在过程级别声明,因此在另一个过程中不可用。当然,除非您根本没有声明它,而是相信 VBA 会为您完成这项工作。它做了。当您第一次使用它时,您在过程级别创建了名称,并且创建了一个过程级别变量。您希望它在其他地方也可用并不是 VBA 的错。 :-)