DirectCast MySQL BLOB to a PictureBox - mysql

frmSingleRecord.picImage.Image = DirectCast(sdr("photo_index"), Image)
This code is from my MysqlDataReader and the photo_index is the Blob from my database. I got error from this code.
Unable to cast object of type 'System.Byte[]' to type
'System.Drawing.Image'.
If its possible to DirectCast a Blob to PictureBox how can I do this right? If not any suggestion will be great!

As noted, you cant cast a byte array to a PictureBox which is a UI control, but you can cast the binary BLOB to Byte() so you can create an image from it. Assuming you did save an Image as Byte() to the DB:
...
If rdr.Read() Then
buff = TryCast(rdr.Item(1), Byte())
If buff IsNot Nothing Then
Using ms As New MemoryStream(buff)
pBox.Image = Image.FromStream(ms)
End Using
End If
End If
First, TryCast tries to cast the field data to Byte() to avoid an Exception which could happen if only some rows have image data for them. If the cast worked, an image is created from the Byte() using a MemoryStream and assigned to the PictureBox.Image property. This is probably the reverse of how you got the data into the DB.
Note that you have created a new Image, so it is up to you to also dispose of it when you are done with it.

Related

VB.net DataGridView not display the Data from MySql Data base

I am trying to display the data from MySql database using DataGridView DataSource and MySqlDataAdapter filling a DataTable .
Then the data goes into the DataGridView. I do not know what is the problem, everything seems right and my code is correct, but nothing is being displayed on my DataGridView.
Try
Me.DataGridViewp.DataSource = Nothing
ConnDB()
sqL = "SELECT picture FROM product"
cmd = New MySqlCommand(sqL, conn)
Dim dtSample As New DataTable
Dim daSample As New MySqlDataAdapter(cmd)
daSample.Fill(dtSample)
Me.DataGridViewp.DataSource = dtSample
conn.Close()
conn.Dispose()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
If I understood you correctly, you are trying to show an image in a DatGridView. You should see your images if they are available in the database as byte array. otherwise, it will not be shown in the DatGridView.
I use the following function to convert images to byte array before saving it to the database. Following is a sample code to convert it to byte array before saving. (I am attaching the code as an image since it does not show correctly formatted when I paste it here). You have to add a reference (System.IO) for this code to work in your relevant form.
This works for me and hope this helps you.
.

SSIS Scientific Notation Desirable

