PDA

Vollständige Version anzeigen : Hauptformular soll UFO automatisch aktualisieren


Simon84
27.04.2011, 07:30
Hallo liebe Community,

Habe ein Hauptformular „frmProjects“ und ein darin eingebundenes UFO „frmBilderVerwalten“ (letzteres abgeleitet aus Sascha Trowitzsch’s BilderDB).
Ich lege nun im Hauptformular einen neuen Datensatz an. Dafür wähle ich über die Navigationsschaltfläche im UFO ein passendes Bild und klicke dann auf den Button ‚Bild übernehmen…’ Ergebnis: Im Hauptformular wird mir der richtige Name des gewählten Bildes angezeigt (im Hintergrund wird auch der Primärschlüssel des betroffenen Bildes übertragen). Funktioniert soweit ganz gut.

Nun habe ich folgendes Problem: Wenn ich im Hauptformular navigiere, hätte ich gerne, dass mir das UFO rückwirkend jeweils wiederum das richtige Bild zeigt. Das bekomme ich trotz Recherche leider nicht hin.

Ich habe probiert das UFO mit dem Hauptformular zu verknüpfen: Verknüpfen von „idBild“ nach „idBild_f“… Jetzt würde ich das zuvor gewählte Bild bei Navigation im Hauptformular sehen, nur kann ich jetzt im UFO nicht mehr navigieren…

Ich hoffe Ihr könnt mir weiterhelfen. Im Anhang die Beispiel-mdb.

Mit freundlichen Grüßen,

Simon

Edit: Sehe gerade meine Beispiels mdb ist ein bisschen zu groß. Ich lege sie auf Uploaded.to ab.
Hier der Link: http://uploaded.to/file/yo3yaofz

maikek
27.04.2011, 09:38
Moin,
kannst du hier mal den Code posten, der da "im Hintergrund ;) " für die Navigation sorgt?
maike

Simon84
27.04.2011, 10:04
Beim Klick auf Button "Bild übernehmen..."

Private Sub Befehl17_Click()
On Error GoTo Err_Befehl17_Click

DoCmd.DoMenuItem acFormBar, acRecordsMenu, 5, , acMenuVer70
Me.Parent!idBild_F = Me!idBild

Exit_Befehl17_Click:
Exit Sub

Err_Befehl17_Click:
MsgBox Err.Description
Resume Exit_Befehl17_Click

End Sub

Im UFO:

Private Sub Form_Current()
Me.Caption = "Anlagenbilder / " & Me!BildName 'Titelzeile
If Not IsNull(Me!BildName) Then Set AXPIX.Object.Picture = CreatePix 'siehe folgende Function
'Me!frmBilderVerwalten.Requery

End Sub

Wenn du Zeit hast, schaue dir die Beispiel DB an.

maikek
27.04.2011, 10:42
BeispielDBs sind für mich immer nur der letzte Notanker ;) .
Zum einen finde ich es oft mühselig, mich da erstmal reinzudenken - es ist imho Aufgabe des Fragestellers, das Problem so zu schildern, dass es verständlich ist. Zum anderen ist es für andere, die hier im Forum nach einer Lösung für ein ähnliches Problem suchen, schwer nachvollziehbar.

Wenn ich den Code richtig interpretiere, müsste es doch ausreichend sein, vom Hauptform aus im FormCurrent ein:
If not IsNull(Me!idBild_F) then
Me!NameDeinesUFOSteuerelementsImHF!idBild = Me!idBild_F
End if
zu setzen?

maike

Simon84
27.04.2011, 11:51
Leider funktioniert das nicht.

Ich versuche den Sachverhalt noch einmal zu erklären:

Prinzipiell habe ich sowohl im Haupt- als auch im Unterformular Navigationsschaltflächen.
Angenommen im Unterformular gibt es 10 Datensätze und im Hauptformular 3.
Verknüpfe ich nun den Primärschlüssel des Unterformulars mit dem Fremdschlüssel des Hauptformulars, so werden bei Datensatznavigation im Hauptformular die richtigen Bilder im Unterformular angezeigt, JEDOCH ist im Unterformular immer nur mehr 1 Datensatz enthalten, d.h. ich kann im UFO nicht mehr navigieren. Warum? Das verstehe ich schon mal nicht...
Ich denke mir, ich muss die Verknüpfung also rausnehmen. Nun kann ich seperat im Haupt- und Unterformular wieder navigieren, JEDOCH wird mir zu einem bestimmten Datensatz im Hauptformular nicht das richtig zugeordnete Foto im UFO angezeigt. Ich denke, man müsste eine Prozedur einfügen, die jedesmal wenn ich im Hauptformular einen Datensatz vor oder zurück schalte einen Abgleich macht zwischen Primär- und Fremdschlüssel und daraufhin automatisch zu dem Datensatz im UFO schaltet. Also eine Art Aktualisierungsprozedur. Was meinst Ihr?

