Supportnet / Forum / Datenbanken
Standardwert - Im neuen Datensatz den Wert des letzten Datensatzes eintragen
Frage
Da das Posting für meine Frage schon geschlossen wurde, hier nochmal die Lösung für alle die das gleiche Problem haben:
Dank OliverV hat's mit folgendem Befehl keklappt:
[code]
=DomLetzterWert("[Feldname]";"[Tabellenname]")
[/code]
(ich hoffe ich hab's richtig geschrieben)
Diesen Befehl einfach im Formularentwurf in die Feldeigenschaften -> Standardwert eingeben und fertig.
Jetzt werden die letzten Werte auch beim neu Öffnen des Formulares angezeigt.
Besten Dank
Antwort 1 von Koebi
Grüezi
Dom-Funktionen sind in der Regel nicht besonders schnell.
Es geht auch anders. Nämlich so, wie es donkarl in der Access-FAQ beschreibt, unter Punkt 4.22
www.donkarl.com/
Gruss
Köbi
Dom-Funktionen sind in der Regel nicht besonders schnell.
Es geht auch anders. Nämlich so, wie es donkarl in der Access-FAQ beschreibt, unter Punkt 4.22
www.donkarl.com/
Gruss
Köbi
Antwort 2 von El Bobbele
Hallo!
Die Sache mit den Standardwerten hat mich auf die Idee zu einer Funktion gebracht, die selbständig alle Felder eines Formulars mit den Daten aus der dazugehörigen Datenherkunft versieht.
FormObject
Nimmt das Formular entgegen, dessen Standardwerte gesetzt werden sollen.
Filter
Optionaler Filter, um den Datensatz mit den Standardwerten zu bestimmen. Ohne Filter wird der erste Datensatz aus der Datenherkunft des Formulars herangezogen.
ExcludeFields
Optionale Liste von Feldnamen, die beim Setzen der Standardwerte nicht berücksichtigt werden sollen. Mehrere Feldnamen müssen mit Komma getrennt werden. Zwischen Kommas und Feldnamen dürfen keine Leerzeichen vorkommen.
Beispiele:
Standardwerte aller Felder des Formulars auf den ersten Datensatz der Datenherkunft festlegen
Standardwerte aller Felder des Formulars auf einen gefilterten Datensatz festlegen
Standardwerte aller Felder des Formulars auf einen gefilterten Datensatz festlegen, "Beispielfeld1" und "Beispieldatum1" werden ignoriert
Die Funktion sollte möglichst im "Nach Aktualisieren"-Ereignis des Formulars aufgerufen werden, wenn der zuvor gespeicherte Datensatz als Grundlage dienen soll.
Es würde mich freuen, wenn das irgendjemand gebrauchen kann. Wenn nicht, auch gut. :-)
Gruss
El Bobbele
Die Sache mit den Standardwerten hat mich auf die Idee zu einer Funktion gebracht, die selbständig alle Felder eines Formulars mit den Daten aus der dazugehörigen Datenherkunft versieht.
SetDefaults (FormObject, [Filter], [ExcludeFields])
FormObject
Nimmt das Formular entgegen, dessen Standardwerte gesetzt werden sollen.
Filter
Optionaler Filter, um den Datensatz mit den Standardwerten zu bestimmen. Ohne Filter wird der erste Datensatz aus der Datenherkunft des Formulars herangezogen.
ExcludeFields
Optionale Liste von Feldnamen, die beim Setzen der Standardwerte nicht berücksichtigt werden sollen. Mehrere Feldnamen müssen mit Komma getrennt werden. Zwischen Kommas und Feldnamen dürfen keine Leerzeichen vorkommen.
Beispiele:
Standardwerte aller Felder des Formulars auf den ersten Datensatz der Datenherkunft festlegen
SetDefaults Me
Standardwerte aller Felder des Formulars auf einen gefilterten Datensatz festlegen
SetDefaults Me, "ID = " & Me.ID
Standardwerte aller Felder des Formulars auf einen gefilterten Datensatz festlegen, "Beispielfeld1" und "Beispieldatum1" werden ignoriert
SetDefaults Me, "ID = " & Me.ID, "Beispielfeld1,Beispieldatum1"
Die Funktion sollte möglichst im "Nach Aktualisieren"-Ereignis des Formulars aufgerufen werden, wenn der zuvor gespeicherte Datensatz als Grundlage dienen soll.
Public Function SetDefaults(FormObject As Form, _
Optional Filter As Variant, _
Optional ExcludeFields As String) As Boolean
Dim db As Database
Dim rec As Recordset
Dim recFilter As Recordset
Dim fld As Field
Dim ctl As Control
Dim blnResult As Boolean
Const PROPERTY_NOT_SUPPORTED = 438
On Error GoTo Err_SetDefaults
If Len(FormObject.RecordSource) > 0 Then
Set db = CurrentDb
Set rec = db.OpenRecordset(FormObject.RecordSource, dbOpenSnapshot)
'Filter anwenden, wenn vorhanden
If Not IsMissing(Filter) Then
rec.Filter = Filter
End If
'Recordset mit aktiviertem Filter neu öffnen
Set recFilter = rec.OpenRecordset(dbOpenSnapshot)
If Not recFilter.EOF Then
'Felder des Recordsets durchlaufen
For Each fld In recFilter.Fields
'Prüfen auf Ausschlussfeld
If InStr("," & ExcludeFields & ",", "," & fld.Name & ",") = 0 Then
'Steuerelemente des Formulars durchlaufen
For Each ctl In FormObject.Controls
'Steuerelement.Steuerelementinhalt = Feld.Name?
If ctl.ControlSource = fld.Name Then
If fld.Type = dbText Or fld.Type = dbMemo Then
'Text-Datentypen
ctl.DefaultValue = Nz("""" + fld.Value + """", "")
ElseIf fld.Type = dbDate Then
'Datum-Datentyp
ctl.DefaultValue = Nz(Format(fld.Value, "\#mm\/dd\/yyyy\#"), "")
Else
'Sonstige Datentypen
ctl.DefaultValue = Nz(fld.Value, "")
End If
End If
Next
End If
Next
End If
End If
blnResult = True
Exit_SetDefaults:
Set rec = Nothing
Set recFilter = Nothing
Set db = Nothing
Exit Function
Err_SetDefaults:
If Err.Number <> PROPERTY_NOT_SUPPORTED Then
'Unerwarteter Fehler, Abbruch
MsgBox Err.Number & ": " & Err.Description, vbCritical
blnResult = False
Resume Exit_SetDefaults
Else
'Nur bei Steuerelementen, die kein Steuerelementinhalt unterstützen
Resume Next
End If
End Function
Es würde mich freuen, wenn das irgendjemand gebrauchen kann. Wenn nicht, auch gut. :-)
Gruss
El Bobbele
Antwort 3 von Koebi
Grüezi El Bobbele
Nicht schlecht, Deine Funktion. Gratulation und besten Dank.
Ein Hinweis noch. Ich habe ein Zeitfeld, Format 24Stunden. Hier funktioniert es nicht. Bevor ich mir meinen löchrigen Kopf zerbreche, weisst Du vielleicht, wie dieser Feldtyp noch in die Funktion einzubauen ist?
Gruss
Köbi
Nicht schlecht, Deine Funktion. Gratulation und besten Dank.
Ein Hinweis noch. Ich habe ein Zeitfeld, Format 24Stunden. Hier funktioniert es nicht. Bevor ich mir meinen löchrigen Kopf zerbreche, weisst Du vielleicht, wie dieser Feldtyp noch in die Funktion einzubauen ist?
Gruss
Köbi
Antwort 4 von ElBobbele
Hi Köbi!
Danke für die Resonanz und für die Bugmeldung! :-)
Du hast Recht, mit Zeitformaten kommt die Funktion noch nicht klar. Ich habe die Format-Eigenschaft des Formularfeldes nicht berücksichtigt. Sinngemäß müsste demnach diese Zeile
ungefähr so heissen:
Ob das reicht, kann ich aber erst heute abend testen und komplett ausformulieren.
Gruss
El Bobbele
Danke für die Resonanz und für die Bugmeldung! :-)
Du hast Recht, mit Zeitformaten kommt die Funktion noch nicht klar. Ich habe die Format-Eigenschaft des Formularfeldes nicht berücksichtigt. Sinngemäß müsste demnach diese Zeile
ctl.DefaultValue = Nz(Format(fld.Value, "#mm/dd/yyyy#"), "")
ungefähr so heissen:
ctl.DefaultValue = Nz("#" + Format(fld.Value, ctl.Format) + "#", "")
Ob das reicht, kann ich aber erst heute abend testen und komplett ausformulieren.
Gruss
El Bobbele
Antwort 5 von Koebi
Grüezi El Bobbele
Das funktioniert leider nicht. Das heisst, jetzt klappt die Anzeige beim Zeitfeld, Format 24Stunden, dafür bei den Datumsfeldern nicht mehr.
Hast Du noch eine gute Idee?
Gruss
Köbi
Das funktioniert leider nicht. Das heisst, jetzt klappt die Anzeige beim Zeitfeld, Format 24Stunden, dafür bei den Datumsfeldern nicht mehr.
Hast Du noch eine gute Idee?
Gruss
Köbi
Antwort 6 von ElBobbele
Hallo Köbi!
Ja, da steckt der Teufel im Detail. Zwischenzeitlich hatte ich etwas experimentiert und bin dabei noch auf Schwierigkeiten gestoßen. Wenn du das Datum auf "Datum, kurz" formatierst, dann heisst das in VBA "Short Date". Beim Auswerten des Ausdrucks schaut Access dann in die Windows Systemsteuerung, wie dort das kurze Datum formatiert wird. Dort steht dann vermutlich TT.MM.JJ oder TT.MM.JJJJ. Dementsprechend wird dann in die DefaultValue-Eigenschaft z.B. "20.03.2004" eingetragen. Das ist aber die deutsche Schreibweise, die DefaultValue-Eigenschaft will jedoch die US-Variante MM/DD/YYYY. Stellt sich die Frage, wie komme ich von der deutschen Formatierung wie z.B. "Datum, kurz" zur dazu passenden englischen Schreibweise MM/DD/YYYY - mit möglichst wenig Aufwand?
Hier scheint die BuildCriteria()-Funktion vielversprechend zu sein, die formt auf jeden Fall aus einem deutschen Datum gleich welcher Formatierung ein passendes US-Datum.
Sowas könnte evtl. helfen:
Testen kann ich das erst nächste Woche, zur Zeit werde ich noch von Weihnachtsfeiern usw. vereinnahmt.
Gruss
El Bobbele
Ja, da steckt der Teufel im Detail. Zwischenzeitlich hatte ich etwas experimentiert und bin dabei noch auf Schwierigkeiten gestoßen. Wenn du das Datum auf "Datum, kurz" formatierst, dann heisst das in VBA "Short Date". Beim Auswerten des Ausdrucks schaut Access dann in die Windows Systemsteuerung, wie dort das kurze Datum formatiert wird. Dort steht dann vermutlich TT.MM.JJ oder TT.MM.JJJJ. Dementsprechend wird dann in die DefaultValue-Eigenschaft z.B. "20.03.2004" eingetragen. Das ist aber die deutsche Schreibweise, die DefaultValue-Eigenschaft will jedoch die US-Variante MM/DD/YYYY. Stellt sich die Frage, wie komme ich von der deutschen Formatierung wie z.B. "Datum, kurz" zur dazu passenden englischen Schreibweise MM/DD/YYYY - mit möglichst wenig Aufwand?
Hier scheint die BuildCriteria()-Funktion vielversprechend zu sein, die formt auf jeden Fall aus einem deutschen Datum gleich welcher Formatierung ein passendes US-Datum.
Sowas könnte evtl. helfen:
strResult = BuildCriteria("Dummy", dbDate, Nz("#" + Format(fld.Value, ctl.Format) + "#", ""))
Testen kann ich das erst nächste Woche, zur Zeit werde ich noch von Weihnachtsfeiern usw. vereinnahmt.
Gruss
El Bobbele
Antwort 7 von ElBobbele
Hi Köbi!
Ich habe die Funktion zwischenzeitlich komplett überarbeitet. Jetzt sollte eigentlich alles funktionieren, was Datumsformatierungen usw. betrifft. Die folgenden Codeabschnitte müssen alle in ein Modul eingefügt werden.
Ich habe die Funktion zwischenzeitlich komplett überarbeitet. Jetzt sollte eigentlich alles funktionieren, was Datumsformatierungen usw. betrifft. Die folgenden Codeabschnitte müssen alle in ein Modul eingefügt werden.
Public Function SetDefaults(FormObject As Form, _
Optional ExcludeFields As String) As Boolean
Dim db As Database
Dim rec As Recordset
Dim fld As Field
Dim ctl As Control
Dim strSQL As String
Dim strDate As String
Dim strDateFormat As String
Dim blnResult As Boolean
Const PROPERTY_NOT_SUPPORTED = 438
On Error GoTo Err_SetDefaults
If Len(FormObject.RecordSource) > 0 Then
Set db = CurrentDb
′Datenherkunft auslesen, ggfs. Semikolon abschneiden
With FormObject
If Right(.RecordSource, 1) = ";" Then
strSQL = Left(.RecordSource, Len(.RecordSource) - 1)
Else
strSQL = .RecordSource
End If
End With
′Leeres Recordset von der Datenherkunft erzeugen,
′um an die Felddefinitionen heranzukommen
strSQL = "SELECT * FROM (" & strSQL & ") WHERE 0=1;"
Set rec = db.OpenRecordset(strSQL, dbOpenSnapshot)
′Steuerelemente des Formulars durchlaufen
For Each ctl In FormObject.Controls
If IsValidControl(ctl) = True Then
Set fld = rec.Fields(ctl.ControlSource)
If IsValidDefault(fld, ctl, ExcludeFields) = True Then
If fld.Type = dbText Or fld.Type = dbMemo Then
′Text-Datentypen
ctl.DefaultValue = Nz("""" + ctl.Value + """", "")
ElseIf fld.Type = dbDate Then
′Datumsformat bestimmen
Antwort 8 von ElBobbele
Select Case ctl.Format
Case "General Date", "Long Date", "Medium Date", "Short Date"
strDateFormat = "mm/dd/yyyy"
Case "Long Time", "Medium Time", "Short Time"
strDateFormat = "hh:nn:ss"
Case Else
strDateFormat = "mm/dd/yyyy hh:nn:ss"
End Select
strDate = Nz("#" + Format(ctl.Value, strDateFormat) + "#", "")
ctl.DefaultValue = strDate
Else
′Sonstige Datentypen, dabei Dezimalstellen
′von Komma nach Punkt konvertieren, wenn vorhanden
ctl.DefaultValue = str(Nz(ctl.Value, ""))
End If
End If
End If
Next
End If
blnResult = True
Exit_SetDefaults:
Set rec = Nothing
Set db = Nothing
Exit Function
Err_SetDefaults:
If Err.Number <> PROPERTY_NOT_SUPPORTED Then
′Unerwarteter Fehler, Abbruch
MsgBox Err.Number & ": " & Err.Description, vbCritical
blnResult = False
Resume Exit_SetDefaults
Else
′Nur bei Steuerelementen, die kein Steuerelementinhalt unterstützen
Resume Next
End If
End Function
Antwort 9 von ElBobbele
Private Function IsValidDefault(fld As Field, ctl As Control, ExcludeFields As String) As Boolean
Dim blnValid As Boolean
If Not fld Is Nothing And Not ctl Is Nothing Then
′Autowerte ignorieren
If (fld.Attributes And dbAutoIncrField) = dbAutoIncrField Then
blnValid = False
′Prüfen auf Ausschlussfeld
ElseIf InStr("," & ExcludeFields & ",", "," & fld.Name & ",") > 0 Then
blnValid = False
′Übereinstimmung von Feldname und Steuerelementinhalt prüfen
ElseIf ctl.ControlSource <> fld.Name Then
blnValid = False
Else
blnValid = True
End If
Else
blnValid = False
End If
IsValidDefault = blnValid
End Function
Private Function IsValidControl(ctl As Control) As Boolean
Dim blnValid As Boolean
If Not ctl Is Nothing Then
′Nur Steuerelemente mit vorhandener Standardwert-Eigenschaft zulassen
If ctl.ControlType <> acTextBox And ctl.ControlType <> acOptionGroup And ctl.ControlType <> acToggleButton And #95
ctl.ControlType <> acListBox And ctl.ControlType <> acOptionButton And ctl.ControlType <> acComboBox And #95
ctl.ControlType <> acCheckBox Then
blnValid = False
ElseIf Len(ctl.ControlSource) = 0 Then
blnValid = False
Else
blnValid = True
End If
Else
blnValid = False
End If
IsValidControl = blnValid
End Function
Antwort 10 von Koebi
Hallo ElBobbele
Da hast du dir ja eine schöne Arbeit eingebrockt. Vielen Dank.
Nur (hüstel....), so ganz klappt es nicht. Oder ich mache wieder mal einen Fehler, was wohl eher der Fall ist.
Wenn ich im Formular an einem Datensatz etwas ändere, kommt beim (automatischen) Speichern die Fehlermeldung
3265: Element in dieser Auflistung nicht gefunden.
Gespeichert wird dann schon.
Der Standardwert wird aber nicht übernommen bei Datumsfeldern, weder beim Typ DatumLang noch bei DatumKurz.
Beim Feld Zeit, 24Stunden hingegen klappt es.
Hast Du eine Erklärung?
Gruss
Köbi
Da hast du dir ja eine schöne Arbeit eingebrockt. Vielen Dank.
Nur (hüstel....), so ganz klappt es nicht. Oder ich mache wieder mal einen Fehler, was wohl eher der Fall ist.
Wenn ich im Formular an einem Datensatz etwas ändere, kommt beim (automatischen) Speichern die Fehlermeldung
3265: Element in dieser Auflistung nicht gefunden.
Gespeichert wird dann schon.
Der Standardwert wird aber nicht übernommen bei Datumsfeldern, weder beim Typ DatumLang noch bei DatumKurz.
Beim Feld Zeit, 24Stunden hingegen klappt es.
Hast Du eine Erklärung?
Gruss
Köbi
Antwort 11 von ElBobbele
Hi Köbi!
Ui? Ich hatte so ziemlich alle Datumsvarianten durchprobiert. Kannst du mal prüfen, welches Steuerelement betroffen ist und wie es vom Format her eingestellt ist? Evtl. könntest du mir die Datenbank zuschicken, damit ich mir ein Bild davon machen kann. Die Adresse ist elbobbele@yahoo.de.
Gruss
El Bobbele
Ui? Ich hatte so ziemlich alle Datumsvarianten durchprobiert. Kannst du mal prüfen, welches Steuerelement betroffen ist und wie es vom Format her eingestellt ist? Evtl. könntest du mir die Datenbank zuschicken, damit ich mir ein Bild davon machen kann. Die Adresse ist elbobbele@yahoo.de.
Gruss
El Bobbele
Antwort 12 von Koebi
Hallo El Bobbele
Mache ich doch gerne. Eine UebungsDB ist schon unterwegs.
Vielen Dank für Deine Hilfe. Ist aber nicht besonders dringend. Du brauchst deswegen nicht die ganze Nacht durchzuarbeiten.;-))
Gruss
Köbi
Mache ich doch gerne. Eine UebungsDB ist schon unterwegs.
Vielen Dank für Deine Hilfe. Ist aber nicht besonders dringend. Du brauchst deswegen nicht die ganze Nacht durchzuarbeiten.;-))
Gruss
Köbi
Antwort 13 von ElBobbele
Hi Köbi!
Danke für die Datenbank, sie hat recht schnell eine weitere Schwäche der Funktion offenbart. Du hast dort ein berechnetes Feld zur Altersberechnung drin, die hatte ich bisher nicht berücksichtigt. Solche Felder müssen nur noch ignoriert werden, da sie sowieso Selbstversorger sind.
Zwischenzeitlich werde ich dein Testformular noch für weitere Tests nutzen, das scheint mir besser geeignet zu sein als meins. .-)
Gruss
El Bobbele
Danke für die Datenbank, sie hat recht schnell eine weitere Schwäche der Funktion offenbart. Du hast dort ein berechnetes Feld zur Altersberechnung drin, die hatte ich bisher nicht berücksichtigt. Solche Felder müssen nur noch ignoriert werden, da sie sowieso Selbstversorger sind.
Zwischenzeitlich werde ich dein Testformular noch für weitere Tests nutzen, das scheint mir besser geeignet zu sein als meins. .-)
Gruss
El Bobbele