Datenerfassung mit Hilfe VON ... BIS
Hallo ACCperten,
Ich meine dieses Mal ein anspruchsvolleres Thema gefunden zu haben :).
Und zwar haben wir für jede Maschine eine Seriennummer (Primärschlüssel, Format Text).
Es gehören aber n Maschinen zu einem Projekt (Format Text).
In den aller meisten Fällen sind die Seriennummern fortlaufend (1000, 1001,1002 usw.), so dass ich mir die Frage gestellt habe, ob es vielleich möglich ist eine Textbox VON und eine andere BIS zu nennen.
Dort würde ich z. B. 1000 und 1002 eintragen.
Kann man einen VBA Code so stricken, dass er über eine Schleife auch die 1001 einträgt und noch dazu gehörige Angaben mit einfügt?
Solche dazugehörigen Angaben sind z. B. Listenpreise, Rabatte, Frachtkosten (alles Zahlformat).
Alle Eingaben würden sich in einer Tabelle befinden.
Hintergrund meiner Anfrage ist, dass ein Projekt schnell über hundert Maschinen haben kann, und wenn ich die Eingaben für jeden Datensatz extra machen muss, habe ich gleich keine Lust mehr ;).
Ich hoffe, dass ich mein Anliegen klar beschrieben habe.
Vielen Dank für Eure Hilfe im Vorraus.
Peter.
Antwort schreiben
Antwort 1 von lorf55 vom 04.02.2021, 00:14 Options
Hallo Peter,
Ich sag mal "Ja".
Das Anliegen habe ich verstanden, aber wo was rein soll nicht.
Gruß
lorf
Antwort 2 von Peter3011 vom 04.02.2021, 11:57 Options
Hallo Lorf,
sämtliche Eingabefelder befinden sich auf einer Registerkarte in einem Formular.
Darunter befindet sich auch gleich die Tabelle in die alle Daten rein sollen.
Die Textfelder tragen auch die selben Namen, wie die Spalten der Tabelle.
Ich hoffe, dass das weiterhilft.
Danke.
Peter
Antwort 3 von lorf55 vom 04.02.2021, 20:37 Options
Hallo Peter,
das ist für den Anfang nicht schlecht. Wir brauchen die Namen:
des Formulars,
der Registerkarte,
der Tabelle,
der Textfelder.
Denn müsste man noch auf der Registerkarte einen Button plazieren können, der den Code startet.
Und das Wichtigste ist natürlich, dass du an den Basic-Editor kommen kannst, damit du den Code einfügen kannst.
Irgendwie liest sich das für mich, als hättest du da fertige Software vor dir, der aber einige Features fehlen, und versuchst nun als letztes Glied in der Kette, was dran zu basteln. Das wird voraussichtlich nicht gelingen. Da würde ich mich an deiner Stelle denn besser an den Hersteller wenden.
Gruß
lorf
Antwort 4 von Peter3011 vom 05.02.2021, 18:18 Options
Hallo Lorf,
Name des Formulars: Frm_Sales
Name der Registerkarte: TabCtl0
Name der Tabelle: Tbl_KZ_Sales_Data
Namen der Textfelder: From, To (in diese Felder sollen die erste und die letzte Seriennummer rein), Project, Qty, List_price_per_unit_USD, Special_handling_costs_per_unit_USD, Estimated_freight_costs_per_unit_USD, Insurance_costs_per_unit_USD, Contracted_Value_per_unit_USD
Das mit dem Button habe ich schon, er heißt Data_Entry.
Mit VBA bin ich in Excel sehr vertraut aber in Access komme ich noch nicht klar.
Meine Datenbank ist 100% Eigenleistung :). Nachdem meine Abfragen aber stehen, geht es an die Prozessoptimierung mit VBA und außer dem Requery habe ich leider noch nichts in VBA zustande bekommen :(.
Danke für Eure Hilfe.
Peter
Antwort 5 von lorf55 vom 08.02.2021, 17:30 Options
Hallo Peter,
eine 1. Variante noch ohne Fehlerprüfung:
Zitat:
Private Sub Data_Entry_Click()
On Error GoTo Err_Data_Entry_Click
Dim rec1 As New ADODB.Recordset
rec1.Open "SELECT * from Tbl_KZ_Sales_Data", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
For prj = Forms!frm_sales!From To Forms!frm_sales!To
CurrentDb.Execute _
"INSERT INTO Tbl_KZ_Sales_Data (Project, Qty, List_price_per_unit_USD, Special_handling_costs_per_unit_USD, Estimated_freight_costs_per_unit_USD, Insurance_costs_per_unit_USD)" + _
"VALUES (" + Str(prj) + "," + _
Str(rec1!Qty) + "," + _
Str(rec1!List_price_per_unit_USD) + "," + _
Str(rec1!Special_handling_costs_per_unit_USD) + "," + _
Str(rec1!Estimated_freight_costs_per_unit_USD) + "," + _
Str(rec1!Insurance_costs_per_unit_USD) + _
");"
Next prj
rec1.Close
Exit_Data_Entry_Click:
Exit Sub
Err_Data_Entry_Click:
MsgBox Err.Description
Resume Exit_Data_Entry_Click
End Sub
Gruß
lorf
Antwort 6 von Peter3011 vom 10.02.2021, 11:46 Options
Danke Lorf,
probiere ich gleich mal aus.
Peter
Antwort 7 von Peter3011 vom 12.02.2021, 15:34 Options
Hallo Lorf,
habe mich intensiv damit beschäftigt, und ich denke, dass ich Dein Makro vom Ablauf her verstanden habe.
Jedoch habe ich noch folgende Probleme.
1. In die Spalte "Special handling costs" wird oft nichts eingetragen, so dass dort oft auch nichts steht, nicht einmal Null.
Dieser Umstand verursacht folgende Fehlermeldung: "Invalid use of Null"
Also habe ich die Spalte "Special handling costs" erst einmal rausgenommen, womit dieses Problem erst mal nach hinten geschoben wurde.
2. Nun erhalte ich aber eine Fehlermeldung, mit der ich nicht mehr klar komme:
"Number of query values and destination fields ar not the same."
Hast Du vielleicht ein Erklärung hierfür, denn ich habe nach und nach alle Spalten rausgenommen, so dass nur noch die Bestellnummern übrig blieben.
Ich vermute daher, das der Fehler daher kommt, dass das Makro die Bestellnummern nicht mit reinzieht.
Für Deinen Rat wäre ich sehr dankbar.
Peter
Ich
Antwort 8 von lorf55 vom 13.02.2021, 20:52 OptionsLösung
Hallo Peter,
die Fehlerprüfung auf NULL (bei leerem Feld) habe ich eingefügt.
Der Fehler Nr. 2 war wahrscheinlich ein Folgefehler, weil du in der Insert-Anweisung nur die Werteliste, aber nicht auch die "Feldnamenliste" bearbeitet hast.
Einen Fehler hatte ich auch noch drin, nämlich in der SELECT-Anweisung. Es wurde einfach alles selektiert und denn immer nur der 1. Datensatz genommen. Jetzt wird der
from-Datensatz selektiert und als
from+1-Project,
from+2-Project, usw. eingefügt.
Es wird
nicht geprüft, ob die
Project-Nr schon mal da ist. Da musst du denn aufpassen, falls die
Project-Nr nur einmal drin stehen darf.
Private Sub Data_Entry_Click()
On Error GoTo Err_Data_Entry_Click
Dim rec1 As New ADODB.Recordset
rec1.Open "SELECT * from Tbl_KZ_Sales_Data WHERE Project=" & _
Forms!frm_sales!From, CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
For prj = Forms!frm_sales!From + 1 To Forms!frm_sales!To
CurrentDb.Execute _
"INSERT INTO Tbl_KZ_Sales_Data (" + _
"Project, Qty, List_price_per_unit_USD, Special_handling_costs_per_unit_USD, " + _
"Estimated_freight_costs_per_unit_USD, Insurance_costs_per_unit_USD)" + _
"VALUES (" + Str(prj) + "," + _
Str(IIf(IsNull(rec1!Qty), "0", _
rec1!Qty)) + "," + _
Str(IIf(IsNull(rec1!List_price_per_unit_USD), "0", _
rec1!List_price_per_unit_USD)) + "," + _
Str(IIf(IsNull(rec1!Special_handling_costs_per_unit_USD), "0", _
rec1!Special_handling_costs_per_unit_USD)) + "," + _
Str(IIf(IsNull(rec1!Estimated_freight_costs_per_unit_USD), "0", _
rec1!Estimated_freight_costs_per_unit_USD)) + "," + _
Str(IIf(IsNull(rec1!Insurance_costs_per_unit_USD), "0", _
rec1!Insurance_costs_per_unit_USD)) + _
");"
Next prj
rec1.Close
Exit_Data_Entry_Click:
Exit Sub
Err_Data_Entry_Click:
MsgBox Err.Description
Resume Exit_Data_Entry_Click
End Sub
Gruß
lorf
Antwort 9 von Peter3011 vom 18.02.2021, 11:08 Options
Danke Lorf und entschuldige bitte meine verspätete Antwort.
Ich bin oft unterwegs und habe leider nicht immer Internetzugang.
Ich probiere Deine Variante heute noch aus.
Danke Dir.
Peter
Antwort 10 von Peter3011 vom 19.02.2021, 16:10 Options
Hallo Lorf,
ich glaube, ich habe mein Problem gefunden, weshalb Deine Makros bei mir nicht funktionieren.
Die beiden Textfelder, in die die Seriennummern reingeschrieben werden, heißen "From" und "To.
In der Tabelle "Tbl_KZ_Sales_Data" wo die Seriennummern mit reingeschrieben werden sollen gibt es die Spalten aber nicht.
Es gibt dort nur die Spalte "Seriennummer", wo praktisch die fortlaufenden Seriennummern aus den Textfeldern "From" und "To" eingetragen werden müssten.
Ich glaube, dass deshalb hier immer eine Fehlermeldung kommt:
Rec1.Open "Select * from Tbl_KZ_Sales_Data where Project =" & _
Forms!Frm_Sales!From, CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
Die Fehlermeldung lautet:
Data type mismatch in criteria expression.
Ich habe wirklich versucht, das Makro zu ändern, aber leider fällt mir Accessprogrammierung wesentlich schwerer als in Excel.
Könntest Du mir bitte noch mal helfen?
Danke
Peter
Antwort 11 von lorf55 vom 19.02.2021, 20:18 Options
Hallo Peter,
stimmt, Project ist ja eine Zeichenkette. Ich habe nur die Zahlen gesehen und irgendwann angenommen, dass es eine Zahl ist.
Deshalb muss es an der Stelle so aussehen:
rec1.Open "SELECT * from Tbl_KZ_Sales_Data " & _
WHERE Project='" & trim(Forms!frm_sales!From) & "'", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
Das trim() entfernt Leerzeichen am Anfang und Ende der Zeichenkette.
Gruß
lorf
Antwort 12 von Peter3011 vom 03.03.2021, 11:27 Options
Hallo Lorf,
zunächst entschuldige ich mich für meine späte Antwort, aber ich war mal wieder unterwegs.
Ich habe auch mal meine Nase in die Bücher gesteckt und dabei folgenden Lösung gefunden, die auch gleich funktioniert hat.
Private Sub test()
On Error GoTo Err_Command10_Click
Dim rst As ADODB.Recordset
Dim conn As ADODB.Connection
Set rst = New ADODB.Recordset
Set conn = CurrentProject.AccessConnection
'Application.Forms("Form1").Controls("txtcocktail").Value = "Hiho"
rst.Open "table1", conn, adOpenKeyset, adLockOptimistic
If rst.Supports(adAddNew) Then
MsgBox ("hi")
End If
For ID = Forms!Form1!txtcocktail To Forms!Form1!txtend
With rst
If .Supports(adAddNew) Then
.AddNew
!Cocktail = ID
!qty = IIf(IsNull(Forms!Form1!txtqty), "0", Forms!Form1!txtqty)
!price = IIf(IsNull(Forms!Form1!txtprice), "0", Forms!Form1!txtprice)
.Update
End If
End With
Next ID
rst.Close
Set rst = Nothing
Exit_Command10_Click:
Exit Sub
Err_Command10_Click:
MsgBox Err.Description
Resume Exit_Command10_Click
End Sub
Was hälst Du davon?
Gruß
Peter
Antwort 13 von lorf55 vom 04.03.2021, 21:48 Options
Hallo Peter,
ich habe nur noch eine Frage. Wie passt:
1.
Zitat:
dabei folgenden Lösung gefunden, die auch gleich funktioniert hat.
2.
Zitat:
!Cocktail = ID
!qty = IIf(IsNull(Forms!Form1!txtqty), "0", Forms!Form1!txtqty)
!price = IIf(IsNull(Forms!Form1!txtprice), "0", Forms!Form1!txtprice)
mit
3.
Zitat:
Name des Formulars: Frm_Sales
Name der Registerkarte: TabCtl0
Name der Tabelle: Tbl_KZ_Sales_Data
Namen der Textfelder: From, To (in diese Felder sollen die erste und die letzte Seriennummer rein), Project, Qty, List_price_per_unit_USD, Special_handling_costs_per_unit_USD, Estimated_freight_costs_per_unit_USD, Insurance_costs_per_unit_USD, Contracted_Value_per_unit_USD
aus Antwort 4 zusammen?
Oder bist du vielleicht schon beim nächsten Problem?
Ansonsten - nimm was funktioniert. ;-)
Gruß
lorf
Antwort 14 von Peter3011 vom 06.03.2021, 13:08 Options
Hallo Lorf,
das ist einfach zu erklären.
Wenn ich etwas Neues ausprobiere, baue ich mir immer einfache testdateien.
Und da ich mir die Lösung aus einem Accessbuch zusammengebaut habe, habe ich auch gleich die Bezeichnungen übernommen.
Deshalb steht da Cocktail z. B.
Abgewandelt habe ich das Makro dann in dem richtigen File, für den Du die Bezeichnungen hast. Also heißt Cocktail im richtigen File Bestellnummer.
Ist das Makro für Dich verständlich. Leider habe ich momentan keinen Serverzugang aber stelle Dir die abgewandelt Form nächste Woche noch mal rein.
Ohne Deine Hilfe wäre ich nie so weit gekommen. Du bist mein Held.
Gruß und ein schönes Wochenende.
Peter
Antwort 15 von RaHi vom 06.03.2021, 17:44 Options
Hallo lorf,
ich finde deine Lösung gelungen. Ich verstehe allerdings nicht warum du nicht zweimal cursorgesteuert die Recordset bearbeitest. Das Execute-Kommando verursacht höhere Kosten (was bei diesen Schleifenanzahlen wahrscheinlich zu vernachlässigen ist). Ich habe mal deinen Code entsprechend angepasst:
Private Sub data_entry_Click()
On Error GoTo Err_Data_Entry_Click
Dim rec1 As New ADODB.Recordset
Dim rec2 As New ADODB.Recordset
DoCmd.RunCommand acCmdSaveRecord
rec1.Open "SELECT * from Tbl_KZ_Sales_Data WHERE Project=" & _
Forms!frm_sales!from, CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
rec2.Open "SELECT * from Tbl_KZ_Sales_Data ", CurrentProject.Connection, adOpenDynamic, adLockOptimistic
For prj = Forms!frm_sales!from + 1 To Forms!frm_sales!to
rec2.AddNew
rec2!Project = Str(prj)
rec2!qty = Nz(rec1!qty, 0)
rec2!List_price_per_unit_USD = Nz(rec1!List_price_per_unit_USD, 0)
rec2!Special_handling_costs_per_unit_USD = Nz(rec1!Special_handling_costs_per_unit_USD, 0)
rec2!Estimated_freight_costs_per_unit_USD = Nz(rec1!Estimated_freight_costs_per_unit_USD, 0)
rec2!Insurance_costs_per_unit_USD = Nz(rec1!Insurance_costs_per_unit_USD, 0)
rec2.Update
Next prj
Forms!frm_sales.Requery
Exit_Data_Entry_Click:
On Error Resume Next
rec1.Close
rec2.Close
Exit Sub
Err_Data_Entry_Click:
MsgBox Err.Description
Resume Exit_Data_Entry_Click
End Sub
Weiterhin habe ich den "acCmdSaveRecord" eingebaut, um zu verhindern, dass der aktuelle Datensatz nach der Erzeugnung wieder rückgängig gemacht werden kann. Das "requery" habe ich eingebaut, damit man auch den Erfolg direkt sieht.
Ich würde evtl. ein völlig ungebundes Formular nehmen und alle Werte aus dem Formular nehmen, statt aus rec1, das ist aber geschmackssache.
Was hältst du davon, Lorf?
Gruß
Ralf
Antwort 16 von lorf55 vom 07.03.2021, 19:43 Options
@Peter:
das rst.Supports kannst du sicherlich weglassen, denn die Tabellen unterstützen das Einfügen.
@RaHi:
Du machst nunmal lieber immer alles mit VBA und das sieht auch immer recht professionell aus.
Meine Variante war eher darauf bedacht, so wenig VBA wie möglich zu benutzen um es
1. "einfach" zu halten und
2. um es portabel zu halten (vielleicht macht Peter mal was mit PHP und ODBC auf einem XAMPP-server oder mit Java und JDBC oder mit VC++, das kann ja auch ADO ...) und
3. weil SQL-Befehle ( hier INSERT) immer schneller sind als VBA (ist zumindest meine Meinung).
Das Argument das "Execute-Kommando verursacht höhere Kosten" kann ich deshalb nicht nachvollziehen und auch deshalb nicht, weil auch meine Variante erst die Daten in rec1 einliest und sie denn wie deine N-mal verteilt (eben nur mit INSERT).
"acCmdSaveRecord" hätte ich mir geschenkt, denn es gibt immer Hektiker, die erst klicken und denn denken und denn gerne rückgängig machen wollen.
Aber letzten Endes ist es Streit um Kaisers Bart, denn eigentlich interessieren in diesem Forum Geschwindigkeit und Kosten nicht . Hier geht es eigentlich nur um "geht" oder "geht nicht" bzw. "kann ich" oder "kann ich nicht".
Na gut, wie immer hat jeder eine andere Meinung und das waren meine 2 1/2 cent zum Samstagabend.
Denn bis demnächst
lorf
Antwort 17 von Peter3011 vom 24.03.2021, 14:50 Options
Hallo Lorf,
danke für Deine Hinweise. Ich habe mir nun ein paar Bücher zugelegt, die mir Eure Programmierungen verständlich gemacht haben.
Ich bedanke mich noch einmal für Deine ausdauernde Hilfe. Es hat mich dazu angespornt, mich mit Access noch weiter zu beschäftigen.
@ RaHi
Deine Lösung arbeitet gut bei mir und ich habe sie in ein anderes Makro eingebaut.
Public Sub test()
On Error GoTo Err_Command10_Click
'Declarations
Dim rst1 As ADODB.Recordset
Dim rst2 As ADODB.Recordset
Dim conn As ADODB.Connection
Set rst1 = New ADODB.Recordset
Set rst2 = New ADODB.Recordset
rst1.Open "Tbl_Specification_codes_accumulated", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
rst2.Open "Tbl_Specification_codes_separated", CurrentProject.Connection, adOpenDynamic, adLockOptimistic
Do While Not rst1.EOF
If IsNull(Len(rst1!Specifications)) Then
GoTo end1
Else
For start = 1 To Len(rst1!Specifications) / 4
rst2.AddNew
rst2!Order_ID = rst1!Order_ID
rst2!Order= rst1!Order
rst2!Base_Code = rst1!Base_Code
rst2!Specifications = Mid(rst1!Specifications, (start - 1) * 4 + 1, 4)
Next
End If
end1:
rst1.MoveNext
Loop
rst1.Close
Exit_Command10_Click:
Exit Sub
Err_Command10_Click:
MsgBox Err.Description
Resume Exit_Command10_Click
End Sub
Es geht darum, die Spezifikationscodes, die hier alle fortlaufend erfasst werden, zu vereinzeln.
Leider funktioniert es nicht wenn das Ergebnis von
Len(rst1!Specifications) / 4
eine ungerade Zahl ergibt z. B. 108/4=27.
In diesem Moment trägt das Makro nicht mehr den allerletzten Wert ein, obwohl dieser eindeutig noch erfasst wird.
Könnt Ihr mir da noch mal kurz helfen?
Gruß
Peter
Antwort 18 von RaHi vom 24.03.2021, 17:55 Options
Hallo Peter,
deine Funktion ist etwas "unsauber". Hier eine Korrektur mit ein paar Anmerkungen. An den Anfang des Moduls nimm bitte die Zeile
option Explicit
auf, die zwingt dich dazu jede Variable zu deklarieren und bewahrt dich vor bösen Tippfehlern.
Public Sub test()
On Error GoTo Err_Command10_Click
'Declarations
Dim start As Long ' Jede Variable deklarieren und "Option explicit" in den Kopf des Moduls!
Dim rst1 As ADODB.Recordset
Dim rst2 As ADODB.Recordset
'Dim conn As ADODB.Connection 'RaHi: auskommentiert, da nicht verwendet
Set rst1 = New ADODB.Recordset
Set rst2 = New ADODB.Recordset
rst1.Open "Tbl_Specification_codes_accumulated", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
rst2.Open "Tbl_Specification_codes_separated", CurrentProject.Connection, adOpenDynamic, adLockOptimistic
While Not rst1.EOF
If Not IsNull(rst1!Specifications) Then ' RaHi: goto-Programme sind schwer lesbar, also raus damit! Len (...) kann nicht NULL sein.
For start = 1 To Len(rst1!Specifications) / 4
rst2.AddNew
rst2!Order_ID = rst1!Order_ID
rst2!Order = rst1!Order
rst2!Base_Code = rst1!Base_Code
rst2!Specifications = Mid(rst1!Specifications, (start - 1) * 4 + 1, 4)
rst2.Update 'RaHi: ohne Update kein guter Weg!
Next
End If
rst1.MoveNext
Wend
Exit_Command10_Click:
'RaHi: im Exitbereich keine Fehlerbehandlung mehr zulassen, sonst kommst du in eine Endlosschleife
On Error Resume Next
rst1.Close ' RaHi: schließen der Recordsets auch im Fehlerfall sinnvoll
rst2.Close ' RaHi: ohne close geht es schief!
Exit Sub
Err_Command10_Click:
MsgBox Err.Description
Resume Exit_Command10_Click
End Sub
Prüfe mal, ob damit dein Problem gelöst ist.
Gruß
Ralf
Antwort 19 von Peter3011 vom 24.03.2021, 18:30 Options
RaHi,
ich bin Dir zu ewigen Dank verpflichtet :).
Es funktioniert absolut perfekt.
Ich danke Dir, Du hast den Tag gerettet.
Einen schönen Abend noch.
Peter