I am working on a SSIS project that scans a directory and loops through each excel files that will then be loaded into MSSQL. Currently, I am having an issue with 2966171 being represented as 2.966171e+006. Here is what I have:
1) The Excel Connection String is passing IMEX=1; (Import Export Mode)
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\\UNC\PATH\TO\Excel.xls;Extended Properties="EXCEL 8.0;HDR=NO;IMEX=1";
2) The has confirmed the data type for this field is DT_WSTR of length 255.
Things I have tried:
1) Changing the datatype in Excel to Text
2) Creating a script component that explicitly converts a string to a decimal back to a string. (Terrible Approach)
3) Casting in a derived column component.
EDIT: I must keep this column a DT_WSTR type, some other rows contain alphanumeric values.
use For-each loop controls to loop over excel files
and map the filepath into a variable (ex: #[User::strExcelFile])
in the foreach container you must use 2 dataflow tasks;
the first one contains an excel source and a script component as a destination, the second DataFlowTask is your task
if the excel files have the same structure you must follow the steps below:
open an excel file and change the entirecolumn type to number
in the excel connection manager choose this file
in the second dataflow task in the Excel Source set the delay validation property to true
in the first dataflow task int the script component
properties (script tab) put the variable "strExcelFile" in the read
only variables, And in the script you must do the following steps:
First Add Microsoft.Office.Interop.Excel.dll as a reference
Second read the ExcelFile path from the variable using the following code:
Imports Microsoft.Office.Interop.Excel
Dim strExcelFiles As String = String.Empty
Public Overrides Sub PreExecute()
MyBase.PreExecute()
strExcelFiles = Variables.strExcelFile
End Sub
Third, in The Main Sub write create an Excel.application set the Visible Property to false
Open the ExcelFile and Change the EntireColumnType to Number and save The Excel File and Close the application using the following Code:
Dim ColIdx As Integer = 0 'Number Column index
Dim appExcel As New Excel.Application
appExcel.Visible = False
Dim wrkbExcel As New Excel.Workbook
wrkbExcel = appExcel.Workbooks.Open(strExcelFile)
Dim wrkshExcel As Excel.Worksheet = wrkbExcel.Worksheets(0)
wrkshExcel.Cells(1, ColIdx).EntireColumn.NumberFormat = "0"
'this will change the EntireColumn Type to Number and eliminate scientific character E+
wrkbExcel.Close(True)
appExcel.Quit()
Brief, every Excel file must be edited before importing data from it because the scientific sign appear when a number is stored in a cell having a datatype different from number

Saving Image as OLE Object, in Access

I have a table with a field that is of type OLE Object. I then have a form with a number of fields. Some are just text fields. But, I also have an Image object on the form. When a user clicks a button, a dialog opens and they can pic a photo. Once they select the photo, the Image object displays that picture. I want to save that image to database. What I have only seems to save a reference to where the file is located, on the computer. So, this would not work if the db is moved. Here is the code I have:
Dim wrkCurrent As DAO.Workspace
Dim dbs As DAO.Database
Dim rstPerson As DAO.Recordset
Set wrkCurrent = DBEngine.Workspaces(0)
Set dbs = CurrentDb
Set rstPerson = dbs.OpenRecordset("SELECT * FROM tbl_person WHERE id =" & ID)
With rstPerson
.Edit
!bio_photo = Me.Image37.picture
.Update
End With
How would I save the image file to the OLE Field, so that I could load it back to the Image object, on the form, at a later time?
Thanks
Answer:
So, what I ended up doing was following this https://support.microsoft.com/en-us/kb/210486 [EDIT: that link is now dead, try this instead]
I use the readBLOB function to read the file and save it into the database. Then, when I run a report or open a form that has the picture, onload, I use the WriteBlob function to write the file to a temp folder and then use that path to populate an Image object.
Databases can grow to enormous sizes when you start embedding images, leading to slower queries, crashes, timeouts, and dissatisfied users. Use OLE with caution when adding images into a database
Simple Google search has how to load ole object from folder into table
And a search on this site comes up with auto attach images using vba

Getting a date from a datetimepicker into mysql

I have a datetimepicker in my app which end users will use to choose when an item will be deferred to.
If the user picks a date and hits confirm, the date should be dropped into the mysql record for this entry, but I cant seem to get VB to update the DATE value :(
I'm thinking its probably a formatting thing, but I'm not sure how to best overcome this.
He're the code behind the 'confirm' button.
Private Sub ConfirmDefer_Click(sender As Object, e As EventArgs) Handles ConfirmDefer.Click
Dim deferdate As Date = Format(nb_deferdatepicker.Value, "yyyy-MM-dd")
updatesql("newbusiness_dataset", "action_date", deferdate, "id='" & nb_prospectid.Text & "'")
nb_defer_schedule.Visible = False
nb_defer_schedule.Enabled = False
End Sub
The 'UpdateSQL' bit is a function I use to simplify updating the db.
Its output SQL command is as follows:
UPDATE newbusiness_dataset SET action_date='20/02/2016' WHERE id='100001'
Any help appreciated! Thanks in advance
output SQL command is as follows:
UPDATE newbusiness_dataset SET action_date='20/02/2016' WHERE id='100001'
The way your function is updating is likely incorrect. Ticks are not all-purpose SQL variable delimiters. They are used to indicate text: so your method is converting the Date to string, and possibly the same for Id which are typically numeric. Similarly, this code:
Dim deferdate As Date = Format(nb_deferdatepicker.Value, "yyyy-MM-dd")
Using Option Strict On this will not compile. Format is a function returning a string, but the code is assigning the result to a DateTime var. There is simply no reason to try to format a DateTimePicker value, because it already is a date, and the MySQL NET data provider objects know how to pass a NET date to the db.
Given the resulting SQL, I also suspect you are using concatenation to glue bits of string together for the query. This is very dangerous and can lead to SQL injection attacks. It will also fail on names like Charles D'Artagnan or Pete's Plumbing.
SQL Parameters prevent this, allow you to pass typed data to the data provider and result in easy to read and maintain SQL. The general approach would be like this:
Dim rows As Int32
Dim SQL = "UPDATE Table_Name SET colA = #p1, colB = #p2, colC = #p3 WHERE Id = #p4"
Using dbcon As New MySqlConnection(connStr)
Using cmd As New MySqlCommand(SQL, dbcon)
cmd.Parameters.Add("#p1", MySqlDbType.String).Value = myFrm.TextBox1.Text
cmd.Parameters.Add("#p2", MySqlDbType.Int32).Value = intVar
cmd.Parameters.Add("#p3", MySqlDbType.DateTime).Value = DateTime.Now
' the where:
cmd.Parameters.Add("#p4", MySqlDbType.Int32).Value = intVarA
dbcon.Open()
rows = cmd.ExecuteNonQuery()
End Using
End Using
The USING blocks dispose of the things which should be disposed of to free resources
A new connection and command object are created, used and disposed of. Often helpers like to reuse these, but especially with the DBCommand object there is nothing reusable about them.
Since ExecuteNonQuery will report how many rows are affected, rows captures that result.
The magic, such as it is, is here:
cmd.Parameters.Add("#p3", MySqlDbType.Date).Value = datetimeVar
Using parameters you can pass an actual DateTime variable instead of text. You can use myDateTimePicker.Value because the value is a DateTime.
For a Date column, using MySqlDbType.Date the parameter will pass just the Date portion to the database.
MySqlDbType.DateTime will save whatever portion of the DateTime the DB is setup to accept.
The same is true using MySqlDbType.Int32 for the Id: rather than converting to string, you can pass the correct data type.

Import OLE Object from Access to MySQL

I have a table in an access table which contains Product entries, one of the columns has a jpg image stored as an OLE Object. I am trying to import this table to MySQL but nothing seems to work. I have tried the MySQL migration tool but that has a known issue with Access and OLE Objects. (The issue being it doesnt work and leaves the fields blank) I also tried the suggestion on this site
and while the data is imported it seems as though the image is getting corrupted in the transfer. When i try to preview the image i just get a binary view, if i save it on disk as a jpg image and try to open it i get an error stating the image is corrupt.
The images in Access are fine and can be previewed. Access is storing the data as an OLE Object and when i import it to MySql it is saved in a MediumBlob field.
Has anyone had this issue before and how did they resolve it ?
Ok so in the interests of airing my dirty code in public here what i came up with.
Note : this is a hack designed to be used once and then thrown away.
This Method takes in a datarowview containing 1 row of data from the access table. The Images are wrapped in OLE serialization, im not entirely familiar with how this works but its how Microsoft apps allow any object to be embedded into something else. (eg images into Excel Cells). I needed to remove the serialization junk around the image so i loaded the entire field as a Byte array and searched through it for 3 concurrent entries (FF D8 FF) which represent the beginning of the image data within the field.
Private Function GetImageFromRow(ByRef row As DataRowView, ByVal columnName As String) As Bitmap
Dim oImage As Bitmap = New Bitmap("c:\default.jpg")
Try
If Not IsDBNull(row(columnName)) Then
If row(columnName) IsNot Nothing Then
Dim mStream As New System.IO.MemoryStream(CType(row(columnName), Byte()))
If mStream.Length > 0 Then
Dim b(Convert.ToInt32(mStream.Length - 1)) As Byte
mStream.Read(b, 0, Convert.ToInt32(mStream.Length - 1))
Dim position As Integer = 0
For index As Integer = 0 To b.Length - 3
If b(index) = &HFF And b(index + 1) = &HD8 And b(index + 2) = &HFF Then
position = index
Exit For
End If
Next
If position > 0 Then
Dim jpgStream As New System.IO.MemoryStream(b, position, b.Length - position)
oImage = New Bitmap(jpgStream)
End If
End If
End If
End If
Catch ex As Exception
Throw New ApplicationException(ex.Message, ex)
End Try
Return oImage
End Function
Then its a matter of pulling out this data into a bitmap. So for each row in the access table i extract the bitmap and then update the corresponding MySQL entry.
It worked fine but im guessing i could have removed the serialisation stuff in a better way, perhaps theres an API to do it.
As far as I remember, the Microsoft "SQL Server Migration Assistant for Access" will properly migrate OLE Images, but this is only for Access->SQLServer. However, what you can do is use this to migrate to SQLServer Express (free download) and then migrate from SQLServer to MySQL.
There's also olefield - Python module to extract data out of OLE object fields in Access. I successfully extracted BMP files with it. It could probably work with jpeg images, but I haven't tried it.