[英]VBA UDF gives different answer when called from Excel vs VBA
The following VBA function counts the number of cells containing formulas in a given range. 以下VBA函数计算包含给定范围内的公式的单元格数。 It works correctly when called from a VBA sub.
从VBA子调用时它可以正常工作。 When called from Excel, it returns the total number of cells in the range.
从Excel调用时,它返回范围中的单元格总数。
The call from Excel is =CountFormulas(A1:C7)
, which returns 21 even though only two cells with formulas are in the range. 来自Excel的调用是
=CountFormulas(A1:C7)
,即使只有两个带公式的单元格在范围内,它也会返回21。
What is causing this discrepancy? 造成这种差异的原因是什么?
Public Function CountFormulas(ByRef rng As Range) As Long
CountFormulas = rng.SpecialCells(xlCellTypeFormulas).Count
End Function
Public Sub CountFormulasFromSub()
Dim rng As Range
Dim res As Integer
Set rng = Sheet1.Range("a1:c7")
res = CountFormulas(rng)
End Sub
This isn't possible. 这是不可能的。 The following link has the things that won't work inside of a UDF.
以下链接包含UDF内部无法解决的问题。
Here - http://support.microsoft.com/kb/170787 这里 - http://support.microsoft.com/kb/170787
EDIT: A manual way of counting works though. 编辑:手动计数方式虽然有效。
Public Function CountFormulas(rng As Range) As Integer
Dim i As Integer
Dim cell As Range
For Each cell In rng
If cell.HasFormula Then
i = i + 1
End If
Next
CountFormulas = i
End Function
Change Integer
to Long
if you think it will exceed 32767. 如果您认为它将超过32767,则将
Integer
更改为Long
。
If I were to send worksheet.cells to the function, it would check all cells in the entire worksheet, quite many and quite slow. 如果我要将workheet.cells发送到该函数,它将检查整个工作表中的所有单元格,非常多且非常慢。 Although Excel 2007+ supports 16384*1048576 rows, only cells which have actually been used are loaded to memory.
虽然Excel 2007+支持16384 * 1048576行,但只有实际使用过的单元格才会加载到内存中。 There would be no need to go through all the other 17 billion cells to check.
没有必要通过所有其他170亿个细胞来检查。 The closest I could get to identifying these was using Worksheet.UsedRange to restrict an arbitrary range input.
我最接近识别这些是使用Worksheet.UsedRange来限制任意范围输入。 It is not perfect though, in cases when cells far apart have been used.
但是,如果使用相距很远的细胞,那么它并不完美。 Eg if cells A1 and XFD1048576 contain data, the entire worksheet would be included in UsedRange.
例如,如果单元格A1和XFD1048576包含数据,则整个工作表将包含在UsedRange中。 Any tips on how to restrict the range to actually used cells (merely two cells in the above example) would be greatly appreciated.
关于如何将范围限制为实际使用的单元格的任何提示(在上面的例子中仅仅是两个单元格)将不胜感激。
Utilizing UsedRange I built a function which I'll share in case anyone else can make use of it: 利用UsedRange我构建了一个函数,我将分享以防其他任何人可以使用它:
Public Function CountIfFormula(ByRef rng As Range, Optional ByVal matchStr As String) As Long
'Counts the number of cells containing a formula and optionally a specific string (matchStr) in the formula itself.
Dim i As Long
Dim isect As Range
'Restricts the range to used cells (checks only cells in memory)
Set isect = Application.Intersect(rng, rng.Parent.UsedRange)
For Each cell In isect
If cell.HasFormula Then
If InStr(1, cell.Formula, matchStr) Then i = i + 1
End If
Next
CountIfFormula = i
End Function
Use of the function: 使用功能:
Sub GetNrOfCells()
Dim i As Long
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
i = i + CountIfFormula(ws.Cells, "=SUM(")
Next
'i will now contain the number of cells using the SUM function
End Sub
Best regards, and thank you for your reply. 致以最诚挚的问候,谢谢你的回复。
Fossie Fossie
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.