Arrays 在VBA中,如何在一条语句中写入多维数组的一个D?
如何在一条语句中编写多维数组的整个维度 编辑2: 澄清: 只需更新VBA数组的一个切片(垂直或水平),而无需循环/处理整个数组Arrays 在VBA中,如何在一条语句中写入多维数组的一个D?,arrays,vba,excel,Arrays,Vba,Excel,如何在一条语句中编写多维数组的整个维度 编辑2: 澄清: 只需更新VBA数组的一个切片(垂直或水平),而无需循环/处理整个数组 我假设我们需要将二维数组转换为一维数组,或者将一维数组转换为二维数组。我不确定这是否必要 我的示例使用工作表范围作为源,但不要因此而分心。我不是在尝试更新工作表,而是在尝试更新数组。我寻求的解决方案不应要求工作表读/写 编辑1:我在VBA中有一个2D数组。它包含从工作表中拉入的单元格数据: dim blockData blockData = [a1:d10] 现在
- 我假设我们需要将二维数组转换为一维数组,或者将一维数组转换为二维数组。我不确定这是否必要
- 我的示例使用工作表范围作为源,但不要因此而分心。我不是在尝试更新工作表,而是在尝试更新数组。我寻求的解决方案不应要求工作表读/写
dim blockData
blockData = [a1:d10]
现在,我想将不同的单元格区域复制到该数组中,只覆盖一行:
dim rowData
' just one row of data, but same width as 2D blockData
rowData = [a20:d20]
' load into array, overwriting row 3 with this new data.
' This is the one-liner i seek:
blockData(3,) = rowData
那么,如何在一条语句中将整个1D数组写入2D数组的一个D,而不进行循环呢
一些想法:
- 我可以使用索引技巧从数组中获取单个列。也许可以通过某种方式加以利用: colArray=WorksheetFunction.Index(rangeArray,0,1) colArray(1,2)=“新单元格值”
- 使用转置(colArray),但到目前为止还没有帮助
- 使用Redim Preserve以某种方式组合阵列,但不确定如何组合 那会有帮助的
- 使用VarPtr将我的更改目录写入原始数组,但是 我不确定没有循环就可以做到这一点
- 在一条语句中将整个数组复制到另一个变量是很容易的。也许可以通过某种方式加以利用:
尺寸a1、a2
a1=数组(1,2,3)
a2=a1
thx在VBA中,二维数组中的列/行没有一个线性行来更新,您必须循环 你有选择。如果您希望留在VBA中,并且希望保持简短,唯一的方法是创建一个为您循环的函数:
Function RowSwap(Arr1, Arr2, Row) As Variant
For col = LBound(Arr1, 2) To UBound(Arr1, 2)
Arr1(Row, col) = Arr2(1, col)
Next col
RowSwap = Arr1
End Function
然后您可以在VBA中编写以下内容:
blockData = RowSwap(blockData, rowData, 3)
这就是您需要的,用rowData
覆盖blockData
的第3行
否则,我认为更改工作表中的源数据是最好的,如果有必要,可以在临时工作表中更改源数据。您可以尝试这种技术,通过使用
Evaluate
和针对源范围的数组公式填充数组。数组公式包含一个IF语句,用于检查目标单元格的行或列,这意味着您可以隔离数组的特定行或列,并在将其映射回源区域之前对其进行更改
请参见下面的示例代码。请注意,中间的一行基本上就是您问题的答案“那么,如何在一条语句中将整个1D数组写入2D数组的一个D,而不循环?”
您可以进行更复杂的示例,但该技术似乎需要评估
,而不是[]
速记:
Dim rngArray As Range
Dim strAddress As String
Dim varRange As Variant
Dim strUpdateValue As String
Dim intTargetRow As Integer
Dim intTargetColumn As Integer
' set array from range - 7 rows x 5 columns of 1s
Set rngArray = Sheet1.Range("D1:H7")
' get full address else Evaluate uses Activesheet
strAddress = rngArray.Address(External:=True)
' update a row e.g IF(ROW(D1:H7)=4,"Robin",D1:H7)
strUpdateValue = "Robin"
intTargetRow = 4
varRange = Evaluate("IF(ROW(" & strAddress & ")=" & intTargetRow & ",""" & strUpdateValue & """," & strAddress & ")")
' set back to range
rngArray.Value = varRange
' update a column e.g IF(COLUMN(D1:H7)=5,"Robin",D1:H7)
strUpdateValue = "Robin"
intTargetColumn = 5
varRange = Evaluate("IF(COLUMN(" & strAddress & ")=" & intTargetColumn & ",""" & strUpdateValue & """," & strAddress & ")")
' set back to range
rngArray.Value = varRange
--如果是元数组(数组数组数组),则可以在单个语句中更新单个行:
ArrayOfArrays(12)=新行数组
--如果是2D数组,则可以使用CopyMemory更新单个列。不适合心脏虚弱的人,如果你做错了,你可能会崩溃(别忘了清理部分)。我还没有弄清楚细节,但有一些线索:
您好,谢谢您的回复,但您不明白我的问题。请看更新的问题,谢谢。@johny为什么我想我理解你的问题。我仍然认为最好在Excel工作表中进行更改,而不是在VBA中进行更改。此解决方案完全在VBA中,但无法避免循环,循环是访问整个数组行/列Shello、thx以获取答复的唯一方法,但您不理解我的问题。请看更新的问题,谢谢。@johnywhy-我想我确实理解了这个问题。我在回答中提出的方法会在将值从范围分配给数组时更改数组值的一部分(例如,列、行或其他部分)。然后,只需从数组中重新分配到范围。赋值是通过引用源范围的数组公式作为一个一行完成的。我认为这符合您的要求。您的两个Evaluate语句似乎用数据加载整个2D数组,而不是一列或一行。尽管公式仅更改单个行或列,但仍将整个二维栅格加载到阵列中。顺便说一句,在范围变量名中使用“array”一词,在数组变量名中使用“range”一词会使代码更难理解。我建议:rngData和aryData。@johnywhy-注意命名约定。我同意我的建议不是100%,因为它不允许在从范围中加载数组的行/列后对其进行操作。我不确定这是否可能。可能的情况是,在加载数组时管理该数组的行/列,这就是我所演示的。祝你一切顺利,罗宾
Dim rngArray As Range
Dim strAddress As String
Dim varRange As Variant
Dim strUpdateValue As String
Dim intTargetRow As Integer
Dim intTargetColumn As Integer
' set array from range - 7 rows x 5 columns of 1s
Set rngArray = Sheet1.Range("D1:H7")
' get full address else Evaluate uses Activesheet
strAddress = rngArray.Address(External:=True)
' update a row e.g IF(ROW(D1:H7)=4,"Robin",D1:H7)
strUpdateValue = "Robin"
intTargetRow = 4
varRange = Evaluate("IF(ROW(" & strAddress & ")=" & intTargetRow & ",""" & strUpdateValue & """," & strAddress & ")")
' set back to range
rngArray.Value = varRange
' update a column e.g IF(COLUMN(D1:H7)=5,"Robin",D1:H7)
strUpdateValue = "Robin"
intTargetColumn = 5
varRange = Evaluate("IF(COLUMN(" & strAddress & ")=" & intTargetColumn & ",""" & strUpdateValue & """," & strAddress & ")")
' set back to range
rngArray.Value = varRange