Zeilen einer Liste nach definierter Anzahl duplizieren
In einer Liste, welche als Datenbasis für einen Seriendruck mit Word dienen wird, sind verschiedene Produkte aufgeführt; in einer definierten Spalte ist die Anzahl vermerkt, wie viele Etiketten jedes Produkts erstellt werden sollen. Da eine andere Abteilung mit dem Druck beauftragt wurde, soll je Etikett 1 Zeile in der Excel-Liste vorhanden sein.
Dass einzelne Produkte mehrfach aufgeführt sind ist dem Umstand geschuldet, dass bei gewerblichen Kunden der Netto- und bei privaten der Brutto-Preis auf das Etikett geschrieben werden soll. Das aber soll im Endeffekt in MS Word ausgewertet werden.
Um das Ziel zu erreichen gibt es unterschiedliche Wege. Der scheinbar simpelste, nämlich die entsprechende Anzahl von erforderlichen Leerzeilen in die Liste einzufügen und dann die jeweils obere Zeile nach unten zu kopieren mag ich Ihnen nicht anbieten bzw. antun. Darum gab es hierfür keine extra Überschrift. 😉
Per Makro / VBA
Eine Möglichkeit, die in praktisch jeder Excel-Version der letzten 15 Jahre funktioniert ist der Einsatz eines Makros, also eines VBA-Skripts. – Der folgende Code ist bezüglich der verwendeten Begriffe exakt auf dieses Arbeitsblatt abgestimmt. Er ist weder übermäßig gestraft noch an allen erdenklichen Positionen kommentiert. Fügen Sie ihn in einem allgemeinen Modul (beispielsweise Modul1) oder im Modul DieseArbeitsmappe ein. Wenn Sie das Makro anschließend beispielsweise per AltF8 aufrufen und ausführen lassen, wird für jedes Produkt die erforderliche Zahl von Zeilen automatisch erstellt. Der PC von Hewlett-Packard wird natürlich nicht vervielfacht, da ja nur ein Etikett gebraucht wird. Hier nun der Code:
Option Explicit
Option Base 1
Sub Makro1()
Dim aData, aMehrData, i As Long, k As Long, Anz As Long
Dim lRow As Long, lCol As Long
With Tabelle1
lRow = .Cells(Rows.Count, 1).End(xlUp).Row
lCol = .Cells(1, Columns.Count).End(xlToLeft).Column
.ListObjects("tbl_Etiketten").Resize Range(.Cells(1, 1), .Cells(lRow, lCol + 1))
lCol = lCol + 1
.Cells(1, lCol) = "Index"
.Cells(2, lCol) = 1
.Cells(3, lCol).FormulaR1C1 = "=R[-1]C+1"
.Cells(3, lCol).AutoFill Destination:=Range(.Cells(3, lCol), .Cells(lRow, lCol))
'In Werte umwandeln, um Fehler nach dem auffüllen zu vermeiden
With Range("tbl_Etiketten[Preis Brutto]")
.Copy
.PasteSpecial Paste:=xlPasteValues, _
Operation:=xlNone, _
SkipBlanks:=False, _
Transpose:=False
End With
aData = .Range(.Cells(2, 1), .Cells(lRow, lCol))
'###
For i = 1 To UBound(aData)
Anz = aData(i, 4)
If Anz > 1 Then
ReDim aMehrData(Anz - 1, lCol)
For k = 1 To Anz - 1 'Eigentlich auch per Schleife, 1 .. lCol
aMehrData(k, 1) = aData(i, 1)
aMehrData(k, 2) = aData(i, 2)
aMehrData(k, 3) = aData(i, 3)
aMehrData(k, 4) = aData(i, 4)
aMehrData(k, 5) = aData(i, 5)
aMehrData(k, 6) = aData(i, 6)
aMehrData(k, 7) = aData(i, 7)
Next k
lRow = Cells(Rows.Count, 1).End(xlUp).Row
Cells(lRow + 1, 1).Resize(Anz - 1, lCol) = aMehrData
End If
Next i
'##
.ListObjects("tbl_Etiketten").Resize .UsedRange
.ListObjects("tbl_Etiketten").Sort. _
SortFields.Clear
.ListObjects("tbl_Etiketten").Sort. _
SortFields.Add Key:=Range("tbl_Etiketten[[#All],[Index]]"), _
SortOn:=xlSortOnValues, _
Order:=xlAscending, _
DataOption:=xlSortTextAsNumbers
With .ListObjects("tbl_Etiketten").Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.Apply
End With
.Columns("G:G").Delete Shift:=xlToLeft 'Index wird nicht mehr gebraucht
.Cells(1, 1).Select '(Der Form halber)
End With
End Sub
Hier habe ich den reinen Text des Codes für Sie als *.zip hinterlegt. Nach dem entpacken wird Ihnen das kopieren vielleicht leichter fallen.
In ihrem eigenen Projekt werden Sie gewiss einen anderen Namen für die Tabelle verwenden und wahrscheinlich auch die Spalte mit der Anzahl an einer anderen Position haben. Sie können auch jederzeit statt der ListObject-Namen für die Spalten auch die standardmäßigen Bereichs-Adressen in A1-Schreibweise verwenden.
Hinweis: Wenn Sie vollkommen oder so gut wie unbedarft sind in Sachen VBA, dann wird Ihnen eine Anpassung des Codes gewiss schwer fallen. Wir (das Blog-Team) haben im Laufe der letzten Jahre die Erfahrung gemacht, dass Nutzer dieses Blocks auch direktbei uns um Hilfe, um eine direkte Anpassung für das eigene Projekt nachfragen. Sorry, da müssen wir auf unseren Sponsor GMG-CC verweisen. Wir investieren in diese Veröffentlichung bereits sehr viel Zeit und können nicht (auch noch) solche Dienstleistungen gratis erbringen. Bitte haben Sie dafür Verständnis.
Mit Power Query
Beginnend mit der Version Excel 2010 können Sie Power Query als Add-In bei Microsoft herunterladen, in 2016⁄365 ist dieses Tool bereits fest integriert. Es geht hier zwar auch nicht ganz ohne Code, aber komplett ohne VBA und somit ist das auch bei Rechnern durchführbar, wo aus Gründen der Sicherheit Makros nicht ausgeführt werden können. Und versprochen, es ist nur eine einzige Formel. 😎
Die folgenden Hinweise/Anleitungen sind nicht wirklich an Null-Einsteiger in Sachen Power Query gerichtet. Das bedeutet, dass sie sich vielleicht ein wenig in die Materie des PQ einarbeiten müssen. Dennoch beschreibe ich hier die wichtigsten Schritte …
Nach dem Import der Tabelle in den Abfrage-Editor stellt sich das so dar:
Idealerweise werden sie die Abfrage sofort per Schließen & laden in ein getrenntes Tabellenblatt schreiben, damit Sie praktisch einen status quo schaffen und sichern. Dennoch möchte ich Ihnen anhand dieses Beispiels einige meiner Überlegungen nicht vorenthalten, denn so einfach wie es auf den ersten Blick zu sein scheint ist es nun doch wirklich nicht. Dass null keineswegs der Zahl 0 gleichzusetzen ist sollte Ihnen bekannt sein. Und dass in der Spalte Preis brutto keine Formeln, sondern nur die berechneten Werte stehen, sollte Ihnen bewusst sein.
Mit den typischen Mitteln des Power Query, nämlich mit einigen Mausklicks werden sie hier nicht zum Ziel gelangen. Da gibt es keine Möglichkeit, Zeilen in eine bestehende Abfrage oder Liste einzufügen. Und ich musste auch einige Zeit damit verbringen, mich durch die Funktionen der Sprache M „durchzuwühlen” und diese Funktion dann auch vernünftig anzuwenden.
Fügen Sie als erstes eine Benutzerdefinierte Spalte hinzu und belassen Sie es bei dem vorgegebenen Namen oder verwenden Sie (wie auch ich) den Namen Liste. Als Benutzerdefinierte Spaltenformel geben Sie folgendes ein:
Der Klarheit wegen hier noch einmal die Formel in geschriebener Form, die sie auch direkt kopieren und in ihre Datei einfügen können:
List.Generate(()=>[Anzahl], each _ >0, each _ - 1)
und bei der Gelegenheit sei angemerkt, dass ich diese Formel fast genauso aus der Hilfe zur Sprache M übernommen und nur minimal angepasst habe. Das war auch schon der schwierigste Teil der Aufgabe.
Erweitern Sie nun die neu erstellte Spalte mit dem immer gleichen Eintrag List durch einen Klick auf den Doppelpfeil und wählen Sie die Möglichkeit Auf neue Zeilen ausweiten. Umgehend wird bei jeder Zeile, wo der Werte in der Spalte Anzahl größer ist als 1 um die entsprechenden Kopien erweitert. Die Sortierung in dieser letzten Spalte ist zwar absteigend, aber das spielt keine Rolle. Wichtig ist nur, dass die einzelnen Produkte nicht „zerrissen” werden.
In jedem Fall können Sie nun die letzte, die eben erstellte Spalte löschen; sie wird nicht mehr gebraucht. Die Spalten Anzahl und Gewerblich können Sie je nach Geschmack bzw. Erfordernis in der Liste belassen oder löschen. Für die Serienetiketten an sich werden die Spalten nicht benötigt, wenn aber eine Liste in der Form, wie sie derzeit auf dem Bildschirm sichtbar ist, ausgedruckt werden soll, kann das ganz hilfreich sein. Jetzt noch einmal Schließen & laden und sie haben das Wunschziel erreicht. Die beiden Spalten mit den Preisen können Sie ja noch als Währung formatieren, aber auch das kann Word beim Ausdruck für Sie erledigen.