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 和一个键。
- DictN 可以是一个函数,由 DictV 调用,也可以是一个 public 变量。它不能是范围限制在某处代码(子或函数)的某些未定义部分的变量。你必须让它可用。我指出,如果它是一个函数,它可以被 DictV 调用,如果它是一个 public 变量,它对 DictV 可用。所以为什么参数?
- 您似乎已将密钥识别为 "RC14"。我不熟悉 RC 表示法,现在不想学习。您可以将单元格指定为
Cell
. 的偏移量
到目前为止,您已经指定了要从中导入值的工作簿和作业sheet。单元格、行和列未定义。您的代码似乎没有暗示您的意图。
我已经努力让代码更加透明,希望能帮助你补上遗漏,让它发挥作用。
从 Option Explicit
和 Dim
语句开始。后者在 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 的错。 :-)
我有:
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 和一个键。
- DictN 可以是一个函数,由 DictV 调用,也可以是一个 public 变量。它不能是范围限制在某处代码(子或函数)的某些未定义部分的变量。你必须让它可用。我指出,如果它是一个函数,它可以被 DictV 调用,如果它是一个 public 变量,它对 DictV 可用。所以为什么参数?
- 您似乎已将密钥识别为 "RC14"。我不熟悉 RC 表示法,现在不想学习。您可以将单元格指定为
Cell
. 的偏移量
到目前为止,您已经指定了要从中导入值的工作簿和作业sheet。单元格、行和列未定义。您的代码似乎没有暗示您的意图。
我已经努力让代码更加透明,希望能帮助你补上遗漏,让它发挥作用。
从 Option Explicit
和 Dim
语句开始。后者在 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 的错。 :-)