2016-08-23 71 views
0

我正在編寫一個VBA公式以檢查單元格「TestChars」中的所有字符是否允許,其中允許表示每個字符出現在由另一個單元格「AllowedChars」定義的列表中。爲了讓事情變得更加困難,我希望這個公式能夠在單元格範圍內工作,而不是在單個單元格上工作。在Excel中使用VBA進行單元格驗證的矢量公式

當前的代碼似乎工作:

Option Explicit 


Public Function AllCharsValid(InputCells As Range, AllowedChars As String) As Boolean 
' Check that all characters in InputCells are among 
' the characters in AllowedChars 

    Dim Char As String 
    Dim Index As Integer 
    Dim RangeTestChars As Range 
    Dim TestChars As String 
    For Each RangeTestChars In InputCells 
     TestChars = RangeTestChars.Value 
     For Index = 1 To Len(TestChars) 
      Char = Mid(TestChars, Index, 1) 
      If InStr(AllowedChars, Char) = 0 Then 
       AllCharsValid = False 
       Exit Function 
      End If 
     Next Index 
    Next RangeTestChars 
    AllCharsValid = True 
End Function 

我有以下問題:

  1. 該公式需要一個範圍,並返回一個布爾值。我更喜歡矢量化函數,在給定輸入範圍的情況下,您會得到相應的布爾值範圍。看起來像'精確'這樣的內置公式可以做到這一點(這些公式,你必須按Ctrl-Shift-Enter來執行它們,並在那裏你得到花括號)。有沒有辦法用用戶定義的函數來做到這一點?
  2. 我對編程並不陌生,但我對VBA來說是全新的(我今天就開始了)。有沒有任何明顯的問題,上面的代碼怪異?
  3. 是否有會導致公式失敗的特殊字符,極長文本或特定輸入值?
  4. 有沒有更簡單的方法來達到相同的效果?代碼是否慢?
  5. 當你開始在Excel中輸入內置公式時,你會得到建議和自動完成。這似乎不適用於我的公式,我是要求太多還是有可能實現這一目標?

我意識到這個問題包含了幾個弱相關的子問題,所以我也會很滿意與子答案。

+0

我不認爲你可以使用一個數組公式在條件格式規則中返回多個值的數組公式,並按照你想要的方式工作。 CF始終是單元格的,我不認爲有任何機制可以在特定範圍的單元格中「分配」返回的真/假數組。 –

+0

我嘗試重寫我的第一個問題。如果您可以輸入'= AND(EXACT(A1:A10,B1))'並按下ctrl-shift-enter,這會使公式顯示爲'{= AND(EXACT(A1:A10,B1)) }'並且向量工作,也就是說EXACT將接受輸入範圍並返回布爾值的相應範圍(或數組?)。然後ALL函數將摺疊這個數組,並告訴你該範圍內的所有單元格是否與B1完全相同。目前,要使用我的函數的一系列值,我做'= AllCharsValid(A1:A10,B1)'。我可以做'= AND(AllCharsValid(A1:A10,B1))','EXACT'功能嗎? – JavaNewbie

+1

是的,你會從你的函數返回一個布爾值數組,每個單元格有一個元素。目前尚不清楚爲什麼你會這樣做,因爲這意味着每個單元格都必須進行測試,而不是在不允許的角色的第一個實例上退出並返回False。 –

回答

1

以下代碼將返回從初始輸入範圍偏移一列的布爾值範圍。只需在Excel中創建一個新選項卡,然後運行testAllCharsValid並在IDE中顯示即時窗口,以查看它的工作原理。

Sub testAllCharsValid() 

    Dim i As Integer 
    Dim cll As Range, rng As Range 
    Dim allowedChars As String 

    ' insert test values in sheet: for testing purposes only 
    With ActiveSheet ' change to Thisworkbook.Sheets("NameOfYourSheet") 
     Set rng = .Range("A1:A10") 
     For i = 1 To 10 
      .Cells(i, 1) = Chr(i + 92) 
     Next i 
    End With 

    ' fill allowedChars with letters a to z: for testing purposes only 
    For i = 97 To 122 
     allowedChars = allowedChars & Chr(i) 
    Next i 

    ' get boolean range 
    Set rng = AllCharsValid(rng, allowedChars) 

    ' check if the returned range contains the expected boolean values 
    i = 0 
    For Each cll In rng 
     i = i + 1 
     Debug.Print i & " boolean value: " & cll.Value 
    Next cll 

End Sub 

' Check that all characters in InputCells are among 
' the characters in AllowedChars 
Public Function AllCharsValid(InputCells As Range, allowedChars As String) As Range 

    Dim BoolTest As Boolean 
    Dim Char As String 
    Dim Index As Integer 
    Dim RangeTestChars As Range, RangeBooleans As Range, RangeTemp As Range 
    Dim TestChars As String 
    For Each RangeTestChars In InputCells 
     BoolTest = True 
     TestChars = RangeTestChars.Value 
     For Index = 1 To Len(TestChars) 
      Char = Mid(TestChars, Index, 1) 
      If InStr(allowedChars, Char) = 0 Then BoolTest = False 
     Next Index 

     Set RangeTemp = RangeTestChars.Offset(0, 1) ' change offset to what suits your purpose 
     RangeTemp.Value = BoolTest 

     If RangeBooleans Is Nothing Then 
      Set RangeBooleans = RangeTestChars 
     Else 
      Set RangeBooleans = Union(RangeBooleans, RangeTemp) 
     End If 

    Next RangeTestChars 

    Set AllCharsValid = RangeBooleans 

End Function 

CF 2)如果測試字符串的長度是零,則該函數返回True所討論的細胞,這可能是不期望的。

cf 3)Excel單元格可以包含多少個字符是有限制的,閱讀更多here。我想,如果你連接了一些非常長的字符串並將它們發送給函數,那麼你可以達到+32767的整數限制,由於整數Index變量會導致運行時錯誤。但是,由於Excel單元格的字符限制完全是+32767,函數應該沒有任何問題。

cf 4)沒有我知道的。

cf 5)這不是最容易實現的,但有幫助可以找到here

相關問題