Makro unterbrechen oder anhalten zwecks "Zwischenspeichern"

Pr3d4tor

Mitglied
Moin,

gerade mal den ersten spontanen Versuch gestartet und ich muss sagen das hat doch mal was...
Ein Missverständnis ist mir allerdings direkt aufgefallen ;-)

Angenommen ich gebe für die Anzahl der Flp "5" ein, dann sollen fünf Flp´s mit jeweils 15 Zeilen erstellt werden UND ZUSÄTZLICH eine 6te Flp in der landen dann die übrig geblieben Zeilen bis zur letzten.
Also:

3Flp + RestFlp
4Flp + RestFlp
5Flp + RestFlp usw.

später mal schauen ob ich das hinbekomme.

Generell aber nochmal an dieser Stelle ein riesen Dankeschön für deine Bemühungen @Yaslaw , dass das vom Code her dann doch mit so "wenig" VBA im Vergleich zu meinem machbar ist, haut mich um.

Eine Frage habe ich aber doch noch, da ich es für einen tollen Zusatz halte und gerne wüsste was davon geht und was die bessere Wahl wäre.Und zwar wäre es ja cool wenn nach dem Erstellen der Flp Blätter diese auch direkt in einem vorgegeben Ordner gespeichert werden natürlich inkl. Vorgegeben Namen.

Oder wäre es in dem Fall sinnvoller deinen Code so umzubauen das anstatt der Blätter dann doch direkt Flp Arbeitsmappen erstellt werden, gespeichert unter vorgegebenen Namen und anschließend auch geschlossen werden?

Später mal näher mit beschäftigen denke ich.
Den Code für das "Zusammenbasteln" vom Dateinamen habe ich ja schon, muss dann nur mal schauen ob und wie ich das in Kombination mit dem Speichern von nem Tabellenblatt hinbekomme.


Nochmals Vieeelen Dank
und einen schönen Feiertag.


Vg
 

Yaslaw

n/a
Moderator
Was soll es machen, wenn der User eine zu hohe Zahl eingibt.
Annahme, es hat "Nur" 10 Datenzeilen und er gibt eine 1 ein. Soll das FLP_2 leer sein?
 

Yaslaw

n/a
Moderator
Achja, eine einfache Funktion zum exportieren. Kann man gemütlich aus der Schleife pro FLP aufrufen
Visual Basic:
'/**
' * Exportiert eine einzelne Exceltabelle
' * @param  Worksheet   Die zu exportierende Tabelle
' * @param  Long        Die FLP-Nummer
' */
Public Sub exportWs(ByRef ioWs As Worksheet, ByVal iFlpNr&)
    Dim filePath$:                  filePath = "C:\_TMP\FLP_" & iFlpNr & ".xlsx" 'TODO: Pfad anpassen
   
    'Prüfen ob bereits vorhanden, ggf löschen
    If Dir(filePath) <> "" Then
        If MsgBox("File " & filePath & " already exists." & vbCrLf & "overwrite?", vbYesNo + vbCritical) = vbNo Then Exit Sub
        Kill filePath
    End If
   
    Dim wbTarget As Workbook:       Set wbTarget = Workbooks.Add        'Neues Workbook
    ioWs.Copy Before:=wbTarget.Sheets(1)
    wbTarget.SaveAs filePath
    wbTarget.Close
End Sub
 

Pr3d4tor

Mitglied
Was soll es machen, wenn der User eine zu hohe Zahl eingibt.
Annahme, es hat "Nur" 10 Datenzeilen und er gibt eine 1 ein. Soll das FLP_2 leer sein?
In dem Fall soll gar nichts passieren bzw. würde ich, denke ich, ne MsgBox "Anzahl der gewünschten Flp´s zu hoch" oder so einfügen....

Es gibt aber, wenn du dir das Bild nochmal anschaust, ja bereits rechts eine Textbox.
Nach dem "Einlesen/Importieren" werden automatisch die Zeilen von Zeile 4 bis zur letzten gefüllten Zelle gezählt und durch die vorgegebene Zeilenmenge pro Flp geteilt. Anschließend wird der Wert dann in der Textbox angegeben. Steht meine ich ja auch schon in dem Bild "Es sind XX Sendungen vorhanden. Es können daher XX Flp´s erstellt werden".
Daher würde dort bei 10 Datenzeilen angezeigt das man 0 Flp´s erstellen kann.

