Supportnet / Forum / Datenbanken
Automatische Nummernvergabe
Frage
Hallo,
kann mir bitte jemand sagen, was ich machen muss, dass jeweils beim Erstellen eines neuen Datensatzes automatisch einem Feld eine bestimmt neue Nummer zugeweist wird. Die Nummer soll mit "GQM" beginnen, dann "07" für das Jahr 2007 folgen und dann "001". (bsp. GQM07001, GQM07002...)
Die Access-Datenbank soll über einen SQL-Server laufen und von mehreren Benutzern gleichzeitig benutzt werden können.
Ich habe die Frage schon mal gestellt, aber da hat mir irgentwie keiner so richtig weiterhelfen können. Ich hab dann mal mit nem "couter" usw versucht aber des hat bei mir überhaupt nicht funktioniert. Ein weiteres Problem ist das bereits ca 120 Datensätze in der Datenbank stehen und somit der Zähler nicht bei 1 anfängt.
Vielleicht muss ich auch dazu sagen, dass ich MS Access07 hab und das Beispiel, das ich hatte, mit dem Couter in Access00 war.
Was soll ich nun machen????
Schon mal danke für die Hilfe.
Tobias
[*][sup][i]
*Threadedit* 23:29:07
Admininfo: Führ bitte einen Thread nicht fort indem du Weitere eröffnest, und vermeide Mehrfachanfragen. Die Datenbank und User werden es dir danken. Siehe [u][url=https://supportnet.de/faqsthread/840]FAQ 2.[/url][/u][/i][/sup]
Antwort 1 von Teddy7
Hallo Tobias !
Wie meistens gibt es mehrere Lösungen.
1) Man kann eine eigene Tabelle anlegen, da die letzte vergebene Nummer hinterlegen und dann bei Neuanlage eines Datensatzes mit VBA-Programmierung diese Tabelle lesen (und damit sperren), den nächsten Schlüssel ermitteln und zurückschreiben und in den Datensatz übernehmen.
2) Die Variante mit dlookup den letzten Schlüssel zu ermitteln ist hier nicht anzuwenden, weil es dabei in einer Mehr-User-Anwendung zu Überschneidungen kommen könnte.
3) die "russische" Lösung: Man legt 3 Felder an, füllt das erste mit der Konstanten GQM, das zweite mit year(date) und das dritte macht man als autowert. Diese Lösung ist dann zu empfehlen, wenn der Schlüssel nicht fortlaufend nachweisbar sein muß, weil der Autowert nach löschen eines Satzes diesen Wert nicht wieder vergibt (es sei denn es war der letzte Satz und die Tabelle wird zwischendurch komprimiert).
Gruß
Teddy
Wie meistens gibt es mehrere Lösungen.
1) Man kann eine eigene Tabelle anlegen, da die letzte vergebene Nummer hinterlegen und dann bei Neuanlage eines Datensatzes mit VBA-Programmierung diese Tabelle lesen (und damit sperren), den nächsten Schlüssel ermitteln und zurückschreiben und in den Datensatz übernehmen.
2) Die Variante mit dlookup den letzten Schlüssel zu ermitteln ist hier nicht anzuwenden, weil es dabei in einer Mehr-User-Anwendung zu Überschneidungen kommen könnte.
3) die "russische" Lösung: Man legt 3 Felder an, füllt das erste mit der Konstanten GQM, das zweite mit year(date) und das dritte macht man als autowert. Diese Lösung ist dann zu empfehlen, wenn der Schlüssel nicht fortlaufend nachweisbar sein muß, weil der Autowert nach löschen eines Satzes diesen Wert nicht wieder vergibt (es sei denn es war der letzte Satz und die Tabelle wird zwischendurch komprimiert).
Gruß
Teddy
Antwort 2 von lleopard
Hi Tobias,
wie stellst du denn die Verbindung zum SQL Server her? Ich nehme mal an per ODBC, oder?
Dein Problem löst du am besten über eine kleine VBA-Routine.
Das besondere bei Zugriffen von Access auf SQL-Datenbanken ist eigentlich nur, daß man beim öffnen eines Recordsets über Currentdb.OpenRecordset die Parameter mit angeben muß (siehe Hilfe zu OpenRecordset ... zB
Currentdb.OpenRecordset (Tabellenname, dbOpenDynaset, dbSQLPassThrough)
Damit solltest du dann die Berechtigung haben auch in die Tabelle zu schreiben.
Wenn du nun einen neuen DS anfügen willst, dann gehst du alle Werte durch
zB
rs.AddNew
rs!Name = Name
...
rs!ID = "GQM" & Format (Date,"yy") & [eine laufende Nummer]
rs.Update 1, 0
Damit hast du den DS erzeugt.
Nun zu der Frage wo die laufende Nummer herkommen soll...
Eine Möglichkeit ist in einer separaten Tabelle festzuhalten was der letzte Wert war. Den setzt du dann um 1 hoch und nimmst den dann für die laufende Nummer. Eine andere Möglichkeit ist eine Abfrage zu basteln, die dir den Max-Wert ausspuckt, den du dann wieder um 1 hochsetzen mußt.
also mal angenommen du hast als letztes GQM07123 eingetragen. Möglichweise hast du ja schon Werte aus mehreren Jahren. Dann filterst du einfach auf die DS aus dem aktuellen jahr, und dann auf den höchsten Wert. Wie das geht?
Neue Abfrage. Gruppierung aktivieren
SQL - Tabelle hinterlegen. Das Feld mit der ID (also das wo die GQM-Werte drinne stehen) brauchst du 2 mal.
Filter1: Mid([ID],4,2)
Kriterium: Format(Date(),"yy")
Filter2: Max(Right([ID],3)
Diese Abfrage kann nur einen Wert liefern, wenn alles richtig hinterlegt ist.
Nun brauchst du nur noch auf diesen Wert zurückzugreifen.
zB
ID = DLookUp("Filter2","Abfrage")
ID = ID + 1
und schon sieht die Zeile:
rs!ID = "GQM" & Format (Date,"yy") & [eine laufende Nummer]
so aus:
rs!ID = "GQM" & Format (Date,"yy") & ID
Gruß leo
wie stellst du denn die Verbindung zum SQL Server her? Ich nehme mal an per ODBC, oder?
Dein Problem löst du am besten über eine kleine VBA-Routine.
Das besondere bei Zugriffen von Access auf SQL-Datenbanken ist eigentlich nur, daß man beim öffnen eines Recordsets über Currentdb.OpenRecordset die Parameter mit angeben muß (siehe Hilfe zu OpenRecordset ... zB
Currentdb.OpenRecordset (Tabellenname, dbOpenDynaset, dbSQLPassThrough)
Damit solltest du dann die Berechtigung haben auch in die Tabelle zu schreiben.
Wenn du nun einen neuen DS anfügen willst, dann gehst du alle Werte durch
zB
rs.AddNew
rs!Name = Name
...
rs!ID = "GQM" & Format (Date,"yy") & [eine laufende Nummer]
rs.Update 1, 0
Damit hast du den DS erzeugt.
Nun zu der Frage wo die laufende Nummer herkommen soll...
Eine Möglichkeit ist in einer separaten Tabelle festzuhalten was der letzte Wert war. Den setzt du dann um 1 hoch und nimmst den dann für die laufende Nummer. Eine andere Möglichkeit ist eine Abfrage zu basteln, die dir den Max-Wert ausspuckt, den du dann wieder um 1 hochsetzen mußt.
also mal angenommen du hast als letztes GQM07123 eingetragen. Möglichweise hast du ja schon Werte aus mehreren Jahren. Dann filterst du einfach auf die DS aus dem aktuellen jahr, und dann auf den höchsten Wert. Wie das geht?
Neue Abfrage. Gruppierung aktivieren
SQL - Tabelle hinterlegen. Das Feld mit der ID (also das wo die GQM-Werte drinne stehen) brauchst du 2 mal.
Filter1: Mid([ID],4,2)
Kriterium: Format(Date(),"yy")
Filter2: Max(Right([ID],3)
Diese Abfrage kann nur einen Wert liefern, wenn alles richtig hinterlegt ist.
Nun brauchst du nur noch auf diesen Wert zurückzugreifen.
zB
ID = DLookUp("Filter2","Abfrage")
ID = ID + 1
und schon sieht die Zeile:
rs!ID = "GQM" & Format (Date,"yy") & [eine laufende Nummer]
so aus:
rs!ID = "GQM" & Format (Date,"yy") & ID
Gruß leo
Antwort 3 von Mrfivejunior
hallo,
leider hats bei mir etwas länger gedauert.
Ich habs jetzt so gelöst:
Private Sub Befehl37_Click()
Dim rsInTable As New ADODB.Recordset
Dim OldGQMNr As String
Dim NewGQMNR As String
Dim LastGQMNR As String
Dim YearGQMNR As Byte
Dim ActualYear As Byte
Dim ReturnValue As String
ActualYear = Mid(CStr(Year(Now())), 3)
Set rsInTable = New ADODB.Recordset ' Recordset-Objekt instanziieren
rsInTable.ActiveConnection = CurrentProject.Connection ' Connection zuweisen
rsInTable.CursorType = adOpenDynamic ' Zugriffsmodus für DB-Cursor
rsInTable.LockType = adLockOptimistic
rsInTable.Open "SELECT Last(Stammdaten.[Stammdaten-ID]) AS [Stammdaten-ID], Last(Stammdaten.[GQM-Nr]) AS [GQM-Nr] " & _
"FROM Stammdaten " & _
"ORDER BY Last(Stammdaten.[GQM-Nr]);"
OldGQMNr = [rsInTable]![GQM-Nr]
If IsNull(OldGQMNr) Then
Me.QM_Nr = "Fehler"
Exit Sub
Else
LastGQMNR = Mid(OldGQMNr, 6)
YearGQMNR = Mid(OldGQMNr, 4, 2)
If ActualYear = YearGQMNR Then 'Neuer Datensatz ist im gleichen Jahr -> Nummer + 1
ReturnValue = "GQM" & Mid((YearGQMNR + 100), 2) & Mid((LastGQMNR + 1000 + 1), 2)
Else
ReturnValue = "GQM" & Mid((ActualYear + 100), 2) & "001"
End If
Me.QM_Nr = ReturnValue
End If
rsInTable.Close
Set rsInTable = Nothing
End Sub
leider hats bei mir etwas länger gedauert.
Ich habs jetzt so gelöst:
Private Sub Befehl37_Click()
Dim rsInTable As New ADODB.Recordset
Dim OldGQMNr As String
Dim NewGQMNR As String
Dim LastGQMNR As String
Dim YearGQMNR As Byte
Dim ActualYear As Byte
Dim ReturnValue As String
ActualYear = Mid(CStr(Year(Now())), 3)
Set rsInTable = New ADODB.Recordset ' Recordset-Objekt instanziieren
rsInTable.ActiveConnection = CurrentProject.Connection ' Connection zuweisen
rsInTable.CursorType = adOpenDynamic ' Zugriffsmodus für DB-Cursor
rsInTable.LockType = adLockOptimistic
rsInTable.Open "SELECT Last(Stammdaten.[Stammdaten-ID]) AS [Stammdaten-ID], Last(Stammdaten.[GQM-Nr]) AS [GQM-Nr] " & _
"FROM Stammdaten " & _
"ORDER BY Last(Stammdaten.[GQM-Nr]);"
OldGQMNr = [rsInTable]![GQM-Nr]
If IsNull(OldGQMNr) Then
Me.QM_Nr = "Fehler"
Exit Sub
Else
LastGQMNR = Mid(OldGQMNr, 6)
YearGQMNR = Mid(OldGQMNr, 4, 2)
If ActualYear = YearGQMNR Then 'Neuer Datensatz ist im gleichen Jahr -> Nummer + 1
ReturnValue = "GQM" & Mid((YearGQMNR + 100), 2) & Mid((LastGQMNR + 1000 + 1), 2)
Else
ReturnValue = "GQM" & Mid((ActualYear + 100), 2) & "001"
End If
Me.QM_Nr = ReturnValue
End If
rsInTable.Close
Set rsInTable = Nothing
End Sub

