Mam arkusz programu Excel składający się z dwóch kolumn, z których jedna jest wypełniona ciągami, a druga jest pusta. Chciałbym użyć VBA do przypisania wartości komórek w pustej kolumnie na podstawie wartości sąsiedniego ciągu w drugiej kolumnie.

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 

Problem polega na tym, że gdy używasz tej pętli dla dużej ilości danych, jej działanie zajmuje zbyt dużo czasu i przez większość czasu po prostu powoduje awarię programu Excel.

Czy ktoś zna lepszy sposób na zrobienie tego?

Odpowiedź

Krótka odpowiedź brzmi:

Nie używaj , użyj formuły. W szczególności kombinacja IF i SEARCH .

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

Ale to jest przegląd kodu, więc zróbmy to mimo wszystko.

  • Regex działa wolno. Wygląda na to, że „używasz go tylko do niewrażliwości na wielkość liter. Biorąc to pod uwagę, możesz bezpośrednio porównać wartości komórek, używając opcji StrComp z opcją vbTextCompare. ( przydatny artykuł na StrComp )

  • i i j zwykle używane do liczników pętli, ale row i col mam więcej sensu w tym przypadku.

Oto, jak to mogłoby wyglądać:

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 

Odpowiedź

Myślę, że proste porównanie ciągów byłoby znacznie szybsze niż 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 

Komentarze

  • Ten kod nie ' odnosi się do porównania bez uwzględniania wielkości liter, ale ' jest poprawny. Wyrażenie regularne jest przesadą i w tym przypadku preferowane jest porównanie ciągów. (Swoją drogą, witamy w przeglądzie kodu!)

Odpowiedź

Czy mogę zasugerować 50% skrócenie czasu działania /wysiłek?

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 

Czy nikt nie zauważył, że OP mówi o „sprawdzaniu JEDNEJ kolumny, pisaniu do następnej sąsiedniej”, naprawdę? Po co więc zapętlić kolumny? Drugi przebieg sprawdziłby tylko pustą komórkę lub komórkę z „Wykorzystaniem”.

Odpowiedź

Wow. Po przeczytaniu pierwszych kilku wierszy zacząłem się zastanawiać:

  • Dlaczego późne wiązanie?
  • Po co w ogóle używać wyrażenia regularnego?

@ ckuhn203 odniósł się już do nazewnictwa w swojej odpowiedzi, ale znalazłem to:

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

Przekształcone w to:

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

… Nie potrzebuje już komentarza.


Chciałbym użyć VBA do przypisania wartości komórek w pustej kolumnie na podstawie wartości sąsiedniego ciągu w drugiej kolumnie.

Myślę, że „s [mis | ab] używając VBA: sam Excel bardzo dobrze radzi sobie z przypisywaniem wartości komórek na podstawie innych komórek ”.


regexAdmin.Pattern = "Admin" 

Myślę, że „s [mis | ab] używając wyrażenia regularnego: jeśli twój wzór jest zwykłym słowem,” najprawdopodobniej próbujesz zabić komara bazooką. Niewłaściwe narzędzie dla t tutaj.

Odpowiedź

Zawsze, gdy uzyskujesz dostęp do obiektu Range, należy to zrobić za pomocą jednej operacji odczytu / zapisu.

Przed wejściem do pętli for powinieneś przeczytać cały zakres, z którym chcesz pracować.

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

Teraz możesz pracować z danymi:

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 

Na koniec zapisz dane z powrotem do programu Excel:

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

Odpowiedź

W B1:

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

Następnie po prostu wypełnij. To jest niewrażliwe na wielkość liter.

To automatyczne wypełnianie można wykonać na dwa sposoby, interaktywnie w arkuszu lub programowo:

Interaktywnie : Excel ma funkcję autouzupełniania. Po zaznaczeniu B1 i wstawieniu tej formuły wystarczy dwukrotnie kliknąć uchwyt wypełniania, który jest małym kwadratem w prawym dolnym rogu komórki, gdy jest on zaznaczony. Program Excel w inteligentny sposób skopiuje formułę na koniec ciągłego zakresu, który ma Oznacza to, że jeśli A1-A256 ma dane bez spacji, wypełni się automatycznie do B256. Alternatywnie, jeśli są spacje, przewiń w dół i wybierz B256 (lub jakikolwiek inny koniec). Następnie Ctrl + Shift + strzałka w górę, aby wybrać zakres prowadzący do B1 i Ctrl + D, aby go skopiować (pomyśl d = ditto)

Korzystanie z VBA … jeśli musisz to zrobić programowo: z formułą zawierającą komórkę jako wybór:

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

Dostępne są inne opcje autouzupełniania, które pozwalają wykonać kilka fajnych sztuczek.Może skopiować wartość literału zamiast formuły lub wypełnić serię na podstawie wzorca. Możesz również ustawić niestandardowe wzorce, które będzie rozpoznawać, na przykład linie biznesowe, które często powtarzasz w rzeczach lub miastach, w których masz sklepy itp.

Komentarze

  • Rzeczywiście, witamy w Code Review! Całkowicie przegapiłem, że OP nie ' nie musiał przeszukiwać kolumny! ++ Najlepsze rozwiązanie tutaj.

Odpowiedź

Połączenie wszystkich pozostałych odpowiedzi sprawiło, że wielkość liter nie była rozróżniana, jak regex w oryginale, usunięto potrzebę określenia liczby wierszy i deklarowania wszystkich zmiennych, ponieważ Option Explicit pozwala uniknąć tak wielu błędów w 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 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *