Jag har ett Excel-kalkylblad som består av två kolumner, varav en är fylld med strängar och den andra är tom. Jag vill använda VBA för att tilldela cellernas värde i den tomma kolumnen baserat på värdet på den intilliggande strängen i den andra kolumnen.

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 

problemet är att när den här slingan används för stora mängder data tar det alldeles för lång tid att arbeta, och för det mesta kraschar det helt enkelt Excel.

Vet någon ett bättre sätt att göra detta?

Svar

Det korta svaret är:

Använd inte , använd en formel. I synnerhet en kombination av IF och SÖK .

=IF(SEARCH($A1,"Admin")>0,"Exploitation","") 

Men det här är kodgranskning, så låt oss göra det ändå.

  • Regex är långsam. Det verkar som att du bara använder det för det sakskänslighet. Med tanke på det kan du direkt jämföra cellvärden genom att använda StrComp med alternativet vbTextCompare. ( användbar artikel om StrComp )

  • i och j används vanligtvis för loopräknare, men row och col meningsfullare i det här fallet.

Så här kan det se ut:

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 

Svar

Jag skulle tro att enkel strängjämförelse skulle vara mycket snabbare än 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 

Kommentarer

  • Den här koden ’ t hanterar inte skiftlägeskänslig jämförelse, men du ’ är korrekt. Regex är överdrivet och strängjämförelse föredras i detta fall. (Välkommen till kodrecension förresten!)

Svar

Får jag föreslå en minskning av körtiden med 50% /ansträngning?

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 

Märkte ingen att OP talar om att ”kontrollera EN kolumn, skriva till NÄSTA intill”, verkligen? Varför slingkolumner då? Det andra passet skulle bara kontrollera antingen en tom cell eller en med ”Exploitation”.

Svar

Wow. Bara att läsa igenom de första par raderna fick mig att undra:

  • Varför senbindningen?
  • Varför använda en regex alls?

@ ckuhn203 adresserade redan namngivningen i sitt svar, men jag finner detta:

Dim i As Integer For i = 1 To 10 "let"s say there is 10 rows 

Omvandlas till det:

Dim row As Integer For row = 1 To 10 "let"s say there is 10 rows 

… Behöver inte kommentaren längre.


Jag vill använda VBA för att tilldela cellernas värde i den tomma kolumnen baserat på värdet på den intilliggande strängen i den andra kolumnen.

Jag tycker att ”s [mis | ab] använder VBA: Excel själv är mycket bra för att hantera tilldelning av cellvärden baserat på andra celler ”värden.


regexAdmin.Pattern = "Admin" 

Jag tror att ”s [mis | ab] använder regex: om ditt mönster bara är ett ord, försöker du troligen att döda en mygga med en bazooka. Fel verktyg för t han jobbar här.

Svar

När du öppnar Range-objektet ska det göras med en enda läs / skriv-operation.

Innan du går in i for-slingan bör du läsa hela intervallet som du vill arbeta med.

data = Range(Cells(1,1), Cells(10,2)).Value 

Nu kan du arbeta med data:

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 

Skriv slutligen tillbaka data för att excel:

Range(Cells(1,1), Cells(10,2)).Value = data 

Svar

I B1:

=if(upper(A1)="ADMIN","Exploitation","") 

Fyll bara i det. Detta är skiftlägeskänsligt.

Den här automatiska fyllningen kan göras på två sätt, antingen interaktivt i kalkylbladet eller programmatiskt:

Interaktivt : Excel har en autofyllningsfunktion. När B1 är valt och den formeln är inlagd, dubbelklickar du bara på fyllningshandtaget, vilket är det lilla fyrkanten i det nedre högra hörnet av cellen när den väljs. Excel kopierar formeln intelligent till slutet av det angränsande intervallet som har data. Det betyder att om A1-A256 inte har några tomma ämnen, fylls den automatiskt på B256. Alternativt, om det är tomma, bläddra till botten och välj B256 (eller vad än än slutet är). Ctrl + Skift + uppåtpilen för att välja intervallet som leder till B1 och Ctrl + D för att kopiera ner det (tänk d = ditto)

Använda VBA … om du måste göra detta programmatiskt: med formeln som innehåller cellen som ditt val:

Selection.AutoFill Destination:=Range("B1:B19") 

Det finns andra alternativ för autofyll för att göra några coola knep.Kan kopiera ett bokstavligt värde istället för en formel eller också fylla en serie baserat på ett mönster. Du kan också ställa in anpassade mönster för att den ska känna igen, till exempel affärsområden som du ofta upprepar i saker eller städer där du har butiker, etc.

Kommentarer

  • Välkommen till Code Review! Jag saknade helt att OP ’ inte behövde söka i kolumnen! ++ Bästa lösningen här.

Svar

Att kombinera alla andra svar tillsammans, gjorde det skiftlägeskänsligt som regex i originalet, tog bort behovet av att ange hur många rader och deklarera alla variabler eftersom Option Explicit undviker så många fel i vba

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 

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *