我有什么:
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。)ThisWorkbook中的公共函数,它从字典中返回值。
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.)公式返回不正确的值,我的猜测是因为它无法在我的udf中看到变量。
有任何建议如何纠正吗?
use variable in excel formula这对我也没有帮助
的 UPD:
现在我得到运行时错误'405',因为它不会变得更糟
答案 0 :(得分:0)
很难说您的代码可能会在何处开始纠正,但很容易同意您指定为错误的部分已被正确诊断。这是一个稍好的版本。
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
不要屏住呼吸。它不起作用,但它在展示它的缺点方面比它原来更好。
首先,我建议不要创建工作表公式来获取数据,然后将公式转换为数据。数据可以直接写入单元格。
所以,我创建了对象WsSource
。我希望我能正确理解你的意图:从字典中提取工作表名称。你应该自己测试DictV(DictN, Key)
并让它发挥作用,因为这是篮子中的坏苹果。函数DictV需要字典DictN以及密钥。
Cell
的偏移量。到目前为止,您已指定了要导入值的工作簿和工作表。单元格,行和列未定义。你的代码似乎没有暗示你的意图。
我试图让代码更加透明,希望能帮助您填补遗漏并使其有效。
答案 1 :(得分:0)
从Option Explicit
和Dim
语句开始。后者在RAM中分配一个地址,基本上是一个“house”号,并将其与一个名称相关联。名称更容易识别,但VBA会将您提供的名称转换为数字,因为这是在RAM中查找内容的方式。 Dim
语句用于“声明”变量。
如果省略声明,VBA将在您为其命名时创建变量,始终为变体。 Option Explicit
选项会禁止自动声明,这是一件好事,可以防止您过早地变为粗体。
通过用于声明变量的方法,您可以确定其“范围”或“可见性”。在过程中声明的任何内容仅在该过程中可见。模块级别的声明,而不是任何过程内部的声明,是声明它们的模块的可见吞吐量,如果它们被声明为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中声明。它已经存在,因为它是在模块的顶部声明的,而sub只是使用它。 DictN在声明它的整个模块中可用,但在其他模块中不可用。即使在子运行之后,过程SetDict
分配给它的值仍保留在字典(对象)中。实际上,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
,默认情况下它将是公开的。
如果模块级变量MyString = DictN(Key)
存在,您可以在模块的任何位置编写DictN
之类的代码。您还可以编写MyString = Dict(Key)
之类的代码,也可以在函数Dict
所在的模块的任何位置编写代码。不同之处在于,函数将在每次调用时创建字典,而变量DictN
最有可能被加载一次,然后被重用。
注意,如果在同一模块中有示例1和2,则代码将无法编译,因为对象DictN在过程级别和模块级别都被声明。您只能使用一次名称。 (请记住,VBA本身会使用某些名称。)
您的代码(在没有声明的情况下提供给我们)似乎具有我的示例#1的结构。 DictN
在过程级别声明,因此在另一个过程中不可用。当然,除此之外,您可能根本没有声明它,相信VBA会为您完成这项工作。它做了。您在第一次使用它时创建了过程级别的名称,并创建了过程级别变量。你期望它在其他地方也可用,这不是VBA的错。 : - )