Updating Image on database MSAccess Database Vb.net? - vb.net

I want to update images in the database but when i press the button it won't update , I don't have any errors on my code. I added some code in "com.executequery" block to try if i get errors, and i get messagebox result "Error"
Private Sub updatebtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles updatebtn.Click
If Agetxt.SelectedItem = Nothing Or gendertxt.SelectedItem = Nothing Or Yrlvltxt.SelectedItem = Nothing Or PictureBox1.Image Is Nothing Then
MsgBox("Please do not leave required fields blanks.", vbExclamation, "Warning!")
Else
Dim memstream As New MemoryStream
Dim datapic_update As Byte()
Me.PictureBox1.Image.Save(memstream, Imaging.ImageFormat.Jpeg)
datapic_update = memstream.GetBuffer()
memstream.Read(datapic_update, 0, memstream.Length)
'to check if connection is open
If con.State = ConnectionState.Open Then
con.Close()
End If
'Updating DB
Dim editQ As String = "Update Infos SET FirstName=#f1, SurName=#f2, MiddleName=#f3, [Birthdate]=#f4, Gender=#f5, HomeAddress=#f6, CityAddress=#f7, BaranggayAddress=#f8, EmailAdd1=#f9, Birthplace=#f10, Yearlevel=#f11, Course=#f12, Emailadd2=#f13, [Age]=#f14, [Telnum]=#f15, [Mobilenum1]=#f16, [Mobilenum2]=#f17, FathersName=#f18, FathersL=#f19, MothersName=#f20, MothersL=#f21, FathersOcc=#f22, MothersOcc=#f23, StreetAdd=#f24, [Image]=#Image WHERE [StudentID]=#fid "
Dim com As New OleDbCommand(editQ, con)
con.Open()
com.Parameters.AddWithValue("#fid", Stdntid.Text.ToString)
com.Parameters.AddWithValue("#f1", fname.Text)
com.Parameters.AddWithValue("#f2", Sname.Text)
com.Parameters.AddWithValue("#f3", Mname.Text)
com.Parameters.AddWithValue("#f4", Datetxt.Value.ToShortDateString)
com.Parameters.AddWithValue("#f5", gendertxt.SelectedItem.ToString)
com.Parameters.AddWithValue("#f6", homaddtxt.Text)
com.Parameters.AddWithValue("#f7", Cityadd.Text)
com.Parameters.AddWithValue("#f8", brgyadd.Text)
com.Parameters.AddWithValue("#f9", emailaddtxt.Text)
com.Parameters.AddWithValue("#f10", birthPtxt.Text)
com.Parameters.AddWithValue("#f11", Yrlvltxt.SelectedItem.ToString)
com.Parameters.AddWithValue("#f12", coursetxt.Text)
com.Parameters.AddWithValue("#f13", emailadd2txt.Text)
com.Parameters.AddWithValue("#f14", Agetxt.SelectedItem.ToString)
com.Parameters.AddWithValue("#f15", telnumtxt.Text)
com.Parameters.AddWithValue("#f16", mobilenum1txt.Text)
com.Parameters.AddWithValue("#f17", mobilenum2txt.Text)
com.Parameters.AddWithValue("#f18", FathersL.Text)
com.Parameters.AddWithValue("#f19", fatherstxt.Text)
com.Parameters.AddWithValue("#f20", MothersL.Text)
com.Parameters.AddWithValue("#f21", motherstxt.Text)
com.Parameters.AddWithValue("#f22", fOcc.Text)
com.Parameters.AddWithValue("#f23", mOcc.Text)
com.Parameters.AddWithValue("#f24", streetadd.Text)
' image content
Dim image As OleDbParameter = New OleDbParameter("#Image", SqlDbType.Image)
image.Value = datapic_update
com.Parameters.Add(Image)
com.ExecuteNonQuery()
If com.ExecuteNonQuery > 0 Then
MsgBox("Records Successfully Updated.", vbInformation, "Updated.")
Else
MsgBox("error")
End If
End If
con.Close()
End Sub

The fact that the ExecuteNonQuery call succeeds but returns zero means that there were no records in your database that match your WHERE clause. The reason is that you're adding your parameters incorrectly.
Both the Jet and ACE OLE DB providers use positional parameters only. Even though you can give your parameters names, those names are ignored by the provider. That means that you need to add your parameters to your OleDbCommand in the same order as they appear in the SQL code. You are not.
In your SQL code, #fid is the last parameter but this is the last parameter you add to the command:
com.Parameters.AddWithValue("#f24", streetadd.Text)
That is therefore the value being used to find matching records. Rearrange the code that adds parameters to the command and add #fid last and you'll be good to go.

Related

datagridview last programmatically changed cell does not get included in changedrows

VB.net app changes values in a datagridview programmatically. The values are all as they should be, but the save routine (dtShipments is the datatable that is the source for the datagridview)
Dim dtChanges As DataTable = dtShipments.getchanges()
If more than one has changed, dtChanges is always missing the last row.
In the routine that changes the cell values, I have tried DatagridView1.EndEdit and DatagridView1.CommitEdit, but the behavior is the same. I even tried adding a SendKeys.Send(vbTab) line, since hitting the tab key when making the changes manually is enough to get all the changes to show up in .GetChanges.
What am I missing?
code per request:
Private Sub btnAssign_Click(sender As Object, e As EventArgs) Handles btnAssign.Click
strModErr = "Form1_btnAssign_Click"
Dim sTruck As String = ""
Try
sTruck = Me.DataGridView2.SelectedCells(0).Value.ToString
For Each row As DataGridViewRow In DataGridView1.SelectedRows
row.Cells("Truck").Value = sTruck
Next
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
Catch ex As Exception
WriteErrorToLog(Err.Number, strModErr + " - " + Err.Description)
End Try
End Sub
Private Function SaveChanges() As Boolean
strModErr = "Form1_SaveChanges"
Dim Conn As New SqlConnection(My.Settings.SQLConnectionString)
Dim sSQL As String = "UPDATE fs_Shipments SET Truck = #Truck, Stop = #Stop WHERE SalesOrder = #SO"
Dim cmd As New SqlCommand(sSQL, Conn)
Dim sSO, sTruck As String
Dim iStop As Integer = 0
Try
DataGridView1.EndEdit()
DataGridView1.ClearSelection()
Dim dtChanges As DataTable = dtShipments.getchanges() 'DataRowState.Modified
If Not dtChanges Is Nothing Then
Conn.Open()
For Each row As DataRow In dtChanges.Rows
sSO = row("SalesOrder").ToString
sTruck = row("Truck").ToString
iStop = CInt(row("Stop").ToString)
With cmd.Parameters
.Clear()
.AddWithValue("#SO", sSO)
.AddWithValue("#Truck", sTruck)
.AddWithValue("#Stop", iStop)
End With
cmd.ExecuteNonQuery()
Next
End If
Return True
Catch ex As Exception
WriteErrorToLog(Err.Number, strModErr + " - " + Err.Description)
Return False
End Try
End Function
I am not exactly 100% sure why this happens. The problem appears to be specific to when the user “selects” the cells in the first grid, and then calls the SaveChanges code “BEFORE” the user has made another selection in the first grid. In other words, if the user “selects” the rows to “assign” the truck to in grid 1, then, “AFTER” the “selected” cells have been filled with the selected truck, THEN, the user selects some other cell in grid 1, THEN calls the save changes code. In that case the code works as expected.
All my attempts at committing the changes, either failed or introduced other issues. I am confident a lot of this has to do with the grids SelectedRows collection. IMHO, this looks like a risky way to set the cell values, I would think a more user-friendly approach may be to add a check box on each row and assign the truck values to the rows that are checked. But this is an opinion.
Anyway, after multiple attempts, the solution I came up with only further demonstrates why using a BindingSource is useful in many ways. In this case, it appears the DataTable is not getting updated with the last cell change. Again, I am not sure “why” this is, however since it appears to work using a BindingSource, I can only assume it has something to do with the DataTable itself. In other words, before the “Save” code is executed, we could call the tables AcceptChanges method, but then we would lose those changes. So that is not an option.
To help, below is a full (no-fluff) example. In the future, I highly recommend you pull out the parts of the code that do NOT pertain to the question. Example, all the code that saves the changes to the DB is superfluous in relation to the question… so remove it. The more unnecessary code you add to your question only increases the number of SO users that will “ignore” the question. If you post minimal, complete and working code that reproduces the problem so that users can simply copy and paste without having to add addition code or remove unnecessary code will increase you chances of getting a good answer. Just a heads up for the future.
The solution below simply adds a BindingSource. The BindingSource’s DataSource is the DataTable dtShipments then the BindingSource is used a DataSource to DataGridView1. Then in the SaveChanges method, “before” the code calls the dtShipment.GetChanges() method, we will call the BindingSources.ResetBinding() method which should complete the edits to the underlying data source, in this case the DataTable dtShipments.
If you create a new VS-VB winforms solution, drop two (2) grids and two (2) buttons onto the form as shown below, then change the button names to “btnAssign” and “btnApplyChanges.” The assign button will add the selected truck in grid two to the selected rows in grid one. The apply changes button simply resets the binding source and displays a message box with the number of rows that were changed in the dtShipments DataTable. It should be noted, that the code calls the dtShipments.AcceptChanges() method to clear the changes. Otherwise, the code will update changes that have already been made.
Dim dtShipments As DataTable
Dim dtTrucks As DataTable
Dim shipBS As BindingSource
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
dtShipments = GetShipmentsDT()
shipBS = New BindingSource()
shipBS.DataSource = dtShipments
dtTrucks = GetTrucksDT()
dtShipments.AcceptChanges()
DataGridView1.DataSource = shipBS
DataGridView2.DataSource = dtTrucks
End Sub
Private Function GetShipmentsDT() As DataTable
Dim dt = New DataTable()
dt.Columns.Add("ID", GetType(String))
dt.Columns.Add("Truck", GetType(String))
dt.Rows.Add(1)
dt.Rows.Add(2)
dt.Rows.Add(3)
dt.Rows.Add(4)
Return dt
End Function
Private Function GetTrucksDT() As DataTable
Dim dt = New DataTable()
dt.Columns.Add("Truck", GetType(String))
For index = 1 To 10
dt.Rows.Add("Truck" + index.ToString())
Next
Return dt
End Function
Private Sub btnAssign_Click(sender As Object, e As EventArgs) Handles btnAssign.Click
Dim sTruck = DataGridView2.SelectedCells(0).Value.ToString
'Dim drv As DataRowView
For Each row As DataGridViewRow In DataGridView1.SelectedRows
'drv = row.DataBoundItem
'drv("Truck") = sTruck
row.Cells("Truck").Value = sTruck
Next
'DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
'shipBS.ResetBindings(True)
'DataGridView1.CurrentCell = DataGridView1.Rows(0).Cells(0)
End Sub
Private Function SaveChanges() As Boolean
Try
shipBS.ResetBindings(True)
Dim dtChanges As DataTable = dtShipments.GetChanges()
If (dtChanges IsNot Nothing) Then
MessageBox.Show("There are " & dtChanges.Rows.Count & " rows changed in the data table")
' update sql DB
dtShipments.AcceptChanges()
End If
Return True
Catch ex As Exception
Return False
End Try
End Function
Private Sub btnApplyChanges_Click(sender As Object, e As EventArgs) Handles btnApplyChanges.Click
Dim ChangesMade As Boolean
ChangesMade = SaveChanges()
End Sub
Lastly, since you are using VB… I highly recommend that you set the “Strict” option to “ON.” When this option is ON, it will flag possible errors that you may be missing. To do this for all future VB solutions, open VS, close any solutions that may be open, then go to Tools->Options->Projects and Solutions->VB Defaults, then set “Option Strict” to “On.” The default setting is off.
I hope this makes sense and helps.