Sorry war viel Text, aber ich weiß nicht wie ich es anders beschreiben könnte. Daher hätte ich auch die Beispiels mdb hochgeladen, zum besseren Nachvollziehen.

Danke schon im Voraus, Simon.

maikek
27.04.2011, 11:57
Hast du die Verknüpfung zwischen Hauptform und UFO rausgenommen, bevor du meinen Code ausprobiert hast?
Wenn ja, speck deine DB auf das Problem und ein paar Dummydaten ab, komprimiere sie (Access, Extras/Dienstprogramme/Komprimieren und Reparieren) und lade sie gezippt hier hoch.
Die Verknüpfung über Primär- und Fremdschlüssel sorgt dafür, dass das UFO mit dem Hauptformular synchron läuft - im Normalfall bei einer 1:n Beziehung, so dass zu einem Masterdatensatz automatisch die entsprechenden Detailsätze angezeigt werden. Dadurch ist das UFO dann natürlich nicht mehr unabhängig vom Hauptform.
maike

Simon84
27.04.2011, 13:28
Hallo maikek,

Ja ich bin so vorgegangen wie du gesagt hast, jedoch ohne erfolg... :/
hier die abgespeckte version mit 2 dummybildern

maikek
27.04.2011, 15:04
Okay, da sind ja noch ein paar andere Dinge im Spiel ;) .
Das Bild wird nicht nur aktualisiert, sondern vor allem erstmal aus den Binärdaten erzeugt ... dazu brauchst du dann die entsprechende Funktion (Sub).
Hab's mal eingebaut (dafür die Sub einfach quick and dirty ins Hauptform kopiert, geht möglicherweise auch eleganter).
maike

Simon84
27.04.2011, 17:02
Vielen Dank, du bist mein Held :cool:

Simon84
28.04.2011, 09:07
Neues Problem...
Deine Lösung funktioniert ganz gut.
Jetzt habe ich ein weiteres Formular, in dem 2 Bildviewer als UFO's eingebaut sind.

Wollte die Aktualisierung mit folgendeme Code machen:

Option Compare Database
Option Explicit

Private Sub Form_Current()

If Not IsNull(Me!idBild1_F) Then
Set Me!Bilderauswahl2!AXPIX.Object.Picture = CreatePix1
End If

If Not IsNull(Me!idBild2_F) Then
Set Me!Bilderauswahl3!AXPIX.Object.Picture = CreatePix2
End If

End Sub

Private Function CreatePix1() As StdPicture
Dim rs1 As Recordset, pix() As Byte, lSize As Long
On Error GoTo Fehler

Set rs1 = Me.RecordsetClone
rs1.MoveFirst
rs1.Bookmark = Me.Bookmark
lSize = rs1("Bild").FieldSize
ReDim pix(lSize)
pix() = rs1("Bild").GetChunk(0, lSize) 'Binärdaten in Arry laden
Set CreatePix1 = BytesToPicture(pix) 'Siehe Funktion im Modul mdlArrayToStdPicture
If CreatePix1 Is Nothing Then MsgBox sError, vbExclamation, "OLE-Fehler" 'Das passiert bei nicht unterstützten Bildformaten

Ende:
Erase pix
Set rs1 = Nothing
Exit Function
Fehler:
MsgBox Err.Description
Resume Ende
End Function

Private Function CreatePix2() As StdPicture
Dim rs2 As Recordset, pix() As Byte, lSize As Long
On Error GoTo Fehler

Set rs2 = Me.RecordsetClone
rs2.MoveFirst
rs2.Bookmark = Me.Bookmark
lSize = rs2("Bild").FieldSize
ReDim pix(lSize)
pix() = rs2("Bild").GetChunk(0, lSize) 'Binärdaten in Arry laden
Set CreatePix2 = BytesToPicture(pix) 'Siehe Funktion im Modul mdlArrayToStdPicture
If CreatePix2 Is Nothing Then MsgBox sError, vbExclamation, "OLE-Fehler" 'Das passiert bei nicht unterstützten Bildformaten

Ende:
Erase pix
Set rs2 = Nothing
Exit Function
Fehler:
MsgBox Err.Description
Resume Ende
End Function


Als Fehler bekomme ich immer: "Element in dieser Auflistung nicht gefunden."
Wo liegt mein Denkfehler?

maikek
28.04.2011, 09:23
Ich hab mich jetzt nicht soweit in die Materie eingearbeitet ... da spielen ja noch ein paar andere Codes/Funktionen mit.
CreatePix1 und CreatePix2 ist Bullshit, bleib mal bei einem und zwar dem Originalen CreatePix.
Element nicht gefunden, da würde ich zunächst mal das Recordset im Verdacht haben. Gibt es dort ein Feld namens "Bild"?
maike

Simon84
28.04.2011, 11:57
Hallo maike,

würde ich zunächst mal das Recordset im Verdacht haben. Gibt es dort ein Feld namens "Bild"?


Ich verstehe die Frage nicht ganz. in der Tabelle Bilder gibt es ein Feld "Bild" vom Typ OLE-Objekt.

CreatePix1 und CreatePix2 ist Bullshit, bleib mal bei einem und zwar dem Originalen CreatePix

Done.

Mein etwas entschlackter Code resultiert wieder in demselben Fehler.. :/

Option Compare Database
Option Explicit

Private Sub Form_Current()

If Not IsNull(Me!idBild1_F) Then
Set Me!BilderVerwalten1!AXPIX.Object.Picture = CreatePix
End If

If Not IsNull(Me!idBild2_F) Then
Set Me!BilderVerwalten2!AXPIX.Object.Picture = CreatePix
End If

End Sub

Private Function CreatePix() As StdPicture
Dim rs As Recordset, pix() As Byte, lSize As Long
On Error GoTo Fehler

Set rs = Me.RecordsetClone
rs.MoveFirst
rs.Bookmark = Me.Bookmark
lSize = rs("Bild").FieldSize
ReDim pix(lSize)
pix() = rs("Bild").GetChunk(0, lSize) 'Binärdaten in Arry laden
Set CreatePix = BytesToPicture(pix) 'Siehe Funktion im Modul mdlArrayToStdPicture
If CreatePix Is Nothing Then MsgBox sError, vbExclamation, "OLE-Fehler" 'Das passiert bei nicht unterstützten Bildformaten

Ende:
Erase pix
Set rs = Nothing
Exit Function
Fehler:
MsgBox Err.Description
Resume Ende
End Function

Im Anhang wieder die mdb.

Gruß, Simon

maikek
28.04.2011, 12:04
Ich verstehe die Frage nicht ganz. in der Tabelle Bilder gibt es ein Feld "Bild" vom Typ OLE-Objekt.
Das weiß ich ;) .
Mit Me.Recordsetclone erzeugst du in der Function CreatePix ein Recordset, das alle Datensätze mit ihren Feldern aus deinem Formular enthält. In diesem Recordset, also in der Datenherkunft des Formulars, muss das Feld "Bild" enthalten sein.
maike

Simon84
28.04.2011, 12:37
Ich glaub ich blick noch nicht so ganz durch. Also noch mal ganz langsam zum Mitschreiben :)

Ich gehe den Code jetzt mal der Reihe nach durch:

If Not IsNull(Me!idBild1_F) Then
Set Me!BilderVerwalten1!AXPIX.Object.Picture = CreatePix
End If

If Not IsNull(Me!idBild2_F) Then
Set Me!BilderVerwalten2!AXPIX.Object.Picture = CreatePix
End If

Hier, also im Hauptformular (gründet auf der Abfrage 'qryBilder') soll mit der Funktion "IsNull" getestet werden ob sich schon Datensätze in der Abfrage befinden, oder? Is dies der Fall, so wird die Funktion "CreatePix" ausgeführt.

Nun erzeugt er also ein Recordset, das alle Datensätze mit ihren Feldern aus deinem Formular enthält.

In der Datenherkunft (qryBilder) gibt es nun das Feld "Bild" nicht, sondern Bilder.Bild und Bilder_1.Bild, wegen den Verknüpfungen der Auswahlabfrage.

Deswegen die Fehlermeldung?

maikek
28.04.2011, 12:46
Sieht so aus.
Wieso hast du das Feld zweimal in der Abfrage?
Poste doch mal den SQL-Code.
maike

Simon84
28.04.2011, 12:49
SELECT ProjektNA.*, Bilder.*, Bilder_1.* FROM Bilder RIGHT JOIN (Bilder AS Bilder_1 RIGHT JOIN ProjektNA ON Bilder_1.idBild = ProjektNA.idBild2_F) ON Bilder.idBild = ProjektNA.idBild1_F;

maikek
28.04.2011, 12:53
Schmeiß die Bilder_1 da wieder raus. Für die gilt dasselbe wie für CreatePix1.
Du musst nicht jeden Schlüsselwert einzeln verknüpfen, eine Verknüpfung über die Schlüsselfelder ist ja gerade der Clou ;) .
Danach dürfte "Bild" wieder vorhanden sein, mal sehen, ob's dann klappt.
maike

Simon84
28.04.2011, 12:59
So würde es funtkionieren, mit der derzeitigen Abfrage:

Private Sub Form_Current()

If Not IsNull(Me!idBild1_F) Then
Set Me!BilderVerwalten1!AXPIX.Object.Picture = CreatePix1
End If

If Not IsNull(Me!idBild2_F) Then
Set Me!BilderVerwalten2!AXPIX.Object.Picture = CreatePix2
End If

End Sub

Private Function CreatePix1() As StdPicture
Dim rs1 As Recordset, pix() As Byte, lSize As Long
On Error GoTo Fehler

Set rs1 = Me.RecordsetClone
rs1.MoveFirst
rs1.Bookmark = Me.Bookmark
lSize = rs1("Bilder.Bild").FieldSize
ReDim pix(lSize)
pix() = rs1("Bilder.Bild").GetChunk(0, lSize) 'Binärdaten in Arry laden
Set CreatePix1 = BytesToPicture(pix) 'Siehe Funktion im Modul mdlArrayToStdPicture
If CreatePix1 Is Nothing Then MsgBox sError, vbExclamation, "OLE-Fehler" 'Das passiert bei nicht unterstützten Bildformaten

Ende:
Erase pix
Set rs1 = Nothing
Exit Function
Fehler:
MsgBox Err.Description
Resume Ende
End Function

Private Function CreatePix2() As StdPicture
Dim rs2 As Recordset, pix() As Byte, lSize As Long
On Error GoTo Fehler

Set rs2 = Me.RecordsetClone
rs2.MoveFirst
rs2.Bookmark = Me.Bookmark
lSize = rs2("Bilder_1.Bild").FieldSize
ReDim pix(lSize)
pix() = rs2("Bilder_1.Bild").GetChunk(0, lSize) 'Binärdaten in Arry laden
Set CreatePix2 = BytesToPicture(pix) 'Siehe Funktion im Modul mdlArrayToStdPicture
If CreatePix2 Is Nothing Then MsgBox sError, vbExclamation, "OLE-Fehler" 'Das passiert bei nicht unterstützten Bildformaten

Ende:
Erase pix
Set rs2 = Nothing
Exit Function
Fehler:
MsgBox Err.Description
Resume Ende
End Function


Aber du hast recht, das muss anders auch gehen; ich versuche die Abfrage zu ändern und es so zu schaffen...

Simon84
28.04.2011, 13:06
Hmm, also ich kann Bilder_1 gar nicht rausschmeißen merke ich gerade...
Ergibt sich durch die Beziehungen so. Ich wüsste ehrlich gesagt auch nicht wie ich es anders verknüpfen sollte.

Ich merke gerade, dass hier bei dieser Anwendung eine 1:n Beziehung schlecht ist

Simon84
28.04.2011, 16:16
Schon wieder was, wo ich hänge:

Will mir gerne in einem Bericht die als long-binary-Dateien gespeicherten Bilder wieder anzeigen lassen.

Folgender Code bringt mir lediglich den Fehler "Objekt erforderlich":


Private Sub Report_Open(Cancel As Integer)

If Not IsNull(Me!idBild1_F) Then
CreatePix

End If

End Sub
Private Function CreatePix() As StdPicture
Dim pix() As Byte, lSize As Long

On Error GoTo Fehler
lSize = Bilder.Bild.FieldSize
ReDim pix(lSize)
pix() = Bilder.Bild.GetChunk(0, lSize) 'Binärdaten in Arry laden
Set CreatePix = BytesToPicture(pix) 'Siehe Funktion im Modul mdlArrayToStdPicture
If CreatePix Is Nothing Then MsgBox sError, vbExclamation, "OLE-Fehler" 'Das passiert bei nicht unterstützten Bildformaten

Ende:
Erase pix
Set rs = Nothing
Exit Function
Fehler:
MsgBox Err.Description
Resume Ende


End Function

maikek
28.04.2011, 16:28
Ich merke gerade, dass hier bei dieser Anwendung eine 1:n Beziehung schlecht ist
So isses.
Wenn jedes Bild zu mehreren Projekten gehören kann und jedes Projekt mehrere Bilder beinhaltet, dann ist das eine m:n Beziehung.
D.h. du brauchst eine Zwischentabelle tblProjektBild:

tblProjekt: ProjektID, weitere Felder
tblBilder: BildID, weitere Felder
tblProjektBild: ProjektBildID, ProjektID_F, BildID_F

In der Zwischentabelle ordnest du Projekten Bilder zu.
maike