[英]How to find if a cell with formula has the function within it using VBA?
我試圖確定一個單元格是否只是一個簡單的引用(例如“ =A2
”),因為它應該包含某些類型的函數/計算(例如“ =sum(A2:A3)
”)。 基本上,我正在尋找一個已經為 hasFunction 或 hasArithmeticOperations 構建的輪子。 查了查,沒找到。
真的很難找出比逐案更簡單的解決方案(已在其中一個答案中寫出來,所以如果您發現錯誤或任何事情,請告訴我),因為我想不出識別的方法...我能想到的最簡單的方法是檢查括號。 然而,用戶輸入很難預測(例如“ =(A2)
”)。 此外,我希望它處理所有簡單的運算符( -,+,/,*,&,^
等)。 必須有一種更簡單的方法,然后將所有這些都放在一起,對嗎?
讓我知道你對此有何看法。
我認為您正在尋找正則表達式。
主要問題是,對於 Excel,所有以“=”開頭的都是公式,函數類型之間沒有區別。 Bar 正則表達式,你可以用兩個 while 循環解析一個模式,第一個從左到右爬行,只要字符是一個字母,第二個當它是一個數字時接管。 如果您通過此到達論壇的末尾,則您成功地確定了一個參考。 正如你所指出的,你必須關心外括號和類似的東西......
你介意詳細說明你想要達到的目標嗎? 如果提供更多上下文,也許會有更多“跳出框框思考”的解決方案......
我實際上有以下解決方案。 任何感興趣的人都可以復制/粘貼以下代碼來檢查是否選擇了任何單元格,看看我是否遺漏了任何邊緣情況。
思路是這樣的:即使用戶選擇使用括號,我們也不希望緊接在“(”之前的任何內容。
同樣,我們想去掉任何簡單的算術運算符(+、-、-、*、/、^)。 我把減法和否定都記在這里,因為對於某些輸入語言(例如中文),這兩個符號可能不同? 不確定,但不想冒險......
最后,我們不想要一系列單元格(即沒有“:”或“,”)。
Sub test()
Dim rng As range
Set rng = Selection
MsgBox (referenceOnly(rng))
End Sub
然后我們有測試它是否只是引用的函數
Function referenceOnly(rng As range) As Boolean
' Three situations tht it might has formula
' 1: has anything before "(" except for "="
' 2: has any of the simple specialsmetic operators
' 3: has ":" which refers to a range of cells
referenceOnly = True
Dim str As String
If rng.HasFormula Then
str = rng.Formula
Else
referenceOnly = False
Exit Function
End If
' start of checks
Dim i As Integer
' start pos of "("
Dim startPos As Integer
' check 1
startPos = InStr(2, str, "(")
If startPos > 0 Then
If startPos <> 2 Then
referenceOnly = False
Exit Function
End If
End If
' referenceOnly 2 and 3
Dim specials(1 To 6) As String
specials(1) = chr(43) '+
specials(2) = chr(45) '-
specials(3) = chr(46) '-
specials(3) = chr(42) '*
specials(4) = chr(47) '/
specials(5) = chr(94) '^
specials(6) = chr(58) ':
For i = 2 To Len(str)
If IsInArray(Mid(str, i, 1), specials) Then
referenceOnly = False
Exit Function
End If
Next i
End Function
幫助函數來查看某個元素是否在數組中。 從某處復制代碼:)
Private Function IsInArray(valToBeFound As Variant, arr As Variant) As Boolean
'INPUT: Pass the function a value to search for and an array of values of any data type.
'OUTPUT: True if is in array, false otherwise
Dim element As Variant
On Error GoTo IsInArrayError: 'array is empty
For Each element In arr
If element = valToBeFound Then
IsInArray = True
Exit Function
End If
Next element
Exit Function
IsInArrayError:
On Error GoTo 0
IsInArray = False
End Function
剛剛發現有人對這個帖子投了反對票。 不知道那是什么,哈哈
我建立了我在評論中建議的方法,看看它是否有效。 結果適用於以下用例:
$A$1 | =A2 | False $A$1 | =SUM(B2:B3) | True $A$1 | =(A2) | False $A$1 | =6+2 | False $A$1 | =ORA2+ORA3 | False $A$1 | =VLOOKUP(B1,C:C,2,0) | True
Option Explicit
Sub test()
Dim rng As Range
Set rng = Range("A1")
If rng.HasFormula Then
Debug.Print rng.Address & " | " & rng.Formula & " | " & hasOperation(Range("A1"))
End If
End Sub
Function hasOperation(rng As Range) As Boolean
Dim formulaText As String
formulaText = rng.Formula
Dim strippedFormula As String
strippedFormula = cleanOperators(formulaText)
If Not IsNumeric(strippedFormula) Then
Dim testRange As Range
On Error Resume Next
Set testRange = Range(strippedFormula)
On Error GoTo 0
If testRange Is Nothing Then
'clear out precedents from string to see if something left
strippedFormula = clearPrecedents(strippedFormula, rng)
If strippedFormula <> vbNullString Then
hasOperation = True
End If
End If
End If
End Function
Function cleanOperators(whichText As String) As String
Dim holdingString As String
holdingString = Replace(whichText, "(", "")
holdingString = Replace(holdingString, ")", "")
holdingString = Replace(holdingString, "+", "")
holdingString = Replace(holdingString, "-", "")
holdingString = Replace(holdingString, "*", "")
holdingString = Replace(holdingString, "/", "")
holdingString = Replace(holdingString, "^", "")
holdingString = Replace(holdingString, ":", "")
holdingString = Replace(holdingString, "=", "")
cleanOperators = holdingString
End Function
Function clearPrecedents(stringToClear As String, rng As Range)
Dim finalresult As String
finalresult = stringToClear
Dim prec As Range
For Each prec In rng.Precedents
finalresult = Replace(finalresult, prec.Address(0, 0), "")
Next
clearPrecedents = finalresult
End Function
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.