How to get the same query results displayed in both MS visual studio and listbox?

I was trying to run a search query to give me all records specified in the where clause in ms management studio with the desired result. However when I transferred that query into my vb project there was only one record displayed on the listbox.
Sql query in ms management studio:
select * from tblInwardFile where org_name = 'MSW' and in_file_date_recieved like '05-Jun-19'
Below is my vb project:
Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click
lstUpload.Items.Clear()
Try
cm = New SqlCommand("select * from tblInwardFile where org_name = 'MSW' and in_file_date_recieved like '05-Jun-19'", cn)
dr.Close()
dr = cm.ExecuteReader
dr.Read()
If dr.HasRows Then
lst = lstUpload.Items.Add(dr.Item(0))
lst.SubItems.Add(dr.Item(1))
lst.SubItems.Add(dr.Item(2))
lst.SubItems.Add(dr.Item(3))
lst.SubItems.Add(dr.Item(4))
lst.SubItems.Add(dr.Item(6))
Else
MessageBox.Show("File not found", "Message", MessageBoxButtons.OK, MessageBoxIcon.Warning)
dr.Close()
viewUploaded()
lowColor()
End If
'dr.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
I would expect to see all records for the same query are displayed in the listbox. This is a query result in ms managment studio
Calling Read and then testing HasRows makes no sense at all. Here's how you should use those two members:
If there will never be more than one row, just call Read. If it returns True then there is data to read and if it returns False then there is no data. You only need an Else block if you want to do something specific if there is no data, e.g. notify the user.
If myDataReader.Read() Then
'Read data here.
End If
If myOtherDataReader.Read() Then
'Read data here.
Else
'There is not data.
End If
If there could be more than one row then you should use a Do or While loop and use the result of Read as the termination condition. As long as it is True, there is data to read, so terminate when it is False.
While myDataReader.Read()
'Read data here.
End While
2A. If there could be more than one row and you want to do something specific if there is none, e.g. notify the user, use an If...Else block to test HasRows and place your loop in the If block.
If myDataReader.HasRows Then
Do While myDataReader.Read()
'Read data here.
Loop
Else
'There is no data.
End If

Check DGV row for missing value with an sql bound back end

I am currently working in vb.net windows express 2013 with an sql back end. I am trying to create an if statement that will look at a specific cell and make a decision based on if the cell has nothing in it or not. I think the return for an sql statement is null but im not 100% sure. I have tried lots of codes I dug up on the internet but none of them have worked for me so far. Here is the line:
Dim Row_Index As Integer = DGVStart.CurrentCell.RowIndex
If DGVStart.Rows(Row_Index).Cells(1).Value Is Nothing Then
This code does work, as in the windows express is telling me the line is fine, however, it seems that I am always getting the return of nothing, even if something is in the cell.I think this problem has something to do with the way i am pulling the value. I have a datagridview checkbox column which i manually added in the design form and if i change it to cells(0), which is my manually inserted column, it picks it up every time. I need to know how to tell my program to differentiate between is null and is not null.
UPDATE: I am now running into new issues after changing to searching for dbnull. here is my code.
Private Sub DGVStart_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DGVStart.CellContentClick
'dim start time
Dim start As String = TxtStart.Text
'fail safe so headers cant be clicked
If e.RowIndex = -1 Then
Exit Sub
End If
'dim row index and check, check is for the parts shear columns
Dim Row_Index As Integer = DGVStart.CurrentCell.RowIndex
'Dim check As String = DGVStart.Rows(Row_Index).Cells(2).Value
'if checkbox is clicked
If e.ColumnIndex = 0 Then
'---------------------------------------------Normal parts---------------------------------------------------------------
'If DGVStart.Rows(Row_Index).Cells(1).Value Then
If IsDBNull(DGVStart.Rows(Row_Index).Cells(3).Value) = True Then
Dim Shear As Date = DGVStart.Rows(Row_Index).Cells(5).Value
Dim Machine As Int16 = DGVStart.Rows(Row_Index).Cells(4).Value
Dim ShearNumber As String = DGVStart.Rows(Row_Index).Cells(1).Value
Dim Parts As String = DGVStart.Rows(Row_Index).Cells(3).Value
'Pull Values for sql statement and other operations
Try
'set up for checkbox event to trigger
If e.ColumnIndex = 0 Then
'safety messagebox
Dim result As Integer = MsgBox("Are you sure Shear Number " & ShearNumber & " is being started?", MessageBoxButtons.YesNo)
'if messagebox is no
If result = DialogResult.No Then
Exit Sub
'if messagebox is yes
ElseIf result = DialogResult.Yes Then
'sql update
Using conn1 As New SqlConnection(connstring)
conn1.Open()
Using comm1 As New SqlCommand("UPDATE table1 SET " & start & " = getdate() Where col = value AND col = value", conn1)
With comm1.Parameters
.AddWithValue("#Shear", Shear)
.AddWithValue("#Machine", Machine)
End With
comm1.ExecuteNonQuery()
End Using
conn1.Close()
End Using
End If
End If
Catch ex As Exception
MsgBox(ex.ToString)
MsgBox("Error checking off start date for this machine, please contact the manufacturing enginnering department.")
End Try
Call refresh()
Call refresh2()
'--------------------------------------------------------Parts special--------------------------------------------------
Else
MsgBox("Parts")
End If
End If
End Sub
***Please note my sql statements have been modified to protect the company I am working for but I am sure the sql code works.
NEW PROBLEM: I am receiving a null error message because if i uncomment this line:
If DGVStart.Rows(Row_Index).Cells(1).Value Then
Then I am trying to see if a cell is null but that causes an error. I am trying to use my if statement to either run the normal parts, or special parts of my code.
Thanks,

