Słyszałem wiele o zrozumiałej wstręt do używania .Select
w Excel VBA, ale nie jestem pewien, jak tego uniknąć. Zauważyłem, że mój kod byłby bardziej przydatny, gdybym mógł używać zmiennych zamiast Select
funkcji. Jednak nie jestem pewien, jak odwoływać się do rzeczy (takich jak ActiveCell
itp.), Jeśli nie używam Select
.
Znalazłem ten artykuł na temat zakresów i ten przykład na temat korzyści płynących z nie używania select, ale nie mogę znaleźć niczego na temat tego, jak ?
Select
i / lubActiveSheet
itp. Itp. Jest całkowicie nieuniknione. Oto przykład, który znalazłem: stackoverflow.com/questions/22796286/….Select / .Selection
to konieczne.Odpowiedzi:
Kilka przykładów unikania wyboru
Użyj
Dim
zmiennych „d”Set
zmienna do wymaganego zakresu. Istnieje wiele sposobów odniesienia do zakresu jednokomórkowegolub zakres wielu komórek
Państwo może używać skrótu do
Evaluate
metody, ale to jest mniej wydajny i generalnie należy unikać w kodzie produkcyjnym.Wszystkie powyższe przykłady odnoszą się do komórek na aktywnym arkuszu . Jeśli nie chcesz pracować tylko z aktywnym arkuszem, lepiej jest również przyciemnić
Worksheet
zmiennąJeśli nie chcą pracować z
ActiveSheet
, dla jasności, że najlepiej być jawne. Ale uważaj, ponieważ niektóreWorksheet
metody zmieniają aktywny arkusz.Ponownie odnosi się to do aktywnego skoroszytu . Jeśli nie chcesz pracować tylko z
ActiveWorkbook
lubThisWorkbook
, lepiej jest również przyciemnićWorkbook
zmienną.Jeśli nie chcą pracować z
ActiveWorkbook
, dla jasności, że najlepiej być jawne. Ale uważaj, ponieważ wieleWorkBook
metod zmienia aktywną książkę.Możesz także użyć tego
ThisWorkbook
obiektu, aby odnieść się do książki zawierającej działający kod.Częstym (złym) fragmentem kodu jest otwieranie książki, pobieranie danych, a następnie zamykanie
To jest złe:
I byłoby lepiej, jak:
Karnet waha się swoimi
Sub
s iFunction
s jako zmienne klasyPowinieneś także zastosować metody (takie jak
Find
iCopy
) do zmiennychJeśli zapętlasz zakres komórek, często lepiej (szybciej) jest najpierw skopiować wartości zakresu do tablicy wariantów i zapętlić
To jest mały degustator tego, co jest możliwe.
źródło
rng1(12, 12)
róg ... np. będzie działał, nawet jeśli rng1 był ustawiony[A1:A10]
tylko na.Range
ten sposób:ActiveSheet.[a1:a4]
lubws.[b6]
.variant
Zmienna nie wymagaSet
aż przypisać obiekt do niego. Na przykładDim x: x = 1
jest w porządku, aleDim x: x = Sheets("Sheet1")
wygeneruje błąd 438. Jednak samo zamieszanie / wyjaśnienie nieDim x: x = Range("A1")
spowoduje błędu. Dlaczego? ... ponieważ przypisuje się wartość obiektu do zmiennej, a nie odwołanie do samego obiektu (ponieważ jest to odpowiednik )Dim x: x = Range("A1").Value
Dwa główne powody, dla których należy unikać
.Select
/.Activate
/Selection
/Activecell
/Activesheet
/Activeworkbook
itpJak tego uniknąć?
1) Bezpośrednio pracuj z odpowiednimi obiektami
Rozważ ten kod
Ten kod można również zapisać jako
2) W razie potrzeby zadeklaruj zmienne. Ten sam kod powyżej można zapisać jako
źródło
Sheets(2).[C10:D12].Value = Sheets(1).[A1:B3].Value
.Activate
aby przejść do oryginalnego arkusza, po prostu użyjApplication.Goto
Jednym drobnym naciskiem położę nacisk na wszystkie doskonałe odpowiedzi podane powyżej:
Prawdopodobnie największą rzeczą, jaką możesz zrobić, aby uniknąć używania Select, jest jak najwięcej, używanie nazwanych zakresów (w połączeniu z sensownymi nazwami zmiennych) w kodzie VBA . Ten punkt został wspomniany powyżej, ale nieco przesadzony; zasługuje jednak na szczególną uwagę.
Oto kilka dodatkowych powodów, aby swobodnie korzystać z nazwanych zakresów, choć jestem pewien, że mógłbym wymyślić więcej.
Nazwane zakresy ułatwiają czytanie i zrozumienie kodu.
Przykład:
Jest dość oczywiste, jaka nazwane zakresy
Months
iMonthlySales
zawierać i jakie procedura robi.Dlaczego to jest ważne? Częściowo dlatego, że innym ludziom łatwiej jest to zrozumieć, ale nawet jeśli jesteś jedyną osobą, która kiedykolwiek zobaczy lub użyje twojego kodu, powinieneś nadal używać nazwanych zakresów i dobrych nazw zmiennych, ponieważ ZAPOMNIJ, co chciałeś z tym zrobić. rok później i ty zmarnujesz 30 minut na zastanawianie się, co robi Twój kod.
Nazwane zakresy zapewniają, że makra nie będą się łamać, gdy (nie jeśli!) Zmieni się konfiguracja arkusza kalkulacyjnego.
Zastanów się, czy powyższy przykład został napisany w ten sposób:
Ten kod na początku będzie działał dobrze - to znaczy dopóki ty lub przyszły użytkownik nie zdecydujesz „gee wiz, myślę, że dodam nową kolumnę z rokiem w kolumnie
A
!” Lub wstawię kolumnę wydatków między miesiącami a kolumny sprzedaży lub dodaj nagłówek do każdej kolumny. Teraz twój kod jest zepsuty. A ponieważ użyłeś okropnych nazw zmiennych, zajmie ci to dużo więcej czasu, aby wymyślić, jak to naprawić, niż powinno.Jeśli na początku używałeś nazwanych zakresów, kolumny
Months
iSales
można przesuwać w dowolne miejsce, a Twój kod będzie działał dobrze.źródło
Dam krótką odpowiedź, ponieważ wszyscy inni udzielili długiej.
Otrzymasz .select i .activate za każdym razem, gdy nagrywasz makra i używasz ich ponownie. Po wybraniu komórki lub arkusza aktywuje się. Od tego momentu za każdym razem, gdy korzystasz z niekwalifikowanych odniesień, tak
Range.Value
jakby korzystali tylko z aktywnej komórki i arkusza. Może to być również problematyczne, jeśli nie oglądasz, gdzie jest umieszczony kod lub użytkownik klika skoroszyt.Możesz więc wyeliminować te problemy, bezpośrednio odwołując się do komórek. Który idzie:
Lub mógłbyś
Istnieją różne kombinacje tych metod, ale taka byłaby ogólna idea wyrażona jak najkrócej dla niecierpliwych ludzi takich jak ja.
źródło
Chociaż nie mogę wymyślić nic poza odosobnioną garstką sytuacji, w których
.Select
byłby lepszy wybór niż bezpośrednie odwoływanie się do komórki, podniosłem się do obronySelection
i wskazałem, że nie należy go wyrzucać z tych samych powodów, których.Select
należy unikać.Są chwile, gdy krótkie, oszczędzające czas makropodprogramy przypisane do kombinacji skrótów dostępnych za naciśnięciem kilku klawiszy oszczędzają dużo czasu. Będąc w stanie wybrać grupę komórek, aby wprowadzić kod operacyjny w operacjach cuda, gdy mamy do czynienia z danymi kieszonkowymi, które nie są zgodne z formatem danych obejmującym cały arkusz roboczy. W ten sam sposób, w jaki możesz wybrać grupę komórek i zastosować zmianę formatu, wybranie grupy komórek, dla których ma zostać uruchomiony specjalny kod makr, może znacznie zaoszczędzić czas.
Przykłady podprogramów opartych na selekcji:
Rzeczywisty kod do przetworzenia może być dowolny, od jednej linii po wiele modułów. Użyłem tej metody do zainicjowania długotrwałych procedur na niewyrównanym wyborze komórek zawierających nazwy plików zewnętrznych skoroszytów.
Krótko mówiąc, nie odrzucaj
Selection
ze względu na bliskie powiązania z.Select
iActiveCell
. Jako właściwość arkusza ma wiele innych celów.(Tak, wiem, że chodziło o to pytanie
.Select
,Selection
ale nie chciałem usunąć nieporozumień, które mogą wnioskować początkujący koderzy VBA).źródło
Selection
może być dowolną częścią arkusza roboczego, więc równie dobrze może najpierw przetestować typ obiektu przed przypisaniem go do zmiennej, ponieważ jawnie zadeklarowano go jakoRange
.Zauważ, że w dalszej części porównuję podejście Select (to, którego OP chce uniknąć), z podejściem Range (i to jest odpowiedź na pytanie). Więc nie przestawaj czytać, gdy zobaczysz pierwszy Wybierz.
To naprawdę zależy od tego, co próbujesz zrobić. W każdym razie przydatny może być prosty przykład. Załóżmy, że chcesz ustawić wartość aktywnej komórki na „foo”. Za pomocą ActiveCell napisałbyś coś takiego:
Jeśli chcesz go użyć dla komórki, która nie jest aktywna, na przykład dla „B2”, musisz ją najpierw wybrać, tak jak poniżej:
Za pomocą zakresów możesz napisać bardziej ogólne makro, którego można użyć do ustawienia wartości dowolnej komórki na dowolne:
Następnie możesz przepisać Macro2 jako:
I Macro1 jako:
Mam nadzieję, że to pomoże trochę wyjaśnić.
źródło
Unikanie
Select
iActivate
jest ruchem, który sprawia, że jesteś trochę lepszym programistą VBA. W ogólności,Select
aActivate
są stosowane, gdy makro jest rejestrowane, zatemParent
arkusz lub zakres jest zawsze uważany za aktywnym.W ten sposób można uniknąć
Select
orazActivate
w następujących przypadkach:Dodanie nowego arkusza i skopiowanie do niego komórki:
Z (kod wygenerowany za pomocą rejestratora makr):
Do:
Gdy chcesz skopiować zakres między arkuszami:
Od:
Do:
Używanie fantazyjnych nazwanych zakresów
Możesz uzyskać do nich dostęp za pomocą
[]
, co jest naprawdę piękne, w porównaniu do innych sposobów. Sprawdź się:Przykład z góry wyglądałby tak:
Nie kopiowanie wartości, ale ich przyjmowanie
Zwykle, jeśli chcesz
select
, najprawdopodobniej coś kopiujesz. Jeśli interesują Cię tylko wartości, jest to dobra opcja, aby uniknąć wyboru:Range("B1:B6").Value = Range("A1:A6").Value
Staraj się zawsze odwoływać również do arkusza roboczego
Jest to prawdopodobnie najczęstszy błąd w vba. Za każdym razem, gdy kopiujesz zakresy, czasami do arkusza nie ma odniesienia, a zatem VBA uważa niewłaściwy arkusz za arkusz ActiveWorks.
Czy naprawdę nigdy nie mogę używać
.Select
ani.Activate
do niczego?.Activate
i.Select
jest to, kiedy chcesz upewnić się, że wybrany arkusz roboczy został wybrany ze względów wizualnych. Na przykład, że program Excel zawsze otwiera się z zaznaczonym najpierw arkuszem okładki, niezależnie od tego, który arkusz ActiveSheet był zamknięty, gdy plik był zamknięty.Zatem coś takiego jak poniższy kod jest absolutnie OK:
Innym dobrym przykładem jest, gdy trzeba wyeksportować wszystkie arkusze do jednego pliku PDF, jak wspomniano w tym przypadku - Jak w tym przykładzie uniknąć wyboru / aktywnych instrukcji w VBA?
Gdy polecenie działa tylko
ActiveWindow
jak ActiveWindow.Zoom lub ActiveWindow.FreezePanesźródło
.Select
- a także mojej pracy - można znaleźć na stronie Jak pisać identyczne informacje na wszystkich arkuszach - @Vityata :).FillAcrossSheets
, więc jest to gdzieś pomiędzy (przynajmniej w moim wyobrażeniu o taksonomii VBA)Zawsze podawaj skoroszyt, arkusz i komórkę / zakres.
Na przykład:
Ponieważ użytkownicy końcowi zawsze po prostu klikają przyciski, a gdy tylko fokus zniknie ze skoroszytu, kod chce z nim pracować, wtedy wszystko idzie zupełnie nie tak.
I nigdy nie używaj indeksu skoroszytu.
Nie wiesz, jakie inne skoroszyty będą otwarte, gdy użytkownik uruchomi Twój kod.
źródło
Te metody są raczej stygmatyzowane, więc objęcie roli @Vityata i @Jeeped w celu narysowania linii w piasku:
Dlaczego nie nazwać
.Activate
,.Select
,Selection
,ActiveSomething
metody / właściwościZasadniczo dlatego, że są one wywoływane głównie w celu obsługi danych wejściowych użytkownika za pośrednictwem interfejsu aplikacji. Ponieważ są to metody wywoływane, gdy użytkownik obsługuje obiekty przez interfejs użytkownika, są to te zarejestrowane przez rejestrator makr, i dlatego wywoływanie ich jest kruche lub nadmiarowe w większości sytuacji: nie musisz wybierać obiekt, aby wykonać akcję
Selection
zaraz potem.Jednak ta definicja określa sytuacje, w których są one wymagane:
Kiedy zadzwonić
.Activate
,.Select
,.Selection
,.ActiveSomething
metody / właściwościZasadniczo, gdy oczekujesz, że użytkownik końcowy będzie odgrywał rolę w wykonaniu.
Jeśli się rozwijasz i spodziewasz się, że użytkownik wybierze instancje obiektów do obsługi twojego kodu, to
.Selection
lub.ActiveObject
są odpowiednie.Z drugiej strony,
.Select
i.Activate
są przydatne, gdy możesz wywnioskować użytkownika o następnej czynności i chcesz, aby Twój kod prowadził użytkownika, prawdopodobnie oszczędzając mu trochę czasu i kliknięć myszą. Na przykład, jeśli Twój kod właśnie utworzył nową instancję wykresu lub zaktualizował ją, użytkownik może chcieć to sprawdzić, a ty możesz wywołać.Activate
ją lub jej arkusz, aby zaoszczędzić czas na szukanie go; lub jeśli wiesz, że użytkownik będzie musiał zaktualizować niektóre wartości zakresu, możesz programowo wybrać ten zakres.źródło
Używanie IMHO
.select
pochodzi od ludzi, którzy podobnie jak ja, zaczęli uczyć się języka VBA z konieczności poprzez rejestrowanie makr, a następnie modyfikowanie kodu, nie zdając sobie sprawy, że.select
iselection
to po prostu niepotrzebni środkowi ludzie..select
można uniknąć, jak już wiele opublikowano, poprzez bezpośrednią pracę z już istniejącymi obiektami, co umożliwia różne pośrednie odniesienia, takie jak obliczanie i i j w złożony sposób, a następnie edytowanie komórki (i, j) itp.W przeciwnym razie nie ma w sobie nic pośredniego
.select
i można to łatwo znaleźć, np. Mam arkusz kalkulacyjny, który wypełniam datą, aktywuję makro, które robi z nim magię i eksportuje go w dopuszczalnym formacie na osobnym arkuszu, który wymaga jednak ostatecznych ręcznych (nieprzewidywalnych) danych wejściowych do sąsiedniej komórki. Nadchodzi moment,.select
że oszczędza mi to dodatkowego ruchu myszy i kliknięcia.źródło
Szybka odpowiedź:
Aby uniknąć korzystania z tej
.Select
metody, możesz ustawić zmienną równą żądanej właściwości.► Na przykład, jeśli chcesz mieć wartość,
Cell A1
możesz ustawić zmienną równą właściwości wartości tej komórki.valOne = Range("A1").Value
► Na przykład, jeśli chcesz mieć kryptonim „Arkusz3”, możesz ustawić zmienną równą właściwości kryptonimu tego arkusza.
valTwo = Sheets("Sheet3").Codename
Mam nadzieję że to pomogło. Daj mi znać, jeśli masz jakieś pytania.
źródło
Zauważyłem, że żadna z tych odpowiedzi nie wspomina o właściwości .Offset . Można to również wykorzystać, aby uniknąć użycia
Select
akcji podczas manipulowania niektórymi komórkami, szczególnie w odniesieniu do wybranej komórki (jak wspomina OPActiveCell
).Oto kilka przykładów.
Zakładam również, że „ActiveCell” to J4 .
ActiveCell.Offset(2, 0).Value = 12
J6
na wartość 12ActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)
k4
doL4
.i4
ActiveCell.Offset(, -1).EntireColumn.ClearContents
Nie oznacza to, że są „lepsze” niż powyższe opcje, a jedynie listę alternatyw.
źródło
Praca z funkcją .Parent. Ten przykład pokazuje, jak ustawienie tylko jednego odwołania myRng umożliwia dynamiczny dostęp do całego środowiska bez funkcji .Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet i tak dalej. (Nie ma funkcji Genereic .Child)
źródło
Głównym powodem, dla którego nigdy nie należy korzystać z Select lub Activesheet, jest to, że większość ludzi będzie miała otwartą co najmniej kolejną parę skoroszytów (czasami dziesiątki) po uruchomieniu makra i jeśli klikną poza arkusz podczas działania makra i klikną inne książkę, którą mają otwartą, następnie zmienia się arkusz „Activesheet”, a także docelowy skoroszyt dla niekwalifikowanego polecenia „Wybierz”.
W najlepszym wypadku makro się zawiesi, w najgorszym wypadku możesz zapisać wartości lub zmienić komórki w niewłaściwym skoroszycie bez możliwości ich „cofnięcia”.
Mam prostą złotą zasadę, którą stosuję: dodaj zmienne o nazwach „wb” i „ws” dla obiektu skoroszytu i obiektu arkusza roboczego i zawsze używaj ich w odniesieniu do mojej książki makr. Jeśli muszę odwoływać się do więcej niż jednej książki lub więcej niż jednego arkusza, dodaję więcej zmiennych.
na przykład
Polecenie „Set wb = ThisWorkbook” jest absolutnie kluczowe. „Ten skoroszyt” jest specjalną wartością w programie Excel i oznacza skoroszyt, z którego obecnie działa Twój kod VBA . Bardzo pomocny skrót do ustawienia zmiennej skoroszytu.
Gdy już to zrobisz u góry Sub, użycie ich nie może być prostsze, po prostu użyj ich wszędzie tam, gdzie użyjesz „Zaznaczenia”:
Aby zmienić wartość komórki „A1” w „Wyjściu” na „Cześć”, zamiast:
Możemy teraz to zrobić:
Który jest nie tylko znacznie bardziej niezawodny i rzadziej ulega awarii, jeśli użytkownik pracuje z wieloma arkuszami kalkulacyjnymi, ale jest także znacznie krótszy, szybszy i łatwiejszy do napisania.
Jako dodatkowy bonus, jeśli zawsze nazywasz swoje zmienne „wb” i „ws”, możesz kopiować i wklejać kod z jednej książki do drugiej i zwykle będzie działał przy minimalnych potrzebnych zmianach, jeśli w ogóle.
źródło
ThisWorkbook
... Nie jestem pewien, czy twój komentarz jest poprawny.Jest to przykład, który wyczyści zawartość komórki „A1” (lub więcej, jeśli typem wyboru jest xllastcell itp.). Wszystko zrobione bez konieczności wybierania komórek.
Mam nadzieję, że to komuś pomoże.
źródło
Workbook(WorkbookName).Worksheets(WorksheetName).Range("A1").ClearContents
jedna linia, a nie dwie, i faktycznie działa ona bez wybierania komórek.