Wichtig war es, das alle gefüllten Zellen von Zelle 4 bis zur letzten gefüllten Kopiert werden und jeder Wert nur einmal vorkommt. Was mit deinem Code ja auch umgesetzt wird, denke ich zumindest ;-), kontrolliert habe ich es noch nicht.

Und was die "Formatierung" der CSV Datei angeht wird das bereits nachdem Importieren gemacht.
Sobald ich deinen Code zum abspeichern drin habe muss ich nur noch Prüfen ob die gespeicherte Datei zur weiteren Verarbeitung in das Datenprogramm fehlerfrei importiert werden kann.

VG
 

Pr3d4tor

Mitglied
Achja, eine einfache Funktion zum exportieren. Kann man gemütlich aus der Schleife pro FLP aufrufen
Ich befürchte dafür bin ich zu blöd ;-)
Egal wo ich den Aufruf für exportWs einfüge, ich erhalte immer die Meldung "Argument ist nicht Optional"

Aber mittlerweile verstehe ich immer mehr warum manche immer so auf eine Beispiel Datei bestehen :-D

Ein weiteres Problem für mich ist das Erstellen des kompletten Dateinamens. Der Dateiname setzt sich aus mehreren Variablen zusammen und wird, wie du ebenfalls dem Bild entnehmen kannst, auch bereits vorab in der Userform dargestellt. In meiner Ursprungsversion, als es zu Testzwecken eine Datei war, wurde zum Speichern "tbxFilename" genutzt.

Er setzt sich wie folgt zusammen: (Das sind nur Teilauszüge. Die entsprechenden Zellen werden natürlich auf Veränderungen überwacht usw. es soll nur Aufzeigen wie sich der Namen zusammen setzt.)
Visual Basic:
strUser = Environ("USERNAME")
flpName = vbNullString
pstrTime = Format(Now, "YYYYMMDDhhmmss")
pstrRelation = Worksheets("Tabelle2").Cells(3, 5).Value
pstrNR = "00"
txtFlp.Text = pstrNR
tbxFilename = EX_PFAD & "\" & strUser & "_" & pstrRelation & "_" & pstrTime & ".csv"

'EX_PFAD
Const EX_PFAD As String = "C:\Users\Public\cda\cup\vF\BDV"

'pstrRelation unter anderem durch
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim l As Long
    Dim r As Long
    If Not Application.Intersect(Target, Range("$E$1")) Is Nothing Then
    ' * UserForm übergibt den ausgewählten Namen der CSV an die Zelle E1
    pstrInt = Worksheets("Tabelle2").Cells(1, 5).Value 
        If pstrInt > 0 Then
            l = InStr(pstrInt, "_") + 1
            r = InStrRev(pstrInt, "_", 20)
        ' * Der Dateiname wird auf den relevanten Teil gekürzt
        pstrX = Mid(pstrInt, l, r - l)
        End If
        Worksheets("Tabelle2").Cells(3, 5).Value = pstrX ' * Hier wird der gerade erstellte Teil für den Dateinamen an die Zelle E3 übergeben.
End If
End Sub

'pstrNR
Private Sub txtFlp_Change()
    pstrNR = Format(txtFlp, "00")
    tbxFilename = EX_PFAD & "\" & strUser & "_" & pstrRelation & "_" & pstrTime & ".csv"
