web-dev-qa-db-fra.com

Rechercher une chaîne dans une cellule à l'aide de VBA

Je me suis rendu fou avec cela pendant une journée, cherché haut et bas, et j'essaie probablement d'être trop mignon, donc je suis totalement coincé.

J'essaie de lancer un si simple alors

Si une cellule contient "%", j'aimerais qu'elle fasse une chose et pas une autre. Pour des raisons que je ne comprends pas, je ne peux pas le faire fonctionner. J'ai clairement pris quelques idées venues d'ailleurs mais je n'arrive toujours pas à les faire fonctionner.

Facteurs compliquant les choses - je ne veux pas exécuter cela sur toute la colonne, mais simplement sur une table, elle est donc incorporée dans un sous-ensemble plus grand utilisant des lots ou des classes ActiveCell relatives. Je ne sais jamais où, dans la colonne A, je vais rencontrer le "% de changement". La plage doit donc toujours être variable. Je veux que VBA/VBE fasse quelque chose de différent quand il tombe sur une cellule contenant le "%". SO 

Voici à quoi ressemblent les données brutes 

Initial Value (6/30/06)

Value (12/31/06)

Net Additions (9/30/07)

Withdrawal (12/07)

Value (12/31/07)

Withdrawal (2008)

Value (12/31/08)

Addition (8/26/09)

Value (12/31/09)

Value (12/31/10)

Value (12/30/11)

Value (3/31/12)

% Change 1st Quarter

% Change Since Inception

Mais lorsque je lance ce qui suit, il reste bloqué dans une mauvaise boucle où il aurait dû sortir dans la partie "If Then" par opposition à la partie "Else" du sous-marin.

Sub IfTest()
 'This should split the information in a table up into cells
 Dim Splitter() As String
 Dim LenValue As Integer     'Gives the number of characters in date string
 Dim LeftValue As Integer    'One less than the LenValue to drop the ")"
 Dim rng As Range, cell As Range
 Set rng = ActiveCell

Do While ActiveCell.Value <> Empty
    If InStr(rng, "%") = True Then
        ActiveCell.Offset(0, 0).Select
        Splitter = Split(ActiveCell.Value, "% Change")
        ActiveCell.Offset(0, 10).Select
        ActiveCell.Value = Splitter(1)
        ActiveCell.Offset(0, -1).Select
        ActiveCell.Value = "% Change"
        ActiveCell.Offset(1, -9).Select
    Else
        ActiveCell.Offset(0, 0).Select
        Splitter = Split(ActiveCell.Value, "(")
        ActiveCell.Offset(0, 9).Select
        ActiveCell.Value = Splitter(0)
        ActiveCell.Offset(0, 1).Select
        LenValue = Len(Splitter(1))
        LeftValue = LenValue - 1
        ActiveCell.Value = Left(Splitter(1), LeftValue)
        ActiveCell.Offset(1, -10).Select
    End If
Loop
End Sub

Toute aide est appréciée, merci!

4
Tommy Z

J'ai simplifié votre code pour isoler le test de "%" dans la cellule. Une fois que cela fonctionne, vous pouvez ajouter le reste de votre code.

Essaye ça:

Option Explicit


Sub DoIHavePercentSymbol()
   Dim rng As Range

   Set rng = ActiveCell

   Do While rng.Value <> Empty
        If InStr(rng.Value, "%") = 0 Then
            MsgBox "I know nothing about percentages!"
            Set rng = rng.Offset(1)
            rng.Select
        Else
            MsgBox "I contain a % symbol!"
            Set rng = rng.Offset(1)
            rng.Select
        End If
   Loop

End Sub

InStr renverra le nombre de fois où votre texte de recherche apparaît dans la chaîne. J'ai changé votre test if pour vérifier d'abord qu'il n'y a pas de correspondance.

Les boîtes de message et le .Selects sont simplement là pour vous permettre de voir ce qui se passe lorsque vous parcourez le code. Sortez-les une fois que vous le faites fonctionner.

4
Jon Crowell

Pour une routine de recherche, vous devriez utiliser les approches Find, AutoFilter ou les tableaux à variantes. Les boucles de plage sont nominalement trop lentes, encore pire si elles utilisent Select

Le code ci-dessous recherche la variable strText dans une plage sélectionnée par l'utilisateur, puis ajoute les correspondances éventuelles à une variable de plage rng2 que vous pouvez ensuite traiter.

Option Explicit

Const strText As String = "%"

Sub ColSearch_DelRows()
    Dim rng1 As Range
    Dim rng2 As Range
    Dim rng3 As Range
    Dim cel1 As Range
    Dim cel2 As Range
    Dim strFirstAddress As String
    Dim lAppCalc As Long


    'Get working range from user
    On Error Resume Next
    Set rng1 = Application.InputBox("Please select range to search for " & strText, "User range selection", Selection.Address(0, 0), , , , , 8)
    On Error GoTo 0
    If rng1 Is Nothing Then Exit Sub

    With Application
        lAppCalc = .Calculation
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With

    Set cel1 = rng1.Find(strText, , xlValues, xlPart, xlByRows, , False)

    'A range variable - rng2 - is used to store the range of cells that contain the string being searched for
    If Not cel1 Is Nothing Then
        Set rng2 = cel1
        strFirstAddress = cel1.Address
        Do
            Set cel1 = rng1.FindNext(cel1)
            Set rng2 = Union(rng2, cel1)
        Loop While strFirstAddress <> cel1.Address
    End If

    If Not rng2 Is Nothing Then
        For Each cel2 In rng2
            Debug.Print cel2.Address & " contained " & strText
        Next
    Else
        MsgBox "No " & strText
    End If

    With Application
        .ScreenUpdating = True
        .Calculation = lAppCalc
    End With

End Sub
0
brettdj

vous ne modifiez jamais la valeur de rng afin qu'il pointe toujours vers la cellule initiale

copier la Set rng = rng.Offset(1, 0) dans une nouvelle ligne avant la boucle

de plus, votre test InStr échouera toujours
True est -1, mais le retour de InStr sera supérieur à 0 lorsque la chaîne est trouvée. changer le test pour enlever = True

nouveau code:

Sub IfTest()
 'This should split the information in a table up into cells
 Dim Splitter() As String
 Dim LenValue As Integer     'Gives the number of characters in date string
 Dim LeftValue As Integer    'One less than the LenValue to drop the ")"
 Dim rng As Range, cell As Range
 Set rng = ActiveCell

Do While ActiveCell.Value <> Empty
    If InStr(rng, "%") Then
        ActiveCell.Offset(0, 0).Select
        Splitter = Split(ActiveCell.Value, "% Change")
        ActiveCell.Offset(0, 10).Select
        ActiveCell.Value = Splitter(1)
        ActiveCell.Offset(0, -1).Select
        ActiveCell.Value = "% Change"
        ActiveCell.Offset(1, -9).Select
    Else
        ActiveCell.Offset(0, 0).Select
        Splitter = Split(ActiveCell.Value, "(")
        ActiveCell.Offset(0, 9).Select
        ActiveCell.Value = Splitter(0)
        ActiveCell.Offset(0, 1).Select
        LenValue = Len(Splitter(1))
        LeftValue = LenValue - 1
        ActiveCell.Value = Left(Splitter(1), LeftValue)
        ActiveCell.Offset(1, -10).Select
    End If
Set rng = rng.Offset(1, 0)
Loop

End Sub
0
SeanC