I am trying to add image with its filename and file path in picture box from SQL but i am getting error "unable to cast system.string to system.byte". how can i do this?
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Dim connection As New SqlConnection("server= .\SQLEXPRESS; database = billing software; integrated security=true")
Dim command As New SqlCommand("select * from stockimagedata where imageid = #imageid", connection)
command.Parameters.Add("#imageid", SqlDbType.Int).Value = TextBox4.Text
Dim table As New DataTable()
Dim adapter As New SqlDataAdapter(command)
adapter.Fill(table)
TextBox4.Text = table.Rows(0)(0).ToString()
TextBox3.Text = table.Rows(0)(1).ToString()
TextBox5.Text = table.Rows(0)(2).ToString()
Dim img() As Byte
img = table.Rows(0)(2)
Dim ms As New MemoryStream(img)
PictureBox1.Image = Image.FromStream(ms)
End Sub
Related
i'm trying to get the image from SQL to picturebox using Listbox in in VB.
here is my sql sample table.
and here is my VB Design form, so what I'm trying to do is when I load the form, if an item in the listbox is selected, i want it to get the image(Binary Data) from sql to picturebox in vb net.
and the code I'm working with it give me this error:
VB full code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
connect()
Dim co As New SqlConnection("Data Source=WXCQSDQSD\SQLEXPRESS;Initial Catalog=food;Integrated Security = True")
co.Open()
Dim com As New SqlCommand("SELECT Image from Items where ItemName = '" & ListBox1.SelectedIndex & "'", co)
Dim img As Byte() = DirectCast(com.ExecuteScalar(), Byte())
Dim ms As MemoryStream = New MemoryStream(img)
Dim dt = GetDataFromSql()
Dim BndSrc As New BindingSource()
BndSrc.DataSource = dt
ListBox1.DisplayMember = "ItemName"
ListBox1.DataSource = BndSrc
TextBox1.DataBindings.Add("Text", BndSrc, "ItemID")
TextBox2.DataBindings.Add("Text", BndSrc, "ItemName")
TextBox3.DataBindings.Add("Text", BndSrc, "Details")
PictureBox1.Image = Image.FromStream(ms)
End Sub
Private Function GetDataFromSql() As DataTable
Dim dt As New DataTable
Using connection As New SqlConnection("Data Source=WXCQSDQSD\SQLEXPRESS;Initial Catalog=food;Integrated Security = True"),
cmd As New SqlCommand("select * FROM Items", connection)
connection.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Remove the picture retrieval from the Form.Load. We have selected all the data in the GetDataFromSql function. The magic happens in the ListBox1.SelectedIndexChanged method.
The SelectedIndexChanged will occur as a result of the code in the Form.Load and every time the selection changes. When we bind the the list box to to binding source the entire row is added as a DataRowView. We can use this to get the data in the Image column. First check if the field is null. Next cast to a byte array. Take the byte array and pass it to the constructor of a MemoryStream. Streams need to be disposed so it is in a Using block. Finally the stream can be assigned to the Image property of the PictureBox.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = GetDataFromSql()
Dim BndSrc As New BindingSource()
BndSrc.DataSource = dt
ListBox1.DisplayMember = "ItemName"
ListBox1.DataSource = BndSrc
TextBox1.DataBindings.Add("Text", BndSrc, "ItemID")
TextBox2.DataBindings.Add("Text", BndSrc, "ItemName")
TextBox3.DataBindings.Add("Text", BndSrc, "Details")
End Sub
Private Function GetDataFromSql() As DataTable
Dim dt As New DataTable
Using connection As New SqlConnection("Data Source=WXCQSDQSD\SQLEXPRESS;Initial Catalog=food;Integrated Security = True"),
cmd As New SqlCommand("select * FROM Items", connection)
connection.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim row = DirectCast(ListBox1.SelectedItem, DataRowView)
If row("Image") IsNot Nothing Then
Dim b() As Byte = DirectCast(row("Image"), Byte()) '< ------ Cast the field to a Byte array.
Using ms As New System.IO.MemoryStream(b)
PictureBox1.Image = System.Drawing.Image.FromStream(ms)
End Using
Else
PictureBox1.Image = Nothing
End If
End Sub
EDIT
I switched the code over to a database I have available for testing. Even though it is not your database, I am sure you will be able to follow the code.
Here is the schema of my database.
The main difference is I moved the DataTable to a class level variable so it can be seen from all methods. I changed the GetDataFromSql to a Sub. It adds the data to the class level DataTable (Bounddt). The AddItem method first gets the Byte() from a file. The row is added to the DataTable with an Object array with elements that match the DataTable.
Private Bounddt As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GetDataFromSql()
Dim BndSrc As New BindingSource()
BndSrc.DataSource = Bounddt
ListBox1.DisplayMember = "CustomerID"
ListBox1.DataSource = BndSrc
TextBox1.DataBindings.Add("Text", BndSrc, "CustomerID")
TextBox2.DataBindings.Add("Text", BndSrc, "CustomerName")
End Sub
Private Sub GetDataFromSql()
Using connection As New SqlConnection("Data Source=****;Initial Catalog='Small Database';Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"),
cmd As New SqlCommand("select * FROM Sales.Customer", connection)
connection.Open()
Using reader = cmd.ExecuteReader
Bounddt.Load(reader)
End Using
End Using
'Return dt
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim row = DirectCast(ListBox1.SelectedItem, DataRowView)
If row("Picture") IsNot Nothing Then
Dim b() As Byte = DirectCast(row("Picture"), Byte()) '< ------ Cast the field to a Byte array.
Using ms As New System.IO.MemoryStream(b)
PictureBox1.Image = System.Drawing.Image.FromStream(ms)
End Using
Else
PictureBox1.Image = Nothing
End If
End Sub
Private Sub AddItem()
Dim picture = GetByteArr("C:\Users\maryo\OneDrive\Documents\Graphics\Animals\squirrel.png")
Bounddt.Rows.Add({5, "George", 74, 62, "George", picture})
End Sub
Private Function GetByteArr(path As String) As Byte()
Dim img = Image.FromFile(path)
Dim arr As Byte()
Dim imgFor As Imaging.ImageFormat
Dim extension = path.Substring(path.LastIndexOf(".") + 1)
'There is a longer list of formats available in ImageFormat
Select Case extension
Case "png"
imgFor = Imaging.ImageFormat.Png
Case "jpg", "jpeg"
imgFor = Imaging.ImageFormat.Jpeg
Case "bmp"
imgFor = Imaging.ImageFormat.Bmp
Case Else
MessageBox.Show("Not a valid image format")
Return Nothing
End Select
Using ms As New MemoryStream
img.Save(ms, imgFor)
arr = ms.ToArray
End Using
Return arr
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
AddItem()
End Sub
Imports System.Data.SqlClient
Imports System.IO
Public Class Form1
Dim con As SqlConnection
Dim cmd As SqlCommand
Dim rdr As SqlDataReader
Dim da As SqlDataAdapter
Private Const cs As String = "ConnectionString"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
con = New SqlConnection(cs)
con.Open()
cmd = New SqlCommand("select * from [dbo].[Item_Details]", con)
rdr = cmd.ExecuteReader()
While rdr.Read
ListBox1.Items.Add(rdr(1))
End While
con.Close()
End Sub
Private Sub ListBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseClick
Try
con = New SqlConnection(cs)
con.Open()
da = New SqlDataAdapter("Select * from Item_Details where itemname='" & ListBox1.SelectedItem.ToString() & "'", con)
Dim dt As New DataTable
da.Fill(dt)
For Each row As DataRow In dt.Rows
TextBox1.Text = row(0).ToString()
TextBox2.Text = row(1).ToString()
TextBox3.Text = row(2).ToString()
Dim data As Byte() = row(3)
Dim ms As New MemoryStream(data)
PictureBox1.Image = Image.FromStream(ms)
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
I'm new to visual basic and I have a problem in loading the image from my database. I'm currently using image data type. This is how I save the image
Imports System.Data
Imports System.Data.SqlClient
Public Class ScannerX_Add
Dim ImageFilename As String
Dim ImageUpload As Image
Private Sub ButtonX1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Btn_Scan.Click
Try
OpenFileDialog1.Title = "Please Select a File"
OpenFileDialog1.InitialDirectory = "C:\Users\ITTestServer\Desktop\Dekstop\"
OpenFileDialog1.ShowDialog()
ScannerX_Pic.Image = Image.FromFile(OpenFileDialog1.FileName)
ImageFilename = OpenFileDialog1.FileName
ImageUpload = Image.FromFile(OpenFileDialog1.FileName)
Catch ex As Exception
MsgBox("Please insert scan finger")
Exit Sub
End Try
End Sub
Private Sub Btn_Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Btn_Save.Click
If ImageFilename <> "" Then
Dim imageNameTemp As String
imageNameTemp = ImageFilename
While (imageNameTemp.Contains("\"))
imageNameTemp = imageNameTemp.Remove(0, imageNameTemp.IndexOf("\") + 1)
End While
Dim ms As New IO.MemoryStream
If ImageFilename.Contains("jpeg") Or ImageFilename.Contains("jpg") Then
ImageUpload.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg)
End If
If ImageFilename.Contains("png") Then
ImageUpload.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
End If
If ImageFilename.Contains("gif") Then
ImageUpload.Save(ms, System.Drawing.Imaging.ImageFormat.Gif)
End If
If ImageFilename.Contains("bmp") Then
ImageUpload.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp)
End If
Dim b() As Byte = ms.ToArray()
Dim cmd As New SqlCommand("Insert into Scanner (Name,Finger) VALUES('" & TxtBox_Name.Text.Trim & "','" & imageNameTemp & "')", Connection)
cmd.Parameters.Add("#BLOBData", SqlDbType.Image, b.Length).Value = b
cmd.ExecuteNonQuery()
MsgBox("Profile Has Been Saved")
Me.Close()
End If
End Sub
Now I need to load my image to picturebox which is currently in the Main form.
Private Sub ButtonX1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonX1.Click
Command.CommandText = ("select Finger FROM Scanner")
Command.Connection = Connection
Dim da As New SqlDataAdapter(Command)
Dim ds As New DataSet()
da.Fill(ds, "projectimages")
Dim c As Integer = ds.Tables(0).Rows.Count
If c > 0 Then
Dim bytBLOBData() As Byte = _
ds.Tables(0).Rows(c - 1)("imagedate")
Dim stmBLOBData As New MemoryStream(bytBLOBData)
ScannerX_Pic2.Image = Image.FromStream(stmBLOBData)
End If
End Sub
Now I get the error Object reference not set to an instance of an object.
To save an image you could do something like this
Dim sql As String = "INSERT INTO Information VALUES(#name,#photo)"
Image Img = PictureBox1.BackgroundImage
Dim cmd As New SqlCommand(sql, con)
cmd.Parameters.AddWithValue("#name", TextBox1.Text)
Dim ms As New MemoryStream()
Img.Save(ms, Img.RawFormat)
Dim data As Byte() = ms.GetBuffer()
Dim p As New SqlParameter("#photo", SqlDbType.Image)
p.Value = data
cmd.Parameters.Add(p)
cmd.ExecuteNonQuery()
And to retrieve an image
cmd = New SqlCommand("select photo from Information where name='Rose'", con)
Dim imageData As Byte() = DirectCast(cmd.ExecuteScalar(), Byte())
If Not imageData Is Nothing Then
Using ms As New MemoryStream(imageData, 0, imageData.Length)
ms.Write(imageData, 0, imageData.Length)
PictureBox1.BackgroundImage = Image.FromStream(ms, True)
End Using
Also check out this article it's doing exactly what you are trying to achieve
http://www.codeproject.com/Articles/437937/Save-and-Retrieve-Image-from-a-SQL-Server-Database
The sql is selecting a column named "Finger":
"select Finger FROM Scanner"
But it's later trying to build an Image object from a column named "imagedate":
ds.Tables(0).Rows(c - 1)("imagedate")
It needs to use the same column name as the SQL result set:
ds.Tables(0).Rows(c - 1)("Finger")
There may be other problems as well, but that's what jumped out at me right away.
This question already has an answer here:
How to Show/Retrieve or Get the Image to PictureBox from Access Database?
(1 answer)
Closed 5 years ago.
Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
GetPicture()
End Sub
Public Sub GetPicture()
con.Open()
Dim dt As New DataTable("Users")
Dim rs As New OleDb.OleDbDataAdapter("Select * from Users where StudentNumber='" & TextBox1.Text & "' ", con)
rs.Fill(dt)
DataGridView1.DataSource = dt
DataGridView1.Refresh()
Label1.Text = dt.Rows.Count
rs.Dispose()
con.Close()
If Val(Label1.Text) = 1 Then
Dim i As Integer
i = DataGridView1.CurrentRow.Index
PictureBox1.Image = FixNull(DataGridView1.Item(6, i).Value)
End If
______________________________
I got this Error on the line: PictureBox1.Image = FixNull(DataGridView1.Item(6, i).Value)
-> Unable to cast object of type 'System.Byte[]' to type 'System.Drawing.Image'.
Screenshot:
I just figgured it out, this is the solution
Public Class Form
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\UsersDB.accdb")
Dim cmd As New OleDbCommand("", con)
Dim Reader As OleDb.OleDbDataReader
Dim cn As New OleDbConnection
Dim i As Integer
Public Sub GetData()
con.Open()
Dim dt As New DataTable("Users")
Dim rs As New OleDb.OleDbDataAdapter("Select * from Users where StudentNumber='" & TextBox1.Text & "' ", con)
rs.Fill(dt)
DataGridView1.DataSource = dt
DataGridView1.Refresh()
Label1.Text = dt.Rows.Count
rs.Dispose()
con.Close()
If Val(Label1.Text) = 1 Then
Dim i As Integer
i = DataGridView1.CurrentRow.Index
'Image
Dim bytes As [Byte]() = (DataGridView1.Item(6, i).Value)
Dim ms As New MemoryStream(bytes)
PictureBox1.Image = Image.FromStream(ms)
End If
End Sub
End Class
I have three columns in SQL, which I want the data displayed in three textboxes by clicking an item in ComboBox.
The issue is not really displaying. I can save the data fine and display. However, one of the text fields will only show one cell and not update when a different item is selected. Hope this is making sense.
Here is the code I have for saving:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim myconnect As New SqlClient.SqlConnection
myconnect.ConnectionString = "Data Source=.\INFLOWSQL;Initial Catalog=RioDiary;Integrated Security=True"
Dim mycommand As SqlClient.SqlCommand = New SqlClient.SqlCommand()
mycommand.Connection = myconnect
mycommand.CommandText = "INSERT INTO MyDiary (Title, DiaryContent, DiaryDate) VALUES (#Title, #DiaryContent, #DiaryDate)"
myconnect.Open()
Try
mycommand.Parameters.Add("#Title", SqlDbType.VarChar).Value = TextBox1.Text
mycommand.Parameters.Add("#DiaryContent", SqlDbType.VarChar).Value = TextBox2.Text
mycommand.Parameters.Add("#DiaryDate", SqlDbType.VarChar).Value = TextBox3.Text
mycommand.ExecuteNonQuery()
MsgBox("Success")
Catch ex As System.Data.SqlClient.SqlException
And here is the code for displaying in form1:
Imports System.Data.SqlClient
Public Class Form1
Dim con As New SqlConnection
Dim ds As New DataSet
Dim da As New SqlDataAdapter
Dim sql As String
Dim inc As Integer
Dim MaxRows As Integer
Dim max As String
Dim dt As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'RioDiaryDataSet5.MyDiary' table. You can move, or remove it, as needed.
Me.MyDiaryTableAdapter.Fill(Me.RioDiaryDataSet5.MyDiary)
Dim con As New SqlConnection(" Data Source=.\INFLOWSQL;Initial Catalog=RioDiary;Integrated Security=True")
Dim cmd As New SqlCommand("Select Title,DiaryContent,DiaryDate FROM MyDiary ")
Dim da As New SqlDataAdapter
da.SelectCommand = cmd
cmd.Connection = con
da.Fill(ds, "MyDiary")
con.Open()
ComboBox1.DataSource = ds.Tables(0)
ComboBox1.DisplayMember = "Title'"
ComboBox1.ValueMember = "DiaryContent"
End Sub
Private Sub NewEntryToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewEntryToolStripMenuItem.Click
AddEntry.Show()
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
If (Not Me.ComboBox1.SelectedValue Is Nothing) Then
Me.TextBox2.Text = ComboBox1.Text
Me.TextBox3.Text = ComboBox1.SelectedValue.ToString
End If
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If dt.Rows.Count > 0 Then
TextBox1.Text = dt.Rows(0)("DiaryDate").ToString() 'Where ColumnName is the Field from the DB that you want to display
End If
End Sub
End Class
As you can see from the code, I want to display Title and DiaryContent in two separate textboxes by clicking on Title in the Combobox. This works fine.
The issue I have is DiaryDate only shows the first entry and does not update when selecting the Item from ComboBox.
Can anyone help?
You can try to play with ComboBox's SelectedItem property. Since ComboBox's DataSource is DataTable here, SelectedItem of ComboBox represent a row in DataTable. Given DataRow in hand, you can display value of any column of DataRow in TextBoxes :
........
If (Not Me.ComboBox1.SelectedItem Is Nothing) Then
Dim SelectedItem = TryCast(comboBox1.SelectedItem, DataRowView)
Me.TextBox1.Text = SelectedItem.Row("Title").ToString()
Me.TextBox2.Text = SelectedItem.Row("DiaryContent").ToString()
Me.TextBox3.Text = SelectedItem.Row("DiaryDate").ToString()
End If
........
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim cn As New SqlClient.SqlConnection("Data Source=thee-pc;Initial Catalog=jobportal;Integrated Security=True")
Dim cmd As New SqlClient.SqlCommand
Dim tbl As New DataTable
Dim da As New SqlClient.SqlDataAdapter
Dim reader As SqlClient.SqlDataReader
Try
cn.Open()
Dim sql As String
sql = "select * from Register"
cmd = New SqlClient.SqlCommand(sql, cn)
reader = cmd.ExecuteReader
While reader.Read
Dim id = reader.Item("cid")
ComboBox1.Items.Add(id)
End While
cn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim cn As New SqlClient.SqlConnection("Data Source=thee-pc;Initial Catalog=jobportal;Integrated Security=True")
Dim cmd As New SqlClient.SqlCommand
Dim tbl As New DataTable
Dim da As New SqlClient.SqlDataAdapter
Dim reader As SqlClient.SqlDataReader
Try
cn.Open()
Dim sql As String
sql = "select * from register where cid ='" + ComboBox1.Text + "'"
cmd = New SqlClient.SqlCommand(sql, cn)
reader = cmd.ExecuteReader
While reader.Read
TextBox1.Text = reader.Item("cname")
TextBox2.Text = reader.Item("dob")
End While
cn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
I have some basic code here that calls in an Access Database ("Houses") and that's about all. However, every time I click the button, the size of the DataGridView doubles. What I mean is that if the actual Access database has 5 rows, the DataGridView shows the correct database initially, but after each click of the button it goes up to 10 rows (they repeat), then 15, then 20 etc. Unfortunately I can't place this in the Form_Load area.
I tried placing "dt.rows.clear()" before "dgv.DataSource = dt", but it wipes everything. Also tried "DirectCast(Dgv.DataSource, DataTable).Rows.Clear()" and "Dgv.Datasource = Nothing"
Public Class frmHouses
Dim dt As DataTable = New DataTable()
Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Houses.accdb"
Dim sqlStr As String = "SELECT * FROM Property"
Private Sub btnRecord_Click(sender As Object, e As EventArgs) Handles btnRecord.Click
Dim dataAdapter As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sqlStr, connStr)
dataAdapter.Fill(dt)
dataAdapter.Dispose()
dgv.DataSource = dt
End Sub
Thanks!
Public Class frmHouses
Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Houses.accdb"
Dim sqlStr As String = "SELECT * FROM Property"
Private Sub btnRecord_Click(sender As Object, e As EventArgs) Handles btnRecord.Click
Dim dt As DataTable = New DataTable()
Dim dataAdapter As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sqlStr, connStr)
dataAdapter.Fill(dt)
dataAdapter.Dispose()
dgv.DataSource = dt
End Sub
OR you can
Public Class frmHouses
Dim dt As DataTable = New DataTable()
Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Houses.accdb"
Dim sqlStr As String = "SELECT * FROM Property"
Private Sub btnRecord_Click(sender As Object, e As EventArgs) Handles btnRecord.Click
dt.clear()
Dim dataAdapter As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sqlStr, connStr)
dataAdapter.Fill(dt)
dataAdapter.Dispose()
dgv.DataSource = dt
End Sub
Public Class frmHouses
Dim dt As DataTable = New DataTable()
Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Houses.accdb"
Dim sqlStr As String = "SELECT * FROM Property"
Private Sub btnRecord_Click(sender As Object, e As EventArgs) Handles btnRecord.Click
Dim dataAdapter As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sqlStr, connStr)
dataAdapter.Fill(dt)
dataAdapter.Dispose()
IF dgv.Rows.Count > 0 Then
dgv.Rows.Clear()
End IF
dgv.DataSource = dt
End Sub