在VBA中,如何为数组的某些元素分配相同的值?

我有兴趣知道如何在VBA中同时赋值给一个元素,一行或一列数组? 例如,我有一个像这样的3×3数组( MyArray

1 2 3 4 5 6 7 8 9 

我需要更改元素MyArray(1,1)MyArray(2,2)MyArray(1,3)MyArray(3,2)的值11或第2行的值13。以单一的陈述来做这些事情? 我以为:

Union(MyArray(1,1), MyArray(2,2), MyArray(1,3), MyArray(3,2)) = 11

 MyArray(2,1 : 2,3) = 13 

会工作,但发生错误。 我处理这个事情的方法是将数组的数据放在一个未使用的工作表上,在那里改变这些值,然后从工作表中读取这些值到像这个方法那样的数组中。 使用上面的例子,然后我使用下面的代码:

 Range("A1:C3") = MyArray: Range("A1,B2,C1,B3") = 11: MyArray = Range("A1:C3") 

 Range("A1:C3") = MyArray: Range("A2:C2") = 13: MyArray = Range("A1:C3") 

有没有其他的select,而不使用工作表或循环?

VBA,因为它不支持这样的事情。 只有一个范围才可能。

理论上….

您可以使用Evaluate以非常有限的方式执行此类操作。 要显示一些仅更改一行/列或二维数组的特定值的示例:

 Dim MyArray() As Variant Public Function MyArrayOut() As Variant MyArrayOut = MyArray End Function Sub testing() 'we are using a 5x4 (4 columns / 5 rows) array ReDim MyArray(0 To 4, 0 To 3) As Variant 'also 1 to 5 and 1 to 4 are possible.... doesn't matter Dim i As Long, j As Long 'input some numbers For i = 0 To 4 For j = 0 To 3 MyArray(i, j) = i + 5 * j + 1 Next Next [A1:D5].Value2 = MyArray Stop ' check the sheet -> should be 1 to 20 'lets add 11 to the second row MyArray = Evaluate("=IF({0;1;0;0;0},MyArrayOut()+11,MyArrayOut())") [A1:D5].Value2 = MyArray Stop ' check again. row 2 should be 13, 18, 23, 28 'set only 1,1 ; 2,2 ; 4,2 and 5,4 to 0. just keep in mind that using math will fail if ANY value is not numeric (or empty) MyArray = Evaluate("=MyArrayOut()*{0,1,1,1;1,0,1,1;1,1,1,1;1,0,1,1;1,1,1,0}") [A1:D5].Value2 = MyArray Stop 'A1, B2, B4, D5 all should be 0 'set column 3 to "abc" MyArray = Evaluate("=IF({0,0,1,0},""abc"",MyArrayOut())") [A1:D5].Value2 = MyArray Stop ' check again. column C should be just abc End Sub 

使用一个有效的IF语句允许做很多事情,但是你需要硬编码,或者是一个非常复杂的algorithm,这个algorithm“杀死”和“不循环”的想法一样好。

而且这样做会花费更多的资源,并且比直接做得慢。 你也需要一个额外的函数来将数组放入评估中。

还有一种情况是可以使用的:通过INDEX提取一行/一列。 请记住,输出仍然是一个2d数组,可以通过Application.Transpose -Trick来确定。 它是可用的原因只是事实,没有必要知道数组的大小。 这样你可以直接通过extrVar = Evaluate("=INDEX(MyArrayOut(),2,)")来提取。 而2可以通过不同的variables设置。 这样你不需要ReDim新variables(在这种情况下是extrVar )。 它只是需要变化。 这就是说,使用Application.Index您也可以在不使用Evaluate情况下实现这一点。 (这也使用更less的资源,更快)

我希望你有一个你可以用评估的方式去做这个工作的想法。

尽pipe如此,VBA本身并没有提供任何通过语法本身来一步操作数组的多个内容的方法。 (至less不是你可以用这种方式)

编辑
我几乎忘了:将一个variables的所有值设置为相同的值,像MyArray = Evaluate("=IF(MyArrayOut()="""",5,5)")将设置为5或MyArray = Evaluate("=IF(MyArrayOut()="""",""abc"",""abc"")")只包含“abc”。 要清空它,你可以使用MyArray = Evaluate("=IF(MyArrayOut()="""","""","""")")但是一个简单的ReDim without Preserve也可以在一行。

编辑2

Range("A1:C3") = MyArray: Range("A1,B2,C1,B3") = 11: MyArray = Range("A1:C3")例子,你可以用它作为自己的基础function如下:

 Public Sub multiSetSame(ByRef arr As Variant, ByVal val As Variant, ParamArray str() As Variant) Dim runner As Variant For Each runner In str arr(Split(runner, ",")(0), Split(runner, ",")(1)) = val Next End Sub Sub test() Dim MyArray(1 To 3, 1 To 4) As Long multiSetSame MyArray, 11, "1,1", "2,2", "1,3", "3,2" [A1:D3].Value2 = MyArray End Sub 

但是对于这个例子,虽然我不知道如何评估哪些值要改变,但是要么在评估时直接改变它,要么总是相同,只要编写一个工作所有的价值。 任何“解决方法”只会减慢整个过程。

如果您还有任何问题,请询问;)

我不完全理解你的问题,所以我专注于问题的标题

在VBA中,如何为数组的某些元素分配相同的值?

我不使用VBA所以我不知道,但在Ruby之前,我使用了VbScript很多,这里是一个例子,如何在VbScript中做到这一点。 我从来没有越过一个VBA脚本不能运行在VBA(反过来我做的),但谁知道..

 MyArray = array(_ array(1, 2, 3),_ array(4, 5, 6),_ array(7, 8, 9)_ ) Wscript.echo MyArray(0)(0) '1' Wscript.echo MyArray(2)(2) '9' 

编辑:正如德克所言:这个解决scheme是一个单维数组与其他数组,在我的解决scheme显示它通常更通用,它不需要被初始化,例如..

为了避免每次需要以定义的模式分配值时编写for-loops,因为我理解这个问题,所以您将不得不像这样实现一个Sub:

 SetArray(MyArray, patternStr, value) 

patternStr是将被parsing的string,并告诉Sub在哪里放置该值。 一些可能性是:

“r1” – 值转到第1行的所有列

“c2” – 值转到列2中的所有行

“全部” – 价值去所有元素

“3,2 1,1” – 值变为(3,2)和(1,1)…如果它是一个3×3的matrix,也许你会想省略模式中的逗号

你将不得不用一些VBA代码来实现这个function,至less一次,然后就可以多次调用它,而不需要太多的努力,而且很容易理解调用代码。

您可能希望以一种与空格串联的方式实现parsing器,如“r1 c2”,做所有的单个分布。

然后,你的例子变成:

 SetArray(MyArray, "1,1 2,2 1,3 3,2", 11) 

EDIT1

也可以将数组包装在自定义类实例中,以便调用变得更短:

 Set aw = New MyArrayWrapper MyArrayWrapper.array = MyArray aw.SetArray("1,1 2,2 1,3 3,2", 11) aw.SetArray("r1 c2", 12) 

如果不清楚,我会编辑。 希望能帮助到你!

我从来没有见过一种可以用矩形数组来做的语言,但是对于数组数组来说,它可以更容易一些:

 MyArray = Array( [{1, 2, 3}], [{4, 5, 6}], [{7, 8, 9}] ) MyArray(0)(1) = 11 MyArray(1) = [Column(A1:A3)*0+13] ' changes a whole "row" to 13 MyArray(2) = MyArray(1) ' copies one row to another 

参差不齐的数组的缺点(或优点)是每个数组可以有不同的大小(元素的数量),甚至是Nothing

VBA没有提供任何方法在单个语句中分配multidimensional array,所以您需要声明该数组,然后分配每个值:

 Dim MyArray(2,2) MyArray(0,0) = 1 MyArray(0,1) = 2 MyArray(0,2) = 3 MyArray(1,0) = 4 MyArray(1,1) = 5 MyArray(1,2) = 6 MyArray(2,0) = 7 MyArray(2,1) = 8 MyArray(2,2) = 9 

编辑 Slai的答案的早期版本有一个部分的解决scheme,我已经充实到避免使用锯齿状数组的解决scheme。

事实certificate,你可以在一个语句中分配一个二维数组,但是这个数组必须是Variant和1,并且只能在Excel中工作。

您可以分配单个元素,并且可以使用CopyMemory技巧分配整个“列”(但分配第一列)。 如果你需要分配整个“行”或“列”,那么你可能会更好的一个锯齿状的数组。

 Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _ lpvDest As Any, _ lpvSource As Any, _ ByVal cbCopy As Long) Sub test() 'assign a 2D array using the [] shorthand syntax for Eval myArray = [{1,2,3;4,5,6;7,8,9}] 'Change an individual value myArray(1, 2) = 11 'Change the entire first row (this ONLY works for the first row) 'Using a 1-based array assigned with []/Eval colarray = [{14,15,16}] CopyMemory myArray(1, 1), colarray(1), (UBound(colarray, 1) - LBound(colarray, 1) + 1) * 16 ' changes a whole "column" 'Change the entire first row (this ONLY works for the first row) 'Using a 0-based array assigned with Array() colarray = Array(17, 18, 19) CopyMemory myArray(1, 1), colarray(LBound(colarray, 1)), (UBound(colarray, 1) - LBound(colarray, 1) + 1) * 16 ' changes a whole "column" End Sub