Ik heb een Excel-werkblad dat uit twee kolommen bestaat, waarvan er één gevuld is met tekenreeksen en de andere leeg is. Ik zou VBA willen gebruiken om de waarde van de cellen in de lege kolom toe te wijzen op basis van de waarde van de aangrenzende string in de andere kolom.
Dim regexAdmin As Object Set regexAdmin = CreateObject("VBScript.RegExp") regexAdmin.IgnoreCase = True regexAdmin.Pattern = "Admin" Dim i As Integer For i = 1 To 10 "let"s say there is 10 rows Dim j As Integer For j = 1 To 2 If regexAdmin.test(Cells(i, j).Value) Then Cells(i, j + 1).Value = "Exploitation" End If Next j Next i
De Het probleem is dat wanneer deze lus wordt gebruikt voor een grote hoeveelheid gegevens, het veel te lang duurt om te werken en meestal Excel crasht.
Kent iemand een betere manier om dit te doen?
Antwoord
Het korte antwoord is:
Gebruik geen vba , gebruik een formule. In het bijzonder een combinatie van IF
en SEARCH .
=IF(SEARCH($A1,"Admin")>0,"Exploitation","")
Maar dit is codereview, dus laten we dat toch doen.
-
Regex is traag. Het lijkt erop dat je het alleen gebruikt voor zijn hoofdlettergevoeligheid. Daarom kunt u celwaarden rechtstreeks vergelijken door
StrComp
te gebruiken met de optievbTextCompare
. ( nuttig artikel over StrComp ) -
i
enj
worden meestal gebruikt voor lustellers, maarrow
encol
in dit geval logischer.
Hier is hoe dit eruit zou kunnen zien:
Dim row As Integer For row = 1 To 10 "let"s say there is 10 rows Dim col As Integer For col = 1 To 2 If StrComp("Admin",Cells(row, col).Value,vbTextCompare) Then Cells(row, col + 1).Value = "Exploitation" End If Next col Next row
Antwoord
Ik zou denken dat eenvoudige stringvergelijking veel sneller zou zijn dan Regex.
Dim pattern as string pattern = "Admin" Dim i As Integer For i = 1 To 10 "let"s say there is 10 rows Dim j As Integer For j = 1 To 2 If Cells(i, j) = pattern Then Cells(i, j + 1) = "Exploitation" End If Next j Next i
Reacties
- Deze code ‘ adres niet hoofdlettergevoelige vergelijking, maar je ‘ correct. De regex is overkill en in dit geval verdient stringvergelijking de voorkeur. (Overigens welkom bij Code Review!)
Antwoord
Mag ik een 50% verkorting van de looptijd voorstellen /inspanning?
Dim row As Integer For row = 1 To 10 "let"s say there is 10 rows If StrComp("Admin",Cells(row, 1).Value,vbTextCompare) Then Cells(row, 2).Value = "Exploitation" End If Next row
Heeft niemand opgemerkt dat het OP het heeft over “ÉÉN kolom controleren, schrijven naar de VOLGENDE aangrenzende”, echt waar? Waarom dan kolommen doorlopen? De tweede doorgang zou alleen een lege cel controleren of een met “Exploitatie” erin.
Antwoord
Wauw. Alleen al het doorlezen van de eerste paar regels deed me afvragen:
- Waarom de late binding?
- Waarom überhaupt een regex gebruiken?
@ ckuhn203 heeft de naamgeving al behandeld in zijn antwoord, maar ik vind dit:
Dim i As Integer For i = 1 To 10 "let"s say there is 10 rows
Daarin veranderd:
Dim row As Integer For row = 1 To 10 "let"s say there is 10 rows
… Heeft de opmerking niet meer nodig.
Ik zou VBA willen gebruiken om de waarde van de cellen in de lege kolom toe te wijzen op basis van de waarde van de aangrenzende string in de andere kolom.
Ik denk dat “s [mis | ab] VBA gebruikt: Excel zelf is erg goed in het toewijzen van celwaarden op basis van andere cellen “waarden.
regexAdmin.Pattern = "Admin"
Ik denk dat “s [mis | ab] gebruik maakt van regex: als je patroon gewoon een gewoon woord is, probeer je waarschijnlijk een mug te doden met een bazooka. Verkeerd hulpmiddel voor t hij werk hier.
Answer
Elke keer dat je het Range-object opent, moet het worden gedaan met een enkele lees- / schrijfbewerking.
Voordat u de for-lus invoert, moet u het hele bereik lezen waarmee u wilt werken.
data = Range(Cells(1,1), Cells(10,2)).Value
Nu kunt u aan de slag met de gegevens:
For i = 1 To 10 "let"s say there is 10 rows Dim j As Integer For j = 1 To 2 If regexAdmin.test(data(i, j)) Then data(i, j + 1) = "Exploitation" End If Next j Next i
Schrijf ten slotte de gegevens terug naar Excel:
Range(Cells(1,1), Cells(10,2)).Value = data
Antwoord
In B1:
=if(upper(A1)="ADMIN","Exploitation","")
Vul het dan gewoon in. Dit is niet hoofdlettergevoelig.
Dit automatisch invullen kan op twee manieren worden gedaan, ofwel interactief in het werkblad, ofwel programmatisch:
Interactief : Excel heeft een functie voor automatisch aanvullen. Als B1 is geselecteerd en die formule is ingevoerd, dubbelklikt u gewoon op de vulgreep. Dit is het kleine vierkantje in de rechterbenedenhoek van de cel wanneer deze is geselecteerd. Excel kopieert de formule op intelligente wijze naar het einde van het aaneengesloten bereik met gegevens. Dit betekent dat als A1-A256 gegevens heeft zonder spaties, het automatisch wordt ingevuld naar B256. Als alternatief kunt u, als er lege plekken zijn, naar beneden scrollen en B256 selecteren (of wat het einde ook is). Vervolgens Ctrl + Shift + pijl-omhoog om het bereik te selecteren dat naar B1 leidt, en Ctrl + D om het naar beneden te kopiëren (denk aan d = dito)
VBA gebruiken … als u dit programmatisch moet doen: met de formule die cel bevat als uw selectie:
Selection.AutoFill Destination:=Range("B1:B19")
Er zijn andere opties beschikbaar voor automatisch aanvullen om een paar coole trucs uit te voeren.Kan een letterlijke waarde kopiëren in plaats van een formule, of kan ook een reeks vullen op basis van een patroon. U kunt ook aangepaste patronen instellen om het te herkennen, zoals bedrijfstakken die u vaak herhaalt in dingen of steden waar u winkels heeft, enz.
Opmerkingen
- Welkom bij Code Review inderdaad! Ik heb helemaal gemist dat OP ‘ niet in de kolom hoefde te zoeken! ++ De beste oplossing hier.
Answer
Door alle andere antwoorden samen te voegen, werd het hoofdletterongevoelig zoals de regex in het origineel, de noodzaak om op te geven hoeveel rijen en het declareren van alle variabelen is verwijderd, omdat Option Explicit
zoveel fouten in vba voorkomt
Option Explicit Sub checkForExploit() Dim row As Integer Dim data() As Variant Dim datarange As Range Set datarange = Range("A1:B10") data = datarange.Value For row = 1 To UBound(data, 1) If LCase(data(row, 1)) = "admin" Then data(row, 2) = "Exploitation" End If Next row datarange.Value = data End Sub