Ich habe viel über die verständliche Abscheu vor der Verwendung .Select
in Excel VBA gehört, bin mir aber nicht sicher, wie ich die Verwendung vermeiden soll. Ich stelle fest, dass mein Code wiederverwendbarer wäre, wenn ich Variablen anstelle von Select
Funktionen verwenden könnte. Ich bin mir jedoch nicht sicher, wie ich mich auf Dinge (wie die ActiveCell
usw.) beziehen soll, wenn ich sie nicht benutze Select
.
Ich habe diesen Artikel über Bereiche und dieses Beispiel über die Vorteile der Nichtverwendung von select gefunden , kann aber nichts darüber finden, wie ?
Select
und / oderActiveSheet
usw. usw. völlig unvermeidbar ist. Hier ist ein Beispiel, das ich gefunden habe: stackoverflow.com/questions/22796286/….Select / .Selection
erforderlich zu sein, alle Blätter in einer Arbeitsmappe auf denselben Wert zu setzen .Antworten:
Einige Beispiele zur Vermeidung von Auswahl
Verwenden Sie
Dim
'd VariablenSet
die Variable auf den gewünschten Bereich. Es gibt viele Möglichkeiten, sich auf einen Einzelzellenbereich zu beziehenoder ein Mehrzellenbereich
Sie können die Verknüpfung zur
Evaluate
Methode verwenden, dies ist jedoch weniger effizient und sollte im Produktionscode generell vermieden werden.Alle obigen Beispiele beziehen sich auf Zellen auf dem aktiven Blatt . Wenn Sie nicht speziell nur mit dem aktiven Blatt arbeiten möchten, ist es besser, auch eine
Worksheet
Variable zu dimmenWenn Sie mit dem arbeiten möchten
ActiveSheet
, ist es aus Gründen der Klarheit am besten, explizit zu sein. Aber seien Sie vorsichtig, da einigeWorksheet
Methoden das aktive Blatt ändern.Dies bezieht sich wiederum auf die aktive Arbeitsmappe . Sofern Sie nicht speziell nur mit dem
ActiveWorkbook
oder arbeiten möchtenThisWorkbook
, ist es besser, auch eineWorkbook
Variable zu dimmen .Wenn Sie mit dem arbeiten möchten
ActiveWorkbook
, ist es aus Gründen der Klarheit am besten, explizit zu sein. Aber seien Sie vorsichtig, da vieleWorkBook
Methoden das aktive Buch verändern.Sie können das
ThisWorkbook
Objekt auch verwenden , um auf das Buch zu verweisen, das den laufenden Code enthält.Ein häufiger (schlechter) Code besteht darin, ein Buch zu öffnen, einige Daten abzurufen und dann wieder zu schließen
Das ist schlecht:
Und wäre besser wie:
Übergeben Sie Bereiche als Bereichsvariablen an Ihre
Sub
s undFunction
sSie sollten auch Methoden (wie
Find
undCopy
) auf Variablen anwendenWenn Sie einen Bereich von Zellen durchlaufen, ist es häufig besser (schneller), die Bereichswerte zuerst in ein variantes Array zu kopieren und diesen zu durchlaufen
Dies ist ein kleiner Vorgeschmack auf das, was möglich ist.
quelle
rng1(12, 12)
funktioniert dies, obwohl rng1[A1:A10]
nur auf eingestellt wurde.Range
:ActiveSheet.[a1:a4]
oderws.[b6]
.variant
Variable ist erst erforderlich,Set
wenn Sie ihr ein Objekt zuweisen.Dim x: x = 1
Ist zum Beispiel in Ordnung,Dim x: x = Sheets("Sheet1")
generiert aber den Fehler 438. Nur zu verwirren / zu klären,Dim x: x = Range("A1")
führt jedoch nicht zu einem Fehler. Warum? ... weil es der Variablen den Wert des Objekts zugewiesen hat , nicht einen Verweis auf das Objekt selbst (da es das Äquivalent von istDim x: x = Range("A1").Value
)Zwei Hauptgründe, warum
.Select
/.Activate
/Selection
/Activecell
/Activesheet
/Activeworkbook
etc ... vermieden werden solltenWie vermeiden wir das?
1) Arbeiten Sie direkt mit den relevanten Objekten
Betrachten Sie diesen Code
Dieser Code kann auch als geschrieben werden
2) Deklarieren Sie bei Bedarf Ihre Variablen. Der gleiche Code wie oben kann geschrieben werden als
quelle
Sheets(2).[C10:D12].Value = Sheets(1).[A1:B3].Value
.Activate
, um zum Originalblatt zu wechseln, verwenden Sie einfachApplication.Goto
Ein kleiner Schwerpunkt, den ich zu allen oben gegebenen hervorragenden Antworten hinzufügen werde:
Das wahrscheinlich größte Mittel, um die Verwendung von Select zu vermeiden, besteht darin , benannte Bereiche (kombiniert mit aussagekräftigen Variablennamen) in Ihrem VBA-Code so weit wie möglich zu verwenden . Dieser Punkt wurde oben erwähnt, aber etwas beschönigt; es verdient jedoch besondere Aufmerksamkeit.
Hier sind ein paar zusätzliche Gründe, benannte Bereiche liberal zu nutzen, obwohl ich mir sicher mehr vorstellen kann.
Benannte Bereiche erleichtern das Lesen und Verstehen Ihres Codes.
Beispiel:
Es ist ziemlich offensichtlich , was die genannten Bereiche
Months
undMonthlySales
enthalten, und was die Prozedur tut.Warum ist das wichtig? Zum Teil, weil es für andere Menschen einfacher ist, es zu verstehen, aber selbst wenn Sie die einzige Person sind, die Ihren Code jemals sehen oder verwenden wird, sollten Sie dennoch benannte Bereiche und gute Variablennamen verwenden, da Sie vergessen werden, was Sie damit vorhatten Ein Jahr später verschwenden Sie 30 Minuten damit, herauszufinden, was Ihr Code tut.
Benannte Bereiche stellen sicher, dass Ihre Makros nicht beschädigt werden, wenn (nicht wenn!) Die Konfiguration der Tabelle geändert wird.
Überlegen Sie, ob das obige Beispiel folgendermaßen geschrieben wurde:
Dieser Code funktioniert zunächst einwandfrei - bis Sie oder ein zukünftiger Benutzer entscheiden, "gee wiz, ich denke, ich werde eine neue Spalte mit dem Jahr in Spalte hinzufügen
A
!", Oder eine Spaltenspalte zwischen den Monaten und einfügen Verkaufsspalten oder fügen Sie jeder Spalte einen Header hinzu. Jetzt ist Ihr Code kaputt. Und weil Sie schreckliche Variablennamen verwendet haben, brauchen Sie viel mehr Zeit, um herauszufinden, wie Sie das Problem beheben können, als es dauern sollte.Wenn Sie zunächst benannte Bereiche verwendet haben, können die Spalten
Months
und undSales
beliebig verschoben werden, und Ihr Code funktioniert weiterhin einwandfrei.quelle
Ich werde die kurze Antwort geben, da alle anderen die lange gegeben haben.
Sie erhalten .select und .activate, wenn Sie Makros aufnehmen und wiederverwenden. Wenn Sie eine Zelle oder ein Blatt auswählen, wird es nur aktiviert. Von diesem Punkt an, wenn Sie nicht qualifizierte Referenzen verwenden, wie
Range.Value
sie nur die aktive Zelle und das Blatt verwenden. Dies kann auch problematisch sein, wenn Sie nicht beobachten, wo Ihr Code platziert ist oder ein Benutzer auf die Arbeitsmappe klickt.Sie können diese Probleme also beseitigen, indem Sie direkt auf Ihre Zellen verweisen. Welches geht:
Oder du könntest
Es gibt verschiedene Kombinationen dieser Methoden, aber das wäre die allgemeine Idee, die für ungeduldige Menschen wie mich so kurz wie möglich ausgedrückt wird.
quelle
Ich kann mir zwar nicht mehr als eine isolierte Handvoll Situationen vorstellen, in denen
.Select
eine bessere Wahl als eine direkte Zellreferenzierung wäre, aber ich würde mich zur Verteidigung erhebenSelection
und darauf hinweisen, dass sie nicht aus den gleichen Gründen verworfen werden.Select
sollte, die vermieden werden sollten.Es gibt Zeiten, in denen kurze, zeitsparende Makro-Subroutinen, die Tastenkombinationen zugewiesen werden, durch Tippen auf einige Tasten viel Zeit sparen. Die Möglichkeit, eine Gruppe von Zellen auszuwählen, auf die der Betriebscode angewendet werden soll, wirkt Wunder, wenn mit Daten in der Tasche gearbeitet wird, die nicht einem arbeitsblattweiten Datenformat entsprechen. Ähnlich wie Sie eine Gruppe von Zellen auswählen und eine Formatänderung anwenden können, kann die Auswahl einer Gruppe von Zellen, für die spezieller Makrocode ausgeführt werden soll, eine erhebliche Zeitersparnis bedeuten.
Beispiele für ein auf Auswahl basierendes Unterframework:
Der tatsächlich zu verarbeitende Code kann von einer einzelnen Zeile bis zu mehreren Modulen reichen. Ich habe diese Methode verwendet, um lang laufende Routinen für eine unregelmäßige Auswahl von Zellen zu initiieren, die die Dateinamen externer Arbeitsmappen enthalten.
Kurz gesagt, nicht wegwerfen,
Selection
da es eng mit.Select
und verbunden istActiveCell
. Als Arbeitsblatteigenschaft hat es viele andere Zwecke.(Ja, ich weiß, dass es um diese Frage ging
.Select
,Selection
aber ich wollte alle Missverständnisse beseitigen, auf die unerfahrene VBA-Codierer schließen könnten.)quelle
Selection
kann alles im Arbeitsblatt sein, testen Sie also zuerst den Typ des Objekts, bevor Sie es einer Variablen zuweisen, da Sie es explizit als deklariert habenRange
.Bitte beachten Sie, dass ich im Folgenden den Select-Ansatz (den das OP vermeiden möchte) mit dem Range-Ansatz vergleiche (und dies ist die Antwort auf die Frage). Hören Sie also nicht auf zu lesen, wenn Sie die erste Auswahl sehen.
Es hängt wirklich davon ab, was Sie versuchen zu tun. Auf jeden Fall könnte ein einfaches Beispiel nützlich sein. Angenommen, Sie möchten den Wert der aktiven Zelle auf "foo" setzen. Mit ActiveCell würden Sie ungefähr Folgendes schreiben:
Wenn Sie es für eine Zelle verwenden möchten, die nicht aktiv ist, z. B. für "B2", sollten Sie es zuerst wie folgt auswählen:
Mithilfe von Bereichen können Sie ein allgemeineres Makro schreiben, mit dem Sie den Wert jeder gewünschten Zelle auf einen beliebigen Wert einstellen können:
Dann können Sie Macro2 wie folgt umschreiben:
Und Macro1 als:
Hoffe, das hilft, die Dinge ein wenig aufzuklären.
quelle
Vermeiden
Select
undActivate
ist der Schritt, der Sie ein bisschen besser VBA-Entwickler macht. Im AllgemeinenSelect
undActivate
wenn ein Makro aufgezeichnet wird, wird dasParent
Arbeitsblatt oder der Bereich immer als aktives betrachtet.So können Sie Folgendes vermeiden
Select
undActivate
in folgenden Fällen:Hinzufügen eines neuen Arbeitsblatts und Kopieren einer Zelle darauf:
Von (Code generiert mit Makrorecorder):
Zu:
Wenn Sie den Bereich zwischen Arbeitsblättern kopieren möchten:
Von:
Zu:
Verwenden Sie ausgefallene benannte Bereiche
Sie können mit ihnen zugreifen
[]
, was im Vergleich zur anderen Art wirklich schön ist. Überprüfen Sie sich:Das Beispiel von oben würde folgendermaßen aussehen:
Werte nicht kopieren, sondern nehmen
Wenn Sie dazu bereit
select
sind, kopieren Sie normalerweise höchstwahrscheinlich etwas. Wenn Sie nur an den Werten interessiert sind, ist dies eine gute Option, um die Auswahl zu vermeiden:Range("B1:B6").Value = Range("A1:A6").Value
Versuchen Sie immer, auch auf das Arbeitsblatt zu verweisen
Dies ist wahrscheinlich der häufigste Fehler in vba. Wenn Sie Bereiche kopieren, wird manchmal nicht auf das Arbeitsblatt verwiesen, und daher betrachtet VBA das falsche Blatt als ActiveWorksheet.
Kann ich wirklich nie
.Select
oder.Activate
für irgendetwas verwenden?.Activate
und.Select
wann Sie sicherstellen möchten, dass ein bestimmtes Arbeitsblatt aus visuellen Gründen ausgewählt ist. Beispiel: Ihr Excel wird immer mit dem zuerst ausgewählten Deckblatt geöffnet, unabhängig davon, welches ActiveSheet beim Schließen der Datei verwendet wurde.Somit ist so etwas wie der folgende Code absolut in Ordnung:
Ein weiteres gutes Beispiel ist, wenn Sie alle Blätter in eine PDF-Datei exportieren müssen, wie in diesem Fall erwähnt. Wie vermeide ich in diesem Beispiel select / active-Anweisungen in VBA?
Wenn ein Befehl funktioniert nur mit
ActiveWindow
wie ActiveWindow.Zoom oder ActiveWindow.FreezePanesquelle
.Select
- sowie meine Arbeit herum - finden Sie unter Wie man identische Informationen auf alle Blätter schreibt - @Vityata :).FillAcrossSheets
, also liegt dies irgendwo dazwischen (zumindest in meiner Vorstellung von der VBA-Taxonomie)Geben Sie immer die Arbeitsmappe, das Arbeitsblatt und die Zelle / den Bereich an.
Zum Beispiel:
Da Endbenutzer immer nur auf Schaltflächen klicken und der Fokus von der Arbeitsmappe abweicht, mit der der Code arbeiten möchte, laufen die Dinge völlig schief.
Und verwenden Sie niemals den Index einer Arbeitsmappe.
Sie wissen nicht, welche anderen Arbeitsmappen geöffnet sind, wenn der Benutzer Ihren Code ausführt.
quelle
Diese Methoden sind eher stigmatisiert, also übernehmen Sie die Führung von @Vityata und @Jeeped, um eine Linie in den Sand zu ziehen:
Warum nicht nennen
.Activate
,.Select
,Selection
,ActiveSomething
Methoden / EigenschaftenGrundsätzlich, weil sie hauptsächlich aufgerufen werden, um Benutzereingaben über die Benutzeroberfläche der Anwendung zu verarbeiten. Da es sich um die Methoden handelt, die aufgerufen werden, wenn der Benutzer Objekte über die Benutzeroberfläche verarbeitet, werden sie vom Makrorecorder aufgezeichnet. Daher ist das Aufrufen in den meisten Situationen entweder spröde oder redundant: Sie müssen keine auswählen Objekt, um eine Aktion mit
Selection
direkt danach auszuführen .Diese Definition regelt jedoch Situationen, in denen sie erforderlich sind:
Wenn nennen
.Activate
,.Select
,.Selection
,.ActiveSomething
Methoden / EigenschaftenGrundsätzlich, wenn Sie erwarten, dass der Endbenutzer eine Rolle bei der Ausführung spielt.
Wenn Sie entwickeln und erwarten, dass der Benutzer die Objektinstanzen auswählt , die von Ihrem Code verarbeitet werden sollen,
.Selection
oder.ActiveObject
sind Sie entsprechend.Auf der anderen Seite
.Select
und.Activate
nützlich, wenn Sie auf die nächste Aktion des Benutzers schließen können und möchten, dass Ihr Code den Benutzer führt, was ihm möglicherweise Zeit und Mausklicks spart. Wenn Ihr Code beispielsweise gerade eine brandneue oder aktualisierte Instanz eines Diagramms erstellt hat, möchte der Benutzer es möglicherweise auschecken, und Sie können.Activate
es oder sein Blatt aufrufen , um dem Benutzer die Zeit für die Suche zu sparen. Wenn Sie wissen, dass der Benutzer einige Bereichswerte aktualisieren muss, können Sie diesen Bereich programmgesteuert auswählen.quelle
IMHO Verwendung von
.select
kommt von Leuten, die wie ich angefangen haben, VBA durch Notwendigkeit zu lernen, indem sie Makros aufzeichneten und dann den Code modifizierten, ohne zu bemerken, dass.select
und anschließendselection
nur ein unnötiger Mittelsmann ist..select
kann vermieden werden, wie viele bereits gepostet haben, indem direkt mit den bereits vorhandenen Objekten gearbeitet wird, was verschiedene indirekte Verweise wie das komplexe Berechnen von i und j und das anschließende Bearbeiten der Zelle (i, j) usw. ermöglicht.Ansonsten ist nichts implizit falsch an sich
.select
selbst und Sie können leicht eine Verwendung dafür finden, z. B. habe ich eine Tabelle, die ich mit Datum fülle, aktiviere ein Makro, das etwas Magie damit macht, und exportiere es in einem akzeptablen Format auf ein separates Blatt, das erfordert jedoch einige endgültige manuelle (unvorhersehbare) Eingaben in eine benachbarte Zelle. Hier kommt also der Moment.select
, der mir diese zusätzliche Mausbewegung und das Klicken erspart.quelle
Schnelle Antwort:
Um die Verwendung der
.Select
Methode zu vermeiden, können Sie eine Variable festlegen, die der gewünschten Eigenschaft entspricht.► Wenn Sie beispielsweise den Wert in möchten, können
Cell A1
Sie eine Variable festlegen, die der value-Eigenschaft dieser Zelle entspricht.valOne = Range("A1").Value
► Wenn Sie beispielsweise den Codenamen 'Sheet3' möchten, können Sie eine Variable festlegen, die der Codenameneigenschaft dieses Arbeitsblatts entspricht.
valTwo = Sheets("Sheet3").Codename
Ich hoffe das hilft. Lassen Sie mich wissen, wenn Sie Fragen haben.
quelle
Mir ist aufgefallen, dass keine dieser Antworten die .Offset-Eigenschaft erwähnt . Dies kann auch verwendet werden, um die Verwendung der
Select
Aktion beim Bearbeiten bestimmter Zellen zu vermeiden , insbesondere in Bezug auf eine ausgewählte Zelle (wie im OP erwähntActiveCell
).Hier sind einige Beispiele.
Ich gehe auch davon aus, dass "ActiveCell" J4 ist .
ActiveCell.Offset(2, 0).Value = 12
J6
auf den Wert 12 geändertActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)
k4
zuL4
.i4
ActiveCell.Offset(, -1).EntireColumn.ClearContents
Diese sollen nicht sagen, dass sie "besser" sind als die oben genannten Optionen, sondern nur Alternativen auflisten.
quelle
Arbeiten mit der .Parent-Funktion. Dieses Beispiel zeigt, wie das Festlegen nur einer myRng-Referenz den dynamischen Zugriff auf die gesamte Umgebung ohne .Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet usw. ermöglicht. (Es gibt keine genereische .Kinderfunktion)
quelle
Der Hauptgrund, warum Sie Select oder Activesheet niemals verwenden, besteht darin, dass die meisten Benutzer mindestens ein paar weitere Arbeitsmappen geöffnet haben (manchmal Dutzende), wenn sie Ihr Makro ausführen und wenn sie während der Ausführung Ihres Makros von Ihrem Blatt wegklicken und auf ein anderes klicken Buch, das sie geöffnet haben, dann ändert sich das "Aktivitätsblatt", und die Zielarbeitsmappe für einen nicht qualifizierten Befehl "Auswählen" ändert sich ebenfalls.
Im besten Fall stürzt Ihr Makro ab, im schlimmsten Fall schreiben Sie möglicherweise Werte oder ändern Zellen in der falschen Arbeitsmappe, ohne sie "rückgängig machen" zu können.
Ich habe eine einfache goldene Regel, der ich folge: Fügen Sie Variablen mit den Namen "wb" und "ws" für ein Arbeitsmappenobjekt und ein Arbeitsblattobjekt hinzu und verwenden Sie diese immer, um auf mein Makrobuch zu verweisen. Wenn ich mich auf mehr als ein Buch oder mehr als ein Blatt beziehen muss, füge ich weitere Variablen hinzu.
zum Beispiel
Der Befehl "Set wb = ThisWorkbook" ist absolut wichtig. "ThisWorkbook" ist ein spezieller Wert in Excel und bezeichnet die Arbeitsmappe, aus der Ihr VBA-Code derzeit ausgeführt wird . Eine sehr hilfreiche Verknüpfung zum Festlegen Ihrer Arbeitsmappenvariablen.
Nachdem Sie dies oben in Ihrem Sub getan haben, könnte die Verwendung nicht einfacher sein. Verwenden Sie sie einfach überall dort, wo Sie "Auswahl" verwenden würden:
So ändern Sie den Wert der Zelle "A1" in "Ausgabe" in "Hallo" anstelle von:
Wir können dies jetzt tun:
Dies ist nicht nur viel zuverlässiger und weniger absturzgefährdet, wenn der Benutzer mit mehreren Tabellen arbeitet, sondern auch viel kürzer, schneller und einfacher zu schreiben.
Wenn Sie Ihre Variablen immer "wb" und "ws" nennen, können Sie als zusätzlichen Bonus Code von einem Buch in ein anderes kopieren und einfügen. Dies funktioniert normalerweise mit minimalen Änderungen, falls vorhanden.
quelle
ThisWorkbook
... Ich bin nicht sicher, ob Ihr Kommentar korrekt ist.Dies ist ein Beispiel, mit dem der Inhalt der Zelle "A1" gelöscht wird (oder mehr, wenn der Auswahltyp xllastcell usw. ist). Alles erledigt, ohne die Zellen auswählen zu müssen.
Ich hoffe das hilft jemandem.
quelle
Workbook(WorkbookName).Worksheets(WorksheetName).Range("A1").ClearContents
eine Zeile und nicht zwei und funktioniert tatsächlich ohne Auswahl von Zellen.