Zellen von Mappe A nach Mappe B effizient kopieren
lima-city → Forum → Programmiersprachen → Basic
anpassen
array
aufzeichnen
code
datum
kopieren
laufzeit
mappe
problem
prozedur
sekunde
set
setzen
spalten
studium
verarbeiten
vorgang
wechsel
zeile
zelle
-
Hallo,
ich habe folgende Problemstellung:
Ich arbeite mit sehr großen Datenmengen und schreibe deshalb viele Makros in Excel, um diese zu verarbeiten.
Dazu gehört unter Anderem, dass ich Daten von einer Excel Mappe in eine andere (Gesamtübersicht) kopiere.
Nun hab ich mal eben folgenden Algorithmus geschrieben:
While AktivZeile <= Zeilen 'den Wert aus A kopieren Workbooks(MappeA).Activate Sheets(1).Select Cells(AktivZeile, AktivSpalte).Copy 'den Wert in B einfügen Workbooks(MappeB).Activate Sheets("Summary").Select Cells(AktivZeileSummary, AktivSpalteSummary).PasteSpecial AktivZeile = AktivZeile + 1 'da Fluxus alle 30 Sekunden aufnimmt, die Summary jedoch alle 5 Sekunden => 30/5 = 6 AktivZeileSummary = AktivZeileSummary + 6 Wend 'AktivZeile < Zeilen
Es wird also ganz simpel eine Zelle kopiert und wo anders eingefügt. Dieser Vorgang dauert leider wirklich lange, da fast 13.000 Zeilen Daten vorhanden sind.
Nun hab ich gedacht, kann man nicht mehrere Werte in den Arbeitsspeicher laden und dann erst wechseln und wieder einfügen? Den Hauptteil der Zeit nimmt ja unter Anderem auch das Mappen-Wechseln ein.
Könnte mir da jemand helfen, wie genau das geht?
Ich vermute irgendwas mit
Dim Variablenwerte[100] As (welcher Variablentyp dafür?)
und dann
while i < 100
Variablenwerte = Zelle_xy.copy (nach dem Prinzip)
wend
Würde mich über kurze korrekte Beispielcodes freuen. :) -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hallo karikato,
der beim Aufzeichen von Makros erzeugte Code ist im Allgemeinen ziemlich mies und man sollte diesen Stil tunlichst vermeiden
Solche Sachen wie "Select", "Activate" und anderes, was nur Umständlich ist und die Performance versaut braucht man normalerweise nämlich gar nicht.
Ich gehe davon aus, dass Du bereits vorher weist, woher Du kopieren willst, wohin Du kopieren willst und wie viele Zeilen/Spalten es sind. Dann lässt sich das wie folgt machen (eine Spalte, 13000 Zeilen aus Tabelle1 nach Position B2 + folgende in Tabelle2):
Sub CopyData() Dim wb As Excel.Workbook Dim src As Excel.Worksheet Dim dst As Excel.Worksheet Set wb = ActiveWorkbook Set src = wb.Worksheets("Tabelle1") Set dst = wb.Worksheets("Tabelle2") src.Range(src.Cells(1, 1), src.Cells(13000, 1)).Copy dst.Cells(2, 2) End Sub
Die Tabellennamen und Quell- bzw. Zielbereich musst Du an Deine Mappe anpassen. -
Hallo darkpandemic,
danke für die Antwort und entschuldige meine späte Reaktion.
Ja da geb ich dir Recht, das Aufzeichnen von Makros ergibt immer einen grauenhaften Code :)
Leider würde dein Vorschlag mit dem schlichten copy-pasta bei meinem Problem nicht funktionieren.
Das Problem bei mir ist nämlich, dass in der einen Mappe die Zeilen alle untereinander sind, wobei die Zeitspalte alle 30 Sekunden aufgenommen hat.
In der Ziel-Arbeitsmappe jedoch alle 5 Sekunden eine Zeile kommt, was bedeutet, dass ich die Zellen von Mappe A gesplittet in Mappe B einfügen muss.
Bei deinem Lösungsvorschlag müsste ich also immernoch die einzelnen Zellen umsortieren, nach dem kopieren. :s -
Hallo karikato,
nach eingem überlegen und Studium deines Codes sehe ich jetzt das Problem:
Du willst immer fünf Zeilen dazwischen frei haben
In dem Fall ist der schnellste Weg der folgende:
Sub CopyData() Dim wb As Excel.Workbook Dim src As Excel.Worksheet Dim dst As Excel.Worksheet Dim i As Integer Set wb = ActiveWorkbook Set src = wb.Worksheets("Tabelle1") Set dst = wb.Worksheets("Tabelle2") For i = 1 To 13000 dst.Cells(6 * i, 1).Value = src.Cells(i, 1).Value Next End Sub
Die For-Schleife geht in Deinem Fall dann von "AktivZeile" bis "Zeilen". -
Hi karikato,
arbeiten mit array's (auch mehrdimensional) macht auch in VBA Spaß und bringt dann auch bei "dezidiertem copy" Sinn (weil ohne ständigen "WorkbookWechsel").
einfach mit
im Deklarationsteil am Anfang (persönlich nutze ich dann gerne eher Public um weiter mittels Forms und anderen Sub's dieses mühsam gefüllte array nutzen zu können).Dim karikato() as variant
Diese werden dann in VBA zur Laufzeit in der Größe geändert, (mittels preserve auch erweitert, unter Beibehaltung der Werte).
Redim preserve karikato(100,100)
wäre dann zweidimesional und adressierbar mit karikato(1,5) usw., also sehr gut mit schleifen bearbeitbar oder lesbar.
Angenehm ist dabei, das in der "IDE" im "Überwachungsfenster" das array als "baumstruktur" angezeigt wird, mittels Setzen von Haltepunkten ist also ein "Befüllen" des arrays anschaulich erlebbar.
ich bin allerdings der Meinung dieser Vorgang kostet wiederum Zeit, also bitte nicht "dynamisch", immer wieder zur Laufzeit anpassen.
Assoziativ kann ich dabei allerdings nichts anbieten, zumindest kenne ich noch keine assoziativen arrays in VBA .....
Prinzipiell Geschwindigkeitsvorteile erhalte ich durch ausschalten der Meldungen und des Bildschirmaufbaues mit:
"Application.ScreenUpdating = False"
bitte vergiß nicht am Ende der Prozedur diesen Wert wieder auf True zu setzen. WICHTIG!
:)
gruß
harro
ohoh jede Menge Tippfehler......
Beitrag zuletzt geändert: 2.8.2012 14:21:24 von harro -
Wow vielen Dank für eure Hilfe!
Das hat mir weitergeholfen und genau das, was harro erklärt hat, habe ich gesucht. :)
Vielen Dank! -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage