I want to pull image data from SQL Server 2008 Express and display it directly in a Crystal Report. I am using Visual Studio 2012 along with Crystal Reports for Visual Studio (also a full version of SAP Crystal Reports 2013).
I have attempted to use samples from Google/SO searches but I seem to be missing at least one key element. In my project I have a dataset with one field which is of System.Byte(), a Crystal Report, and a viewer.
Here is the snippet of code which queries the database, reads the memorystream, and puts the image data into the dataset.
Dim ds As New DataSet1
Dim row As DataRow
Dim objConn As New SqlConnection(DatabaseConnection.CTLDataConnectionString)
Dim objCommand As SqlCommand = objConn.CreateCommand
objCommand.CommandText = "SELECT Content FROM Report WHERE HandlingUnitID = " & HandlingUID
Dim dr As SqlDataReader = Nothing
If objConn.State = ConnectionState.Closed Then objConn.Open()
dr = objCommand.ExecuteReader
If dr.HasRows Then
dr.Read()
Dim b() As Byte = DirectCast(dr("Content"), Byte())
Using ms As New MemoryStream(b)
ds.DataTable1.Rows.Add(b)
End Using
End If
Dim rpt As New ShipLabel
rpt.SetDataSource(ds.Tables("DataTable1"))
Dim frm As New CRviewer
frm.CRvwr.ReportSource = rpt
frm.ShowDialog()
This will bring up the Crystal Viewer but it is a blank report. I want to know if I have the correct sequence for getting the data, and if I am storing it correctly in the dataset.
After a lot more reading/researching I have the following snippets of code which appear to have the correct sequencing, and correctly storing the data in the dataset. This snippet is from a cellclick event.
Dim ds As New DataSet1
Dim row As DataRow
Dim img As Bitmap
Dim objConn As New SqlConnection(DatabaseConnection.CTLDataConnectionString)
Dim objCommand As SqlCommand = objConn.CreateCommand
objCommand.CommandText = "SELECT Content FROM Report WHERE HandlingUnitID = " & HandlingUID
Dim dr As SqlDataReader = Nothing
If objConn.State = ConnectionState.Closed Then objConn.Open()
dr = objCommand.ExecuteReader
If dr.HasRows Then
dr.Read()
Dim b() As Byte = dr("Content")
Using ms As New MemoryStream(b)
img = Image.FromStream(ms)
b = ConvertImageToByte(img)
ds.DataTable1.Rows.Add(b)
End Using
End If
objConn.Close()
Dim rpt As New ShipLabel
rpt.SetDataSource(ds.Tables("DataTable1"))
rpt.SetParameterValue("JobNumber", OrderNumber.ToString)
Dim frm As New CRviewer
frm.CRvwr.ReportSource = rpt
frm.ShowDialog()
And this function:
Public Shared Function ConvertImageToByte(ByVal Value As Image) As Byte()
If Value IsNot Nothing Then
Dim fs As MemoryStream = New MemoryStream()
CType(Value, Bitmap).Save(fs, ImageFormat.Jpeg)
Dim retval As Byte() = fs.ToArray()
fs.Dispose()
Return retval
End If
Return Nothing
End Function
Related
I'm trying to use an autocomplete textbox, fed from a SQL Serve .mdf database file.
This is my code:
Dim cmd As New SqlCommand("Select col_name FROM college ", cn)
If cn.State = ConnectionState.Closed Then cn.Open()
Dim ds As New DataSet
Dim sqda As New SqlDataAdapter(cmd)
sqda.Fill(ds, "college")
Dim col As New AutoCompleteStringCollection
Dim i As Integer
For i = 0 To ds.Tables(0).Rows.Count - 1
col.Add(ds.Tables(0).Rows(i)("col_name").ToString())
Next
TextBox1.AutoCompleteSource = AutoCompleteSource.CustomSource
TextBox1.AutoCompleteCustomSource = col
TextBox1.AutoCompleteMode = AutoCompleteMode.Suggest
Since I am using SQL Server, the data not showing in the list.
I think its needs to use character N like
Insert data into SQL Server as:
cmd = New SqlCommand("insert into college (col_name) values (N'" & TextBox1.Text.Trim & "')", cn)
Keep your database objects local so you can control the closing and disposing. Using...End Using blocks handle this even if there is an error.
Always use parameters to avoid Sql injection.
In .net Char supports Unicode so strings (which are arrays of Char) also support Unicode. As long as the field in Sql Server is of type NVarChar. I don't see a problem
Private Sub SetUpAutoComplete()
Dim dt As New DataTable
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand("Select col_name FROM college ", cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
Dim col As New AutoCompleteStringCollection
For Each row As DataRow In dt.Rows
col.Add(row("col_name").ToString)
Next
'Just to check if we have some data
Debug.Print(col.Count.ToString)
TextBox3.AutoCompleteSource = AutoCompleteSource.CustomSource
TextBox3.AutoCompleteCustomSource = col
TextBox3.AutoCompleteMode = AutoCompleteMode.Suggest
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
SetUpAutoComplete()
End Sub
Private Sub InsertCollege()
Using cn As New SqlConnection("Your Connection string")
Using cmd As New SqlCommand("insert into college (col_name) values (#Name)", cn)
cmd.Parameters.Add("#Name", SqlDbType.NVarChar).Value = TextBox1.Text.Trim
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End Sub
I have problem with my code which fills multi tables into my dataset. It loads all contents contained in tables of my database to only one table in dataset. My code is shown below. How to load those tables from database into a dataset , that has the same number of tables and contents.
Private Sub Filldataset()
Private cnn As OleDbConnection
Private dt As New DataTable
Private da As New OleDbDataAdapter
Private cmd As New OleDbCommand
Private ds As New DataSet
Dim tblrestrictions As String() = New String() {Nothing, Nothing, Nothing, "TABLE"}
Dim userTables As DataTable = Nothing
userTables = cnn.GetSchema("Tables", tblrestrictions)
Dim i As Integer
For i = 1 To userTables.Rows.Count - 1 Step 1
cnn = New OleDbConnection(Str)
cnn.Open()
cmd = cnn.CreateCommand
cmd.CommandText = "select * from" & " " & userTables.Rows(i)(2).ToString
dt.Clear()
da.SelectCommand = cmd
da.Fill(dt)
da.Fill(ds)
Next
cnn.Close()
MessageBox.Show(ds.Tables.Count)
End Sub
Connections can be created elsewhere but should not be opened or closed until directly before an directly after you use them. You will have to adjust this code for an Oledb application.
Private Sub GetData()
cn.Open()
Dim dt As DataTable = cn.GetSchema("Tables")
cn.Close()
Dim ds As New DataSet
Dim row As DataRow
For Each row In dt.Rows
Dim strTableName As String = row(2).ToString
Dim strSQL As String = "Select * From " & strTableName
Dim cmd As New SqlCommand(strSQL, cn)
Dim da As New SqlDataAdapter
da.SelectCommand = cmd
da.Fill(ds, strTableName)
Next
Debug.Print(ds.Tables.Count.ToString)
End Sub
I scoped several variables locally that you will want to scope to the class like the dataset
I inserted an image into a .mdb database with this code from my WPF app :
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & GetCurrentDirectory() & "\Data\rctts.mdb;Jet OLEDB:Database Password=arn33423342;")
con.Open()
Dim cmd As New OleDbCommand("Insert into recents(Uname,Pic,Email)values(#uname,#pic,#email)", con)
image1.Source = New BitmapImage(New Uri("D:\logo.png"))
Dim buffer As Byte()
Dim bitmap = TryCast(image1.Source, BitmapSource)
Dim encoder = New PngBitmapEncoder()
encoder.Frames.Add(BitmapFrame.Create(bitmap))
Using stream = New MemoryStream()
encoder.Save(stream)
buffer = stream.ToArray()
End Using
cmd.Parameters.AddWithValue("#pic", buffer)
The Pic column or cell's data type is OLE Object...Anyway,after inserting the data,i opened my database,i saw that a new record was added but the value of the Pic column was Long binary data.Anyway,then i went on retrieving the image in my wpf app.I used this code ?
Dim cmd As New OleDbCommand("Select * from recents", con)
Dim table As New DataTable
Dim adap As New OleDbDataAdapter(cmd)
adap.Fill(table)
If table.Rows.Count <= 0 Then
Else
For Each row In table.Rows
recentbtn.Image.ImageSource = BytesToImage(CType(row(1), Byte()))
recentbtn.Names.Text = table.Rows(0)(0).ToString
AddHandler recentbtn.MouseDown, AddressOf recentbtn_mousedow
RecentsList.stp.Children.Add(recentbtn)
Next
End If
loadingrecents.Visibility = Visibility.Hidden
End Sub
Private Shared Function BytesToImage(ByVal bytes As Byte()) As BitmapImage
Dim bm = New BitmapImage()
Using stream As MemoryStream = New MemoryStream(bytes)
stream.Position = 0
stream.Seek(0, SeekOrigin.Begin)
bm.BeginInit()
bm.StreamSource = stream
bm.CreateOptions = BitmapCreateOptions.PreservePixelFormat
bm.CacheOption = BitmapCacheOption.OnLoad
bm.EndInit()
End Using
Return bm
End Function
But it's returning an error : No imaging component suitable to complete the operation was found
Fixed it...For anyone who faces this error in future :
Make sure you're inserting the data in the proper way(sometimes corrupted data in the db causes such errors)
2 . You don't need to do some heavy coding to convert the image to byte!
Finally,let's code :
Public Sub read()
con.Open()
Dim cmd As New OleDbCommand("Select * from recents", con)
Dim _dr As OleDbDataReader
_dr = cmd.ExecuteReader
Dim _photo As Byte()
While _dr.Read()
Try
_photo = CType(_dr(1), Byte())
Dim strm As MemoryStream = New MemoryStream(_photo)
Dim img As System.Drawing.Image = System.Drawing.Image.FromStream(strm)
Dim bi As BitmapImage = New BitmapImage()
bi.BeginInit()
Dim ms As MemoryStream = New MemoryStream()
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp)
ms.Seek(0, SeekOrigin.Begin)
bi.StreamSource = ms
bi.EndInit()
image1.Source = bi
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End While
I've tried to add relation, to show the data on combobox and datagridview. I've tried this code below
Private Sub LoadSemester()
Me.OpenConn()
Dim dSet As New DataSet
Dim sql1 As String = "SELECT * FROM tbl_semester"
Dim comm1 As New SqlClient.SqlCommand(sql1, cnn)
Dim daSemester As SqlClient.SqlDataAdapter
Dim sql2 As String = "SELECT * FROM tbl_mk"
Dim comm2 As New SqlClient.SqlCommand(sql2, cnn)
Dim daMK As SqlClient.SqlDataAdapter
daMK = New SqlClient.SqlDataAdapter(comm2)
dSet.Clear()
daMK.Fill(dSet, "tbl_mk")
daSemester = New SqlClient.SqlDataAdapter(comm1)
dSet.Clear()
daSemester.Fill(dSet, "tbl_semester")
dSet.Relations.Add("relation", dSet.Tables("tbl_semester").Columns("id_pk"), dSet.Tables("tbl_pk").Columns("id_pk"))
With cmbSemester
.DataSource = dSet.Tables("tbl_semester")
.DisplayMember = "semester"
.ValueMember = "id_semester"
.SelectedIndex = 0
End With
'my datagridview here
End Sub
But it displayed nothing. But when I deleted the 'dSet.Relations.Add("relation", dSet.Tables("tbl_semester").Columns("id_pk"), dSet.Tables("tbl_pk").Columns("id_pk"))' the combobox showed the data.
I figured out maybe the problem is the dSet.Relation code. FYI, I am using SQLServer 2005 and VS Express 2012.
In my VB.net code i have:
cmd.CommandText = "SELECT * FROM [strfg].[dbo].[Myfunc] (#MyParam)"
Dim myparam As New SqlParameter("#MyParam", a)
cmd.Parameters.Add(myparam)
The function (runnig on SQL server) returns a table with four columns, one row.
How do I call this function from Visual Basic? cmd.ExecuteScalar() is obviously not correct. In c++ I use a recordset. What is the equivalent in vb? Does anyone have a short example?
You want to do something like this:
Dim reader As SqlDataReader= cmd.ExecuteReader
Dim MyList as new List(Of WhateverObject)
Do While reader.Read
Dim obj as new WhateverObj
obj.Property1 = Reader.GetInt32(0)
obj.Property2 = Reader.GetString(1)
MyList.add(obj)
Loop
reader.Close()
cmd.Dispose()
Where you use the index value based on the order of the returned fields, and its type in the Get.
If you want something that is similar to a recordset consider using a datatable. Your code can look like:
Dim custId As String = "ALFKI"
Dim conn As New SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=True")
Dim da As New SqlDataAdapter("SELECT * FROM Customers Where CustomerId=#CustomerId", conn)
da.SelectCommand.Parameters.AddWithValue("#CustomerId", custId)
Dim ds As DataSet = New DataSet
da.Fill(ds)
Dim dt As DataTable = ds.Tables(0)
The datatable has a collection of Rows which contains your data.