Combo box not refreshed after insert/delete records

I am using vb.net and access 2007
I have a problem regarding combo box refresh
This is my code:
Private Sub comboRefresh()
Try
cmbSn_no.DataSource = Nothing
cmbSn_no.Items.Clear()
Dim asql As String = ("SELECT * FROM Vendor_det")
da = New OleDb.OleDbDataAdapter(asql, cnnOLEDB)
da.Fill(ds, "Vendor_det")
cmbSn_no.ValueMember = "sr_no"
cmbSn_no.DataSource = ds.Tables(0)
cmbSn_no.SelectedIndex = 0
'DataGridView1.DataSource = ds.Tables(0)
'DataGridView1.Update()
Catch ex As Exception
MsgBox("ERROR : " & ex.Message.ToString)
End Try
End Sub
Private Sub cmbSn_no_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmbSn_no.SelectedIndexChanged
Dim asql As String = ("SELECT * FROM Vendor_det where sr_no='" & cmbSn_no.Text & "'")
cnnOLEDB.Open()
cmd = New OleDb.OleDbCommand(asql, cnnOLEDB)
dr = cmd.ExecuteReader
If dr.Read = True Then
cmbSn_no.Text = dr("sr_no")
txtPart_no.Text = dr("part_no")
..........
End If
cnnOLEDB.Close()
End Sub
And i call comborefresh() method from add and delete record button click events.
if i dont use the commented code and click on add / delete button then the output comes some how like this:
records in db:
abcd123
bbbc123
if i add a record cccc123.. it should update and my combo box should fill with following records:
abcd123
bbbc123
cccc123
but it fills with
abcd123
bbbc123
cccc123
abcd123
bbbc123
and if i use the commented line then the combo box is filled with "System.Data.DataRowView"
No prompted error comes but i am not getting my answer...
even i have tried with....
combobox.refresh()
combobox.selectedindex=-1
and
combobox.items.clear()
it does not work
Please resolve my problem....
Thank you in advance...:)
Your code to refresh the ComboBox should be OK, but no need to call cmbSn_no.Items.Clear() since cmbSn_no.DataSource = Nothing will remove all data from the ComboBox.
However, based on your code I assume that you declare your DataSet (ds) as form variable, thus when you want to fill in the ds, the old data (first 2 data - abcd123 bbbc123) is still there, and then run the Fill method will add those old data with a whole set of new data - that are abcd123 bbbc123 cccc123. To make sure, try to add this code after da.Fill(ds, "Vendor_det"):
MsgBox.Show(ds.Tables(0).Rows.Count)
I think it will show 5, not 3. If that's the case, try to refresh the DataSet first before Fill, either by creating a new instance of DataSet, or delete the table.

