将垂直切片插入数组 [英] Insert vertical slices into array

查看:116
本文介绍了将垂直切片插入数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在最近的帖子我演示了如何在 Application.Index() 函数(而不是单个索引)中使用数组参数
可以在任意方向上重新排列当前列的顺序(切换列,省略/删除列)。

  Application.Index(data, {垂直行数组},{水平列数组})

这种方法不需要循环,可以获取任何新的仅通过在OP中列出新列位置来定义列顺序,例如通过

  Array(1、4、2)

换句话说



  • 第一列,

  • (第三列被省略=已删除),

  • 其余第4列和第2列按切换顺序*:


  Sub DeleteAndSwitch()
'[1]获取数据
昏暗数据:data = Sheet1.Range( A1:D4)
'[2]通过Array(1、4, 2),即省略第一列,第四列和第二列,省略第三列
'(求值将所有现有行作为垂直2维数组)
data = Application.Index(data,Evaluate( row(1:& UBound(data)&)),Array(1,4,2))
'[3]写入任何目标
Sheet2.Range( A1)。Resize(UBound(data),UBound(data,2))=数据
End Sub

询问相关评论



我可以切片 2D数组,我可以消除列,重新排序列,但我不能在这样的数组中►插入一列切片...
实际上,我可以使用迭代来做到这一点,但是您是否找到了类似的方式来插入这样的数组垂直切片?


系统提示


原样至少经常已知的给定列(例如可以通过

  Column4Data =来从数组(例如 data )中切片Application.Index(data,0,4)

最终得出基于1的2维垂直图像。


不可能 ,但是要将垂直切片分配给另一个切片;以下代码将引发1004错误(应用程序定义的错误或对象定义的错误):

  Application.Index(data,0,4)= Application.Index(data,0,1)

问题


是否有 种可能在阵列中插入列切片(无迭代)?


确实存在将此类列数据排列在临时数组阵列(锯齿状数组 )中并从该基数构建2维数组的可能性。 / p>

为了避免过分收费这篇文章,我将展示这种相当未知的方法,因为►单独的答案期待任何其他或更好的方法


相关链接
Application.Index()函数

解决方案

使用 Application.Index()<


为了完整起见,我展示了这种方法,目的是演示应用程序的另一种广泛未知的可能性。 Index()函数。


通过将(转置的)切片添加到临时数组数组,首先,可以使用以下语法通过双零 参数在第二步中创建2维数组(请参见 [ 2] b ):

  data = Application.Transpose(Application.Index(data,0, 0))


  Sub InsertSlices()
'Auth:https: //stackoverflow.com/users/6460297/tm
'[0]定义额外的数组(或从其他数据源进行切片和转置)
Dim Extra:额外= Array(100,200,300,400 )'示例数据
'[1]获取数据
暗淡数据:data = Tabelle7.Range( A1:D4)
'[2] a)将数据重写为1-dim切片列数组的数组
data = Array(Extra,Slice(data,1),Slice(data,4),Slice(data,2))
'~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
'[2] b)重建为2维数组
'~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
data = Application.Transpose(Application.Index(data,0,0))
'[3]写入任意目标
Tabelle7.Range( F1)。Re size(UBound(data),UBound(data,2))=数据
End Sub


  Function Slice(DataArr,ByVal colNo As Long)As Variant()
'目的:将整个列数据返回为2-dim数组,而
'在此处将它们转置以获得扁平具有应用程序
Slice = .Transpose(.Index(DataArr,0,colNo))的一维列数据
数组

结尾的函数

注意: 对于较大的数据集,两步重复进行数据转换会很耗时。




解决方法


因此,我希望在通过 Application.Index()函数中的► array arguments 引用的帖子,但通过在物理数据范围中插入(例如临时)列 first ,最后通过在新位置(例如,顶部)重新排列包括新添加的额外数据(最后位置)的列。

  Sub DelSwitchAndInsert()
'Auth:https://stackoverflow.com/users/6460297/tm
'[0]将其他数组数据作为最后一列添加到现有范围
Sheet1.Range( E1:E4)= Application.Transpose(Array(1、2、3、4))
'[1]获取数据
昏暗数据:d ata = Tabelle7.Range( A1:E4)
'[2]通过Array(1、4、2)重新排序,即获得第一列,第四列和第二列,省略了第三列
数据= Application.Index(data,Evaluate( row(1:; & UBound(数据)& )),Array(UBound(data,2),1、4、2))
'[3]写入任何目标
Sheet2.Range( A1)。Resize (UBound(数据),UBound(数据,2))=数据
End Sub

附录解决方案以响应最近的评论 // Edit / 2020-07-07


遵循解决方案逻辑的灵活示例,用于插入垂直额外任意给定列中的单列数据数量可以如下:我不认为这既不是最好的方法也不是最好的编码方式:

  InsCol数据,额外的3’插入,例如作为新的第三列 


  Sub InsertExtraData()
'目的:插入单列数组(2-dim,从1开始)
'[0]定义额外的数组(或从其他数据源进行切片和转置)
额外的Dim:extra = Application.Transpose(Array(100,200, 300,400))'示例数据
'[1]获取数据(或现有的2维数组)
昏暗数据:data = Sheet1.Range( A1:D4)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'[2]在>>>>>< 3 ;<
列'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InsCol数据,额外,3
'[3]写入任何目标
Sheet2.Range( A1)。Resize(UBound(data),UBound(data,2))=数据
End Sub


  Sub InsCol(data,extra,Optional ByVal colNo As Long = 1)
使用Sheets.Add
'[0]将数据添加到临时范围
中。Range( B1)。Resize(UBound(data),UBound(data,2))=数据
.Range( B1)。Offset(0,UBound(data,2))。Resize(UBound(extra)-LBound(extra)+ 1,1)=额外
'[1]获取数据
data = .Range( B1)。Resize(UBound(data),UBound(data,2)+ 1)
'[2]通过Array(5,1,2,3, 4)
data = Application.Index(data,Evaluate( row(1:& UBound(data)&))),getColNums(data,colNo))
'[3]删除临时表
Application.DisplayAlerts = False:。删除
Application.DisplayAlerts = True
E nd With
End Sub


  Function getColNums(main,可选ByVal colNo只要Long = 1)如Variant()
'cf :https://stackoverflow.com/questions/53727578/joining-two-arrays-in-vba/60082345#60082345
'购买。:返回基于0的1维数组组合的序数元素计数器
Dim i& ;, n& ;: n = UBound(main)+ 1'+1作为一列,+1从基于0的基础到基于>的
ReDim tmp(0至n-1)'redim到扩大尺寸(从零开始)
如果colNo> n然后colNo = n
如果colNo< 1然后colNo = 1
对于i = 0到colNo-1:tmp(i)= i + 1:下一个i
tmp(colNo-1)= n
对于i = colNo至UBound(tmp):tmp(i)= i:下一个i
getColNums = tmp'返回组合的元素计数器,例如Array(1,2,>> 5<,3,4)
结束函数


In a recent post I demonstrated how to use array arguments in the Application.Index() function (instead of single indices) to rearrange the current columns order in any direction (switch columns, omit/delete columns).

    Application.Index(data, {vertical rows array}, {horizontal columns array})

This approach doesn't need loops and allows to get any new column order defined just by listing the new column positions, in OP e.g. via

     Array(1, 4, 2)

in other words

  • the 1st column,
  • (the 3rd one omitted=deleted),
  • the remaining columns 4 and 2 in switched order*:

Sub DeleteAndSwitch()
'[1]get data
    Dim data: data = Sheet1.Range("A1:D4")
'[2]reorder columns via Array(1, 4, 2), i.e. get 1st column, 4th and 2nd column omitting the 3rd one
'   (evaluation gets all existing rows as vertical 2-dim array)
    data = Application.Index(data, Evaluate("row(1:" & UBound(data) & ")"), Array(1, 4, 2))
'[3]write to any target
    Sheet2.Range("A1").Resize(UBound(data), UBound(data, 2)) = data
End Sub

A related comment asked:

"I can slice a 2D array, I can eliminate column, reorder columns, but I cannot ►insert a column(s) slice in such an array... In fact, I can do it using iteration, but did you find a similar way to insert such a vertical slice?"

Methodical hints

As is at least frequently known, a given column (e.g. the 4th) can be sliced from an array (here e.g. data) via

    Column4Data = Application.Index(data, 0, 4)

resulting itself in a 1-based 2-dim "vertical" array.

It's not possible, however to assign a vertical slice to another one; the following code would raise a 1004 error (Application-defined or object-defined error):

Application.Index(data, 0, 4) = Application.Index(data, 0, 1)

Question

Is there any possibility to insert a column(s) slice in an array (without iteration)?

There does exist a possibility to arrange such column data in a temporary array of arrays ("jagged array") and to build a 2-dim array from this base.

In order not to overcharge this post I'll demonstrate this rather unknown approach as ►separate answer looking forward to any other or better approach.

Related link Some pecularities of the Application.Index() function

解决方案

Jagged array approach using Application.Index()

For the sake of completeness I show this approach in order to demonstrate a further and widely unknown possibility of the Application.Index() function.

By adding (transposed) slices to a temporary "Array of Arrays" first, it's possible to create a 2-dim array in a second step via double zero arguments using the following syntax (c.f. section [2]b):

    data = Application.Transpose(Application.Index(data, 0, 0))

