VisualStudioのPictureBoxにaccdbの添付ファイル型に格納した画像を表示したい

タグの編集
投稿者 ブンブン  (社会人) 投稿日時 2019/11/27 09:52:55
恐れ入ります。
長年参考にさせていただいております。
Windows10 Pro で Vsualstudio2010 と Access2010 を使用しております。
題名の通りなのですが、ご教授いただけないでしょうか。
ネットでいくら調べても答えが見つけられなくて…
よろしくお願いいたします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2019/11/27 14:33:55
添付ファイル型以外(たとえば数値や文字列)の読み書きに関する基本的な知識はあるという前提で回答します。

TBL 表において、ID 列(テキスト型)が主キー、
CONTENTS 列が添付ファイル型になっているとした場合、
 TBL.CONTENTS.FileName で添付ファイル名
 TBL.CONTENTS.FileType で拡張子
 TBL.CONTENTS.FileData で添付データ
が返されます。

FileData の先頭にはヘッダ部が含まれていますので、
先頭 4 バイトをオフセットとして読み取った位置が
添付ファイルの本体データとなります。


Imports System.Data.OleDb
Imports System.IO

Public Class Form1
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Me.FlowLayoutPanel1.AutoScroll = True
        Me.FlowLayoutPanel1.BorderStyle = BorderStyle.Fixed3D
        Me.FlowLayoutPanel1.FlowDirection = FlowDirection.TopDown
        Me.FlowLayoutPanel1.WrapContents = False
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        ClearItems()

        Dim sql As String = "SELECT TBL.CONTENTS.FileName AS NM, TBL.CONTENTS.FileType AS EXT, TBL.CONTENTS.FileData AS BIN FROM TBL WHERE TBL.ID=?"
        Using conn As New OleDbConnection(My.Settings.ConnectionString)
            conn.Open()
            Using cmd As New OleDbCommand(sql, conn)
                cmd.Parameters.Add("id", OleDbType.VarChar, 3)
                cmd.Parameters("id").Value = TextBox1.Text

                Dim reader = cmd.ExecuteReader()
                Do While reader.Read()
                    Dim nm As String = CStr(reader!NM)
                    Dim ext As String = CStr(reader!EXT)
                    Dim bin() As Byte = DirectCast(reader!BIN, Byte())
                    AddItem(nm, ext, bin)
                Loop
            End Using
            conn.Close()
        End Using
    End Sub


    Private Sub AddItem(attachName As String, extension As String, contents As Byte())
        Debug.WriteLine(attachName)
        Debug.WriteLine(extension)
        Debug.WriteLine(BitConverter.ToString(contents))

        Dim offset As Integer = BitConverter.ToInt32(contents, 0)
        Dim bin() As Byte = contents.Skip(offset).ToArray()

        Dim lblFileName As New Label()
        lblFileName.Text = attachName
        lblFileName.AutoSize = True
        lblFileName.UseMnemonic = False
        lblFileName.ForeColor = Color.Blue
        Me.FlowLayoutPanel1.Controls.Add(lblFileName)

        Dim lblSize As New Label()
        lblSize.Text = String.Format("{0:N0} Bytes", contents.Length)
        lblSize.AutoSize = True
        Me.FlowLayoutPanel1.Controls.Add(lblSize)

        Dim pic As New PictureBox()
        pic.BorderStyle = BorderStyle.FixedSingle
        pic.BackColor = Color.White
        pic.Margin = New Padding(0, 0, 0, 20)
        Dim stm As New MemoryStream(bin)
        Try
            pic.Image = Image.FromStream(stm)
            pic.Size = pic.Image.Size
            lblSize.Text &= String.Format(", ({0}x{1})", pic.Width, pic.Height)
        Catch
            stm.Dispose()
            pic.Image = pic.ErrorImage
        End Try
        Me.FlowLayoutPanel1.Controls.Add(pic)
    End Sub

    Private Sub ClearItems()
        Me.FlowLayoutPanel1.SuspendLayout()
        For Each ctrl In Me.FlowLayoutPanel1.Controls.OfType(Of Control)().ToArray()
            Using ctrl
                Me.FlowLayoutPanel1.Controls.Remove(ctrl)
            End Using
        Next
        Me.FlowLayoutPanel1.ResumeLayout(True)
    End Sub
End Class
投稿者 ブンブン  (社会人) 投稿日時 2019/11/27 15:51:06
魔界の仮面弁士さまからお返事いただけるなんて感動いたしました。
このサイトと、あなたさまの書き込みには本当に助けられております。
今回、記載していただいたコードの動作確認もできました。
重ねてお礼を申し上げます。
投稿者 (削除されました)  () 投稿日時 2019/11/27 19:11:41
(削除されました)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2019/11/27 19:15:39
一箇所訂正します。

'lblSize.Text = String.Format("{0:N0} Bytes", contents.Length) 
lblSize.Text = String.Format("{0:N0} Bytes", bin.Length)