我在MATLAB中创建了一个简单的函数,并试图将该函数转换为Excel VBA函数。我的目标是创建一个Excel公式=RT("dB水平范围","增量时间"(,并输出估计的混响时间。数学很简单,请参阅下面的MATLAB代码:
function rr=RT(lvl_broad, dt)
n=12; %number of samples within slope calc
slope=zeros(length(lvl_broad), 1);
for i=1:length(lvl_broad)
if i<((n/2)+1) | i>length(lvl_broad)-(n/2)-1
slope(i)=0;
else
slope(i)=(lvl_broad(i+(n/2))-lvl_broad(i-(n/2)))/n;
end
end
min_slope=min(slope);
rr=abs(dt./min_slope)*60;
end
在excel中,我修改/简化了它,直到我不再有错误,然而,我在其中输入"RT"函数的单元格返回#VALUE,我不知道为什么。下面的代码中有突出的内容吗?(注意,我将输入范围从lvl_broad更改为InterruptedNZ(
Function RT(InterruptedNZ, dt)
Dim Slope As Double
Slope = Slope(InterruptedNZ.Height, 1)
For i = 1 To InterruptedNZ.Height
If i < ((6) + 1) Or i > (InterruptedNZ.Height - (6) - 1) Then
Slope(i) = 0
Else
Slope(i) = (InterruptedNZ(i + (6)) - InterruptedNZ(i - (6))) / 12
End If
Next
End
min_slope = Application.WorksheetFunction.Min(Slope)
RT = Abs((dt / min_slope) * 60)
End Function
以下是将MATLAB代码转换为VBA代码的一些技巧:
长度((
如果要获取范围的维度,则需要对正在使用的范围使用.Rows.Count
或.Columns.Count
属性。
性能说明:当您有足够大的范围时,最好将范围的值存储在数组中,因为这样可以减少从工作表访问数据的次数,这可能会带来大量开销。如果是,则必须使用
ubound()
和lbound()
。
zeros((
在VBA中,没有与MATLAB中的zeros((函数完全等效的函数。初始化一个零数组的方法只是初始化一个双精度数组(或另一种数值类型(。由于double的默认值为零,我们不需要做任何其他事情:
Dim Slope() As Double
ReDim Slope(1 To InterruptedNZ.Rows.Count)
请注意,不能在Dim
语句中传递维度,因为它只接受常量作为参数,所以我们需要将Slope
创建为一个双精度的动态数组,然后将其重新定为所需的大小。
把这两个原则放在一起,你的代码看起来像这样:
Function RT(ByRef InterruptedNZ As Range, ByVal dt As Double)
Dim Slope() As Double
ReDim Slope(1 To InterruptedNZ.Rows.Count)
Dim i As Long
For i = 1 To InterruptedNZ.Rows.Count
If i < ((6) + 1) Or i > (InterruptedNZ.Rows.Count - (6) - 1) Then
Slope(i) = 0
Else
Slope(i) = (InterruptedNZ(i + (6)) - InterruptedNZ(i - (6))) / 12
End If
Next
Dim min_slope As Double
min_slope = Application.WorksheetFunction.Min(Slope)
RT = Abs((dt / min_slope) * 60)
End Function
添加注释:
引用像
InterruptedNZ(i)
这样的范围中的单元格是有效的,但最好像这样更具体(假设列范围(:InterruptedNZ.Cells(i,1)
在我的测试中,由于min_slope为零,我出现了一个除以零的错误。您可能需要在代码中说明这一点。