Sub InsertSlices()
'Auth: https://stackoverflow.com/users/6460297/t-m
'[0]define extra array (or slice AND transpose from other data source)
    Dim Extra: Extra = Array(100, 200, 300, 400)   ' example data
'[1]get data
    Dim data: data = Tabelle7.Range("A1:D4")
'[2]a) rewrite data as 1-dim array of sliced column arrays
    data = Array(Extra, Slice(data, 1), Slice(data, 4), Slice(data, 2))
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'[2]b) rebuild as 2-dim array
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    data = Application.Transpose(Application.Index(data, 0, 0))
'[3]write to any target
    Tabelle7.Range("F1").Resize(UBound(data), UBound(data, 2)) = data
End Sub

Function Slice(DataArr, ByVal colNo As Long) As Variant()
'Purpose: return entire column data as 2-dim array and
'         transpose them here to get a "flat" 1-dim array of column data
With Application
    Slice = .Transpose(.Index(DataArr, 0, colNo))
End With
End Function

Caveat: The repeated transformation of data in two steps can be time consuming for larger data sets.


Workaround

Therefore I'd prefer the basic approach in the cited post via ►array arguments in the Application.Index() function, but by inserting a (e.g. temporary) column to the physical data range first and eventually by rearranging the columns including the newly added extra data (last position) at any new position (e.g. here on top).

Sub DelSwitchAndInsert()
'Auth: https://stackoverflow.com/users/6460297/t-m
'[0]add other array data as last column to existing range
    Sheet1.Range("E1:E4") = Application.Transpose(Array(1, 2, 3, 4))
'[1]get data
    Dim data: data = Tabelle7.Range("A1:E4")
'[2]reorder via Array(1, 4, 2), i.e. get 1st column, 4th and 2nd column omitting the 3rd one
    data = Application.Index(data, Evaluate("row(1:" & UBound(data) & ")"), Array(UBound(data, 2), 1, 4, 2))
'[3]write to any target
    Sheet2.Range("A1").Resize(UBound(data), UBound(data, 2)) = data
End Sub

Addendum to workaround in response to recent comments //Edit/2020-07-07

A flexible example following the workaround logic for insertion of vertical extra single-column data at any given "column" number could be as follows; I don't pretend this to be neither the best method nor the best way to code:

    InsCol data, extra, 3        ' insertion e.g. as new 3rd "column"

Sub InsertExtraData()
'Purpose:  insert a single-column array (2-dim, 1-based)
    '[0]define extra array (or slice AND transpose from other data source)
        Dim extra: extra = Application.Transpose(Array(100, 200, 300, 400))   ' example data
    '[1]get data (or existing 2-dim array)
        Dim data: data = Sheet1.Range("A1:D4")
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    '[2]insert extra as >>3rd<< column
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        InsCol data, extra, 3
    '[3]write to any target
        Sheet2.Range("A1").Resize(UBound(data), UBound(data, 2)) = data
End Sub

Sub InsCol(data, extra, Optional ByVal colNo As Long = 1)
With Sheets.Add
    '[0]add data to temporary range
    .Range("B1").Resize(UBound(data), UBound(data, 2)) = data
    .Range("B1").Offset(0, UBound(data, 2)).Resize(UBound(extra) - LBound(extra) + 1, 1) = extra
    '[1]get data
        data = .Range("B1").Resize(UBound(data), UBound(data, 2) + 1)
    '[2]reorder via Array(5, 1, 2, 3, 4)
        data = Application.Index(data, Evaluate("row(1:" & UBound(data) & ")"), getColNums(data, colNo))
    '[3]delete temporary sheet
        Application.DisplayAlerts = False: .Delete
        Application.DisplayAlerts = True
End With
End Sub

Function getColNums(main, Optional ByVal colNo As Long = 1) As Variant()
    'c.f. : https://stackoverflow.com/questions/53727578/joining-two-arrays-in-vba/60082345#60082345
    'Purp.: return ordinal element counters of combined 0-based 1-dim arrays
    Dim i&, n&: n = UBound(main) + 1    ' +1 as one column, +1 from 0-based~>one-based
    ReDim tmp(0 To n - 1)               ' redim to augmented size (zero-based)
    If colNo > n Then colNo = n
    If colNo < 1 Then colNo = 1
    For i = 0 To colNo - 1: tmp(i) = i + 1: Next i
    tmp(colNo - 1) = n
    For i = colNo To UBound(tmp): tmp(i) = i: Next i
    getColNums = tmp        ' return combined elem counters,  e.g. Array(1,2, >>5<< ,3,4)
End Function

这篇关于将垂直切片插入数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