Supportnet Computer
Planet of Tech

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

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.

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

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

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

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:
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.


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

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

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

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

Ich möchte kostenlos eine Frage an die Mitglieder stellen:


Ähnliche Themen:


Suche in allen vorhandenen Beiträgen: