簡體   English   中英

如何使用VBA查找帶有公式的單元格是否具有其中的功能?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM