Hallo Access-O-Maniacs,
ich möchte eine strukturierte Tabelle importieren und dann per VBA / SQL einige Daten in dieser Tabelle nachtragen um danach die Daten in andere Tabelle zu übertragen.
Die Tabellen-Struktur sieht wie folgt aus
Level Artikel Stueckliste
1 1235
1 2568
2 5689
3 7854
3 9856
1 2145
2 3652
3 5432
usw....
Habe es so versucht
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
var_form = "123456"
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do While Not rs.EOF
If rs.Fields("Level") = "1" Then
rs.Edit
rs.Fields("Stueckliste") = var_form
rs.Update
End If
rs.MoveFirst
If rs.Fields("Level") > 1 Then
rs.MovePrevious
stl = rs.Fields("Sachnummer")
rs.MoveNext
rs.Edit
rs.Fields("Stueckliste") = stl
rs.Update
End If
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
aber das Ergebnis sieht dann so aus
Level Artikel Stueckliste
1 1235 123456
1 2568 123456
2 5689 2568
2 1689 5689
3 7854 1689
3 9856 7854
3 1856 9856
1 2145 123456
2 3652 2145
3 5432 3652
Das Ergebnis sollte so aussehen
Level Artikel Stueckliste
1 1235 123456
1 2568 123456
2 5689 2568
2 1689 2568
3 7854 1689
3 9856 1689
3 1856 1689
1 2145 123456
2 3652 2145
3 5432 3652
Wäre für Hilfe dankbar
Moinsen,
bitte immer den vollständigen Code angeben - bei dir fehlt zB der Deklarationsteil, das Feld Sach hast du verschwiegen. Ein Update nach deinen Vorstellungen sollte so funktionieren, wenn die Felder vom Wert Zahl sind:
Public Sub ErgaenzeDaten()
Dim db as DAO.Database, rs as DAO.Recordset
Dim dblStl as Double, dblSach as Double
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
db.execute "UPDATE tblImport_Stuecklisten_neu " & _
"SET Stueckliste = 123456 " & _
"WHERE Level=1"
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do Until rs.eof
If Isnull(rs!Stuckliste) then
rs.Edit
rs!Stueckliste = dblStl
rs.Update
Else
rs.Edit
rs!Stueckliste = dblSach
rs.Update
End If
dblStl = rs!Stueckliste
dblSach = rs!Sach
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Moin Jürgen (El Gomero),
erst einmal danke für die schnelle Hilfe.
die Spalte "Sach" gibt es gar nicht, nur die Spalte "Sachnummer".
Dim dblStl as Double, dblSach as Double
Heist dass die Variablen dblStl und dblSach as Zahl laufen und nicht als Text ?
Es gibt aber auch Sachnummern mit Buchstaben drin und was nun ?
doch als String deklarieren ?
Ich werde es mal versuchen, genauso mit den Zahlen.
Gruss
Atuatuca (von der Ostseeküste)
funktioniert leider nicht.
anbei eine Tabelle wie das Ergebnis sein sollte.
Gruss
Atuatuca (von der Ostseeküste)
Zitat
Heist dass die Variablen dblStl und dblSach as Zahl laufen und nicht als Text ?
genau das, ist ja auch so deklariert.
Zitat
Es gibt aber auch Sachnummern mit Buchstaben drin und was nun ?
doch als String deklarieren ?
Hättest du gleich verraten können - genau dann muss die Variable eben ein String werden.
Zitat
Ich werde es mal versuchen, genauso mit den Zahlen.
Und wie sieht dein Code jetzt aus?
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
CurrentDb.Execute "UPDATE tblImport_Stuecklisten_neu " & _
"SET Stueckliste = 123456 " & _
"WHERE Level='1'"
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do Until rs.EOF
If IsNull(rs!Stueckliste) Then
rs.Edit
rs!Stueckliste = stl
rs.Update
Else
rs.Edit
rs!Stueckliste = sachnr
rs.Update
End If
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
stl und sachnr sind mit
Dim stl as String
Dim sachnr as String
deklariert
na dann probier mal:
Dim strStl as String, strSachnr as String
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu")
db.Execute "UPDATE tblImport_Stuecklisten_neu " & _
"SET Stueckliste = 123456 " & _
"WHERE Level='1'"
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do Until rs.EOF
If IsNull(rs!Stueckliste) Then
rs.Edit
rs!Stueckliste = strStl
rs.Update
Else
rs.Edit
rs!Stueckliste = strSachnr
rs.Update
End If
' diese Zuweisungen waren in meinen Code - warum hast du die weggelassen?
strStl = rs!Stueckliste
strSachnr = rs!Sachnummer
rs.movenext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
und nochmal: immer die vollständige Prozedur posten !
Hallo Jürgen,
leider funktioniert es immer noch nicht so wie ich möchte. Habe mal eine Excel angehängt, welche
das Ergebnis von deinem Code (Stückliste (ist) und so wie es sein sollte (Stückliste (soll).
ich versuche es mal in Worte zu fassen.
- mache solange bis spalte Stueckliste nicht mehr leer ist
- gehe zum 1. Datensatz
- gehe zum Datensatz wo Wert in Spalte Level +1 (hier gleich 2) ist von 1. Datensatz
- gehe zum vorherigen Datensatz
- lese den Wert der Spalte Sachnummer aus und speichere ihn in "stl"
- gehe zum nächsten Datensatz und schreibe in der Spalte Stueckliste den Wert welche er sich gerade geholt hat ("stl")
- trage diesen Wert (stl) solange ein in Spalte Stueckliste ein, bis der Wert der Spalte Level größer oder kleiner ist als der aktueller Wert
- wenn der Wert in Spalte Level höher ist, dann gehe 1 Datensatz zurück (level = level-1)
- nehme den Wert der Spalte Sachnummer ("stl") und gehe zum nächsten Datensatz (level=level+1)
- trage diesen Wert (stl) solange ein in Spalte Stueckliste ein, bis der Wert der Spalte Level größer oder kleiner ist als der aktueller Wert
- ist der Wert der Spalte Level kleiner (level =level-1) dann gehe zurück bis zum Datensatz wo Level=level-1
Für den Fall dass Sachnummer kein Wert hat, sollte er ihn überspringen oder den Wert "N/A" eintragen.
Hier mein vollständiger Code (sicherlich verbesserungswürdig), bin aber noch ein Anfänger:
Private Sub cmd_Import_Stuecklisten_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim Dateipfad As String
Dim Datei As String
Dim dlg As Object
Dim var_form As String
Dim i As String
Dim stl As String
Dim sachnr As String
Dim level As String
Dim level1 As String
Set dlg = Application.FileDialog(3)
'Titelzeile
dlg.Title = "Bitte Exceldatei(en) auswählen !"
'standardpfad
dlg.InitialFileName = "E:\test\stücklisten\"
'Mehrfachauswahl erlauben
dlg.AllowMultiSelect = True
'Button text
dlg.ButtonName = "Importieren"
dlg.Filters.Clear
'Nur Dateien mit Endung .XLS* sichtbar
'dlg.Filters.Add "CSV-Datei", "*.csv"
dlg.Filters.Add "Excel-Datei", "*.xls*"
If dlg.Show Then
DoCmd.SetWarnings False
Dateipfad = dlg.SelectedItems(1) 'Pfad in Variable
Datei = Dir(Dateipfad)
'DoCmd.TransferText acImportDelim, , "tblImport_Stuecklisten_neu", Dateipfad, True
'DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, "tblImport_Stuecklisten_neu", Dateipfad, True
DoCmd.TransferSpreadsheet acImport, , "tblImport_Stuecklisten_neu", Dateipfad, True
'hier wird der Wert in der Spalte "Level" in eine reale Zahl um gewandelt
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
DoCmd.OpenQuery "qryLevel_Normalisieren", acViewNormal
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do While Not rs.EOF
If rs.Fields("Level") = "0,2" Then
rs.Edit
rs.Fields("Level") = "2"
rs.Update
End If
'Hier wird für jeden Datensatz eine ID generiert aus verschiedenen Spalten der Tabelle
rs.Edit ' Wenn Daten im Datensatz geändert werden sollen
rs.Fields("[ID_Temp_Stueckliste_Neu]") = rs!ID_Stueckliste_Neu & "_" & rs!Stueckliste & "_" & rs!sachnummer & "_REV_[0" & rs![Stü-ÄZ] & "]"
rs.Update 'Änderungen am / neuen Datensatz speichern
'Hier wird die Sachnummer und die Revisionsnummer in eine neue Spalte geschrieben
rs.Edit ' Wenn Daten im Datensatz geändert werden sollen
rs.Fields("[SachNr_Rev]") = rs!sachnummer & "-0" & rs![Stü-ÄZ]
rs.Update 'Änderungen am / neuen Datensatz speichern
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
CurrentDb.Execute "UPDATE tblImport_Stuecklisten_neu " & _
"SET Stueckliste = 123456 " & _
"WHERE Level='1'"
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do Until rs.EOF
If IsNull(rs!Stueckliste) Then
rs.Edit
rs!Stueckliste = stl
rs.Update
Else
rs.Edit
rs!Stueckliste = sachnr
rs.Update
End If
' diese Zuweisungen waren in meinen Code - warum hast du die weggelassen?
stl = rs!Stueckliste
sachnr = rs!sachnummer
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End If
End Sub
Moin,
den Code habe ich mit Kommentaren versehen, vielleicht hilft dir das schon mal. Ansonsten bitte keine Excel-dateien hochladen, wenn dann die auf das Problem reduzierte Datenbank, komprimiert und gepackt - bevorzugt als mdb.
Private Sub cmd_Import_Stuecklisten_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim Dateipfad As String
Dim Datei As String ' Bezeichner geändert
Dim dlg As Object
Dim var_form As String ' warum erhält ein String als Präfix var = Variant?
Dim i As String ' warum erhält ein String als Präfix i = Integer?
Dim stl As String ' warum mal mit mal ohne Präfix - mich verwirrt das beim Lesen des Codes
Dim sachnr As String
Dim level As String
Dim level1 As String
Set dlg = Application.FileDialog(3)
'Titelzeile
dlg.Title = "Bitte Exceldatei(en) auswählen !"
'standardpfad
dlg.InitialFileName = "E:\test\stücklisten\"
'Mehrfachauswahl erlauben
dlg.AllowMultiSelect = True
'Button text
dlg.ButtonName = "Importieren"
dlg.Filters.Clear
'Nur Dateien mit Endung .XLS* sichtbar
'dlg.Filters.Add "CSV-Datei", "*.csv"
dlg.Filters.Add "Excel-Datei", "*.xls*"
If dlg.Show Then
DoCmd.SetWarnings False
Dateipfad = dlg.SelectedItems(1) 'Pfad in Variable
Datei = Dir(Dateipfad)
'DoCmd.TransferText acImportDelim, , "tblImport_Stuecklisten_neu", Dateipfad, True
'DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, "tblImport_Stuecklisten_neu", Dateipfad, True
DoCmd.TransferSpreadsheet acImport, , "tblImport_Stuecklisten_neu", Dateipfad, True
' Ende des eigentlichen Importvorgangs ab hier würde ich eine neue Prozedur für die Bearbeitung starten
'hier wird der Wert in der Spalte "Level" in eine reale Zahl um gewandelt
'wenn wirklich immer nur eine Zahl in dem Feld steht, könnte dies bereits über eine Importspezi als Zahlenfeld festgelegt werden
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
DoCmd.OpenQuery "qryLevel_Normalisieren", acViewNormal ' wie sieht das SQL-Statement dieser Query aus?
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do While Not rs.EOF
If rs.Fields("Level") = "0,2" Then ' warum können Kommawerte in dem Feld stehen? - s.oben Importspezi
rs.Edit
rs.Fields("Level") = "2"
rs.Update
End If
' kommende Block könnte über eine Aktualisierungsabfrage realisiert werden - wozu soll das aber dienen?
'Hier wird für jeden Datensatz eine ID generiert aus verschiedenen Spalten der Tabelle
rs.Edit ' Wenn Daten im Datensatz geändert werden sollen
rs.Fields("[ID_Temp_Stueckliste_Neu]") = rs!ID_Stueckliste_Neu & "_" & rs!Stueckliste & "_" & rs!sachnummer & "_REV_[0" & rs![Stü-ÄZ] & "]"
rs.Update 'Änderungen am / neuen Datensatz speichern
'Hier wird die Sachnummer und die Revisionsnummer in eine neue Spalte geschrieben
rs.Edit ' Wenn Daten im Datensatz geändert werden sollen
rs.Fields("[SachNr_Rev]") = rs!sachnummer & "-0" & rs![Stü-ÄZ]
rs.Update 'Änderungen am / neuen Datensatz speichern
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
Set db = CurrentDb ' Datenbank definieren -- warum nochmal? vorige Zeile weglassen und db weiter nutzen
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
CurrentDb.Execute "UPDATE tblImport_Stuecklisten_neu " & _
"SET Stueckliste = 123456 " & _
"WHERE Level='1'"
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do Until rs.EOF
If IsNull(rs!Stueckliste) Then
rs.Edit
rs!Stueckliste = stl
rs.Update
Else
rs.Edit
rs!Stueckliste = sachnr
rs.Update
End If
' diese Zuweisungen waren in meinen Code - warum hast du die weggelassen? hier musst du dich ggf auf den Level beziehen, hab den Code aus dem Ärmel geschüttelt ohne zu testen ...
stl = rs!Stueckliste
sachnr = rs!sachnummer
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End If
End Sub
Hallo Jürgen,
hier nochmal den Code mit ergänzenden Kommentaren.
Den u.g. Code lässt alle Felder leer wo der Wert in der Spalte Lever grösser wie 1 ist.
Private Sub cmd_Import_Stuecklisten_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim Dateipfad As String
Dim Datei As String
Dim dlg As Object
Dim var_form As String 'diese Variable kommt nachher per Eingabe aus einem Unterformular
'Dim i As String 'wird z.Zt. nicht benötigt
Dim stl As String 'ob stl oder strstl ist geschmackssache
Dim sachnr As String
Dim level As String
Dim level1 As String
Set dlg = Application.FileDialog(3)
'Titelzeile
dlg.Title = "Bitte Exceldatei(en) auswählen !"
'standardpfad
dlg.InitialFileName = "E:\Test\Stücklisten\"
'Mehrfachauswahl erlauben
dlg.AllowMultiSelect = True
'Button text
dlg.ButtonName = "Importieren"
dlg.Filters.Clear
'Nur Dateien mit Endung .XLS* sichtbar
'dlg.Filters.Add "CSV-Datei", "*.csv"
dlg.Filters.Add "Excel-Datei", "*.xls*"
If dlg.Show Then
DoCmd.SetWarnings False
Dateipfad = dlg.SelectedItems(1) 'Pfad in Variable
Datei = Dir(Dateipfad)
'DoCmd.TransferText acImportDelim, , "tblImport_Stuecklisten_neu", Dateipfad, True
'DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, "tblImport_Stuecklisten_neu", Dateipfad, True
DoCmd.TransferSpreadsheet acImport, , "tblImport_Stuecklisten_neu", Dateipfad, True
'hier wird der Wert in der Spalte "Level" in eine reale Zahl um gewandelt, in der Excel stehen nicht nur Zahlen
Set db = CurrentDb ' Datenbank definieren
Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
DoCmd.OpenQuery "qryLevel_Normalisieren", acViewNormal 'habe ich von Jürgen übernommen
'UPDATE tblImport_Stuecklisten_neu SET tblImport_Stuecklisten_neu.[Level] = Replace([Level],".","");
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do While Not rs.EOF
If rs.Fields("Level") = "0,2" Then 'weil Excel den Wert .2 als 0,2 darzustellt
rs.Edit
rs.Fields("Level") = "2"
rs.Update
End If
'Hier wird für jeden Datensatz eine ID generiert aus verschiedenen Spalten der Tabelle
'Wird benötigt als ID für die spätere Vater / Sohn beziehung usw....
rs.Edit ' Wenn Daten im Datensatz geändert werden sollen
rs.Fields("[ID_Temp_Stueckliste_Neu]") = rs!ID_Stueckliste_Neu & "_" & rs!Stueckliste & "_" & rs!sachnummer & "_REV_[0" & rs![Stü-ÄZ] & "]"
rs.Update 'Änderungen am / neuen Datensatz speichern
'Hier wird die Sachnummer und die Revisionsnummer in eine neue Spalte geschrieben
rs.Edit ' Wenn Daten im Datensatz geändert werden sollen
rs.Fields("[SachNr_Rev]") = rs!sachnummer & "-0" & rs![Stü-ÄZ]
rs.Update 'Änderungen am / neuen Datensatz speichern
rs.MoveNext
Loop
rs.Close
' hier wurde
'Set rs = Nothing
'Set db = Nothing
'Set db = CurrentDb ' Datenbank definieren
'Set rs = db.OpenRecordset("tblImport_Stuecklisten_neu") 'Tabelle definieren und öffnen
'gelöscht
CurrentDb.Execute "UPDATE tblImport_Stuecklisten_neu " & _
"SET Stueckliste = 123456 " & _
"WHERE Level='1'"
If Not rs.EOF Then rs.MoveFirst ' gehe zum ersten Datensatz
Do Until rs.EOF ' Ausführen solange bis letzter Datensatz erreicht ist
If IsNull(rs!Stueckliste) Then ' wenn Wert in Spalte "Stueckliste" leer ist dann
rs.Edit ' Bearbeitungsmodus aktivieren
rs!Stueckliste = stl ' den Wert der Variable "stl" in der Spalte "Stueckliste" eintragen
rs.Update ' Datensatz aktualisieren
Else
rs.Edit ' Bearbeitungsmodus aktivieren
rs!Stueckliste = sachnr ' Wert in Spalte "Stueckliste in der Variable "sachnr" speichern
rs.Update ' Datensatz aktualisieren
End If
' diese Zuweisungen waren in meinen Code - warum hast du die weggelassen?
' habe rumprobiert
stl = rs!Stueckliste
sachnr = rs!sachnummer
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End If
End Sub
ich werde mir deinen Code am späten abend ansehen - derweil kannst du dich mal mit der ungarischen Notation vertraut machen: http://www.access-tutorial.de/namenskonventionen.htm
Hallo Jürgen,
danke für den Link. Wer ich mir mal zugemüte führen.
Gruss
Atuatuca
Hallo,
leider sind die Beispieldaten in deiner Excel-datei ungeeignet um weiterführende Aktionen durchzuführen. Anbei eine db, die mit den vorhandenen Angaben einen sinnvollen Import durchführt. Für einen 2. Schritt fehlen relevante Daten mit denen experementiert werden kann.
Moin Jürgen,
erstmal vielen Dank für deine Bemühungen.
anbei meine abgespeckte DB, sonst bringt mein Arbeitgeber mich um .-)
Die Tabelle 123456_original.xlsx ist die wie ich Sie bekomme.
Die Tabelle 123456_soll.xlsx ist die, wie sie nach her unter tbl_Import_Stueckliste_Neu,
ohne der Spalte "Kommentare" :-)
Ich muss ein Autowert haben, da sonst die Reihenfolge nicht wieder hergestellt werden könnte.
Die Tabelle muss so wie sie ist importiert werden, ohne dass die Reihenfolge verändert wird.
Hoffe die DB ist hilfreicher, als nur die Excel-Listen.
Hi,
Zitatanbei meine abgespeckte DB, sonst bringt mein Arbeitgeber mich um
Beispiel-DBs sollten stets nur das Allernotwendigste enthalten, um das aktuelle Problem nachstellen zu können, und selbstverständlich nur anonymisierte Testdaten.
Du brauchst also keinen Mordanschlag zu befürchten, wenn du diese Regeln beherzigst. ;-)
Hallo,
also wenn ich mit deiner 123456_original.xlsx den Import anschubse, werden regelmässig die Level mit den vorangestellten Punkten nicht importiert - auch wenn die Tabelle schon vorhanden ist und das Feld als Text deklariert wurde. Klappt der Import bei dir? Weitere Frage - gibt es nur diese 3 Level oder können im Echtbetrieb weitere vorkommen? Der Import wird wahrscheinlich öfter benötigt, da du die Auswahl über den Filedialog steuerst?
Hallo Jürgen,
in der Tabelle muss die Spalte "Level" auf "Text" gesetzt werden, war "Standard" drin.
Dann klappt es auch mit dem Import.
Die "Level" sollten unbegrenzt sein. Beim aktuellen Projekt habe ich schon Level 11 gesehen
und es ist einer der kleineren Projekte.
Ich doktere auch immer noch an der Routine für die Erzeugung der Werte in der Spalte Stückliste.
Vielleicht irgend was mit DLookup(Ausdruck, Domäne [, Kriterien]) oder rs.find
Ich meine zu wissen, dass bei Dloopup es auch ein vorwärts und rückwärts definition gibt.
Syntax bekomme ich aber nicht mehr zusammen.
Gruss
Atuatuca
Moinsen,
Zitat
in der Tabelle muss die Spalte "Level" auf "Text" gesetzt werden, war "Standard" drin.
Dann klappt es auch mit dem Import.
Die "Level" sollten unbegrenzt sein. Beim aktuellen Projekt habe ich schon Level 11 gesehen
und es ist einer der kleineren Projekte.
naja, der Import klappt jetzt - ist es denn gewährleistet, dass die Eigenschaft künftig immer auf Text steht? Und welche Spielarten (Nachkomma, ... , usw) gibt es denn noch???
Zitat
Ich doktere auch immer noch an der Routine für die Erzeugung der Werte in der Spalte Stückliste.
Erst mal die primären Punkte klären, dann geht es an die nächste Baustelle ...
Hallo Jürgen,
die Spalte Level kommt aus der Quelle als Textspalte.
Gruss
Atuatuca
Zitat
die Spalte Level kommt aus der Quelle als Textspalte.
interpretiere ich jetzt mal wohlwollend, dass dies für die Zukunft so gegeben ist ...
Wie sehen die Werte für die weiteren Level aus?
Hallo Jürgen,
1
.2
..3
...4
....5
usw.....
Gruss
Atuatuca
Moin,
Zitat
1
.2
..3
...4
....5
usw.....
in der Beispieldatei stehen aber Werte wie 1 0,2 ..3
Sei's drum, ich gehe jetzt davon aus, dass deine künftigen Daten im geschilderten Format kommen - falls nicht musst du eben die Werte abfangen.
Werde mir die Geschichte heute abend nochmal ansehen.
Moin Jürgen,
Du hast recht. Die Quelle gibt folgende Werte in Spalte "Level" aus:
1
0,2
..3
...4
....5
.....6
......7
usw....
Grus
Atuatuca
ich hab mir mal die Tabellen angesehen und komme noch nicht damit klar wie die Regel aussehen soll.
Für mein Verständnis fehlt in den zur Verfügung gestellten Tabellen ein Sortiermerkmal (hast du wohl in der letzten Version als Autowert eingefügt) oder eben die Stücklistennummer.
Die Sortierung soll dann imo nach der Autowertnummer erfolgen, bei Level1 wird jeweils der Wert 123456 gesetzt. Dann wird die Tabelle durchlaufen, ändert sich der Level auf >1 wird die Sachnummer des vorherigen Level in Feld Stückliste geschrieben. Hat der nächste DS den Level 1 beginnt das Spiel von vorne. Soweit richtig? Falls ja, lade nochmal eine vollständige Beispieltabelle hoch.
Hallo Jürgen,
die Spalte "autowert" stammt nicht aus der Quelle, ich habe sie selbst eingefügt. (zur Kontrolle der Reihenfolge). Ich gehe davon aus das Acces die Zeilen der Excel-Tabelle einzeln einliest und den Autowert einträgt. Somit ist die richtige Reihenfolge, sofern Access der Spalte Autowert aufsteigend sortiert, gegeben.
ZitatDie Sortierung soll dann imo nach der Autowertnummer erfolgen, bei Level1 wird jeweils der Wert 123456 gesetzt. Dann wird die Tabelle durchlaufen, ändert sich der Level auf >1 wird die Sachnummer des vorherigen Level in Feld Stückliste geschrieben. Hat der nächste DS den Level 1 beginnt das Spiel von vorne. Soweit richtig?
Soweit richtig und das solange wie der Wert in der Spalte Level sich nicht ändert. Gleiches gilt auch wenn der Wert in Spalte "Level" steigt (strlevel+1). Kompliziert wird es wenn der Wert in Spalte "Level" fällt (strlevel-1), dann soll er rückwärts suchen bis er ein Datensatz findet wo der Wert in Spalte "Level" = strlevel-1 und den Wert aus der Spalte Sachnummer nehmen oder rückwärts Suche bis im Datensatz level = strlevel und dann zu den Datensatz zurück gehen wo er hergekommen ist (isnull(RS.Stückliste)) oder dlookup forward only.
Siehe hierzu den Kommentaren in der Tabelle 123456_soll.xlsx
Gruss
Atuatuca
Zitat
die Spalte "autowert" stammt nicht aus der Quelle, ich habe sie selbst eingefügt. (zur Kontrolle der Reihenfolge). Ich gehe davon aus das Acces die Zeilen der Excel-Tabelle einzeln einliest und den Autowert einträgt.
Da gehst du falsch aus ... In einer Datenbank werden die Datensätze eher willkürlich abgelegt, die Ausgabe erfolgt dann mit gewünschter Sortierung. Insofern ist es also wichtig die gewünschte Reihenfolge nachvollziehen zu können, in dem Fall über den Autowert, der eine laufende Nummer enthält.
In der Anlage hab ich dir eine Musterlösung eingebaut.
Moin Jürgen,
erst schon mal vielen danke, für deine Mühen.
Gucke mir gerade deine "Arbeit" an. Leider kann ich Modul "mod_Code" nicht testen.
Er bleibt stehen bei dem roten Text. Desweiten ist noch ein kleiner Fehler im Modul "mod_import".
Private Sub
anstatt Sub
Mir ist auch aufgefallen das manche Sachnummer doppelt vorkommen, vielleicht hast Du mehrmals "durchlaufen" lassen?
Werde mir den Code nochmal genauer angucken, hoffentlich kann ich einiges verstehen, was da genau passiert.
Option Compare Database
Option Explicit
Sub Set_Stueckliste()
Dim db As DAO.Database, rs As DAO.Recordset, strSQL As String
Set db = CurrentDb
Set rs = db.OpenRecordset("Select * From tbl_Import_final Order by Autowert")
rs.MoveFirst
Do Until rs.EOF
If IsNull(rs!sachnummer) Then rs.MoveNext
If rs!Level = 1 Then
db.Execute "DELETE * FROM tmp_Hierarchie"
strSQL = "INSERT INTO tmp_Hierarchie ( [Level], Stl ) " & _
"Select 1 AS L, " & rs!sachnummer & " AS Snr"
[color=red][b][u]db.Execute strSQL[/u][/b][/color]
Else
strSQL = "INSERT INTO tmp_Hierarchie ( [Level], Stl ) " & _
"Select " & rs!Level & " AS L, " & rs!sachnummer & " AS Snr"
db.Execute strSQL
rs.Edit
rs!Stl_Ist = DLookup("Stl", "tmp_Hierarchie", "Level=" & rs!Level - 1)
rs.Update
End If
rs.MoveNext
Loop
rs.Close: Set rs = Nothing
Set db = Nothing
End Sub
Gruss und bis später
Atuatuca von der Ostsee
die beiden Subs Import_File und Set_Stueckliste müssen Public deklariert, stimmt, da war ein kleiner Fehler. Also nicht Private Sub ... sondern Public Sub ...
Der Code ist bei mir einwandfrei durchgelaufen. Wenn er bei dir an der markierten Stelle hängen bleibt, kannst du dir per ?strSQL im Direktfenster das Statement ausgeben lassen und prüfen.
Moin Jürgen,
habe nochmal getestet. Jetzt klappt es aus mit db.Execute strSQL
. Keine Ahnung, warum er vorher gemeckert hat.
Noch 2 falsche Werte drin (ich erkenne dahinter keine Logik/Regelmäßigkeit)
Zeile 50 (Stl_ist: 6907300; Stl_soll: 6907301)
Nimmt den Wert der Spalte Sachnummer von Zeile 30
Zeile 111 (Stl_ist: 6908511; Stl_soll: 6908512)
Nimmt den Wert der Spalte Sachnummer von Zeile 109
Werde es auch nochmal mit den tatsächlichen Daten testen. Kann aber ein wenig dauern.
Gruss
Atuatuca
Moin Jürgen,
habe mir noch mal ein paar "original" Daten gezogen und getestet.
Es scheint ein Problem zugeben, wenn der Wert in der Spalte "Level"
"3" ist.
Habe dein Code noch ergänzt, sodass er am Ende der Konvertierung
alle Tabellen außer der "Finale" geleert werden.
Anbei nochmal meine abgespeckte DB mit 2 Excel-Files zum importieren.
Ich gucke mir dein Code im Modul "mod_Code" nochmal an, vielleicht
fällt mir da was auf, aber da ich ein Newbie bin wohl eher nicht.
Aber auch ein blindes Huhn findet manchmal ein Korn :-)
Gruss
Atuatuca
Hallo,
hab noch ne kleine Änderung vorgenommen und die Verarbeitung flutscht mit beiden Dateien. Wobei in einer ein DS mit einer leeren Sachnummer vorkommt. Da solltest du mal die Qualität prüfen.
Moin Jürgen,
erst einmal vielen Dank.
habe schon mal ein kurzen Blick rein geworfen. Sieht SEHR GUT aus. Werde mir dein Code
mal zur Brust nehmen und analysieren, was da genau gemacht wird, bzw. passiert.
Das mit dem Artikel ohne Sachnummer wurde schon an die/den entsprechenden Konstrukteur[in] / Entwickler[in] weitergegeben. Kommt aber nur sehr selten vor.
Die Arbeit ist jetzt ein sehr großen Schritt voran gekommen. Jetzt heißt es Daten in andere Tabellen
transferieren und mit einer entsprechenden ID und VaterID versehen. Abgleichen mit den gemachten Bestellungen und dann ein Bericht erzeugen mit den noch zu bestellenden Artikeln.
Nochmals vielen Dank.
Gruss
Atuatuca
Moin Jürgen,
versuche gerade den Wert für Stückliste bei für Level = 1 per User-Eingabe im Formular zu realisieren,
leider funktioniert es irgendwie nicht.
Habe es in der qry_Set_Level1 versucht mit:
UPDATE tbl_Import_final SET tbl_Import_final.Stl_Ist = [Formulare]![frmDialogImport]![txt_Stueckliste]
WHERE (((tbl_Import_final.Level)=1));
frmDialogImport ist das gleiche wie frmImport nur eben mit einen Textfeld mit den Namen txt_Stueckliste
als Ereignis für das txt_Stueckliste, nach Aktualisieren, habe ich
Private Sub txt_Stueckliste_AfterUpdate()
txt_Stueckliste = stl_import
End Sub
Es kommt eine Fehlermeldung:
Laufzeiten Fehler 3061
1 Parameter wurde erwarte, aber es wurden zu wenig Parameter übergeben
Wenn ich in der Abfrage qry_Set_Level1 dann
UPDATE tbl_Import_final SET tbl_Import_final.Stl_Ist = 'stl_import'
WHERE (((tbl_Import_final.Level)=1));
eingebe, wird der Text "stl_import" in den Datensätze eingetragen unter Stl, wo Level =1,
jedoch nicht die Variable "stl_import.
Ich verstehe nur Bahnhof.
Gruss
Atuatuca
Moin Jürgen,
konnte das Problem jetzt doch selber lösen. Habe in ein Modul
Public Sub Set_Level_Eingabe()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
Set db = CurrentDb
Set rs = db.OpenRecordset("Select * From tbl_Import_final Order by Autowert")
rs.MoveFirst
Do Until rs.EOF
If rs.Fields("Stl_Ist") = "123456" Then
rs.Edit
rs.Fields("Stl_Ist") = [Forms]![frmDialogImport]![txt_Stueckliste]
rs.Update
End If
rs.MoveNext
Loop
rs.Close: Set rs = Nothing
Set db = Nothing
End Sub
eingegeben
und das Modul wird wiederum per Schaltfläche ausgeführt (call Set_Level_Eingabe)
Learning by doing :-)
Gruss
Atuatuca
Moin,
das mag ja funktionieren, eleganter und performanter wäre das mit einer Aktualisierungsabfrage zu lösen. Hatte ich wohl auch schon so in der db eingebaut.
Public Sub Set_Level_Eingabe()
Dim db As DAO.Database
Dim strSQL As String
SET db = currentdb
strSQL = "UPDATE tbl_Import_final " & _
"SET Stl_Ist=" & [Forms]![frmDialogImport]![txt_Stueckliste] & " " & _
"WHERE Stl_Ist=123456"
db.execute strSQL
SET db = nothing
End Sub
Hallo Jürgen,
versuche es auf direktem Wege, aber er sagt mir immer:
"1 Parameter wurde erwartet, aber zu wenig Parameter übergeben"
SQL in der Aktualisierungsabfrage qry_Set_Level1
UPDATE tbl_Import_final SET tbl_Import_final.Stl_Ist = [Forms]![frmDialogImport]![txt_Stueckliste]
WHERE (((tbl_Import_final.Level)=1));
Gruss
Atuatuca
hmmm,
ist das Formular denn zur Laufzeit der Abfrage offen und enthält txt_Stueckliste einen gültigen Wert?
Hallo Jürgen,
Hier der Code hinter der Schaltfläche
Private Sub cmd_Uebernehmen_Click()
Call Import_File 'modul mod_Import ausführen
Set db = CurrentDb
db.Execute "DELETE * FROM tbl_Import_final" 'tbl_Import_final leeren
db.Execute "qry_tbl_Stueckliste_final", dbFailOnError 'Abfrage qry_tbl_Stueckliste_final durchführen
Set db = Nothing
CurrentDb.Execute "qry_Set_Level1", dbFailOnError 'Abfrage qry_Set_Leverl1 durchführen
Call Set_Stueckliste 'modul mod_Set_Stueckliste ausführen
'Call Set_Level_Eingabe 'modul mod_Set_Level_Eingabe ausführen
DoCmd.SetWarnings False 'Warnungen ausschalten
SQLdelete = "delete * from tbl_Import_Stuecklisten_raw" 'Tabelle tbl_Import_Stuecklisten_raw leeren
DoCmd.RunSQL SQLdelete
SQLdelete = "delete * from tmp_Hierarchie" 'Tabelle tmp_Hierarchie leeren
DoCmd.RunSQL SQLdelete
DoCmd.SetWarnings True 'Warnungen einschalten
End Sub
Formular frmDialogImport ist geöffnet und im Textfeld wird eine Zahl eingetragen.
Bild vom Formular im Anhang.
Gruss
Atuatuca
verbesserter code:
Private Sub cmd_Uebernehmen_Click()
' Option Explicit einschalten !!! dann muss zB SQLDelete deklariert werden
Dim Set db AS DAO.Database, SQLDelete as String
Set db = CurrentDb
' ruft eigenständige Prozedur auf
Call Import_File 'modul mod_Import ausführen
' ausführen mit dem Currentdb -Objekt
db.Execute "DELETE * FROM tbl_Import_final" 'tbl_Import_final leeren
db.Execute "qry_tbl_Stueckliste_final", dbFailOnError 'Abfrage qry_tbl_Stueckliste_final durchführen
' Set db = Nothing
db.Execute "qry_Set_Level1", dbFailOnError 'Abfrage qry_Set_Leverl1 durchführen
Call Set_Stueckliste 'modul mod_Set_Stueckliste ausführen
'Call Set_Level_Eingabe 'modul mod_Set_Level_Eingabe ausführen
' überflüssig
'DoCmd.SetWarnings False 'Warnungen ausschalten
' Import-Tabellen leeren
SQLdelete = "DELETE * FROM tbl_Import_Stuecklisten_raw" 'Tabelle tbl_Import_Stuecklisten_raw leeren
' warum DoCmd?
'DoCmd.RunSQL SQLdelete
db.Execute SQLdelete
SQLdelete = "DELETE * FROM tmp_Hierarchie" 'Tabelle tmp_Hierarchie leeren
db.Execute SQLdelete
End Sub
Hallo Jürgen,
habe es jetzt so versucht, aber immer noch die gleiche Fehlermeldung. Er hängt bei
db.Execute "qry_Set_Level1", dbFailOnError 'Abfrage qry_Set_Leverl1 durchführen
Option Compare Database
Option Explicit
Private Sub cmd_Uebernehmen_Click()
' Option Explicit einschalten !!! dann muss zB SQLDelete deklariert werden
Dim db As DAO.Database
Dim SQLDelete As String
Set db = CurrentDb
' ruft eigenständige Prozedur auf
Call Import_File 'modul mod_Import ausführen
' ausführen mit dem Currentdb -Objekt
db.Execute "DELETE * FROM tbl_Import_final" 'tbl_Import_final leeren
db.Execute "qry_tbl_Stueckliste_final", dbFailOnError 'Abfrage qry_tbl_Stueckliste_final durchführen
db.Execute "qry_Set_Level1", dbFailOnError 'Abfrage qry_Set_Leverl1 durchführen
Call Set_Stueckliste 'modul mod_Set_Stueckliste ausführen
' Import-Tabellen leeren
SQLDelete = "DELETE * FROM tbl_Import_Stuecklisten_raw" 'Tabelle tbl_Import_Stuecklisten_raw leeren
db.Execute SQLDelete
SQLDelete = "DELETE * FROM tmp_Hierarchie" 'Tabelle tmp_Hierarchie leeren
db.Execute SQLDelete
End Sub
qry_Set_Level1
UPDATE tbl_Import_final SET tbl_Import_final.Stl_Ist = [Forms]![frmDialogImport]![txt_Stueckliste]
WHERE (((tbl_Import_final.Level)=1));
Gruss Atuatuca
Hallo,
eine mögliche Lösung könnte diese sein:
UPDATE tbl_Import_final
SET tbl_Import_final.Stl_Ist = EVAL("[Forms]![frmDialogImport]![txt_Stueckliste]")
WHERE (((tbl_Import_final.Level)=1));
Du könntest auch eine vollständig formulierte Parameterabfrage verwenden ...
PARAMETERS
[$Eintrag$] INT
;
UPDATE
tbl_Import_final
SET
Stl_Ist = [$Eintrag$]
WHERE
Level = 1
;
... und diese wie folgt verwenden:
ExecuteParamQdf "qry_Set_Level1", Forms!frmDialogImport!txt_Stueckliste
Die verwendete Hilfsfunktion findest Du hier:
Insert oder Update als Parameter-Abfrage (http://wiki.access-codelib.net/Insert_oder_Update_als_Parameter-Abfrage)
Hallo MaggieMay,
dein Code funktioniert.
Vielen Dank.
Gruss
Atuatuca
Hi,
Zitatdein Code funktioniert.
wobei der Ansatz von ebs17 natürlich höheres Nutzungspotenzial in sich trägt.