End Sub
Wie ich dein FLP_NR jetzt noch mit (strUser & "_" & pstrRelation & "_" & pstrTime & ".csv) in
Code:
Dim wbTarget As Workbook:       Set wbTarget = Workbooks.Add        'Neues Workbook
    ioWs.Copy Before:=wbTarget.Sheets(1)
    wbTarget.SaveAs filePath
    wbTarget.Close
Einbinden ist mir noch nicht ganz klar.
Den Pfad habe ich aus dem EX_PFAD kopiert und für filePath genutzt aber das mit dem Namen kann ich leider auch nicht testen da wie gesagt exportWs noch nicht funzt. Und ich Aufgrund der mehrfachen Erstellung auch nicht wüsste wie ich die FLP_NR als Variable in die Userform bekommen sollte. Mit einem Namen gings ja noch aber mehrere Beispielname.......

VG
 

Pr3d4tor

Mitglied
Nabend oder besser guten Morgen,
ich wollte mal kurz nen kleines Update bringen.

Also ich habe es mittlerweile dann doch mal geschafft @Yaslaw seine Function zum Speichern der einzelnen Tabellenblätter in eine eigene Mappe zu nutzen. Außerdem habe ich es auch hinbekommen den Dateinamen inkl. Pfad an meine Wünsche anzupassen. Sogar das Anzeigen der Flp Nr. aus der Function herraus in meine Userform habe ich schließlich am Ende hinbekomme.

Hier mal die Codes:
Visual Basic:
'Den Anfang habe ich mal hier weggelassen da der komplette Code ja hier im Beitrag zu finden ist'
'
'
        'Die Datenzeilen kopieren
        wsSrc.Range( _
            wsSrc.Cells(flpStartRow, C_DATA_FIRST_COL), _
            wsSrc.Cells(flpEndRow, C_DATA_LAST_COL) _
        ).Copy wsFlp.Cells(C_HEAD_ROWS + 1, 1)

    'Die einzelnen Flp Tabellen werden durch den Aufruf von Call exportWS in einzelne Arbeitsmappe gespeichert
    Call exportWs(wsFlp, flpNr&)
    Next
End Sub


'/**
' * Exportiert eine einzelne Exceltabelle
' * @param  Worksheet   Die zu exportierende Tabelle
' * @param  Long        Die FLP-Nummer
' */
Public Sub exportWs(ByRef ioWs As Worksheet, ByVal iFlpNr&)
    Dim filePath$:                  filePath = "C:\Users\Public\cda\cup\vF\BDV\" & strUser & "_" & pstrRelation & "_" & "FLP_" & iFlpNr & "_" & pstrTime & ".csv" 'TODO: Pfad anpassen
  
    'Prüfen ob bereits vorhanden, ggf löschen
    If Dir(filePath) <> "" Then
        If MsgBox("File " & filePath & " already exists." & vbCrLf & "overwrite?", vbYesNo + vbCritical) = vbNo Then Exit Sub
        Kill filePath
    End If
  
    Dim wbTarget As Workbook:       Set wbTarget = Workbooks.Add        'Neues Workbook
    ioWs.Copy Before:=wbTarget.Sheets(1)
    wbTarget.SaveAs filePath
    wbTarget.Close
End Sub

Das es bisher in den Tests lief gehe ich mal davon aus das der Aufruf mit "Call exportWs(wsFlp, flpNr&)" richtig ist oder gibt es noch eine bessere Methode?Alle meine anderen Tests haben dazu geführt das entweder nur einen Tabellenblatt in eine neue Mappe exportiert wurde oder aber nach dem ersten Durchlauf ein zweiter stattfand aber man weiß ja nie ;-)

Zwei Fragen habe ich allerdings dann doch noch daher ich selbst noch kein Ergebnis erzielen konnte.
1. Wie muss ich den Code für die FLPs umstellen damit immer eine Flp bzw. Tabelle mehr erstellt wird als angegeben? in dieser sollen sich ja die restlichen Zeilen befinden.

Also die Eingabe von:
2 erstellt 3 Flp´s ( 2 Flp´s mit den voreingestellten Datenzeilen + 1Flp mit den restlichen Zeilen)
3 erstellt 4 Flp´s ( 3 Flp´s mit den voreingestellten Datenzeilen + 1Flp mit den restlichen Zeilen)
4 erstellt 5 Flp´s ( 4 Flp´s mit den voreingestellten Datenzeilen + 1Flp mit den restlichen Zeilen) usw.

2. Kann man das eigentlich auch so Angeben das FLP_1 oder FLP_2 durch FLP_01 oder FLP_02 ersetzt wird? (Das allerdings kein muss, sondern mehr Neugier zu Lernzwecken).

Wäre cool, wenn mir jemand bei Frage 1 weiterhelfen kann und vorab schon mal ein riesen Danke
schön an alle, besonders an @Yaslaw für seine Codes.


VG
 

Pr3d4tor

Mitglied
Wie ist der Stand? Hast du die Tage schon selber Lösungen gefunden?
Letzter bzw. aktueller Stand ist folgender:

