Excel TDEV.S生成(我已经从STDEV.S函数中手动排除了带有#N/A的单元格),但它们只在第13个小数点上有所不同(我的函数给出93.5950714912684,而STDEV.S给出93.5950714912683),这应该是一个足够小的错误,因此不相关。有趣的是,如果我将所有值放在一行(即,我将所有值放在例如(M34:Y34))上,那么我的函数和内置函数都会给出完全相同的结果(即93.5950714912683)。错误似乎源于含有1分钟的细胞;如果我将00:01:00更改为任何其他时间值(例如00:01:01或01:01:00),则无论值是放置在一行上还是作为工作表上随机分布的区域,这两个函数都会产生完全相同的结果
我无法解释这种奇怪的行为,但到目前为止,它似乎只产生了一个无关紧要的错误,因此我将假设我的代码按预期工作。不是完整答案,而是检查范围的Areas属性,并在函数中内置一个检查来计算区域数。如果为1,则按on,如果>1,则通过每个区域循环并合并为单个阵列。可能有点假,这里的一些聪明人可能有一个好主意。您也可以将连续和不连续范围作为字符串传递给UDF,然后自己解析字符串以获取Excel TDEV.S生成(我已经从STDEV.S函数中手动排除了带有#N/A的单元格),但它们只在第13个小数点上有所不同(我的函数给出93.5950714912684,而STDEV.S给出93.5950714912683),这应该是一个足够小的错误,因此不相关。有趣的是,如果我将所有值放在一行(即,我将所有值放在例如(M34:Y34))上,那么我的函数和内置函数都会给出完全相同的结果(即93.5950714912683)。错误似乎源于含有1分钟的细胞;如果我将00:01:00更改为任何其他时间值(例如00:01:01或01:01:00),则无论值是放置在一行上还是作为工作表上随机分布的区域,这两个函数都会产生完全相同的结果,excel,input,user-defined-functions,vba,Excel,Input,User Defined Functions,Vba,我无法解释这种奇怪的行为,但到目前为止,它似乎只产生了一个无关紧要的错误,因此我将假设我的代码按预期工作。不是完整答案,而是检查范围的Areas属性,并在函数中内置一个检查来计算区域数。如果为1,则按on,如果>1,则通过每个区域循环并合并为单个阵列。可能有点假,这里的一些聪明人可能有一个好主意。您也可以将连续和不连续范围作为字符串传递给UDF,然后自己解析字符串以获取(您的区域设置似乎也是如此)和:。感谢您的评论-您两位(@SJR&@Ralph)所描述的正是我想要做的。我的问题仍然是我没有足够
(您的区域设置似乎也是如此)和:
。感谢您的评论-您两位(@SJR&@Ralph)所描述的正是我想要做的。我的问题仍然是我没有足够的VBA技能来为它编写代码:/看看前面的这个问题,看看它是否有任何启示@SJR谢谢你的提示
Date pH Na+ conc K+ conc ...lots of other variables
Date 1 7.4 140 3 ...
Date 2 7.1 #N/A 4 ...
.... ... ... ... ...
Date N 7.3 143 3.5 ...
Function StdevNaN_S(xRange)
'Sample Standard deviation which excludes NaN values
xR = xRange 'I can, for some strange reason, not use UBound unless I re-store the data in xR...
NoE1 = UBound(xR, 1) 'Number of Elements along dimension 1 (columns)
NoE2 = UBound(xR, 2) 'Number of Elements along dimension 2 (rows)
NoE = NoE1 * NoE2 'Total Number of Elements (this way makes it work regardless of row or column range)
'Need to first calculate the NaN excluded average value - could use the AVERAGEIF to simplify, but that will break if the range is discontinuous
xSum = 0
xAmount = 0
For N = 1 To NoE
If IsNumeric(xRange(N)) Then
xSum = xSum + xRange(N)
xAmount = xAmount + 1 'counting how many cells that are used in the sum, used as the divisor in the average and the variance expression. Couldn't use the "CountIf" expression as it counted cells which contained text
Else
End If
Next N
xAvg = xSum / xAmount
'Uses the average in the variance calculation
xSum = 0
For N = 1 To NoE
If IsNumeric(xRange(N)) Then
xSum = xSum + (xRange(N) - xAvg) ^ 2 'Summing up (x - x_avg) ^ 2, which is the dividend of the variance expression
Else
End If
Next N
StdevNaN_S = (xSum / (xAmount - 1)) ^ 0.5 'the sample standard deviation is the square root of the corrected variance
End Function
Function SumOf(ParamArray Nums() As Variant) As Variant
''''''''''''''''''''''''''''''''''
' Add up the numbers in Nums
''''''''''''''''''''''''''''''''''
Dim N As Long
Dim D As Double
For N = LBound(Nums) To UBound(Nums)
If IsNumeric(Nums(N)) = True Then
D = D + Nums(N)
Else
SumOf = CVErr(xlErrNum)
Exit Function
End If
Next N
SumOf = D
End Function
Function NaNStdev_S(ParamArray xRange() As Variant) As Double
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'A function to calculate the sample standard deviation of any ranges of cells
'while excluding text, logicals, empty cells and cells containing #N/A.
'Can handle both continuous and discontinuous ranges.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim CellsUsed As Integer
Dim NumArg As Integer
Dim NumCell As Integer
Dim xAvg As Double
Dim xSum As Double
Dim xTemp As Variant
Dim xVect() As String
NumArg = UBound(xRange) 'Counts the number of input arguments (i.e., number of discontinuous regions)
For i = 0 To NumArg 'Goes through each discontinuous region
xTemp = xRange(i) 'Stores the current region in a temporary variable as several of the later operations cannot be performed on the full input array
If IsArray(xTemp) Then 'Checks if the current region is an array; if yes, then that array will be continuous
NumCell = UBound(xTemp, 1) * UBound(xTemp, 2) 'Checks how many cells are in the array
For j = 1 To NumCell 'Goes through all cells in the current region
If IsEmpty(xRange(i).Cells(j)) Then 'do nothing
ElseIf Application.IsLogical(xRange(i).Cells(j)) Then 'do nothing
ElseIf IsNumeric(xRange(i).Cells(j)) Then 'If the content of the cell is numeric, then use it
xSum = xSum + xRange(i).Cells(j) 'Add the current cell value to the sum of all cell values
CellsUsed = CellsUsed + 1 'Counts how many of the cell values that are actually used
ReDim Preserve xVect(CellsUsed) 'Adjusts the size of xVect
xVect(CellsUsed) = xRange(i).Cells(j) 'Reformats all usable values into one single vector for later use
Else
End If
Next j
Else 'If the current region is not an array, then it's just a single value
If IsEmpty(xRange(i)) Then 'do nothing
ElseIf IsNumeric(xRange(i)) Then 'If the content of the current region is numeric, then use it
xSum = xSum + xRange(i) 'Add the current cell (region) value to the sum of all cell values
CellsUsed = CellsUsed + 1 'Increase the counter of used values
ReDim Preserve xVect(CellsUsed) 'Adjusts the size of xVect
xVect(CellsUsed) = xRange(i) 'Adds the current value into the reformatted vector for later use
Else
End If
End If
Next i
xAvg = xSum / CellsUsed 'Average of all cells which contains numbers
xSum = 0 'resets the sum as it's no longer needed
For i = 1 To CellsUsed 'Goes through the reformatted vector and calculates the sum of (x - x_avg) ^ 2
xSum = xSum + (xVect(i) - xAvg) ^ 2 'This is the dividend of the variance equation
Next i
NaNStdev_S = (xSum / (CellsUsed - 1)) ^ 0.5 'the sample standard deviation is the square root of the corrected variance
End Function
Function NaNStdev_P(ParamArray xRange() As Variant) As Double
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'A function to calculate the population standard deviation of any ranges of cells
'while excluding text, logicals, empty cells and cells containing #N/A.
'Can handle both continuous and discontinuous ranges.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim CellsUsed As Integer
Dim NumArg As Integer
Dim NumCell As Integer
Dim xAvg As Double
Dim xSum As Double
Dim xTemp As Variant
Dim xVect() As String
NumArg = UBound(xRange) 'Counts the number of input arguments (i.e., number of discontinuous regions)
For i = 0 To NumArg 'Goes through each discontinuous region
xTemp = xRange(i) 'Stores the current region in a temporary variable as several of the later operations cannot be performed on the full input array
If IsArray(xTemp) Then 'Checks if the current region is an array; if yes, then that array will be continuous
NumCell = UBound(xTemp, 1) * UBound(xTemp, 2) 'Checks how many cells are in the array
For j = 1 To NumCell 'Goes through all cells in the current region
If IsEmpty(xRange(i).Cells(j)) Then 'do nothing
ElseIf Application.IsLogical(xRange(i).Cells(j)) Then 'do nothing
ElseIf IsNumeric(xRange(i).Cells(j)) Then 'If the content of the cell is numeric, then use it
xSum = xSum + xRange(i).Cells(j) 'Add the current cell value to the sum of all cell values
CellsUsed = CellsUsed + 1 'Counts how many of the cell values that are actually used
ReDim Preserve xVect(CellsUsed) 'Adjusts the size of xVect
xVect(CellsUsed) = xRange(i).Cells(j) 'Reformats all usable values into one single vector for later use
Else
End If
Next j
Else 'If the current region is not an array, then it's just a single value
If IsEmpty(xRange(i)) Then 'do nothing
ElseIf IsNumeric(xRange(i)) Then 'If the content of the current region is numeric, then use it
xSum = xSum + xRange(i) 'Add the current cell (region) value to the sum of all cell values
CellsUsed = CellsUsed + 1 'Increase the counter of used values
ReDim Preserve xVect(CellsUsed) 'Adjusts the size of xVect
xVect(CellsUsed) = xRange(i) 'Adds the current value into the reformatted vector for later use
Else
End If
End If
Next i
xAvg = xSum / CellsUsed 'Average of all cells which contains numbers
xSum = 0 'resets the sum as it's no longer needed
For i = 1 To CellsUsed 'Goes through the reformatted vector and calculates the sum of (x - x_avg) ^ 2
xSum = xSum + (xVect(i) - xAvg) ^ 2 'This is the dividend of the variance equation
Next i
NaNStdev_P = (xSum / CellsUsed) ^ 0.5 'the population standard deviation is the square root of the variance
End Function
Function NaNAverage(ParamArray xRange() As Variant) As Double
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'A function to calculate the average of any ranges of cells
'while excluding text, logicals, empty cells and cells containing #N/A.
'Can handle both continuous and discontinuous ranges.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim CellsUsed As Integer
Dim NumArg As Integer
Dim NumCell As Integer
Dim xSum As Double
Dim xTemp As Variant
NumArg = UBound(xRange) 'Counts the number of input arguments (i.e., number of discontinuous regions)
For i = 0 To NumArg 'Goes through each discontinuous region
xTemp = xRange(i) 'Stores the current region in a temporary variable as several of the later operations cannot be performed on the full input array
If IsArray(xTemp) Then 'Checks if the current region is an array; if yes, then that array will be continuous
NumCell = UBound(xTemp, 1) * UBound(xTemp, 2) 'Checks how many cells are in the array
For j = 1 To NumCell 'Goes through all cells in the current region
If IsEmpty(xRange(i).Cells(j)) Then 'do nothing
ElseIf Application.IsLogical(xRange(i).Cells(j)) Then 'do nothing
ElseIf IsNumeric(xRange(i).Cells(j)) Then 'If the content of the cell is numeric, then use it
xSum = xSum + xRange(i).Cells(j) 'Add the current cell value to the sum of all cell values
CellsUsed = CellsUsed + 1 'Counts how many of the cell values that are actually used
Else
End If
Next j
Else 'If the current region is not an array, then it's just a single value
If IsEmpty(xRange(i)) Then 'do nothing
ElseIf IsNumeric(xRange(i)) Then 'If the content of the current region is numeric, then use it
xSum = xSum + xRange(i) 'Add the current cell (region) value to the sum of all cell values
CellsUsed = CellsUsed + 1 'Increase the counter of used values
Else
End If
End If
Next i
NaNAverage = xSum / CellsUsed 'Average of all cells which contains numbers
End Function
(00:01:00, -10, -33, 10, 33, 20, 66, 30, 40, 300, TRUE, {empty cell} , #N/A)