Catch Access DB Error (FormatException) And Return Custom Message?

I have an access database with a field that requires an integer. I am passing in some data that is retrieved from an Excel spreadsheet and if a string is retrieved from the cell then the calling function's Try/Catch will hit a FormatException. What I am trying to figure out is if it's possible (and it always is) to throw a custom error message that will display the cell address that contained the invalid data. Here is some example code of what I have.
Public Class Main
Private cellAddress As String
Private Sub btn_Import(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnImport.Click
Dim openFileDialog As New OpenFileDialog()
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
openFileDialog.Filter = "Excel Files (*.xls)|*.xlsx|All files (*.*)|*.*"
openFileDialog.RestoreDirectory = True
If openFileDialog.ShowDialog() <> Windows.Forms.DialogResult.OK Then
Return
End If
Try
ImportWorksheet(New FileInfo(openFileDialog.FileName))
Catch ex As FormatException
MessageBox.Show("The data contained within cell " & cellAddress & " is invalid.", "Error")
End Try
End Sub
Private Sub ImportWorksheet(ByVal excelFile As FileInfo)
Dim cnn As New OleDbConnection(My.Settings.cnn)
Dim cmd As OleDbCommand = GetCommand("UpdateSite")
Dim worksheet1 As ExcelWorksheet = package.Workbook.Worksheets(1)
Using package As New ExcelPackage(excelFile)
Using cmd.Connection
cmd.Connection.Open()
cmd.Parameters.Add("#MyData", OleDbType.Integer).Value = GetCellContents(worksheet1, "K8")
cmd.ExecuteNonQuery()
End Using
End Sub
Private Function GetCellContents(ByVal worksheet As ExcelWorksheet, ByVal address As String) As Object
If worksheet.Cells(address).Value Is Nothing Then
Return DBNull.Value
Else
cellAddress = address
Return worksheet.Cells(address).Value
End If
End Function
End Class
Don't think I'm missing anything here, I kind of copied and pasted and altered the code to shorten and not give up any unneeded info. Once the code hits the ExecuteNonQuery() method, the error bubbles up and says whatever I have written in. I want to pass the cell address when this happens if at all possible so they know where to look.
The only way I can think of doing this would be to add a class level variable and set it to the current cell every time it gets the value. The only issue is that since it only fires at ExecuteNonQuery(), and I have multiple parameters, if the first added parameter is invalid but the next parameter isn't, then the cell is set to the last parameter every time and I get the wrong result. Is there a way to get some kind of message back from the database that will tell me specifically which parameter didn't convert properly?
Nevermind, I just went with this for now... It works, but if you guys can give me something better, please do.
cmd.Parameters.Add("#MyData", OleDbType.Integer).Value = GetCellContents(worksheet2, "K8", "Int32")
Private Function GetCellContents(ByVal worksheet As ExcelWorksheet, ByVal address As String, Optional ByVal type As String = Nothing) As Object
If worksheet.Cells(address).Value Is Nothing Then
Return DBNull.Value
Else
cellAddress = address
Select Case type
Case Is = "String"
Return Convert.ToString(worksheet.Cells(address).Value)
Case Is = "Int32"
Return Convert.ToInt32(worksheet.Cells(address).Value)
Case Is = "DateTime"
Return Convert.ToDateTime(worksheet.Cells(address).Value)
Case Else
Return worksheet.Cells(address).Value
End Select
End If
End Function