【问题标题】:Excel convert 2d range to 1d range for use in functionsExcel 将 2d 范围转换为 1d 范围以用于函数
【发布时间】:2017-04-28 20:39:45
【问题描述】:

令人惊讶的是,在 Google 和这个网站上搜索答案,并没有找到明显的答案,所以我想我会发布它。

我正在尝试创建一个宏(可能是 UDF),它将二维单元格范围(如 A1:C3)转换为一维范围(一列或一行,如 A1: A10)。当需要二维数组时,这将用于诸如MATCH() 之类的函数,例如在 A1:C3 中查找特定值。但我希望该功能具有通用性,以便我可以将它围绕任何 2D 数组拍打以使其成为 1D。喜欢=INDEX(ARRAYDIMENSION(A1:C1),4)=MATCH("hello",ARRAYDIMENSION(A1:C1),0)

我已经想出了一个讨厌的方法;我将数组的每一列(对于A1:C3,即A1:A3B1:B3C1:C3)在一个新工作表中的彼此下方(因此A2被复制到新工作表的A2,C3被复制到A9,B1到A4等)

然后我返回我的新数组的引用 (Sheet2!A1:A9) 所以 MATCH()INDEX() 或者现在看起来在那里的任何东西。

它有效,但有一些明显的缺陷;添加新工作表对于宏而言既耗时又丑陋,将各个列相互堆叠并不是最有效的方法。但特别是,宏编辑工作表,因此不能是 UDF(我不认为),这意味着我必须将它用作 Worksheet_Calculate Sub,它比仅仅将它放入任何需要它的公式中更少自包含。


我认为这比较清楚,请帮助/建议最好的方法,我只做了几个星期的 VBA,所以我还不是超级圆滑。

【问题讨论】:

  • 您到底想做什么?数组公式是可选的吗?

标签: arrays vba excel user-defined-functions


【解决方案1】:

这会让你开始:

Function ArrayDim(rn As Range, dir As Integer)
Dim test() As Variant
Dim rng() As Variant
Dim cell As Range
Dim i As Long
rng = rn.Value
ReDim test(1 To UBound(rng, 1) * UBound(rng, 2))
i = 1

If dir = 0 Then
    For r = 1 To UBound(rng, 1)
        For c = 1 To UBound(rng, 2)
            test(i) = rng(r, c)
            i = i + 1
        Next c
    Next r
Else
    For c = 1 To UBound(rng, 2)
        For r = 1 To UBound(rng, 1)
            test(i) = rng(r, c)
            i = i + 1
        Next r
    Next c
End If

ArrayDim = test
End Function

第二个标准是排序的方法:

0 = 逐行 1 = 逐列

【讨论】:

  • 有趣的是,Excel 会自动按行然后按列(至少当两者数量相等时)。我想 OP 可能希望反过来?
  • @SJR 已调整,因此 OP 可以决定任何一种方法。
  • @Scott Craner - 超出职责范围先生!
【解决方案2】:

大概是这样的吧?

Function OneDimArray(rng As Excel.Range) As Variant()

Dim v() As Variant
Dim b As Boolean
Dim a() As Variant
Dim irow As Integer
Dim icol As Integer
Dim r As Range

Set r = Range("a1:c2")
v = r.Value

ReDim a(0)

For icol = 1 To r.Columns.Count
    For irow = 1 To UBound(v)
        a(UBound(a)) = v(irow, icol)
        ReDim Preserve a(UBound(a) + 1)
    Next irow
Next icol

OneDimArray = a

End Function

【讨论】:

  • 您可以一次调整数组的大小,而不是每次通过循环调整大小:对于可能变得昂贵的大范围......
  • 我认为您正在测试但我看不到您在哪里使用传递给函数的范围。你也可以不使用内存很重的 Redim 保留,Redim A(1 to R.rows.count * r.columns.count)
  • 是的,斯科特,但我相信,如果用户正在编码,那么可以自己完成一些工作,与设置数组的基础有关,无论是他们自己还是你如何'我做到了。当它付钱时,我会做更多:)
  • 我明白你的意思,但要提出相反的观点,我们不仅要回答当前的 OP,还要回答以后搜索的那些。
  • 再次,如果他们正在搜索.....他们准备嫁接,并再次提示问题如何将数组以 1 为基础,否则会导致他们认为他们必须可能以(1 到 x)的方式声明数组 :) 就在我们过去阅读 Access/Excel 书籍的那一代人中 :)
猜你喜欢
  • 2014-12-03
  • 1970-01-01
  • 2016-02-29
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
  • 2021-05-15
  • 1970-01-01
相关资源
最近更新 更多