区分“1”和“11”

Differentiate between "1" and "11"

我有 20 个案例。对于我的 sheet 中的每一行,我都有一个为其分配相关案例编号的单元格。一行可以在该单元格中分配多个案例编号(示例:1,2,11,12)

我正在编写一个代码来复制分配给它们的案例编号 1 的所有行,将它们复制到其他地方.. 然后转到案例 2 并重复相同的操作..

这是我正在使用的:

For CaseNumbers = 1 To 20
    For i = Row1 To RowLast
        If InStr(1, Range(CaseNoCell & i).Value, CaseNumbers & ",") Then
        COPY AND PASTE CODE
        End If
    Next
Next

我面临的问题是,代码也将案例编号 11 视为案例编号 1(因为它有数字 1)。

这是我第一次编写 VBA 代码,我没有这方面的背景知识。 有人可以建议更好的方法吗?我应该为每一行分配一个清单吗? 我想要做的就是找到分配了案例编号 1 的所有行,复制它们.. 然后找到分配了案例 2 的所有行,复制它们.. 等等。

请帮忙。

嗯,您正在使用这段代码:

If InStr(1, Range(CaseNoCell & i).Value, CaseNumbers & ",") Then

这会对照 1,12,、...进行检查,但显然它不会涵盖最后一个条目,因此您需要添加该条目。而且您遇到的问题是 11, 被视为 1,.

以类似的方式你可以使用这段代码:

If InStr(1, Range(CaseNoCell & i).Value, "," & CaseNumbers & ",") Then

这会检查 ,1,,12,、...所以它将解决您的错误,但显然它不会涵盖最后一个 和第一个 条目,所以这是您需要添加的内容。

您可以使用一个函数来做测试

Public Function isCaseNumberIncluded(ByVal caseToCheck As Long, ByVal caseNumbers As String) As Boolean

'add , to make all values distinct
caseNumbers = "," & caseNumbers & ","

Dim strCaseToCheck As String
strCaseToCheck = "," & caseToCheck & ","

If InStr(1, caseNumbers, strCaseToCheck) > 0 Then
    isCaseNumberIncluded = True
End If

End Function

您可以像这样在主代码中调用此函数:

Dim caseNumber As Long         'I removed the s - as this could be misleading in my eyes
For caseNumber = 1 To 20
    For i = Row1 To RowLast
        If isCaseNumberIncluded(caseNumber, Range(CaseNoCell & i).Value) Then
            COPY AND PASTE CODE
        End If
    Next
Next

使用单独的函数来运行测试有两个好处:

  • 您的代码变得更具可读性,即您通过阅读函数名称知道结果应该是什么 - 而无需阅读整个代码如何去做:-)
  • 你可以re-use这个代码在另一个地方

或者您可以先测试功能:

Public Sub test_isCaseNumberIncluded()

Debug.Print isCaseNumberIncluded(1, "1,2,11,12"), "Should be true"
Debug.Print isCaseNumberIncluded(1, "2,11,12"), "Should be false"
Debug.Print isCaseNumberIncluded(11, "1,2,11,12"), "Should be true"
Debug.Print isCaseNumberIncluded(11, "1,2,12"), "Should be false"

End Sub

识别条件行

Option Explicit

Sub Test()

    Const WordSeparator As String = ","
    
    Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
    
    Dim CaseNumber As Long
    Dim i As Long
    Dim cValue As Variant
    Dim cString() As String

    For CaseNumber = 1 To 20
        For i = Row1 To RowLast
            cValue = CStr(ws.Range(CaseNoCell & i).Value)
            If Len(cValue) > 0 Then
                cString = Split(cValue, WordSeparator)
                If IsNumeric(Application.Match( _
                        CStr(CaseNumber), cString, 0)) Then
                    ' CopyAndPasteCode CaseNumber
                    Debug.Print "Case " & CaseNumber & ": " & "Row " & i 
                End If
            End If
        Next i
    Next CaseNumber

End Sub

这是应该封装在函数中而不是在线完成的事情。 VBA 中提供的用于标记字符串的方法是 'Split'.

您可以编写一个函数来逐一检查标记,或者编译标记的集合,然后使用集合的内置检查方法来确定指定的标记是否存在。

在这个具体案例中,我选择使用收集方法。集合的特定对象是 ArrayList(但 Scripting.Dictionary 也是可能的)。该函数包含对零长度字符串的检查,并允许指定分隔符(如果不是逗号)。

Option Explicit

Function FindToken(ByVal ipToken As String, ByVal ipTokenList As String, Optional ByVal ipSeparator As String = ",") As Boolean

    ' Guard against ipSeparator being vbnullstring
    Dim mySeparator As String
    mySeparator = IIf(VBA.Len(ipSeparator) = 0, ",", ipSeparator)


    'Raise an error if ipToken or ipTokenList are empty strings
    If VBA.Len(ipToken) = 0 Or VBA.Len(ipTokenList) = 0 Then
    
        Err.Raise 17, "Empty string error"
        
    End If
    
    'Convert the token list to tokens
    Dim myTokens As Variant
    myTokens = VBA.Split(ipTokenList, mySeparator)
    
    ' Put the tokens in an ArrayList so we can use the contains method
    ' no point is doing early binding as arraylist doesn't provide intellisense
    Dim myAL As Object
    Set myAL = CreateObject("System.Collections.ArrayList")
    
    Dim myItem As Variant
    For Each myItem In myTokens
        ' Trim just in case there are spaces
        myAL.Add VBA.Trim(myItem)
    Next
    
    'Finally test if the Token exists in the token list
    Find = myAL.contains(VBA.Trim(ipToken))
    
End Function

这意味着您的代码

If InStr(1, Range(CaseNoCell & i).Value, CaseNumbers & ",") Then

现在可以重写为

If FindToken(CStr(CaseNUmbers), Range(CaseNoCell & cstr(i)).Value) Then