为什么我的数组函数不起作用?

时间:2015-11-21 15:55:05

标签: vba excel-vba excel

我试图在VBA中编写一个简单的冒泡排序功能,但它不起作用。代码如下:

Public Function BubbSort(arr As Variant) As Variant

Dim arrReturn As Variant
arrReturn = Array()
ReDim arrReturn(UBound(arr))
arrReturn = arr.Value

For i = 1 To UBound(arr) - 1
    For j = 1 To UBound(arr) - 1
        If arrReturn(j) > arrReturn(j + 1) Then
            temp = arrReturn(j)
            arrReturn(j) = arrReturn(j + 1)
            arrReturn(j + 1) = temp
        End If
    Next j
Next i

arr = arrReturn

End Function

在Excel中我尝试选择4x1范围的单元格并插入公式$ = BubbSort(A1:A4)$并按Ctrl + Shift + Enter以使其作为数组函数工作,但它说"函数有错误& #34 ;.有什么帮助吗?

2 个答案:

答案 0 :(得分:2)

如果arr是一个范围,则UBound(arr)会抛出错误。解决这个问题的方法是使用

arrReturn = arr.Value

而不仅仅是

arrReturn = arr

然后使用Ubound(arrReturn)

此外 - arrReturn将是一个二维数组而不是一维数组。对arrReturn的所有引用应如下所示: arrReturn(j,1)

最后 - 你没有返回任何东西(在VBA中分配给函数名)。

以下代码似乎有效(如果冒充排序可以被描述为"正在工作"):

Public Function BubbSort(arr As Variant) As Variant

Dim arrReturn As Variant
Dim i As Long, j As Long, temp As Variant

arrReturn = arr.Value

For i = 1 To UBound(arrReturn) - 1
    For j = 1 To UBound(arrReturn) - 1
        If arrReturn(j, 1) > arrReturn(j + 1, 1) Then
            temp = arrReturn(j, 1)
            arrReturn(j, 1) = arrReturn(j + 1, 1)
            arrReturn(j + 1, 1) = temp
        End If
    Next j
Next i

BubbSort = arrReturn

End Function

上述内容仅在传递列中包含的范围时有效。可以使其更灵活,能够处理列范围或行范围或VBA阵列。

答案 1 :(得分:2)

虽然John Coleman的代码在技术上有效,但它存在根本缺陷。您会注意到i上的外环是不变的 - 从不使用循环值。

Bubblesort 确实是低效的(至少对于长序列而​​言),但没有代码执行的那么多。
在内循环的末尾,最大的元素将传播到序列的最末端。因此,在内循环的下一次重复期间,无需将其与任何先前的元素进行比较。如果每次将内循环缩短1(总计,到目前为止的外循环完成次数Public Function Bubble1(arr As Variant) As Variant Dim arrReturn As Variant Dim i As Long, j As Long, temp As Variant arrReturn = arr.Value For i = UBound(arrReturn, 1) To 2 Step -1 For j = 1 To i - 1 If arrReturn(j, 1) > arrReturn(j + 1, 1) Then temp = arrReturn(j, 1) arrReturn(j, 1) = arrReturn(j + 1, 1) arrReturn(j + 1, 1) = temp End If Next j Next i Bubble1 = arrReturn End Function ),则将循环次数减少50%:

Public Function Bubble2(arr As Variant) As Variant
    Dim arrReturn As Variant
    Dim i As Long, j As Long, temp As Variant
    Dim sorted As Boolean

    arrReturn = arr.Value
    For i = UBound(arrReturn, 1) To 2 Step -1
        sorted = True
        For j = 1 To i - 1
            If arrReturn(j, 1) > arrReturn(j + 1, 1) Then
                temp = arrReturn(j, 1)
                arrReturn(j, 1) = arrReturn(j + 1, 1)
                arrReturn(j + 1, 1) = temp
                sorted = False
            End If
        Next j
        If sorted Then Exit For
    Next i
    Bubble2 = arrReturn
End Function

虽然我们可以通过观察,如果所有元素都已排序(即内部循环中没有发生交换),我们可以进一步减少工作量 - 进一步的循环是多余的。我们可以使用标志来实现它:

> "one, two, three ".split(',').map(s => s.trim());
[ 'one', 'two', 'three' ]