我正在尝试在VBA中编写一个函数来计算包含特定范围内某些字母的单元格。到目前为止,我的代码是
Function letters(list As range) As Double
Dim limit As Integer
limit = UBound(list.Value)
Dim total As Double
total = 0
Dim i As Integer
For i = 1 To limit
If range(list).Offset(i, 2) = "PD" Then
total = total + 1
End If
Next i
letters = total
End Function
所以我的输入是=字母(A1:B6),让我们说B2,B3和B5的文字是“PD”。我希望我的答案是3,但我得到#value!错误。我哪里错了?
提前致谢。
答案 0 :(得分:1)
您可以遍历范围中的每个单元格,并使用INSTR查找单元格是否包含文本。如果计数器增加计数器然后输出它。
Function findText(myRange As Range, toFind As String)
Dim ra As Range
Dim rCount As Integer
rCount = 0
For i = 1 To myRange.Rows.Count
If InStr(1, myRange(i, 1), toFind, vbTextCompare) Then
rCount = rCount + 1
End If
Next i
findText = rCount
End Function
这将计算在单元格中任何位置具有所需文本的单元格的事件。如果要匹配整个单元格内容,只需使用
即可If myRange(i, 1) = toFind Then
此外,该功能适用于单列范围。
答案 1 :(得分:1)
回答你的问题
我哪里错了?
有一些问题需要解决:
你说你用
打电话给你的功能 =letters(A1:B6)
但是A1:B6
并不意味着什么,而你有两个选择:
要么将您的函数调用为文字string
作为有效的Range
地址
=letters("A1:B6")
或者您称之为直接传递Range
对象
=letters(Range("A1:B6"))
一旦你完成了前一点,你必须采取一致行动,即:
选项1:将文字string
作为有效Range
地址传递
然后"A1:B6"
(请注意围绕A2:B6
的双引号)是您的范围的地址,因此您必须:
变化:
limit = UBound(list.Value) '<--| error
string
没有Value
属性
到:
limit = UBound(Range(list).Value) '<--| OK
Range("A1:B6")
是有效的Range
参考,因此您可以访问其Value
属性
变化:
Range(list).Offset(i, 2) '<--| this references a range as large as the one it's being called upon!
Offset(nRows, nColumns)
方法将引用一个范围,该范围从被调用的范围“移位”到您放入其参数的行数和列数。因此,当Offset(i,2)
= 1时,Range("A1:B6")
引用Range("C2:D7")
引用i
,Range("C3:D8")
= 2时引用i
,依此类推
为:
Range(list).Cells(i, 2) '<--| it references a single cell
Cells(iRow, iColumn)
方法将引用正在调用的iRow
iColumn
行和Range
列中的单元格。所以Range("A1:B6").Cells(1,2)
引用单元格“B7”
选项2:传递Range
对象
由于list
已经是Range
个对象(即Range("A1:B6")
),您必须:
变化:
If Range(list).Offset(i, 2) = "PD" Then '<--| error
您无法将Range
对象作为另一个Range
对象的唯一参数传递
为:
If list.Cells(i, 2) = "PD" Then '<--| Ok
您使用Cells
对象的Range
属性,如选项1中所述
那么您可能需要考虑以下 miscellanea :
从Function
类型
Long
自:
您将返回一个整数值,因此无需使用Double
类型
行数可超过Integer
类型变量的65 k限制
声明Dim limit As Long
因为
limit = UBound(Range(list).Value) '<--| correct use of 'list' if it's a literal 'string'
你要为它指定一个范围的实际行数,它可能会超过Integer
类型变量的约65k限制
所有这一切,我认为最有效的VBA解决方案是使用WorksheetFunction.CountIF()函数,如下所示:
Function letters(list As String) As Long
letters = WorksheetFunction.CountIf(Range(list).Columns(2), "PD")
End Sub
您使用.Columns(n)
对象的Range
属性来引用它被调用的Range
的第n列
通过将其参数列表扩展为搜索的字符串
,您可以更加通用Function letters(list As String, myLetters As String) As Long
letters = WorksheetFunction.CountIf(Range(list).Columns(2), myLetters)
End Sub
你打电话给:
MsgBox letters("A1:B6", "PD")
答案 2 :(得分:0)
如果您愿意,您可以通过使用以下公式而不是使用VBA来实现此目的。
b_memcpy.vfunc()
您需要输入此数组公式,即输入公式并按 Ctrl Shift Enter
如果找不到每个单元格的文本, =SUMPRODUCT(--(IFERROR(FIND("PD",A1:A25,1)>0,FALSE)))
会为您提供文本位置或错误。
FIND("PD",A1:A25,1)
将数字转换为TRUE。如果错误>0
将其转换为FALSE。因此,您获得了IFERROR
和TRUEs
的数组FALSEs
{TRUE,FALSE,...}
将数组转换为1和0。 --({...})
为1,TRUE
为0。 FALSE
添加了这个数字数组,以便为您提供计数。