Am o foaie de lucru Excel formată din două coloane, dintre care una este umplută cu șiruri și cealaltă este goală. Aș dori să folosesc VBA pentru a atribui valoarea celulelor din coloana goală pe baza valorii șirului adiacent din cealaltă coloană.

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 

problema este că, atunci când utilizați această buclă pentru o cantitate mare de date, durează mult timp pentru a funcționa și, de cele mai multe ori, pur și simplu se blochează Excel.

Știe cineva un mod mai bun de a face acest lucru?

Răspuns

Răspunsul scurt este:

Nu utilizați , utilizați o formulă. În special, o combinație de IF și CĂUTARE .

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

Dar aceasta este revizuirea codului, așa că „să facem asta oricum.

  • Regex este lent. Se pare că „îl folosești doar pentru insensibilitate la caz”. Având în vedere acest lucru, puteți compara direct valorile celulei utilizând StrComp cu opțiunea vbTextCompare. ( articol util despre StrComp )

  • i și j sunt de obicei utilizate pentru contoare de bucle, dar row și col are mai mult sens în acest caz.

Iată cum ar putea arăta acest lucru:

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 

Răspuns

Aș crede că o comparație simplă a șirurilor ar fi mult mai rapidă decât 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 

Comentarii

  • Acest cod nu ‘ nu se adresează comparării insensibile la majuscule, dar ‘ nu este corect. Regexul este suprasolicitat și compararea șirurilor este preferată în acest caz. (Bun venit la Code Review de altfel!)

Răspunde

Îți pot sugera o reducere de 50% a timpului de rulare /efort?

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 

N-a observat nimeni că PO vorbește despre „verificarea UNEI coloane, scrierea în NEXT adiacent”, într-adevăr? De ce buclă coloanele atunci? A doua trecere ar verifica doar o celulă goală sau una cu „Exploatare” în ea.

Răspuns

Wow. Doar citind primele două rânduri m-am făcut să mă întreb:

  • De ce legarea târzie?
  • De ce să folosim deloc un regex?

@ ckuhn203 a abordat deja denumirea în răspunsul său, dar găsesc acest lucru:

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

Transformat în:

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

… Nu mai are nevoie de comentariu.


Aș dori să folosesc VBA pentru a atribui valoarea celulelor din coloana goală pe baza valorii șirului adiacent din cealaltă coloană.

Cred că „s [mis | ab] folosind VBA: Excel în sine este foarte bun în gestionarea atribuirii valorilor celulei pe baza altora valori „celule.


regexAdmin.Pattern = "Admin" 

Cred că „folosește regex: dacă modelul tău este doar un cuvânt simplu, probabil că încerci să omori un țânțar cu un bazooka. Instrument greșit pentru t lucrează aici.

Răspuns

Ori de câte ori accesați obiectul Range ar trebui să se facă cu o singură operație de citire / scriere.

Înainte de a introduce bucla for, ar trebui să citiți întregul interval cu care doriți să lucrați.

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

Acum puteți lucra cu datele:

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 

În cele din urmă scrieți datele înapoi în Excel:

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

Răspunde

În B1:

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

Apoi completează-l. Aceasta nu este sensibilă la majuscule.

Această completare automată poate fi realizată în două moduri, fie interactiv în foaia de lucru, fie programatic:

Interactiv : Excel are o caracteristică de completare automată. Cu B1 selectat și acea formulă introdusă, faceți dublu clic pe mânerul de umplere, care este micul pătrat din colțul din dreapta jos al celulei atunci când este selectat. Excel va copia în mod inteligent formula până la sfârșitul intervalului contigu care are date. Adică dacă A1-A256 are date fără spații libere, va completa complet B256. Alternativ, dacă există spații goale, derulați în partea de jos și selectați B256 (sau oricare ar fi sfârșitul). Apoi Ctrl + Shift + Săgeată sus pentru a selecta intervalul care duce la B1 și Ctrl + D pentru a o copia (gândiți d = idem)

Utilizarea VBA … dacă trebuie să faceți acest lucru programatic: cu formula care conține celula ca selecție:

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

Există alte opțiuni disponibile pentru completarea automată pentru a face câteva trucuri interesante.Poate copia o valoare literală în locul unei formule sau poate completa și o serie bazată pe un model. De asemenea, puteți seta modele personalizate pentru a fi recunoscute, cum ar fi liniile de activitate pe care le repetați în mod obișnuit în lucruri sau în orașele în care aveți locații de vânzare cu amănuntul etc.

Comentarii

  • Bine ați venit la Code Review! Mi-a fost complet dor că OP nu ‘ nu a trebuit să caute coloana! ++ Cea mai bună soluție aici.

Răspuns

Combinând toate celelalte răspunsuri împreună, a făcut-o să distingă majuscule și minuscule regex în original, a eliminat necesitatea de a specifica câte rânduri și declararea tuturor variabilelor deoarece Option Explicit evită atât de multe erori în 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 

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *