Datagridview Bild aus DB in GridView anzeigen

  • VB.NET
  • .NET (FX) 1.0–2.0

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von steel75.

    Du verwendest in der AccessDB einen Spaltendatentyp Anlage. Verwende doch den Typ OLE-Objekt und hole dir die Daten als Byte() von dort ab - das hat dir auch @vb_fan schon vorgeführt...
    Ich täte dir eine Tutorial von @ErfinderDesRades empfehlen: siehe hier (Da wird gezeigt, wie ich oben schon einmal gesagt habe, dass du dir dein AccessDB-Model in ein typ. Dataset deines Projektes herüberholst...)
    Da ist am Anfang des Tut's auch ein weiterführender Verweis angegeben, den solltest du dir auch einmal einverleiben...
    Du solltest auch dein 2005-Studio upgraden... VS 2013(oder 2015) Community Edition - das ist kostenlos.
    Dann kannst du auch mein hochgeladenes Projekt (das wird mit typ. Dataset und sehr wenig Usercode abgehandelt) ansehen und brauchst nicht immer mit Notepad++ herumsuchen...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB1963“ ()

    Moin VS1963,
    mit dem Demo von VB_fan läuft es jetzt mit OLE-Objekt,
    • Bild wird im DGV angezeigt,
    • bei CellClick in picturebox geladen,
    • hinzufügen geht auch,
    • nur beim Update da harpert es noch. Auch da hab ich jetzt, wie beim INSERT mit OleDBParameter gemacht, der Code wird auch fehlerfrei ausgeführt, nur das Update in der DB passiert nicht.
      Man findet da auch zwei unterschiedliche Notationen einmal im SQL String ...Gerätebild = ?... und einmal mit ...Gerätebild = @Gerätebild..., da aber beide aktuell nicht gehen, muss es auch
      noch an was anderem liegen. ?(
    Aber neue VS Version 2013 professional hab ich schon bestellt :thumbsup: , ich kann aber solange nicht wechseln, hier sind noch viele andere Projekte, die teilweise, sehr spezielle Einstellungen haben.
    Das wird ne ganz schöne Schlacht werden, alle Projekte zu migrieren, alle Abhängigkeiten zu ändern.

    Den Hauptfehler, in diesem Zusammenhang, dass das Bild nicht geladen wurde, konnte ich ausmachen. Es lag an der Art des Einfügens, bei genauer Betrachtung fiel mir auf das der Anfang des Byte() Array sich nach dem INSERT geändert hat, ein bisschen weiterlesen
    brachte dann zu Tage, dass es tatsächlich drauf ankommt wie eingefügt wird. Dies löst sonst intern bei Access etwas aus, was als generierter OLE Header beschrieben wurde und für Access wichtig ist um die richtige Datei Assoziation hinzubekommen.

    Dies sind die Identifier für die Dateitypen jpg, bmp, png, gif, tiff. Sie werden dem Byte() Array in Access voran gestellt. Sie sind aber inkompatibel mit der Darstellung im DGV, dass DGV erkennt den Dateityp nicht, Auto Generierung der Image Spalte schlägt fehl, es tritt
    eine ConvertException auf. Ein solches Bild mit OLE-Header ist auch nicht in der Picturebox darstellbar, auch wenn es sich grundsätzlich um die richtige Datentyp Form handelt Byte() Array. Dieser OLE-Header muss manuell rausgerechnet und bereinigt werden,
    oder man muss von Anfang an richtig in die DB einfügen, dann kann man auch ohne Probleme direkt auslesen, egal ob OLE-Objekt oder Anlage.

    VB.NET-Quellcode

    1. 'Identifier aus dem MSDN Forum
    2. Dim BITMAP_ID_BLOCK As String = "BM"
    3. Dim JPG_ID_BLOCK As String = ChrW(&HFF).ToString() & ChrW(&HD8).ToString() & ChrW(&HFF).ToString()
    4. Dim PNG_ID_BLOCK As String = ChrW(&H89).ToString() & "PNG" & vbCrLf & ChrW(&H1A).ToString() & vbLf
    5. Dim GIF_ID_BLOCK As String = "GIF8"
    6. Dim TIFF_ID_BLOCK As String = "II*" & ChrW(&H0).ToString()


    Hier stand bei vb_fan die Lösung

    VB.NET-Quellcode

    1. Private Function GetPhoto(ByVal FilePath As String) As Byte()
    2. Dim FileStream As FileStream = New FileStream(FilePath, FileMode.Open, FileAccess.Read)
    3. Dim BinaryReader As BinaryReader = New BinaryReader(FileStream)
    4. Dim Photo() As Byte = BinaryReader.ReadBytes(Convert.ToInt32(FileStream.Length))
    5. BinaryReader.Close()
    6. FileStream.Close()
    7. Return Photo
    8. End Function


    Den da wird BinaryReader verwendet und ich hatte MemoryStream verwendet, beide fügen die Bilder in die accdb ein, aber bei MemoryStream bekommt man sie nicht ohne weiteres wieder
    in sein Programm geladen, in Access selber ist es kein Problem unter Anlagen diese aufzurufen. Das macht das ganze etwas verwirrend, man bekommt es in Access angezeigt, aber nicht in seinem
    Programm und da muss man erst mal drauf kommen, dass da ein Header generiert und eingefügt wird. Die beiden Methoden behandeln die Daten intern offensichtlich anderes, nun funktioniert es
    ohne Probleme, es ist nicht mal notwendig eine DatagridviewImageColumn einzufügen, den nun erkennt das DGV den Image Datentyp direkt und ColumnAutoGenerate = true generiert die Spalte
    selber.


    VG steel

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „steel75“ ()

    steel75 schrieb:

    VB.NET-Quellcode

    1. Dim JPG_ID_BLOCK As String = ChrW(&HFF).ToString() & ChrW(&HD8).ToString() & ChrW(&HFF).ToString()
    Ohne das ganze jetzt verfolgt zu haben:
    Wozu dient diese Variable (und die anderen)?
    Kann es sein, dass da iwo Bytes stehen müssen, nicht aber ein String?
    Bilder
    • JPG_ID_BLOCK.jpg

      9,42 kB, 742×70, 118 mal angesehen
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo RodFromGermany,
    das könnte man auch so äquivalent so darstellen...

    VB.NET-Quellcode

    1. Dim BITMAP_ID_BLOCK As String = “BM”
    2. Dim JPG_ID_BLOCK As String =\u00FF\u00D8\u00FF”
    3. Dim PNG_ID_BLOCK As String =\u0089PNG\r\n\u001a\n”
    4. Dim GIF_ID_BLOCK As String = “GIF8”
    5. Dim TIFF_ID_BLOCK As String = “II*\u0000”


    Diese Header Werte gibt es mit Sicherheit für alle Dateitypen, vllt. auch mit Überschneidung, dass z.B. SVG und PSD den selben Wert haben. Aber trotz Suchens konnte ich nicht mehr als diese hier finden. Ich hätte da gerne ne Liste drüber was z.B. bei PDF also
    stehen muss, damit der Header korrekt entfernt werden kann.

    Die folgende Methode entfernt diesen Header der Access Dateityp Assoziation für das Öffnen von Dateien innerhalb Access aus dem Byte() Array.
    Die Methode gibt ein bereinigtes Byte() Array ohne OLE Header zurück

    VB.NET-Quellcode

    1. 'Diese Methode entfernt den OLE Header (Dateityp Erkennung)
    2. 'C# Portierung aus dem MSDN Forum
    3. Public Function byteArrayClearing(ByVal bArray() As Byte) As Byte()
    4. 'Identifier
    5. Dim BITMAP_ID_BLOCK As String = "BM"
    6. Dim JPG_ID_BLOCK As String = ChrW(&HFF).ToString() & ChrW(&HD8).ToString() & ChrW(&HFF).ToString()
    7. Dim PNG_ID_BLOCK As String = ChrW(&H89).ToString() & "PNG" & vbCrLf & ChrW(&H1A).ToString() & vbLf
    8. Dim GIF_ID_BLOCK As String = "GIF8"
    9. Dim TIFF_ID_BLOCK As String = "II*" & ChrW(&H0).ToString()
    10. Dim imageBytes() As Byte
    11. 'UTF7 Encoded string version
    12. Dim u7 As System.Text.Encoding = System.Text.Encoding.UTF7
    13. Dim strTemp As String = u7.GetString(bArray)
    14. Dim strVTemp As String = strTemp.Substring(0, 300)
    15. 'Suche nach dem Headerblock
    16. Dim iPos As Integer = -1
    17. If strVTemp.IndexOf(BITMAP_ID_BLOCK) <> -1 Then
    18. iPos = strVTemp.IndexOf(BITMAP_ID_BLOCK)
    19. ElseIf strVTemp.IndexOf(JPG_ID_BLOCK) <> -1 Then
    20. iPos = strVTemp.IndexOf(JPG_ID_BLOCK)
    21. ElseIf strVTemp.IndexOf(PNG_ID_BLOCK) <> -1 Then
    22. iPos = strVTemp.IndexOf(PNG_ID_BLOCK)
    23. ElseIf strVTemp.IndexOf(GIF_ID_BLOCK) <> -1 Then
    24. iPos = strVTemp.IndexOf(GIF_ID_BLOCK)
    25. ElseIf strVTemp.IndexOf(TIFF_ID_BLOCK) <> -1 Then
    26. iPos = strVTemp.IndexOf(TIFF_ID_BLOCK)
    27. Else
    28. Throw New Exception("Die OLE Header Größe konnte nicht bestimmt werden.")
    29. End If
    30. If iPos = -1 Then 'kein Header vorhanden
    31. Return bArray
    32. Else 'OLE Header wird nun entfernt
    33. imageBytes = New Byte(CInt(bArray.LongLength - iPos - 1)) {}
    34. Array.ConstrainedCopy(bArray, iPos, imageBytes, 0, bArray.Length - iPos)
    35. Return imageBytes
    36. End If
    37. End Function
    VG steel
    OK.

    steel75 schrieb:

    VB.NET-Quellcode

    1. If iPos = -1 Then 'kein Header vorhanden
    An Dieser Stelle kommt das Programm nicht vorbei, denn das ist mit

    VB.NET-Quellcode

    1. Throw New Exception("Die OLE Header Größe konnte nicht bestimmt werden.")
    bereits erledigt.
    ======
    Vielleicht siehst Du Dir mal mehrere Dateien gleicher Extension in einem Binary-Viewer an, um das experimentell rauszukriegen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!