Makro läuft bisher problemlos durch und erfüllt seinen Zweck ;-)

Zu 1:
Konnte ich Lösen, vielleicht etwas umständlich oder unschön, aber was besser ist mir (noch) nicht eingefallen. Ich habe die Eingabe in der txtFlp an eine Zelle weitergegeben und in einer weiteren mit 1 addieren lassen. Das Ergebnis übernimmt dann die Funktion als Anzahl der zu erstellenden Flps.
So wird aus Eingabe 5 automatisch 6 usw. was andere ist mir bisher nicht eingefallen und löst ja auch im Grunde das Problem.

Zu 2:
war wie gesagt nicht wirklich Wichtig/Erforderlich, hätte mich nur interessiert. Daher noch nicht gelöst und wird vielleicht später nochmal in Angriff genommen.

Neu hinzugekommen: ;-)
Aufgrund der doch recht verschiedenen Dateien aus denen die Flps mal erstellt werden sollen hat sich nun folgendes Ergeben.
Im Moment überlege ich ob man den festen Wert "Const C_FLP_SIZE_DEFAULT& = 15" auch noch irgendwie "erweitern" oder "variabler" gestalten kann. Das Makro zählt ja zu Beginn erst einmal alle Zeilen von 4 an bis zu letzten gefüllten und teilt diesen Wert dann durch den Wert der "Size_Default".
Nun überlege ich ob man vielleicht hingeht bzw. das so in den Code einbauen kann, dass:

- Wenn der errechnete Wert für die maximalen Flps = < 5 dann "Const C_FLP_SIZE_DEFAULT& = 15"
- Wenn der errechnete Wert für die maximalen Flps = > 5 dann "Const C_FLP_SIZE_DEFAULT& = 20"
- Wenn Wert = < 10 dann "Const C_FLP_SIZE_DEFAULT& = 30" usw.

Oder ob man den Code so lässt und vielleicht zusätzlich noch eine Textbox "Gewünschte Anzahl an Sendungen pro Flp" (Textbox = txtFlpVar) in die Userform packt um eine freie Eingabe für die "Size_Default" zu ermöglich.

Also z.B.: wenn txtFlpVar < = 0 oder auch, wenn txtFlpVar ="" dann "Const C_FLP_SIZE_DEFAULT& = 15"
ansonsten Wert von txtFlpVar als Default übernehmen. Aber das hat sich auch wirklich erst heute Nachmittag ergeben daher habe ich in diese Richtung noch gar nichts Versucht.

VG
 

Zvoni

Erfahrenes Mitglied
Freie Eingabe würde ich nicht machen, wenn du wirklich de facto feste Werte für dein SIZE_DEFAULT haben willst.
Würde dann eher mit einem Array arbeiten, und anstatt ner Const dann zwangsläufig eine Variable.

Übrigens: Das ist Unfug (mal schauen, ob du den Fehler siehst....):
Wenn Flps<=5 Dann SIZE=15
Wenn Flps>=5 Dann SIZE=20
 

Pr3d4tor

Mitglied
Freie Eingabe würde ich nicht machen, wenn du wirklich de facto feste Werte für dein SIZE_DEFAULT haben willst.
Würde dann eher mit einem Array arbeiten, und anstatt ner Const dann zwangsläufig eine Variable.
Naja die "freie" Eingabe sollte ja schon, denke ich zumindest, eingeschränkt sein.
Dachte da halt an sowas wie EIN default Wert welcher eben bei Bedarf einmalig durch eine Benutzereingabe "überschrieben" werden kann. Nach dem Durchlauf würde dann wieder die Default gelten.

Ich werde mich aber mal mit dem Array beschäftigen, mal schauen ob ich da was hinbekomme.
Vielleicht hat @Yaslaw ja auch noch ne "verrückte" Idee ;-)

Übrigens: Das ist Unfug (mal schauen, ob du den Fehler siehst....):
Wenn Flps<=5 Dann SIZE=15
Wenn Flps>=5 Dann SIZE=20
Wie war das noch gleich.... War Blöd, merkste selbst ne? :-D
Vielleicht sollte ich ausführliche Rückmeldungen nicht kurz vor Schicht beginn schreiben, da bleibt dann nicht viel Zeit zum Korrekturlesen.