Supportnet Computer
Planet of Tech

Supportnet / Forum / Datenbanken

Felder vorbelegen in ACCESS 97





Frage

Gibt es eine Möglichkeit, dass bei der Eingabe eines neuen Datensatzes alle Felder durch die Inhalte des unmittelbar zuvor eingegebenen Datensatzes vorbelegt werden?

Antwort 1 von Teerbaby

Naja, du kannst den vorigen Datensatz einfach kopieren.


Antwort 2 von Realist

Hi Teerbaby,

die Möglichkeit des Kopierens ist mir bekannt. Ich bin jedoch auf eine einfachere Lösung aus. In DBASE war das Vorbelegen von Datenfeldern aus den vorherigen jedenfalls möglich.

Antwort 3 von .struppi

Hallo,
Man kann das auf verschiedene Weise tun.
Eine Möglichkeit wäre mit einem Recordset auf die Tabelle den letzten Datensatz auszulesen und die Textfelder zu füllen.
Die Frage ist nur an welches Ereignis diese Aktion zu hängen ist. Dazu müßte auch geklärt werden auf welche Art Du neue Datensätze anlegst.

Man kann auch etwas mit der dlast-Funktion machen oder den eben eingegebenen Datensatz zwischenspeichern.
Kommt jetzt ganz auf die Gegebenheiten an.
gruß struppi

Antwort 4 von PotzBlitz

Hallo Realist,

mit deiner Aufgabe hast du tatsächlich noch am späten Abend meinen ehrgeizigen Basteltrieb geweckt. :-) Ich habe zwischenzeitlich eine Prozedur erstellt, welche die Werte alle Felder des gerade geänderten Datensatzes in die jeweiligen Standardwert-Eigenschaften schreibt. Dadurch wird nicht automatisch ein neuer Datensatz angelegt, sondern nur für den Fall, DASS mal ein Datensatz hinzugefügt wird, die Standardwerte vorab bestückt.

Das Besondere an dieser Prozedur ist aber die Rekursion, mit der alle Unterformulare abgeklappert und entsprechend präpariert werden. Dabei spielt es keine Rolle, in welchem der Unterformulare eine Änderung durchgeführt wird. Die Prozedur hangelt sich hoch bis zur obersten Formular-Ebene und beginnt dann von dort aus die Rekursion, mit der dann alle Unterformulare und Unter-Unterformulare erwischt werden.

Um die Prozedur verwenden zu können, muss im betroffenen Formular inkl. aller Unterformulare jeweils im Ereignis "Nach Aktualisierung" die folgende Zeile hinzugefügt werden:

′-----------------------
Private Sub Form_AfterUpdate()
   UpdateDefaultValues Me
End Sub
′-----------------------

Antwort 5 von PotzBlitz

Anschliessend stellt man die Prozedur selbst in ein globales Modul, wo sie für alle Formulare bei Bedarf zur Verfügung steht.

