Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1296to1300
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Formeln kopieren bei eingefügter Zelle
19.02.2013 10:13:19
Martin
Guten Tag liebe Community
1. Ich habe mehrere Tabellenblätter
2. In jedem Blatt Stehen in den ersten 4 Spalten A-D Namen / Bezeichnungen
3. In den Folgenden Spalten (Anzahl variiert von T bis hin zu CZ) stehen einfache Formeln der Form ('Wert aus Tabellenblatt 1' * 'Wert aus einer anderen Exceldatei')
also: In E2 steht z.b.: ='Tabelle1'!E2 * 'C:\blabla[bla.xlsm]Tabelle1!$E2
In E4 = 'Tabelle1'!E4 * 'C:\blabla[bla.xlsm]Tabelle1!$E4
In J6 = 'Tabelle1'!J6 * 'C:\blabla[bla.xlsm]Tabelle1!$J6 usw.
4. Die erste Zeile dient zur Spaltenidentifikation (Name1, Name2, Name3, Name4, Formel1, Formel2, ....)
5. Über ein UserForm habe ich es geschafft neue Zeilen einzufügen. Das Makro dazu:
Dim emptyRow2 As Long
Sheets("Tabelle1").Select
emptyRow2 = WorksheetFunction.CountA(Range("A:A")) + 1
Cells(emptyRow2, 1).Value = TextBox_A.Value
Cells(emptyRow2, 2).Value = TextBox_B.Value
Cells(emptyRow2, 3).Value = TextBox_C.Value
Cells(emptyRow2, 4).Value = TextBox_D.Value

Nun mein Problem:
Im ersten Schritt sollen die Daten nach Spalte A, dann nach B sortiert werden. Dank Makrorekorder habe ich folgendes im Gebrauch:
Range("A1:T300").Select
ActiveWorkbook.Worksheets("Tabelle1").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Tabelle1").AutoFilter.Sort.SortFields.Add Key _
:=Range("A2:A300"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Tabelle1").AutoFilter.Sort.SortFields.Add Key _
:=Range("B2:B300"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Tabelle1").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With

Im Folgenden sollen die Formeln aus der ersten Formelzeile (also in dem Fall Zeile 2) an alle darunterliegenden Formeln übernommen werden. Das habe ich so gelöst:
Range("E2:T2").Select
Selection.AutoFill Destination:=Range("E2:T300"), Type:=xlFillDefault

Wie ihr sehr ist das ganze sehr unelegant und wenig dynamisch. Ich musste bislang für jedes Tabellenblatt die Spaltenanzahl in beiden Makros manuell anpassen. Weiterhin bin ich bei der Erstellung der "Makros" davon ausgegangen, dass die Liste letzendlich maximal 299 Positionen umfasst. Davon abgesehen ist es selbst für mich als Neuling ersichtlich, dass bei dieser Vorgehensweise Ressourcen verschwendet werden. Als Beispiel befinden sich in einem Tabellenblatt 100 Spalten. Multipliziert mit den 300 Zeilen sind wir bei 30.000 Formeln die übernommen werden müssen, obwohl vieleicht nur 200 Zeilen in Spalte A-D einen Namen enthalten.
Vieleicht könnt Ihr mir helfen einen eleganteren Weg zu entwickeln. Ich wäre für jede Hilfe dankbar.
Liebe Grüße
Martin

38
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 10:36:17
Klaus
Hallo Martin,
die letzte Zeile kannst du auch dynamisch feststellen.
schreib an den Anfang deines Makros:
Dim lRow as long
und irgendwo, um die letzte Zeile festzustellen (aus Spalte A):
lRow = cells(rows.count,1).end(xlup).row
(um die letzte Zeile aus Spalte B festzustellen, tauscht du die 1 gegen eine 2 usw.)
Jetzt kannst du dynamisch den Bereich bis zur letzten Zeile holen, indem du
Range("A1:T300").Select
austauscht gegen
Range("A1:T" & lRow).Select
Allerdings löst das nicht dein Performanceproblem. Das liegt an der Verwendung von .select, .selection und .activate - das kann und sollte zu 99,9% vermieden werden. Der Rekorder kann es leider nicht ohne!
Ein Beispiel: der unperformante Rekordercode
Sheets("Tabelle1").activate
Range("A1").select
selection.copy

kann vereinfacht werden zu:
Sheets("Tabelle1").Range("A1").copy
Das macht das gleiche, aber der Coursor läuft nicht mehr Gassi.
Eine excellente Erklärung (bitte entschuldige das Wortspiel) dazu schreibt Peter Haserodt:
http://www.online-excel.de/excel/singsel_vba.php?f=78
Wenn du deinen gesamten Code hochlädst, am besten in der Datei, schaue ich da gerne einmal drüber und optimiere ihn für dich.
Grüße,
Klaus M.vdT.

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 10:56:05
Martin
Ich hab den Anfang des Macros mal in eine .txt Datei gepackt.
https://www.herber.de/bbs/user/83966.txt
Mach dir bitte nicht zuviel Arbeit im Grunde läuft das ganze ja schon, ich möchte eigentlich nur die "sinnlosen" Zeilen los werden. Sprich, dass die Formel maximal bis zur letzten Zeile, und zur letzten Spalte kopiert wird.
LG & Danke
Martin

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 11:15:09
Klaus
Hi,
Schau dir das mal an.
Die Sub "Spreche30BlaetterAn" enthält die Zeile
Call DatenEinfuegen(Sheets("Mengen"))
Dadurch wird "Daten Einfuegen" (hab ich mal so genannt) mit dem Blatt "Mengen" gefüttert
Sub DatenEinfuegen(wksMy As Worksheet)
wksMy entspricht jetzt sheets("Mengen"), das heisst überall im Code wo wksMy steht wird der Code ausgeführt als stände dort sheets("Mengen").
Die Zeile
With wksMy
wird also gleichbedeutend mit
With Sheets("Mengen")
das WITH (eingeschlossen durch ein END WITH am Ende des Codes) sagt, dass ab sofort jeder Ausdruck der mit . anfängt direkt mit dem WITH-Zusatz angesprochen wird.
.Range("A1")
wird jetzt also angesprochen als wäre es
wksMy.Range("A1")
das behandelt wird als wäre es
sheets("Mengen").Range("A1")
Beachte in der Codeänderung, wie ich vor jeden Verweis einen . gesetzt habe der vorher nicht da war. Ausserdem habe ich die letzte Zeile dynamisiert, wie oben beschrieben. Das Makro selbst rufst du aus dem ersten Makro X-Mal auf, jeweils für die Tabellenblattnamen. Die sinnlose 30-Fache wiederholung entfällt so, und wenn sich was ändert musst du es nur 1-mal ändern statt 30 mal.

Sub Spreche30BlaetterAn()
Call DatenEinfuegen(Sheets("Mengen"))
Call DatenEinfuegen(Sheets("Kosten"))
Call DatenEinfuegen(Sheets("Fläche"))
Call DatenEinfuegen(Sheets("Tabelle10"))
'[USW]
Call DatenEinfuegen(Sheets("Tabelle43"))
End Sub
Sub DatenEinfuegen(wksMy As Worksheet)
Dim emptyRow2 As Long
Dim lRow As Long
'Sheets("Mengen").Select
With wksMy
'letzte Zeile
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
' Daten in Datenbank einfügen ->   Mengen
emptyRow2 = WorksheetFunction.CountA(.Range("A:A")) + 1
.Cells(emptyRow2, 1).Value = TextBox_A.Value
.Cells(emptyRow2, 2).Value = TextBox_B.Value
.Cells(emptyRow2, 3).Value = TextBox_ger.Value
.Cells(emptyRow2, 4).Value = TextBox_eng.Value
' Datenbank sortieren ->   Mengen
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Formeln übernehmen / vervollständigen ->   Mengen
'Range("E2:T2").Select
'Selection.AutoFill Destination:=Range("E2:T300"), Type:=xlFillDefault
'COPY ist viel schneller als AutoFill und macht das gleiche!
.Range("E2:T2").Copy
.Range("E3:T" & lRow).PasteSpecial
End With
End Sub
Der Code ist NICHT getestet, da ich von dir nur eine TXT bekommen habe. Hättest du die Datei selbst hochgeladen, hätte ich dir eine Funktionsgarantie geben können.
Grüße,
Klaus M.vdT.

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 11:45:14
Martin
Großartig, das funktioniert prima ! Habe nur noch ein Problem: Bislang werden ja nur die Formeln von E-T übernommen. Jetzt habe ich aber einige Blättern wo die Spalten bis AC, BR, sogar CZ reichen. Kann man das auch noch irgendwie integrieren?
LG Martin

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 11:58:34
Klaus
Hi Martin,
Spalten bis AC, BR, sogar CZ
entweder: die Spaltenangabe mit ins Call schreiben (umständlich).
Oder:
die Spaltenangabe genauso dynamisch ermitteln wie die Zeilenangabe.
Dazu müsste ich eben wissen, WIE ich die letzte Spalte in deiner Datei feststellen darf. Deine Antwort ist idealerweise so oder so ähnlich:
"In jedem Blatt ist die Zeile 7 mit Überschriften gefüllt, die Formeln gehen bis zur letzten Spalte die in Zeile 7 gefüllt ist".
Schuss ins Blaue: Es soll die letzte Spalte aus Zeile 2 mitkopiert werden. Dann so:
das tauscht du:

.Range("E2:T2").Copy
.Range("E3:T" & lRow).PasteSpecial

gegen:

dim iColLast as integer
iColLast = .cells(2,.columns.count).end(xltoleft).column
.Range(.cells(2,5),.cells(2,iColLast)).copy
.Range(.cells(3,5),.cells(lRow,iColLast)).pastespecial

kurze Erklärung: Cells(Zeile,Spalte) heisst, Cells(2,3) spricht die Zelle C2 an, also Cells(2,3) ist das gleiche wie range("C2"). Range(Cells(2,3),cells(2,5)) spricht alle Zellen von C2 bis E2 an.
Das ist einfacher mit den Variablen (lRow, iColLast) zu füllen als den RANGE-Begriff umständlich umzuschreiben. Die .Punkte vor dem .Range und .Cells im Code sind jeweils da, um den WITH wksMy-Rahmen anzusprechen.
Grüße,
Klaus M.vdT.

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 12:14:48
Martin
Okay, folgendes: die ersten 3 Blätter (Mengen, Kosten, Fläche) gehen tatsächlich alle bis Spalte T,
Die Spalten der darauf folgenden Blätter varriieren Teils aber enden mit einer Regel: In der letzten Spalte steht in Zeile 1 immer: "Summe"
Gibt es eine Möglichkeit dir die 2 besagten Exceldateien persönlich zukommen zu lassen, bspw per Mail? Ich würde diese ungern veröffentlichen, habe aber die Vermutung dass durch meine Unwissenheit und magere Ausdrucksweise evtl Unklarheiten entstehen.
Liebe Grüße Martin

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 12:17:51
Klaus
Hi Martin,
In der letzten Spalte steht in Zeile 1 immer: "Summe"
dann ist es ganz einfach: Tausche wie oben beschrieben, aber gegen diesen Code:
dim iColLast as integer
iColLast = .cells(1,.columns.count).end(xltoleft).column
.Range(.cells(2,5),.cells(2,iColLast)).copy
.Range(.cells(3,5),.cells(lRow,iColLast)).pastespecial

Es wird immer die letzte Spalte aus Zeile 1 ermittelt, das passiert hier:
iColLast = .cells(1,.columns.count).end(xltoleft).column
Grüße,
Klaus M.vdT.

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 12:08:22
Martin
Jetzt hab ich mich selbst ein wenig überschätzt. Ich hätte folgenden Sachverhalt erklären müssen:
Das UserForm befindet sich in einer Stammdatendatei. Über die bestätigung des OK buttons wird folgendes Sub ausgelöst:
https://www.herber.de/bbs/user/83968.txt
Kurzum: Nachdem die Stammdaten eingetragen wurden öffnet sich die o.g. Datenbank woraufhin dort die Spalten 1-4 eingefügt werden. Ich habe dein Makro eben in der Datenbank getestet wo es auch prima funktioniert.
Nachdem ich es in meinen Stammdaten verwenden wollte gab es jedoch ein Problem mit dem UserForm.
Hab' es zu Testzwecken so gemacht, dass ich in ein bestehendes Modul der Stammdatendatei deinen Macrotext geschrieben habe, und unter den Zeilen
Dim WbDatei1 As Workbook
Set WbDatei1 = Workbooks.Open("C:\asdfg\Datenbank.xlsm")

im Commandbuttonsub geschrieben habe: Spreche30BlaetterAn in der Hoffnung nach dem öffnen des Workbooks Datenbank würde das Sub SPreche30BlaetterAn funktionieren.
Jedoch wird nun anscheinend die Eingabe der Daten des UserForms in den Stammdaten nicht erkannt.
Kann man das Problem umgehen?
Liebe Grüße Martin

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 12:26:59
Klaus
Hi Martin,
wenn du das ganze in einem anderem WORKBOOK machst, musst du das Workbook auch referenzieren. Das hier (ungetestet!!!) müsste laufen:
     Sub Spreche30BlaetterAn()
Dim WbDatei1 As Workbook
Set WbDatei1 = Workbooks.Open("C:\TestTMP\Zufall.xlsx") 'Meine Testdatei, ändern!
'Debug.Print WbDatei1.Name
Call DatenEinfuegen(Sheets("Mengen"), WbDatei1)
Call DatenEinfuegen(Sheets("Kosten"), WbDatei1)
Call DatenEinfuegen(Sheets("Fläche"), WbDatei1)
End Sub
Sub DatenEinfuegen(wksMy As Worksheet, wbMy As Workbook)
Dim emptyRow2 As Long
Dim lRow As Long
Dim iColLast As Integer
'Sheets("Mengen").Select
With wbMy.wksMy
'letzte Zeile
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
' Daten in Datenbank einfügen ->   Mengen
emptyRow2 = WorksheetFunction.CountA(.Range("A:A")) + 1
.Cells(emptyRow2, 1).Value = TextBox_A.Value
.Cells(emptyRow2, 2).Value = TextBox_B.Value
.Cells(emptyRow2, 3).Value = TextBox_ger.Value
.Cells(emptyRow2, 4).Value = TextBox_eng.Value
' Datenbank sortieren ->   Mengen
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Formeln übernehmen / vervollständigen ->   Mengen
'Range("E2:T2").Select
'Selection.AutoFill Destination:=Range("E2:T300"), Type:=xlFillDefault
'COPY ist viel schneller als AutoFill und macht das gleiche!
'.Range("E2:T2").Copy
'.Range("E3:T" & lRow).PasteSpecial
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub
Schau dir an, wie ich das Workbook im Call übergebe und im Makro mit
With wbMy.wksMy
referenziere - alles andere innerhalb des WITH-Rahmen referenziert jetzt auch auf das Workbook, ich musste nur eine Stelle aktualiseren!
Bitte Test ob es läuft und Rückmeldung.
Mit zukommen lassen kannst du die Datei sicherlich (ich habe ja E-Mail), nur will ich das ehrlich gesagt nicht. Probleme sollten im Forum gelöst werden. Was du immer machen kannst ist, die Zahlen in deiner Datei mit Zufallszahlen zu tauschen und und dann alles auf 10 Zeilen zusammen zu stauchen (ein Makro dass in 10 Zeilen läuft, das läuft auch in 10.000 Zeilen).
Dann dürften keine vertraulichen Daten mehr drinnen sein.
Grüße,
Klaus M.vdT.

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 13:04:00
Martin
Okay, verständlich das Argument Forum !
Ich habe es nun getestet mit dem Sub auf dem Commandbutton:

Private Sub CommandButton1_Click()
' Neue Stammdaten in einfügen
Dim emptyRow As Long
Dim lRow As Long
Sheets("Stammdaten").Select
emptyRow = WorksheetFunction.CountA(Range("A:A")) + 1
Cells(emptyRow, 1).Value = TextBox_A.Value
Cells(emptyRow, 2).Value = TextBox_B.Value
Cells(emptyRow, 3).Value = TextBox_ger.Value
Cells(emptyRow, 4).Value = TextBox_eng.Value
Cells(emptyRow, 5).Value = TextBox_cost.Value
Cells(emptyRow, 6).Value = TextBox_area.Value
' Stammdaten Sortieren
Range("A1:F300").Select
ActiveWorkbook.Worksheets("Stammdaten").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Stammdaten").Sort.SortFields.Add Key:=Range( _
"A2:A232"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ActiveWorkbook.Worksheets("Stammdaten").Sort.SortFields.Add Key:=Range( _
"B2:B232"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Stammdaten").Sort
.SetRange Range("A1:F300")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Spreche30BlaetterAn
End Sub

Wir sind wohl auf dem richtigen Weg. Die Daten werden auch in die Stammdaten geschrieben, dann wird die Datenbank geöffnet. Nun erscheint aber ein Laufzeitfehler (438): Objekt oder Eigenschaft unterstuetzt diese Methode nicht. Beim Debuggen scheiterts an dieser Zeile:
With wbMy.wksMy

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 13:24:06
Klaus
Hallo,
ich poste gleich in einem neuem Beitrag dieses Themas Schritt 2.
aber zuerst Schritt 1: Optimieren des Code auf deinem Button 1
Private Sub CommandButton1_Click()
' Neue Stammdaten in einfügen
Dim lRow As Long
Dim iCol As Integer
'Sheets("Stammdaten").Select
With Sheets("Stammdaten")
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
iCol = .Cells(1, Columns.Count).End(xlToLeft).Column
.Cells(lRow, 1).Value = TextBox_A.Value
.Cells(lRow, 2).Value = TextBox_B.Value
.Cells(lRow, 3).Value = TextBox_ger.Value
.Cells(lRow, 4).Value = TextBox_eng.Value
.Cells(lRow, 5).Value = TextBox_cost.Value
.Cells(lRow, 6).Value = TextBox_area.Value
' Stammdaten Sortieren
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .Sort
.SetRange .Range(.Cells(1, 1), .Cells(lRow, iCol))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Spreche30BlaetterAn
End Sub
Eine Anmerkung gleich: Gewöhn dir an, einen Button SOFORT zu benennen. In zwei Jahren weisst du nicht mehr, was CommandButton1_Click ist. Wenn du den Button erstellst und gleich umbenennst, zB in CmB_NeueStammdaten ... dann schaust du in zwei Jahren in den Code, siehst Cmb_NeueStammdaten_Click und weisst sofort: "Achja, der Button der die Neuen Stammdaten einfügt".
Grüße,
Klaus M.vdT.

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 13:33:56
Klaus
dann wird die Datenbank geöffnet
Deine Sheets "Mengen", "Kosten", "Fläche" usw ... wo sind die? In deiner Masterdatei ODER in der Datenbank?
Erstmal in DatenEinfuegen() nur
With wksMy (das wbMy. löschen)
Wenn die Blätter in der Masterdatei sind, sollte es dann so gehen:
    Sub Spreche30BlaetterAn()
Dim WbDatei1 As Workbook
Dim wbDateiOld As Workbook
Set wbDateiOld = ActiveWorkbook
Set WbDatei1 = Workbooks.Open("C:\TestTMP\Zufall.xlsx") 'Meine Testdatei, ändern!
wbDateiOld.Activate
'Erklärung: das "öffnen" der Datenbank macht diese zum "aktiven" Workbook. Ich geh darum  _
zurück
'ins alte Fenster (hab mir den Fensternamen in wbDateiOld gemerkt) bevor der Rest passiert
Call DatenEinfuegen(Sheets("Mengen"))
Call DatenEinfuegen(Sheets("Kosten"))
Call DatenEinfuegen(Sheets("Fläche"))
End Sub
Wenn die Blätter in der Datenbank sind, dann bleiben wir nach dem "open" einfach im richtigem Fenster, dem Datenbankfenster (das DIM-SET ist nicht notwendig, um eine Datei zu öffnen.
    Sub Spreche30BlaetterAn()
Workbooks.Open ("C:\TestTMP\Zufall.xlsx") 'Meine Testdatei, ändern!
Call DatenEinfuegen(Sheets("Mengen"))
Call DatenEinfuegen(Sheets("Kosten"))
Call DatenEinfuegen(Sheets("Fläche"))
End Sub
Und?
Grüße,
Klaus M.vdT.

Anzeige
AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 14:08:14
Martin
Okay nun sieht der CommandButton wie folgt aus:

Private Sub CommandButton1_Click()
' Neue Stammdaten in einfügen
Dim emptyRow As Long
Dim lRow As Long
lRow = Cells(Rows.Count, 1).End(xlUp).Row
Sheets("Stammdaten").Select
emptyRow = WorksheetFunction.CountA(Range("A:A")) + 1
Cells(emptyRow, 1).Value = TextBox_A.Value
Cells(emptyRow, 2).Value = TextBox_B.Value
Cells(emptyRow, 3).Value = TextBox_ger.Value
Cells(emptyRow, 4).Value = TextBox_eng.Value
Cells(emptyRow, 5).Value = TextBox_cost.Value
Cells(emptyRow, 6).Value = TextBox_area.Value
' Stammdaten Sortieren
Dim iColLast As Integer
lRow = Cells(Rows.Count, 1).End(xlUp).Row
iColLast = Cells(1, Columns.Count).End(xlToLeft).Column
ActiveSheet.Range("a1", ActiveSheet.Cells(lRow, iColLast)).Select
ActiveWorkbook.Worksheets("Stammdaten").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Stammdaten").Sort.SortFields.Add Key:=Range( _
"A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ActiveWorkbook.Worksheets("Stammdaten").Sort.SortFields.Add Key:=Range( _
"B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Stammdaten").Sort
.SetRange Range("a1", ActiveSheet.Cells(lRow, iColLast))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Spreche30BlaetterAn
End Sub

Die Sheets befinden sich in der Datenbank.
Beim Klicken des Buttons tritt wieder ein Laufzeitfehler auf (424) Objekt erforderlich. Beim Debuggen haben wir Folgende Zeile markiert: .Cells(emptyRow2, 1).Value = TextBox_A.Value
Die beiden Subs sehen nun wie folgt aus:
Sub Spreche30BlaetterAn()
Workbooks.Open ("C:\test\Datenbank.xlsm") 'Meine Testdatei, ändern!
'Debug.Print WbDatei1.Name
Call DatenEinfuegen(Sheets("Mengen"))
Call DatenEinfuegen(Sheets("Kosten"))
Call DatenEinfuegen(Sheets("Fläche"))
End Sub
Sub DatenEinfuegen(wksMy As Worksheet)
Dim emptyRow2 As Long
Dim lRow As Long
Dim iColLast As Integer
'Sheets("Mengen").Select
With wksMy
'letzte Zeile
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
' Daten in Datenbank einfügen -> Mengen
emptyRow2 = WorksheetFunction.CountA(.Range("A:A")) + 1
.Cells(emptyRow2, 1).Value = TextBox_A.Value
.Cells(emptyRow2, 2).Value = TextBox_B.Value
.Cells(emptyRow2, 3).Value = TextBox_ger.Value
.Cells(emptyRow2, 4).Value = TextBox_eng.Value
' Datenbank sortieren -> Mengen
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Formeln übernehmen / vervollständigen -> Mengen
'Range("E2:T2").Select
'Selection.AutoFill Destination:=Range("E2:T300"), Type:=xlFillDefault
'COPY ist viel schneller als AutoFill und macht das gleiche!
'.Range("E2:T2").Copy
'.Range("E3:T" & lRow).PasteSpecial
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub Liebe Grüße
Martin

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 14:17:03
Martin
Vll sollte ich auch erwähnen, dass der Laufzeitfehler nicht beim Commandbutton auftritt, sondern erst wenn die Datenbank geöffnet wird und das Sub DatenEinfuegen geladen wird.

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 14:19:13
Klaus
Hi,
du hast den Code deines Button nicht optimiert (siehe mein Beitrag 1 weiter oben). Ich hätte vielleicht das Thread-Betreff wechseln sollen, es sieht jetzt aus wie ein Doppelpost - es ist kein Doppelpost!
Zurück zum Thema
.Cells(emptyRow2, 1).Value = TextBox_A.Value
Das Problem hier ist TextBox_A.Value. Das referenziert auf die aktuelle Textbox, die aber NICHT in der Datenbank ist. Die müsste man jetzt korrekt referenzieren, aber ich hab grad keine Ahnung wie das geht.
Ich greif mal in die Trickkiste, um das zu lösen ...

Sub Spreche30BlaetterAn()
Dim TB_A As String
Dim TB_B As String
Dim TB_ger As String
Dim TB_eng As String
TB_A = TextBox_A.Value
TB_B = TextBox_B.Value
TB_ger = TextBox_ger.Value
TB_eng = TextBox_eng.Value
'ich übergebe den Inhalt der Textboxen, solange ich noch in der "richtigen" Datei bin
Workbooks.Open ("C:\TestTMP\Zufall.xlsx") 'Meine Testdatei, ändern!
'jetzt hat sich der Focus geändert, aber
Call DatenEinfuegen(Sheets("Mengen"), TB_A, TB_B, TB_ger, TB_eng)
'ich schreibe den TextBox-Inhalt einfach mit in das Call, um ihn später zu nutzen!
Call DatenEinfuegen(Sheets("Kosten"), TB_A, TB_B, TB_ger, TB_eng)
Call DatenEinfuegen(Sheets("Fläche"), TB_A, TB_B, TB_ger, TB_eng)
End Sub
Sub DatenEinfuegen(wksMy As Worksheet, wbMy As Workbook, sEins As String, sZwei As String,  _
sDrei As String, sVier As String)
Dim lRow As Long
Dim iColLast As Integer
With wksMy
'letzte Zeile
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
' Daten in Datenbank einfügen ->   Mengen
.Cells(lRow, 1).Value = sEins
.Cells(lRow, 2).Value = sZwei
.Cells(lRow, 3).Value = sDrei
.Cells(lRow, 4).Value = sVier
' Datenbank sortieren ->   Mengen
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Formeln übernehmen / vervollständigen ->   Mengen
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub
ich hab noch ein paar Kleinigkeiten verändert, bitte beide Makros komplett kopieren und testen.
Grüße,
Klaus M.vdT.

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 14:28:21
Martin
Soweit sogut, nun tritt im Call folgender Fehler auf: Fehler beim Komplimieren: Argumenttyp ByRef unverträglich
Markierung im Sub Spreche30BlaetterAn auf TB_A
Liebe Grüße

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 14:32:27
Klaus
Hi,
was steht denn in den vier Textboxen?
Grüße,
Klaus M.vdT.

AW: Formeln kopieren bei eingefügter Zelle
19.02.2013 14:35:23
Klaus
Hi,
was steht denn in den vier Textboxen?
Grüße,
Klaus M.vdT.

dann anders:
19.02.2013 14:39:25
Klaus
Hi,
neuer Versuch:
Achtung: Hier:
.Cells(lRow, 1).Value = wbMy.Sheets("Tabelle1").TextBox_A.Value
.Cells(lRow, 2).Value = wbMy.Sheets("Tabelle1").TextBox_B.Value
.Cells(lRow, 3).Value = wbMy.Sheets("Tabelle1").TextBox_ger.Value
.Cells(lRow, 4).Value = wbMy.Sheets("Tabelle1").TextBox_eng.Value

Musst du natürlich den korrekten Tabellennamen eintragen statt Tabelle1 !!
Option Explicit
Sub Spreche30BlaetterAn()
Dim wbOld As Workbook
Set wbOld = ActiveWorkbook
Workbooks.Open ("C:\TestTMP\Zufall.xlsx") 'Meine Testdatei, ändern!
Call DatenEinfuegen(Sheets("Mengen"), wbOld)
Call DatenEinfuegen(Sheets("Kosten"), wbOld)
Call DatenEinfuegen(Sheets("Fläche"), wbOld)
End Sub
Sub DatenEinfuegen(wksMy As Worksheet, wbMy As Workbook)
Dim lRow As Long
Dim iColLast As Integer
With wksMy
'letzte Zeile
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
' Daten in Datenbank einfügen ->   Mengen
.Cells(lRow, 1).Value = wbMy.Sheets("Tabelle1").TextBox_A.Value
.Cells(lRow, 2).Value = wbMy.Sheets("Tabelle1").TextBox_B.Value
.Cells(lRow, 3).Value = wbMy.Sheets("Tabelle1").TextBox_ger.Value
.Cells(lRow, 4).Value = wbMy.Sheets("Tabelle1").TextBox_eng.Value
' Datenbank sortieren ->   Mengen
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Formeln übernehmen / vervollständigen ->   Mengen
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub

AW: dann anders:
19.02.2013 15:16:51
Martin
In den Textboxes A / B geb ich zahlen ein, in den Textboxex ger / eng geb ich Bezeichnungen / Namen ein.
Welche Tabellennamen muss ich angeben? Dort wo sich das UserForm befindet? Habe es jetzt so gemacht:
Option Explicit
Sub Spreche30BlaetterAn()
Dim wbOld As Workbook
Set wbOld = ActiveWorkbook
Workbooks.Open ("C:\test\Datenbank.xlsm") 'Meine Testdatei, ändern!
Call DatenEinfuegen(Sheets("Mengen"), wbOld)
Call DatenEinfuegen(Sheets("Kosten"), wbOld)
Call DatenEinfuegen(Sheets("Fläche"), wbOld)
End Sub

Sub DatenEinfuegen(wksMy As Worksheet, wbMy As Workbook)
Dim lRow As Long
Dim iColLast As Integer
With wksMy
'letzte Zeile
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
' Daten in Datenbank einfügen ->   Mengen
.Cells(lRow, 1).Value = wbMy.Sheets("Stammdaten").TextBox_A.Value
.Cells(lRow, 2).Value = wbMy.Sheets("Stammdaten").TextBox_B.Value
.Cells(lRow, 3).Value = wbMy.Sheets("Stammdaten").TextBox_ger.Value
.Cells(lRow, 4).Value = wbMy.Sheets("Stammdaten").TextBox_eng.Value
' Datenbank sortieren ->   Mengen
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Formeln übernehmen / vervollständigen ->   Mengen
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub

Bekomme aber wieder einen Laufzeitfehler (438): Objekt unterstützt diese Eigenschaft oder Methode nicht. Egal ob ich im DatenEinfuegen Sub nun Stammdaten (Der Ort wo sich das UserForm befindet), oder Mengen (Der Ort wo die Eingaben aus der UserForm gespeichert werden sollen) angebe.
Zeile beim Debuggen ist wie vorhin:
.Cells(lRow, 1).Value = wbMy.Sheets("Stammdaten_NCV3").TextBox_A.Value

AW: dann anders:
19.02.2013 15:20:43
Martin
edit:
Zeile beim Debuggen ist wie vorhin:
.Cells(lRow, 1).Value = wbMy.Sheets("Stammdaten").TextBox_A.Value

falsch abgeändert hihi

das kann nicht so schwer sein :-/ wir packen das!
19.02.2013 15:32:21
Klaus
Hi Martin,
ich glaube ich / wir verennen uns hier. Letzter Versuch für heute, dann will ich bald in den Feierabend:
Im Button folgenden Code
Private Sub CommandButton1_Click()
' Neue Stammdaten in einfügen
Dim lRow As Long
Dim iCol As Integer
'Sheets("Stammdaten").Select
With Sheets("Stammdaten")
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
iCol = .Cells(1, Columns.Count).End(xlToLeft).Column
.Cells(lRow, 1).Value = TextBox_A.Value
.Cells(lRow, 2).Value = TextBox_B.Value
.Cells(lRow, 3).Value = TextBox_ger.Value
.Cells(lRow, 4).Value = TextBox_eng.Value
.Cells(lRow, 5).Value = TextBox_cost.Value
.Cells(lRow, 6).Value = TextBox_area.Value
   .Range(.Cells(lRow, 1), .Cells(lRow, 4)).Copy
' Stammdaten Sortieren
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
_
DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
_
DataOption:=xlSortNormal
With .Sort
.SetRange .Range(.Cells(1, 1), .Cells(lRow, iCol))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Spreche30BlaetterAn
End Sub
Damit landet der Inhalt der Textboxen (den du in die Stammdaten geschrieben hast) erstmal in der Zwischenablage.
in Sub DatenEinfuegen() sparen wir uns dann die gesamten Textboxen und fügen einfach aus der Zwischenablage ein:

' Daten in Datenbank einfügen ->   Mengen
    .range(.cells(lrow,1),.cells(lrow,4)).pastespecial
'    .Cells(lRow, 1).Value = wbMy.Sheets("Stammdaten").TextBox_A.Value
'    .Cells(lRow, 2).Value = wbMy.Sheets("Stammdaten").TextBox_B.Value
'    .Cells(lRow, 3).Value = wbMy.Sheets("Stammdaten").TextBox_ger.Value
'    .Cells(lRow, 4).Value = wbMy.Sheets("Stammdaten").TextBox_eng.Value

Jetzt weiss ich zwar immer noch nicht, wie ich eine Textbox korrekt referenziere - aber vielleicht klappt es ja mit diesem "dirty trick".
Grüße,
Klaus M.vdT.

AW: das kann nicht so schwer sein :-/ wir packen das!
19.02.2013 15:49:11
Martin
Okay, mach erstmal Feierabend, das eilt nicht ! Ich denk ich mach mich auch nun auf den Weg nach Hause. Hab das nun mal fix getestet mit folgendem CommandButton:
Private Sub CommandButton1_Click()
' Neue Stammdaten in einfügen
Dim lRow As Long
Dim iCol As Integer
'Sheets("Stammdaten").Select
With Sheets("Stammdaten")
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
iCol = .Cells(1, Columns.Count).End(xlToLeft).Column
.Cells(lRow, 1).Value = TextBox_A.Value
.Cells(lRow, 2).Value = TextBox_B.Value
.Cells(lRow, 3).Value = TextBox_ger.Value
.Cells(lRow, 4).Value = TextBox_eng.Value
.Cells(lRow, 5).Value = TextBox_cost.Value
.Cells(lRow, 6).Value = TextBox_area.Value
.Range(.Cells(lRow, 1), .Cells(lRow, 4)).Copy
' Stammdaten Sortieren
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
_
_
DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
_
_
DataOption:=xlSortNormal
With .Sort
.SetRange .Range(.Cells(1, 1), .Cells(lRow, iCol))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Spreche30BlaetterAn
End With
End Sub
und folgenden Subs :
Option Explicit
Sub Spreche30BlaetterAn()
Dim wbOld As Workbook
Set wbOld = ActiveWorkbook
Workbooks.Open ("C:\Test\Datenbank.xlsm") 'Meine Testdatei, ändern!
Call DatenEinfuegen(Sheets("Mengen"), wbOld)
Call DatenEinfuegen(Sheets("Kosten"), wbOld)
Call DatenEinfuegen(Sheets("Fläche"), wbOld)
End Sub Sub DatenEinfuegen(wksMy As Worksheet, wbMy As Workbook)
Dim lRow As Long
Dim iColLast As Integer
With wksMy
'letzte Zeile
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
.Range(.Cells(lRow, 1), .Cells(lRow, 4)).PasteSpecial
' .Cells(lRow, 1).Value = wbMy.Sheets("Stammdaten").TextBox_A.Value
' .Cells(lRow, 2).Value = wbMy.Sheets("Stammdaten").TextBox_B.Value
' .Cells(lRow, 3).Value = wbMy.Sheets("Stammdaten").TextBox_ger.Value
' .Cells(lRow, 4).Value = wbMy.Sheets("Stammdaten").TextBox_eng.Value
' Datenbank sortieren -> Mengen
.AutoFilter.Sort.SortFields.Clear
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("A2:A" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.AutoFilter.Sort.SortFields.Add Key _
:=.Range("B2:B" & lRow), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
' Formeln übernehmen / vervollständigen -> Mengen
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub
Hier Aber schon im Stammdatenblatt Probleme: Laufzeitfehler (438) Objekt unterstützt Eigenschaft / Methode nicht. Debug:
With .Sort
.SetRange .Range(.Cells(1, 1), .Cells(lRow, iCol))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Ist mir richtig unangenehm dich derartig zu belästigen!
Grüße und schönen Feierabend!

AW: das kann nicht so schwer sein :-/ wir packen das!
19.02.2013 17:16:57
Martin
Zum besseren Verständnis und damit du nicht gegen eine Wand reden musst, habe ich mal eine stark abgespeckte Form der beiden Dateien erstellt.
https://www.herber.de/bbs/user/83975.zip
Liebe Grüße !!
Martin

AW: das kann nicht so schwer sein :-/ wir packen das!
19.02.2013 17:20:11
Martin
Und natürlich habe ich in die .zip Datei die Stammdaten-Datei ohne Makros gepackt. Es wird bei mir auch langsam Zeit für Feierabend, mein Kopf qualmt.
Hier also die Stammdaten-Datei mit Makros und UserForm
https://www.herber.de/bbs/user/83976.xlsm
Gruß Martin

Schau ich mir an!
19.02.2013 21:28:26
Klaus
Hallo Martin,
die Dateien schaue ich mir an. Auf meinem Netbook habe ich leider (oder: zum Glück?) kein Excel. Ich melde mich morgen mittag oder so!
Grüße,
Klaus M.vdT.

AW: das kann nicht so schwer sein :-/ wir packen das!
20.02.2013 09:03:53
Klaus
Hi,
mit Datei ist alles leichter! Sollte jetzt laufen wie gewünscht.
Ich habe einen Fehler in der Referenzierung gemacht (fürs Protokoll: nach WITH .Sort kann kein .Range folgen) und wusste schlicht nicht, dass deine TextBoxen in einer USERFORM stehen - da kann ich ja stundenlang versuchen, auf die TABELLE zu referenzieren :-)
https://www.herber.de/bbs/user/83982.xlsm
Kleinigkeiten:
den "Datenbank-öffen" Vorgang habe ich durch eins meiner Standardmakros ersetzt, um die Excel-Fehlermeldung "Datei ist bereits geöffnet" zu umgehen.
Du musst im Code wieder deinen korrekten Dateipfad eintragen (aber zweigeteilt Pfad / Datei - im Makro siehst du wie das gemeint ist).
Wenn ich das richtig verstehe, hat deine Datenbank 30 Blätter (Flächen, Mengen, usw ...) in die alle der Eintrag aus den Textboxen kommt, und dann wird sortiert.
Du kannst natürlich 30 Calls schreiben, aber alle Blätter einer seperaten Datei anzusprechen ginge auch in 3-4 Zeilen :-) Egal, auf jedem Fall besser als das ganze Makro 30 mal zu wiederholen.
Grüße,
Klaus M.vdT.

AW: das kann nicht so schwer sein :-/ wir packen das!
21.02.2013 08:01:58
Martin
Soeben getestet! Funktioniert genau wie gewünscht ! Vielen Dank, das hätte ich wohl alleine nie hinbekommen. Jetzt versuche ich noch zu verstehen was genau passiert, und dann im nächsten Schritt werde ich mein "Löschen"-Makro, welches sich auch in den Stammdaten befindet versuchen anzupassen.
*thumbsup*

Danke für die Rückmeldung! mit Text
21.02.2013 08:13:28
Klaus
Hi Martin,
danke für die Rückmeldung, hat Spass gemacht daran zu knobeln!
Wenn du Fragen zum Code hast, kannst du sie mir (oder den anderen) gerne hier stellen. Zu 90% habe ich nur deinen vorhandenen Code angepasst.
Die wichtigste Änderung war meiner Meinung nach, deinen 30-fach wiederholten Code auf eine Wiederholung einzustampfen. Merke: wenn du identischen Code mehr als einmal wiederholst, dann gibt es Optimierungspotential!
Grüße,
Klaus M.vdT.

AW: Danke für die Rückmeldung! mit Text
21.02.2013 09:53:07
Martin
Soo, ich habe mich mal selbst getestet und versucht deine Makros auf mein nächstes Problem zu beziehen. Die Problematik ist die selbe wie zuvor, nur dass ich nun Positionen entfernen möchte. Mein bisheriger Ansatz ist den Dateien zu entnehmen:
https://www.herber.de/bbs/user/84005.zip
Wie zu erkennen: Die gleiche Ressourcenfresserei wie zuvor.
Also war mein erster Schritt ein neues Modul zu erstellen
Sub SprecheAlleDatenAn_Loeschen()
Dim wbOld As Workbook
Set wbOld = ActiveWorkbook
Dim a As Variant
Dim b As Variant
a = UserForm2.TextBox1.Value
b = UserForm2.TextBox2.Value
Call FileCheckOpen("C:Test", "Datenbank.xlsm")
'Workbooks.Open ("C:\TestTmp\Zufall.xlsx")
'die Zeile Workbooks.Open erzeugt eine Fehlermeldung, wenn die Datenbank bereits geöffnet ist
'das Makro FileCheckOpen verhindert diese Fehlermeldung!
Application.ScreenUpdating = False
'lästiges Bildschirmflackern abschalten
Call DatenLoeschen(Sheets("Mengen"),a, b)
Call DatenLoeschen(Sheets("Kosten"), a, b)
Call DatenLoeschen(Sheets("Fläche"), a, b)
wbOld.Activate
'wieder zurück zu den Stammdaten
Application.ScreenUpdating = True
Application.CutCopyMode = False
'CutCopyMode: die "Ameisen" nach einem Kopiervorgang abschalten
End Sub
Das Löschen Sub sieht wie folgt aus:
Sub DatenLoeschen(wksMy As Worksheet, a As Variant, b As Variant)
Dim t As Long
Dim lRow As Long
Dim iColLast As Integer
With wksMy
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
For t = lRow To 2 Step -1
If Cells(t, 1).Value = CLng(a) And Cells(t, 2).Value = CLng(b) Then
Rows(t).Delete shift:=xlUp
End If
Next t
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub Auf dem CommandButton der das Löschen auslöst:
Private Sub CommandButton1_Click()
Dim i As Integer
' Equipment in Stammdaten löschen #########################
Sheets("Stammdaten").Select
i = Cells(Rows.Count, 1).End(xlUp).Rows.Row
For t = i To 2 Step -1
If Cells(t, 1).Value = CLng(TextBox1) And Cells(t, 2).Value = CLng(TextBox2) Then
Rows(t).Delete shift:=xlUp
End If
Next t
SprecheAlleDatenAn_Loeschen
End Sub

Das funktioniert auch FAST!
Bei der Eingabe von der ersten und zweiten IdentNr in den Textfeldern des UserForms der Stammdaten werden die jeweiligen Stammdaten dort gelöscht, die Datenbank öffnet sich aber jetzt kommt es:
Die Daten werden hier nur aus dem letzten Call Sheets("Fläche") entfernt.
Kannst du mir sagen wo hier das Problem liegt?
Vieleicht Optimierungspotential?
Liebe Grüße und schonmal Besten Dank
Martin

Neues Thema (wir sollten mal nach links umziehen)
21.02.2013 10:14:46
Klaus
Hi Martin,
Das Makro sieht doch echt gut aus!
du löscht ja hier:
With wksMy
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
For t = lRow To 2 Step -1
If Cells(t, 1).Value = CLng(a) And Cells(t, 2).Value = CLng(b) Then
Rows(t).Delete shift:=xlUp
End If
Next t
Ich rate: das erste Blatt, dass du in der Datenbank aktiviert hast, ist "Fläche"? Wenn du stattdessen "Mengen" markierst, wird nur hier gelöscht?
ich hab dir mal ein paar Dinge Fett markiert. Diese verweisen auf das AKTIVE sheet! Die sollen aber, im width-Rahmen, auf das Sheet aus dem CALL verweisen (wksMy). Wie geht das? Mit einem Punkt davor!
With wksMy
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
For t = lRow To 2 Step -1
If .Cells(t, 1).Value = CLng(a) And .Cells(t, 2).Value = CLng(b) Then
.Rows(t).Delete shift:=xlUp
End If
Next t
Merke: innerhalb eines WITH-Rahmens referenziert alles mit einem .Punkt davor auf den WIDTH-Rahmen, alles ohne Punkt davor auf das AKTIVE Objekt, meist ist das ein Blatt.
Auf dem Code deines Buttons darfst du das natürlich nicht machen - durch "sheets("Stammdaten").select" ist ja bereits das richtige Blatt referenziert.
(Man könnte den Button-Code auch in einen WITH sheets("Stammdaten")- Block packen und mit Punkten referenzieren, das währe eleganter. Ist aber nicht notwendig)
Das müsste dein Problem bereits gelöst haben, oder?
Nochmal ein Lob hinterher: sehr schön, wie du die variablen a und b aus den Textboxen an das Löschen-Makro übergibtst und dort als Löschbedingung abfragst. Daumen hoch, so gehts!
Grüße,
Klaus M.vdT.

AW: Neues Thema (wir sollten mal nach links umziehen)
21.02.2013 10:33:09
Martin
Grandios ! Funktioniert, Danke Sehr! Was 3 kleine Pünktchen bewirken können. Du hast es mir ja vorgestern erklärt warum du dort Punkte setzt aber ich Dussel hab es ein wenig verworfen.
Ich habe testweise mal 2 Positionen eingefügt und wieder gelöscht. Dabei ist mir aufgefallen, dass ich nach 1x hinzufügen & löschen eine Formelzeile zu viel habe (Beispiel: Positionsliste geht bis Zeile 200, Formelzeile daneben bis 201).
Nach 2x Hinzufügen und Löschen sind es zwei Zeilen zu viel. (Positionsliste bis 200, Formelzeile bis 202).
Diese Formeln verweisen quasi "ins Leere", da in den Stammdaten an Position 201 / 202 ja garnichts steht.

gelöst
20.02.2013 16:01:37
Klaus
Hallo Martin,
du hast dich heute gar nicht mehr gemeldet. Warscheinlich steht mein neuester Beitrag zu weit rechts um ihn zu sehen! Darum hier (ganz links) nochmal ein Verweis:
https://www.herber.de/forum/messages/1300147.html
Problem gelöst (hoffe ich)
Grüße,
Klaus M.vdT.

optimierungen im Löschen-Makro
21.02.2013 11:08:39
Klaus
Hallo Martin,
mit meiner Bildschirmauflösung sehe ich am rechten Thread-Rand nichts mehr, darum habe ich deinen letzen Beitrag mal hier hin kopiert und mache hier weiter:
Grandios ! Funktioniert, Danke Sehr! Was 3 kleine Pünktchen bewirken können. Du hast es mir ja vorgestern erklärt warum du dort Punkte setzt aber ich Dussel hab es ein wenig verworfen.
Ich habe testweise mal 2 Positionen eingefügt und wieder gelöscht. Dabei ist mir aufgefallen, dass ich nach 1x hinzufügen & löschen eine Formelzeile zu viel habe (Beispiel: Positionsliste geht bis Zeile 200, Formelzeile daneben bis 201).
Nach 2x Hinzufügen und Löschen sind es zwei Zeilen zu viel. (Positionsliste bis 200, Formelzeile bis 202).
Diese Formeln verweisen quasi "ins Leere", da in den Stammdaten an Position 201 / 202 ja garnichts steht.

Schauen wir uns mal den Codeteil an, der die Formeln einfügt (wichtiges Fett markiert)
Sub DatenLoeschen(wksMy As Worksheet, a As Variant, b As Variant)
Dim t As Long
Dim lRow As Long
Dim iColLast As Integer
With wksMy
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
For t = lRow To 2 Step -1
If .Cells(t, 1).Value = CLng(a) And .Cells(t, 2).Value = CLng(b) Then
.Rows(t).Delete shift:=xlUp
End If
Next t
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
End With
End Sub
lRow möchte momentan die letzte Zeile +1 finden. Das +1 ist ein Artefakt aus dem vorherigem "Eintragen" Makro. Logisch: Wenn ich in die LETZTE Zeile etwas eintrage, dann ÜBERSCHREIBE ich ja den dortigen Eintrag. Darum möchte ich beim Eintragen nicht die letzte Zeile finden, sondern die letzte Zeile +1.
Jetzt löscht du aber. Die Lösch-Überprüfung muss nur von der letzten Zeile an stattfinden. Das heisst, das +1 ist hier überflüssig! (du willst ja nicht die erste freie Zeile mit überprüfen).
Erster Ansatz: das +1 vom lRow einfach rauswerfen.
Dann kommt aber das nächste Problem: du fragst erst die letzte Zeile ab, dann löscht du Zeilen, dann schreibst du Formeln bis zur ehemals letzten Zeile ... gemerkt?
Beispiel: es gibt 10 Zeilen. lRow ergibt 10. Jetzt löscht du 2 Zeilen (meinetwegen die ersten beiden). Die Datenbank hat noch 8 Zeilen. Jetzt kopierst du die Formeln bis lRow ... moment, lRow ist aber doch 10! Ergebniss: 8 Zeilen mit Daten, aber 10 Zeilen mit Formeln! (darum habe ich unten die Formel-Einfügen-Zeile-lRow auch fett markiert, das siehst dus)
Einfachster WorkAround: lRow nach dem Löschen nochmal abfragen. Das Makro sähe dann so aus:
Sub DatenLoeschen(wksMy As Worksheet, a As Variant, b As Variant)
Dim t As Long
Dim lRow As Long
Dim iColLast As Integer
With wksMy
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'ohne +1
For t = lRow To 2 Step -1
If .Cells(t, 1).Value = CLng(a) And .Cells(t, 2).Value = CLng(b) Then
.Rows(t).Delete shift:=xlUp
End If
Next t
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'nach dem löschen erneut letzte Zeile erfragen _
b>
iColLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(2, 5), .Cells(2, iColLast)).Copy
.Range(.Cells(3, 5), .Cells(lRow, iColLast)).PasteSpecial
'Formeln bis zur wirklich letzten Zeile kopieren
End With
End Sub
Grüße,
Klaus M.vdT.

Nachtrag:
21.02.2013 11:17:59
Klaus

Hallo Nochmal,
beim genaueren Überlegen ... wenn du Zeilen löscht, dann löscht du ja auch deren Formeln. Alle anderen Zeilen in der Datenbank müssten noch Formeln haben. Ich kenne ja deine Formeln nicht, aber wenn die nicht anfällig für Bezugsfehler sind dann kannst du im Löschen-Makro das gesamte Formelschreiben einfach sein lassen, das reine löschen reicht dann ja.
Sub DatenLoeschen(wksMy As Worksheet, a As Variant, b As Variant)
Dim t As Long
Dim lRow As Long
Dim iColLast As Integer
With wksMy
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'ohne +1
For t = lRow To 2 Step -1
If .Cells(t, 1).Value = CLng(a) And .Cells(t, 2).Value = CLng(b) Then
.Rows(t).Delete shift:=xlUp
End If
Next t
End SUb
Wenn das allerdings Bezugsfehler verursacht, dann hast du noch ein Problem. Solltest du jemals den allerersten Datenbankeintrag löschen, dann zieht die zweite Zeile (mit Bezugsfehler) nach oben und wird von da aus wieder nach unten kopiert. Ergebnis: eine ganze Datenbank voller #Bezug!
Das kann man abfangen, indem man entweder die erste Datenbankzeile unlöschbar macht, zb so:
if t > 2 then
.Rows(t).Delete shift:=xlUp
else
msgbox ("Die erste Zeile darf nicht gelöscht werden!)
end if

oder die Formeln im VBA nicht kopiert, sondern direkt schreibt (bei 30 Tabellen sehr aufwenig).
Probier mal aus, löschen ohne Formeln neu schreiben. Wenn dann alles funktioniert, kannst du ruhig schlafen :-)
Grüße,
Klaus M.vdT.
(Edge-Case: Wenn in der Datenbank bereits alle Eintrage bis auf einen gelöscht wurden, und du diesen Eintrag auch löscht, dann verlierts du alle Formeln. Kommt aber warscheinlich in der Realität nie vor.)

AW: optimierungen im Löschen-Makro
21.02.2013 11:21:02
Martin
Macht exakt was es soll ! Besten Dank !
Ich muss mich wirklich bei Zeiten mal mehr mit VBA auseinander setzen. Hab während meines Ingenieurstudiums leider zu wenig VBA gelernt - merke nun immer wieder wie wichtig und mächtig das doch ist !
Liebe Grüße
Martin

OT: VBA und Excel
21.02.2013 11:56:59
Klaus
Hi Martin,
Wenn du mächtige VBA-Anwendungen sehen willst, schau dir mal die Forumsbeiträge vom User Nepumuk an.
Willst du dagegen mal sehen, was man alles OHNE Vba lösen kann, dann schaust du auf http://www.excelformeln.de vorbei (die haben sogar das Conway-Game-Of-Life in Excel nachgebaut - nur mit Formeln).
Was ich / wir hier machen, ist nur Spielkram dagegen.
Grüße,
Klaus M.vdT.

346 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige