Je suis nouveau sur Excel VBA et j'ai une question simple. Une fois que je comprends comment faire cette boucle, je peux construire dessus.
Je voudrais automatiser une classification. Les données se répètent dans une seule colonne, c'est-à-dire sampleA, sampleA, sampleA, sampleB, sampleB, sampleC, sampleC, sampleC, etc. Je voudrais que ma macro identifie quand le nom de l'échantillon change entre les noms d'échantillon. Ainsi, par exemple, lorsque la cellule suivante après sampleA se transforme en sampleB, je voudrais que la macro comprenne qu'il y a un changement et écrive une phrase à côté de ceci (cela se transformera ensuite en une équation avec les données dans les lignes respectives de l'échantillon mais baby steps :)).
Dans l'ensemble, la macro a besoin de détecter les changements entre une colonne de noms d'échantillons identiques jusqu'à ce qu'un nouveau nom soit atteint.
J'ai recherché des solutions et la boucle «faire jusqu'à» semble être la solution la plus proche de ce dont j'ai besoin. Aussi, pour montrer que sampleA n'est pas le même que sampleB, j'ai utilisé .
Sample: Classification sampleA -- sampleA -- sampleA hello sampleB -- sampleB goodbye sampleC -- sampleC -- sampleC see you soon
Résultats réels: erreur au niveau des cellules (classification, "B ") .Valeur = réponse Quelque chose cloche ici. J'essaie d'afficher les résultats dans la colonne "B".
Résultats attendus sur la feuille de calcul Excel dans les colonnes:
Sub DoUntilStringMacro()
Dim sampleA As String
Dim sampleB As String
Dim sampleC As String
Dim classification As String
Do Until ActiveCell.Value = ""
If sampleA <> sampleB Then
classification = "hello"
ElseIf sampleB <> sampleC Then
classification = "goodbye"
ElseIf sampleC <> sampleA Then
classification = "see you soon"
End If
answer = classification
Cells(classification, "B").Value = answer
Loop
End Sub
3 Réponses :
Vous pouvez essayer la boucle For:
Option Explicit
Sub Change()
Dim Lastrow As Long, Row As Long
Dim PreviousString As String, CurrenctString As String
'With statement refers to shee 1
With ThisWorkbook.Worksheets("Sheet1")
'Find last row in Sheet 1 - Column A
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
'Loop each row start from 3 to lastrow
For Row = 3 To Lastrow
PreviousString = .Range("A" & Row - 1).Value
CurrenctString = .Range("A" & Row).Value
'Check if both strings are not the same
If PreviousString <> CurrenctString Then
If PreviousString = "sampleA" And CurrenctString = "sampleB" Then
.Range("B" & Row - 1).Value = "hello"
ElseIf PreviousString = "sampleB" And CurrenctString = "sampleC" Then
.Range("B" & Row - 1).Value = "goodbye"
ElseIf PreviousString = "sampleC" And CurrenctString = "sampleD" Then
.Range("B" & Row - 1).Value = "see you soon"
End If
End If
Next Row
End With
End Sub
Merci, erreur 1004! Cela a très bien fonctionné et j'ai appris de la structure de ce script. J'ai deux questions sur la façon de le modifier. Maintenant, au lieu d'être très spécifique et de nommer sampleA, sampleB, etc., comment puis-je dire au script de simplement lire la colonne A sous forme de chaîne? Existe-t-il un moyen que je puisse simplement appeler ces chaînes "sampleX" afin que je puisse parcourir une énorme feuille de calcul sans spécifier? Avec cela, puis-je faire une boucle jusqu'à la fin de la feuille de calcul pour dire "bonjour", par exemple, chaque fois qu'il y a une chaîne différente? Merci merci!
Heureux d'entendre cela une aide! Oui, vous pouvez faire une boucle sur chaque ligne et changer "PreviousString = .Range (" A "& Row - 1) .Value" en "sampleX = .Range (" A "& Row - i) .Value" et jouer avec le code. Essayez-le et faites-moi savoir si vous avez besoin de plus d'aide.
Vous déclarez vos variables sampleA, B, C mais vous ne les définissez jamais, donc lorsque vous comparez ces trois variables, rien ne se passe.
À l'intérieur de votre boucle, vous ne définissez jamais ActiveCell sur quoi que ce soit, donc ActiveCell reste ce qu'il est. Vous bouclerez pour toujours à cause de cela.
Voici une réécriture qui n'est pas vraiment optimisée. Il y a certainement de meilleures façons de le faire (en utilisant une boucle for sur la Range ("A1: A" & lastFilledRow) par exemple), mais je voulais garder cela assez proche de votre tentative de voir comment pour résoudre ce problème comme vous l'aviez prévu, car c'est certainement une manière viable et raisonnable de le faire.
J'ai ajouté une tonne de commentaires pour expliquer ce qui se passait.
Sub DoUntilStringMacro()
Dim currentValue As String
Dim previousValue As String
Dim classification As String
'set the first cell to search and we will iterate
' from there
Dim searchCell As Range
Set searchCell = Sheet1.Range("A2")
'Lets also get a counter variable to see how many
' times we've found a change...
Dim changesFound As Integer
'Loop until the searchCell is empty
Do Until searchCell.Value = ""
'set the currentValue
currentValue = searchCell.Value
'If the previousValue variable is empty then
' this is the first cell we're analyzing
' so don't bother running this bit of code
' that does the comparison
If previousValue <> "" Then
'Compare to what we stored in previousValue
If currentValue <> previousValue Then
'We found a change, increment our counter
changesFound = changesFound + 1
'and based on that value lets figure out
' what to write out
Select Case changesFound
Case 1
'This is the first time we hit a
' a change so write out "hello"
'BUT!!! we need to write it the
' cell above the current
' searchCell and one column over
' We'll use .Offset() to do that
searchCell.Offset(-1, 1).Value = "Hello"
Case 2
searchCell.Offset(-1, 1).Value = "goodbye"
Case 3
searchCell.Offset(-1, 1).Value = "see you soon"
End Select
End If
End If
'So we are going to iterate again, lets capture
' the currentValue into the previousValue
' variable so we have it to compare on the
' the next loop
previousValue = currentValue
'Also... we want to make sure that searchCell
' is the next cell otherwise we will just
' keep testing the same cell over and over
' again until excel crashes.
'Again we'll use `.Offset()` to move to the
' next row
Set searchCell = searchCell.Offset(1)
Loop
'Heres the kicker... we needed one more iteration
' since we exited when the searchCell was blank...
' so that Case 3 never hit...
' we'll just go ahead and fill that out now
searchCell.Offset(-1, 1).Value = "See you soon"
End Sub
J'ai éliminé ActiveCell depuis ce n'est pas une bonne idée. Sélectionnez , Activer , ActiveCell ce sont toutes des photos de merde dans VBA. Il est préférable de dire "explicitement cette cellule / plage est ce que je veux" plutôt que d'espérer que la cellule que vous souhaitez est actuellement active.
Merci pour cet indice, JNevill! J'aime l'apparence de ce script et je comprends jusqu'à certains points. Ma première question est: une fois que nous avons mis ce compteur à chaque fois qu'il y a un changement, ces entiers 1, 2, 3, etc. remplaceront la colonne A? Il semble que vous n'ayez jamais défini de colonne pour ces éléments. Ma deuxième question est la suivante: pourrions-nous ajouter à la colonne suivante, C, une formule pour uniquement les lignes contenant un entier? Et ma troisième question est: j'obtiens une erreur à currentValue = searchCell.Value. Pourquoi est-ce? Merci beaucoup!
1) Nous définissons une colonne en utilisant ce offset (-1,1) . Cela signifie monter sur la ligne à partir de la cellule actuelle et sur une colonne. 2) Je ne vous suis pas sur votre utilisation de la colonne C . "Seulement les lignes qui ont un entier" mais je ne vois aucun entier dans vos données ou les données que nous écrivons dans la colonne B . 3) Quelle est l'erreur que vous obtenez? Cliquez également sur le bouton "Déboguer" pour que la ligne soit mise en surbrillance et survolez searchCell.Value et voyez quelle valeur il rapporte dans cette cellule. Cela peut donner quelques indices (à côté du message d'erreur, ce qui est encore plus important)
Merci pour la réponse rapide. 1) Donc offset (-1,1) se trouve dans la ligne changesFound = changesFound + 1 ? 2) Oui, vous avez raison. Je voulais dire toutes les lignes de la colonne B qui ont maintenant une chaîne, bonjour, au revoir, etc., et pour que le script reconnaisse qu'il y a une chaîne là-bas et applique une formule à ces chaînes à afficher dans la colonne C. 3) Les états d'erreur qu'il y a un problème avec la gamme.
changesFound est juste une variable que nous incrémentons. La valeur de cette variable est contenue uniquement dans cette variable et nous ne l'écrivons jamais nulle part. Cependant, en utilisant l'instruction SELECT CASE , nous écrivons une chaîne dans la colonne B en utilisant Offset (1, -1) .value = "somestring" code >. Je suppose que vous pouvez mettre ce que vous voulez dans la colonne C. Si vous voulez le faire dans VBA, vous pouvez simplement ajouter searchCell.Offset (-1, 2) .value = "Ceci est la colonne C, et la colonne B est actuellement peuplé! ". Toujours pas sûr de cette erreur. Y a-t-il un numéro d'erreur associé?
D'accord, je vois. Nous pouvons insérer Offset (1, -1) .value = "somestring" après l'instruction Do Until? Pareil avec celui qui contrôle la colonne C? Il semble que l'erreur d'exécution exacte soit: '-2147417848 (80010108)': la méthode 'Value' de l'objet 'Range' a échoué et elle pointe vers currentValue = searchCell.Value
J'ai découvert mon erreur pour l'erreur. Merci encore :)
Vous pouvez utiliser des formules et éviter les boucles:
Sub IdentifySampleNameChanges()
With Worksheets("Sheet1") â change âSheet1â to your actual sheet name
With .Range("A2", .Cells(.Rows.Count, "A").End(xlUp)).Offset(, 1)
.Formula = "=IF(A2<>A3,""Hello"","""")"
.Value = .Value
End With
End With
End Sub
C'est génial. Je vous remercie! Pour ajouter à cela, comment appliquer une formule à toutes les valeurs sampleA, sampleB, etc. au-dessus de chaque bonjour?
Je vous en prie. Si ma réponse a résolu votre question originale , vous pouvez envisager de la marquer comme acceptée. Je vous remercie. En ce qui concerne la "formule au-dessus de chaque bonjour", vous voudrez peut-être donner plus de détails
Se fier à
ActiveCellpeut entraîner des problèmes. Au lieu d'utiliser une boucleDo Until, pensez peut-être à recherche de la dernière ligne , puis boucle de la ligne de départ à la dernière ligne.SampleAetc. ne sont jamais initialisés et la cellule que vous attendez de quelque chose commeCells ("goodbye", "B")depuis"n'est pas claire. au revoir "n'est manifestement pas un numéro de ligne.Peut-il y avoir des cellules vides dans la plage? Et la classification peut-elle se répéter ou ne doit-elle intervenir que juste avant un changement? La dernière valeur avant le blanc de fin constitue-t-elle un changement (semble-t-il ...)? La commande des données est-elle garantie?
Vous avez omis des parties du code car on ne sait pas d'où viennent ces
exemplesvariables. Si vous traitez avecActiveCell, vous devez le faire avancer dans une boucle - sinon vous êtes coincé avec une seule et même cellule.