′-----------------------
Public Sub UpdateDefaultValues(frm As Form, Optional blnFindTopLevel As Boolean = True)
   Dim rec As Recordset
   Dim fld As Field
   Dim ctl As Control
   Dim frmTemp As Form
   Dim strName As String
  
   On Error GoTo Err_UpdateDefaultValues
  
   If blnFindTopLevel = True Then
      ′In dieser Phase wird das oberste Formular gesucht. Ein übergeordnetes Formular ist _
      vorhanden, wenn der Name der Parent-Eigenschaft nicht leer ist.
      strName = frm.Parent.Name
      If Len(strName) = 0 Then
         ′Im obersten Formular angekommen, nun beginnt die Aktualisierung der _
         Standard-Eigenschaften.
         UpdateDefaultValues frm, False
      Else
         ′Eine Ebene höher wechseln
         UpdateDefaultValues frm.Parent.Form, True
      End If
   Else
      ′Es sollen nur die Steuerelemente verarbeitet werden, die auch tatsächlich in _
      der Tabelle gespeichert werden können.
      Set rec = frm.RecordsetClone
      For Each fld In rec.Fields
         For Each ctl In frm.Controls
            If ctl.ControlType = acSubform Then
                ′Das aktuelle Steuerelement ist ein Unterformular, also wird zuerst dort _
                die Arbeit fortgesetzt. Anschliessend wird die Aktualisierung des _
                zwischenzeitlich pausierenden Formulars wieder aufgenommen.
                Set frmTemp = ctl.Form
                UpdateDefaultValues frmTemp, False
            Else
               ′Nur Steuerelemente berücksichtigen, die auch eine Standardwert- _
               Eigenschaft besitzen.
               If HasControlSource(ctl.ControlType) = True Then
                   ′Steuerelement zum aktualisieren gefunden
                   If ctl.ControlSource = fld.Name Then
                       ′Werte vom Typ Text müssen in Anführungszeichen an die _
                       ′Standardwert-Eigenschaft übergeben werden, daher den _
                       Typ des Recordsetfeldes ermitteln und ggfs. formatieren
                       If fld.Type = dbMemo Or fld.Type = dbText Then
                           ctl.DefaultValue = "=""" & ctl.Value & """"
                        Else
                           ctl.DefaultValue = "=" & ctl.Value
                       End If
                   End If
               End If
            End If
         Next
      Next
   End If
Exit_UpdateDefaultValues:
   If Not rec Is Nothing Then rec.Close
   Set rec = Nothing
   Exit Sub
Err_UpdateDefaultValues:
   ′Laufzeitfehler 2452 tritt auf, wenn versucht wird, auf ein nicht vorhandenes, _
   übergeordnetes Formular zuzugreifen.
   If Err <> 2452 Then
      Debug.Print Err.Number & " " & Err.Description
   End If
   Resume Next
End Sub

Private Function HasControlSource(intControlType As Integer) As Boolean
′Hilfsfunktion zur Ermittlung des Steuerelement-Typs. Es werden nur _
′Steuerelemente mit einer Standardwert-Eigenschaft berücksichtigt.
    HasControlSource = (intControlType = acCheckBox Or _
        intControlType = acComboBox Or _
        intControlType = acListBox Or _
        intControlType = acOptionButton Or _
        intControlType = acTextBox Or _
        intControlType = acToggleButton)
End Function
′-----------------------

Die Kommentarzeilen verwirren hier im Forum etwas. Am besten in ein Modul kopieren, dann wird es auch übersichtlich eingefärbt.

Gruss
PotzBlitz

Antwort 6 von PotzBlitz

... Ups, da ist mir bei der abschliessenden Durchsicht doch glatt ein Schönheitsfehler aufgefallen. Die Funktion HasControlSource() sollte eher heissen HasDefaultValue() bzw. HasDefaultValueProperty(). Der jetzige Name war noch ein Überbleibsel aus dem Anfangsstadium der Entwicklung. Beeinflussen tut das den Programmablauf natürlich nicht.

Gruss
PotzBlitz

Antwort 7 von Knubbel

@ Realist

es geht auch über ein Makro "SetzenWert", z.B. beim Ereignis "bei Fokuserhalt"

Unter Wert (der eingetragen werden soll) ist dann eine Domänfunktion einzutragen:
z.B.: DLast(....
oder DMax(....

Schau mal in der Onlinehilfe nach.

mfg Knubbel

Antwort 8 von .struppi

Hallo,
Das will ich auch meinen... geht wirklich einfacher.

Man kann ZB für jedes Textfeld als Standardwert die dlast Funktion schreiben, sieht dann so aus:

=DomLetzterWert("TabellenfeldName";"TabellenName")

Der TabellenName ist der Name der Tabelle, die dem Formular zu Grunde liegt.
Der TabellenfeldName ist der Name des Tabellen-Feldes, daß die Daten für das entsprechende Textfeld liefert.

gruß struppi


Antwort 9 von Koebi

Grüezi

Oder man schaut in der Access-FAQ von donkarl, Punkt 4.22

www.donkarl.com/

Gruss
Köbi

Antwort 10 von Knubbel

Hi, ich nochmal

Ich benutze die Domänfunktionen z.B. zum Hochzählen von Feldinhalten. Mit nachstehendem Ausdruck wird z.B. die Auftragsnummer bei einem neuen Datensatz jeweils um 1 erhöht (ausgehend von der höchsten):

DomMax("[Auftrag]![Auftrags-Nr] +1";"[Auftrag]")


mfg Knubbel

Antwort 11 von PotzBlitz72.tmp

Hallo alle zusammen,

wieso sollte die Verwendung von DLast() usw. "einfacher" sein? Nehmen wir mal an, wir hätten ein Formular mit 30 gebundenen Steuerelementen. Dazu kommen noch zwei Unterformulare mit jeweils 10 Steuerelementen. Dann müsste ich 50 mal(!) mit DLast herumhantieren und die Parameter jeweils individuell anpassen?! Wäre es da nicht "einfacher", wenn man wg. der drei Formulare DREIMAL die Zeile "UpdateDefaultValues Me" verbaut?

Unter "einfach" verstehe ich die einfache Nutzung(!) einer Sache. Ob im Hintergrund komplizierte Arbeiten durchgeführt werden müssen, spielt dabei keine Rolle. Schaut euch doch mal die Replace()-Funktion von Access 2000/2002 an:

Replace(strText, strWas, strWomit)

Sieht irgendwie einfach aus und ist auch einfach zu nutzen, nicht wahr? Deswegen ist sie auch immer wieder gern gesehen in den eigenen Programmen. Dabei könnte sich der Code von Replace über mehrere Bildschirmseiten erstrecken, weil aus Geschwindigkeitsgründen keine Textblöcke hin- und her geschoben werden, sondern Zeiger über das Windows-API auf die relevanten Adressen im Arbeitsspeicher verbogen und gesammelt werden, der Text selbst ändert sich bis zum Schluss nicht, es ändern sich nur die Zeiger. Die Arbeitsweise einer Funktion ist für den Nutzer daher irrelevant, wichtig ist nur, dass sie einfach nur das tut, was man von ihr erwartet:

UpdateDefaultValues Me

Das ist ja noch "einfacher", denn die Zeile hat nur einen Parameter und der ändert sich noch nicht einmal. Dazu kommt noch, dass sich UpdateDefaultValues nicht für etwaige geänderte Tabellen- oder Feldnamen interessiert, es nimmt schlicht nur das, was gerade da ist. DLast() interessiert sich dagegen schon sehr für die richtigen Tabellen- und Feldnamen:

=DLast("Feld1","Tabelle1")
=DLast("Feld2","Tabelle1")
=DLast("Feld3","Tabelle1")
=DLast("Feld1","Tabelle2")
=DLast("Feld2","Tabelle2")
=DLast("Feld3","Tabelie2")
=DLast("Feld1","Tabelle3")
=DLast("Feld2","Tabelle3")
=DLast("Feld3","Tabelle3")

Hmm, "einfach" ist anders. Ausserdem ist mir dabei ein Tippfehler unterlaufen, viel Spass beim Suchen. Und viel Glück beim Pflegen von DLast()-Lösungen. ;-)

Gruss
PotzBlitz

Antwort 12 von .struppi

Hallo Potzblitz,
Die Erfahrung zeigt, daß hier im Forum meist keine professionellen Datenbankentwickler Fragen stellen.
Für diese User ist es oftmals "einfacher" eine kurze Codzeile als Eigenschaft eines Textfeldes einzutragen oder ein Makro zu benutzen. Dafür gibt es die Funktionen und Makros nämlich. Um die Benutzung von Access zu "vereinfachen".
Ich verstehe aber, daß Du so reagierst, weil es schließlich Mühe macht einen Code zu entwickeln und die Anerkennung dafür nicht auf der Strecke bleiben soll. Natürlich soll durch ZB meinen Vorschlag Deine Variante keinenfalls herabgesetzt oder geschmälert werden. Sollte nur eine Ersatzmöglichkeit für diejenigen sein, die vor der Einbindung von VBA-Code zurückschrecken. Und vielleicht auch mit dabei auftretenden Fehlern nicht zurecht kommen.
Also nicht sauer sein..ok ?
Gruß Struppi

Antwort 13 von Knubbel

@ Struppi
Ich stimme Dir in allen Punkten zu!

@ Potzblitz
Meine Anmerkung zu Struppi stimmt!
Auch ich möchte nicht Deine Kenntnisse über VB oder sonstige Entwicklercodes in Frage stellen!

Meine Meinung ist jedoch, wenn ein Programm (hier Access) schon viele Funktionen integriert hat, sollte man die "einfachste" Lösung auch anwenden. Ich gestehe ja, ich kenne mich mit VB nicht aus.

Wenn eine Anwendung natürlich so komplex ist, wie Du sie angedeutet hast, ist Deine Lösung sicherlich von Vorteil.
Aber, wenn hier im SN jemand nach einer einfachen Lösung eines Problems fragt, unterstelle ich, dass er kein VB-Profi ist.

mfg Knubbel

Antwort 14 von PotzBlitz

@struppi & Knubbel

Danke euch beiden für die Aufmunterung. :-) Ich muss gestehen, dass ich ziemlich frustriert war, nachdem ich knapp zwei Stunden bis kurz nach Mitternacht an diesem Problem sass, nur um dann festzustellen, dass niemand für diese Prozedur eine Verwendung hat. Nun ja, immerhin weiss ich jetzt, wie man das ursprüngliche Problem angehen könnte. Ich habe während der Entwicklung selbst wertvolle Erkenntnisse daraus ziehen können und werde davon sicherlich noch profitieren können. Schon allein deswegen müsste ich mich bei Realist bedanken, da seine Frage ja der Stein des Anstosses war. :-)

Aus diesem Fall werde ich aber trotzdem meine Konsequenzen ziehen und zukünftig genauer drauf achten, wie weit ich mit meinen Lösungsvorschlägen gehen kann, denn die Vorstellung, am hiesigen Strom vorbei zu helfen, würde mir auf Dauer überhaupt nicht gefallen.

Gruss
PotzBlitz

Antwort 15 von Koebi

Grüezi an alle

@PotzBlitz

Ich habe mir soeben Deine Prozedur zu Gemüte geführt, und siehe da, sie funktioniert!:-)) (Eigentlich habe ich auch nichts anderes erwartet.)

Nun möchte ich auch den Standardwert für Datums- und Zeitfelder übernehmen. Gemäss donkarl geht das ungefähr so:

= CDbl(Me!DeinFeldName)

Ich habe das mit

ElseIf fld.Type = dbDate Then ctl.DefaultValue = "=" & "CDbl" & "(" & ctl.Value & ")"

versucht.

Ist aber nicht das Gelbe vom Ei. Funktioniert nämlich nicht.:-((
Kannst Du mir da weiterhelfen?

Vielen Dank schon.

Gruss
Köbi