Excel 如何使用子元素填充(动态)数组的值
我想使用Sub读取excel工作簿中某列的值(从Excel 如何使用子元素填充(动态)数组的值,excel,vba,Excel,Vba,我想使用Sub读取excel工作簿中某列的值(从单元格(3,1))然后将数组传递给主函数,但Sub中获取的值不会返回到主函数中的数组 我目前在单元格(3,1)和(4,1)中有值,我知道子模块可以工作,因为我在子模块中放入了一个消息框,它可以读取这两个值 我试着将Sub转换成一个函数,将Sub参数的名称更改为与主函数(tru des)中的数组相同的名称,还有很多类似的东西 Option Explicit Private Sub cmd_openform_Click() '"Main" functi
单元格(3,1)
)然后将数组传递给主函数,但Sub中获取的值不会返回到主函数中的数组
我目前在单元格(3,1)
和(4,1)
中有值,我知道子模块可以工作,因为我在子模块中放入了一个消息框,它可以读取这两个值
我试着将Sub转换成一个函数,将Sub参数的名称更改为与主函数(tru des)中的数组相同的名称,还有很多类似的东西
Option Explicit
Private Sub cmd_openform_Click() '"Main" function
Dim tr_des() As String
Call getDescriptions(tr_des)
uf_TestSelector.Show vbModal 'shows properly
MsgBox tr_des(1) 'shows empty MsgBox
End Sub
Sub-getdescription(ByRef des_array()作为字符串)
尺寸描述为字符串,尺寸描述为整数
作为整数的Dim i
i=0
尺寸=1
ReDim des_阵列(大小)
执行While单元格(i+3,1)。值“”
des_数组(i)=单元格(i+3,1).值
MsgBox des_array(i)'两次都以正确的值打开MsgBox
尺寸=尺寸+1
ReDim des_阵列(大小)
i=i+1
环
端接头
我希望
MsgBox tru des(1)
从excel工作表的列返回一个值,但它总是返回一个空的MsgBox您需要使用ReDim Preserve
如果在ReDim
之后执行MsgBox des_array(i)
,您将看到值消失了:)
(不带Preserve
)将数组重新分配到指定的维度。使用ReDim Preserve
可以在不删除数组内容的情况下增加数组的大小
如果使用Preserve
关键字,则只能调整最后一个数组维度的大小,并且根本无法更改维度的数量。例如,如果数组只有一个维度,则可以调整该维度的大小,因为它是最后一个也是唯一的维度。但是,如果数组有两个或多个维度,则可以仅更改最后一个维度的大小,同时仍保留数组的内容
@DavidZemens引入了
ReDim Preserve
作为解决您的问题的一种方法。我推荐一种不同的编程方法,以避免昂贵的VBAPreserve
操作(性能损失在大型阵列上可能很明显,但在您的情况下可能并不重要)
这种方法使用了一种功能范例,其中计算了一个新的数组。下面是基于代码的简单重写
Option Explicit
Private Sub cmd_openform_Click() '"Main" function
Dim tr_des As Variant
tr_des = getDescriptions
uf_TestSelector.Show vbModal 'shows properly
MsgBox tr_des(1)
End Sub
Function getDescriptions() as Variant
Dim tValidRange as Range
Dim i As Integer
Set tValidRange = Nothing ' Not really required but nice to be explicit
i = 0
Do While Cells(i + 3, 1).Value <> ""
If tValidRange is Nothing Then
Set tValidRange = Cells(i + 3, 1)
Else
Set tValidRange = Union(tValidRange,Cells(i + 3, 1))
'Set tValidRange = tValidRange.Resize(tValidRange.Rows.COunt + 1,1) ' Alternate approach
End If
i = i + 1
Loop
getDescriptions = tValidRange.Value ' Places values into an array.
End Sub
选项显式
Private Sub cmd_openform_Click()'“Main”函数
作为变体的Dim tr_des
tr_des=getDescriptions
uf_TestSelector.Show vbModal'正确显示
MsgBox tr_des(1)
端接头
函数getDescriptions()作为变量
变暗tValidRange作为范围
作为整数的Dim i
Set tValidRange=Nothing“不是真正需要的,但是很好的明确
i=0
执行While单元格(i+3,1)。值“”
如果tValidRange什么都不是
设置tValidRange=单元格(i+3,1)
其他的
设置tValidRange=Union(tValidRange,单元格(i+3,1))
“设置tValidRange=tValidRange.Resize(tValidRange.Rows.COunt+1,1)”替代方法
如果结束
i=i+1
环
getDescriptions=tValidRange.Value'将值放入数组中。
端接头
当然,新的思维方式会导致代码的进一步细化
Function getDescriptions() as Variant
Dim tValidRange as Range
Dim tRangeToCheck as Range
Dim i As Integer
Set tValidRange = Nothing ' Not really required but nice to be explicit
Set tRangeToCheck = Cells(3,1) 'This really should be fully qualified but ...
' ... you have not provided enough information for an example.
Do While tRangeToCheck.Value <> ""
If tValidRange is Nothing Then
Set tValidRange = tRangeToCheck
Else
Set tValidRange = tValidRange.Resize(tValidRange.Rows.Count + 1,1) ' expand range down by one row.
End If
Set tRangeToCheck = tRangeToCheck.Offset(1,0) ' move down one row
Loop
getDescriptions = tValidRange.Value ' Places values into an array.
End Sub
函数getDescriptions()作为变量
变暗tValidRange作为范围
Dim tRangeToCheck as范围
作为整数的Dim i
Set tValidRange=Nothing“不是真正需要的,但是很好的明确
设置tRangeToCheck=Cells(3,1)'这确实应该是完全限定的,但是。。。
' ... 您没有为示例提供足够的信息。
在TransGetOcheck.Value“”时执行此操作
如果tValidRange什么都不是
设置tValidRange=transgetocheck
其他的
设置tValidRange=tValidRange.Resize(tValidRange.Rows.Count+1,1)“将范围向下扩展一行。
如果结束
设置tRangeToCheck=tRangeToCheck.Offset(1,0)'向下移动一行
环
getDescriptions=tValidRange.Value'将值放入数组中。
端接头
Function getDescriptions() as Variant
Dim tValidRange as Range
Dim tRangeToCheck as Range
Dim i As Integer
Set tValidRange = Nothing ' Not really required but nice to be explicit
Set tRangeToCheck = Cells(3,1) 'This really should be fully qualified but ...
' ... you have not provided enough information for an example.
Do While tRangeToCheck.Value <> ""
If tValidRange is Nothing Then
Set tValidRange = tRangeToCheck
Else
Set tValidRange = tValidRange.Resize(tValidRange.Rows.Count + 1,1) ' expand range down by one row.
End If
Set tRangeToCheck = tRangeToCheck.Offset(1,0) ' move down one row
Loop
getDescriptions = tValidRange.Value ' Places values into an array.
End Sub