I have what I believe to be a small oddity in my code. I have a textbox (txtEmail) that get text added to it via code: txtEmail.Text = "Text Here" If I don't tab through the text box before I try to save the record, the text is lost when executing the DataTable.AcceptChanges.
I have tested this by:
Not tabbing through the textboxes - Text gets lost
Tabbing through the textboxes- Text is committed
"Selecting" the textbox via code, then selecting another textbox - Text is commited
Is there something I am missing? Is there any way I can commit the text without selecting or tabbing through the textboxes?
For reference, the textboxes are bound to a binding source, who's DataSource is a DataTable.
Some snippets of code to maybe help...
Filling DA and DT, setting BS:
Using SQLcmd As New SqlCommand With {
.Connection = Vars.sqlConn,
.CommandText = "SELECT * FROM [Database].[Table]"}
da_Users.SelectCommand = SQLcmd
Dim sqlCB As New SqlCommandBuilder(da_Users)
AddHandler da_Users.RowUpdated, AddressOf OnRowUpdated
da_Users.Fill(dt_Users)
dt_Users.Columns("Active").DefaultValue = True
dt_Users.Columns("Phone").DefaultValue = "6-1800, ()"
bs_Users.DataSource = dt_Users
bsnav_Users.BindingSource = bs_Users
End Using
Updating Email Textbox
Private Sub txtName_Leave(sender As Object, e As EventArgs) Handles txtLastName.Leave, txtFirstName.Leave
Try
Dim tb As TextBox = DirectCast(sender, TextBox)
tb.Text = StrConv(tb.Text, VbStrConv.ProperCase)
If Not txtFirstName.Text = "" And Not txtLastName.Text = "" Then
Dim strFNames() = txtFirstName.Text.Trim.Split(New Char() {" "c})
Dim strLNames() = txtLastName.Text.Trim.Split(New Char() {" "c})
txtEmail.Text = strLNames(0) & "." & strFNames(0) & "#sample.com"
End If
Catch ex As Exception
CustExErrorMsg(Name, Reflection.MethodBase.GetCurrentMethod().Name, GetExceptionInfo(ex))
End Try
End Sub
Saving the record:
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles BNavSaveItem.Click
Try
If IsComplete() Then
If blnNew Then If IsDuplicate() Then Exit Sub
lblTSS.Text = "Saving..."
lblTSS.BackColor = Color.IndianRed
Application.DoEvents()
'Added to commit text
txtEmail.Select()
txtFirstName.Select()
Me.Validate()
If blnNew Then dt_Users.AcceptChanges()
bs_Users.EndEdit()
da_Users.Update(dt_Users)
lblTSS.Text = "Done"
lblTSS.BackColor = Color.LightGreen
End If
Catch SqlExceptionErr As SqlException
CustSQLErrorMsg(Name, System.Reflection.MethodBase.GetCurrentMethod().Name, SqlExceptionErr.Message)
Catch ex As Exception
CustExErrorMsg(Name, Reflection.MethodBase.GetCurrentMethod().Name, GetExceptionInfo(ex))
End Try
End Sub
Related
The code below works as intended in DEBUG with no errors. I input my search parameters, the record returns and populates all textboxes and loads the PDF file into the AxAcroPDF1 viewer.
However, after I compile and install the program I am receiving the error "Access to the path 'C:\Program Files (x86)\NAME OF PROGRAM\temp.file' is denied'
This only occurs when I search for a record and the PDF (in Binary format in the DB) to that record is supposed to load fails with the error message listed above. How can I resolve the permissions level (assuming this is the issue) to allow for the PDF to load? The area of concern presumably and more specifically is the LoadPDF() sub.
My code is as follows:
Imports System.Data.SqlClient
Public Class LoadDocs
Private DV As DataView
Private currentRow As String
Private Sub LoadDocs_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'DocDataset.Documents_Table' table. You can move, or remove it, as needed.
Documents_TableTableAdapter.Fill(DocDataset.Documents_Table)
'Loads last record on to form
DocumentsTableBindingSource.Position = DocDataset.Documents_Table.Rows.Count - 1
DV = New DataView(DocDataset.Documents_Table)
'LoadPDF()
End Sub
Private Sub BtnOpenPDF_Click(sender As Object, e As EventArgs) Handles btnOpenPDF.Click
tbRecNumb.Clear()
tbFileName.Clear()
tbPetsLoadNumber.Clear()
tbBrokerLoadNumber.Clear()
tbFilePath.Clear()
Dim CurYear As String = CType(Now.Year(), String)
On Error Resume Next
OpenFileDialog1.Filter = "PDF Files(*.pdf)|*.pdf"
OpenFileDialog1.ShowDialog()
AxAcroPDF1.src = OpenFileDialog1.FileName
tbFilePath.Text = OpenFileDialog1.FileName
Dim filename As String = tbFilePath.Text.ToString
tbFileName.Text = filename.Substring(Math.Max(0, filename.Length - 18))
Dim loadnumber As String = tbFileName.Text
tbPetsLoadNumber.Text = loadnumber.Substring(7, 7)
End Sub
' Search for PETS Load Number, Broker Load Numberthen load record if found
Private Sub BtnSearchBtn_MouseEnter(sender As Object, e As EventArgs) Handles btnSearch.MouseEnter
Cursor = Cursors.Hand
btnSearch.BackgroundImage = My.Resources.ButtonDwn_Teal_Trans
End Sub
Private Sub BtnSearchBtn_MouseLeave(sender As Object, e As EventArgs) Handles btnSearch.MouseLeave
Cursor = Cursors.Default
btnSearch.BackgroundImage = My.Resources.Button_Teal_Trans
End Sub
Private Sub TbSearchInput_KeyDown(sender As Object, e As KeyEventArgs) Handles tbSearchInput.KeyDown
Cursor = Cursors.Hand
If e.KeyCode = Keys.Enter Then
Search()
End If
End Sub
Private Sub BtnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click
btnSearch.BackgroundImage = My.Resources.ButtonClk_Teal_Trans
Cursor = Cursors.Hand
Search()
End Sub
Private Sub Search()
Cursor = Cursors.WaitCursor
If cbColName.Text = "SEARCH BY:" Then
MeMsgBoxSearchCriteria.ShowDialog()
Else : lblSearchResults.Items.Clear()
Select Case DocDataset.Documents_Table.Columns(cbColName.Text).DataType
Case GetType(Integer)
DV.RowFilter = cbColName.Text & " = " & tbSearchInput.Text.Trim
Case GetType(Date)
DV.RowFilter = cbColName.Text & " = #" & tbSearchInput.Text.Trim & "#"
Case Else
DV.RowFilter = cbColName.Text & " LIKE '*" & tbSearchInput.Text.Trim & "*'"
End Select
If DV.Count > 0 Then
For IX As Integer = 0 To DV.Count - 1
lblSearchResults.Items.Add(DV.Item(IX)("PETS_LOAD_NUMBER"))
Next
If DV.Count = 1 Then
lblSearchResults.SelectedIndex = 0
Dim ix As Integer = DocumentsTableBindingSource.Find("PETS_LOAD_NUMBER", CInt(lblSearchResults.SelectedItem.ToString))
DocumentsTableBindingSource.Position = ix
LoadPDF()
Else
lblSearchResults.Visible = True
lblSearchResults.BringToFront()
End If
Else
' Display a message box notifying users the record cannot be found.
MeMsgBoxNoSearch.ShowDialog()
End If
End If
Cursor = Cursors.Default
End Sub
Private Sub LblSearchResults_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lblSearchResults.SelectedIndexChanged
Dim ix As Integer = DocumentsTableBindingSource.Find("PETS_LOAD_NUMBER", CInt(lblSearchResults.SelectedItem.ToString))
DocumentsTableBindingSource.Position = ix
lblSearchResults.Visible = False
End Sub
Private Sub LoadPDF()
Dim temp = Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.User)
If File.Exists(Application.StartupPath() & "\temp.file") = True Then
AxAcroPDF1.src = "blank.pdf"
My.Computer.FileSystem.DeleteFile(Application.StartupPath() & "\temp.file")
End If
Dim cmd As New SqlCommand
cmd.CommandText = "SELECT DOCUMENTS FROM Documents_Table WHERE PETS_LOAD_NUMBER = #pl"
cmd.Parameters.AddWithValue("#pl", tbPetsLoadNumber.Text)
cmd.CommandType = CommandType.Text
cmd.Connection = New SqlConnection With {
.ConnectionString = My.MySettings.Default.PETS_DatabaseConnectionString
}
Dim Buffer As Byte()
cmd.Connection.Open()
Buffer = cmd.ExecuteScalar
cmd.Connection.Close()
File.WriteAllBytes(Application.StartupPath() & "\temp.file", Buffer)
'DATA READER
AxAcroPDF1.src = Application.StartupPath() & "\temp.file"
End Sub
Private Sub DocumentsTableBindingSource_PositionChanged(sender As Object, e As EventArgs) Handles DocumentsTableBindingSource.PositionChanged
Try
currentRow = DocDataset.Documents_Table.Item(DocumentsTableBindingSource.Position).ToString
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub BtnSavePDF_Click(sender As Object, e As EventArgs) Handles btnSavePDF.Click
If tbPetsLoadNumber.Text.Length = 0 Then
MessageBox.Show("Please enter a PETS Load Number", "Missing Load Number", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
ElseIf tbBrokerLoadNumber.Text.Length = 0 Then
MessageBox.Show("Please enter a Broker Load Number", "Missing Load Number", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
ElseIf tbFileName.Text.Length = 0 Then
MessageBox.Show("Please enter a Filename", "Missing Filename", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End If
Try
Using OpenFileDialog As OpenFileDialog = OpenFileDialog1()
If (OpenFileDialog.ShowDialog(Me) = DialogResult.OK) Then
tbFilePath.Text = OpenFileDialog.FileName
Else 'Cancel
Exit Sub
End If
End Using
'Call Upload Images Or File
Dim sFileToUpload As String = ""
sFileToUpload = LTrim(RTrim(tbFilePath.Text))
'Initialize byte array with a null value initially.
Dim data As Byte() = Nothing
'Use FileInfo object to get file size.
Dim fInfo As New FileInfo(tbFilePath.Text)
Dim numBytes As Long = fInfo.Length
'Open FileStream to read file
Dim fStream As New FileStream(tbFilePath.Text, FileMode.Open, FileAccess.Read)
'Use BinaryReader to read file stream into byte array.
Dim br As New BinaryReader(fStream)
'Supply number of bytes to read from file.
'In this case we want to read entire file. So supplying total number of bytes.
data = br.ReadBytes(CInt(numBytes))
'Insert the details into the database
Dim cmd As New SqlCommand
cmd.CommandText = "INSERT INTO Documents_Table (BROKER_LOAD_NUMBER, PDF_FILENAME, PETS_LOAD_NUMBER, DOCUMENTS)
VALUES (#bl, #fn, #pl, #pdf)"
cmd.Parameters.Add("#fn", SqlDbType.NVarChar, 50).Value = tbFileName.Text
cmd.Parameters.Add("#pl", SqlDbType.Int).Value = tbPetsLoadNumber.Text
cmd.Parameters.Add("#bl", SqlDbType.NVarChar, 20).Value = tbBrokerLoadNumber.Text
cmd.Parameters.Add("#pdf", SqlDbType.VarBinary, -1).Value = data
cmd.CommandType = CommandType.Text
cmd.Connection = New SqlConnection With {
.ConnectionString = My.MySettings.Default.PETS_DatabaseConnectionString
}
cmd.Connection.Open()
cmd.ExecuteNonQuery()
cmd.Connection.Close()
MsgBox("File Successfully Imported to Database")
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub
End Class
In your function LoadPDF you create a reference to tempdir and then don't use it. Instead, you use Application.StartupPath() which will point to C:\Programs(x86) and is usually not writeable without admin rights.
But why don't you use your temp dir:
Dim temp = SpecialDirectories.Temp 'more robust approach to get tempdir
If File.Exists(temp & "\temp.file") = True Then
AxAcroPDF1.src = "blank.pdf"
My.Computer.FileSystem.DeleteFile(temp & "\temp.file")
End If
...
File.WriteAllBytes(temp & "\temp.file", Buffer)
'DATA READER
AxAcroPDF1.src = temp & "\temp.file"
Im doing a school project. and I was testing a login form for my app. I'm trying separately from my login form and a profile pic form. I have successfully managed to save the image to the access database but I have had quite a few problems trying to display it on a textbox on my form.
This is the whole app code:
Imports System.Data.OleDb
Imports System.IO
Public Class Form2
Dim con As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\geral\source\repos\BD de imagenes\BD de imagenes\DBImagenes.mdb")
Dim cmd As New OleDbCommand
Dim sql As String
Dim da As New OleDb.OleDbDataAdapter
Dim result As Integer
Private Sub saveimage(sql As String)
Try
Dim arrimage() As Byte
Dim mstream As New System.IO.MemoryStream
PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Png)
arrimage = mstream.GetBuffer()
Dim Filesize As UInt32
Filesize = mstream.Length
mstream.Close()
con.Open()
cmd = New OleDbCommand
With cmd
.Connection = con
.CommandText = sql
.Parameters.AddWithValue("#Imagen", arrimage)
.Parameters.Add("#Nombre", OleDbType.VarChar).Value = TextBox1.Text
.ExecuteNonQuery()
End With
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
End Try
End Sub
'End Try
Public conex As New OleDbConnection()
Public Sub conexion()
conex.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\geral\source\repos\BD de imagenes\BD de imagenes\DBImagenes.mdb"
conex.Open()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles BTNGuardar.Click
sql = "Insert into TBImg (Imagen, Nombre) Values (#Imagen, #Nombre)"
'sql = "Insert into TBImg (Imagen) Values (#Imagen)"
saveimage(sql)
MsgBox("Image has been saved in the database")
End Sub
Private Sub BtnExaminar_Click(sender As Object, e As EventArgs) Handles BtnExaminar.Click
OpenFileDialog1.Filter = "Imagenes JPG|*.jpg|Imagenes PNG|*.png"
OpenFileDialog1.RestoreDirectory = True
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
End If
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
End Sub
Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click
Try
With OpenFileDialog1
'CHECK THE SELECTED FILE IF IT EXIST OTHERWISE THE DIALOG BOX WILL DISPLAY A WARNING.
.CheckFileExists = True
'CHECK THE SELECTED PATH IF IT EXIST OTHERWISE THE DIALOG BOX WILL DISPLAY A WARNING.
.CheckPathExists = True
'GET AND SET THE DEFAULT EXTENSION
.DefaultExt = "jpg"
'RETURN THE FILE LINKED TO THE LNK FILE
.DereferenceLinks = True
'SET THE FILE NAME TO EMPTY
.FileName = ""
'FILTERING THE FILES
.Filter = "(*.jpg)|*.jpg|(*.png)|*.png|(*.jpg)|*.jpg|All files|*.*"
'SET THIS FOR ONE FILE SELECTION ONLY.
.Multiselect = False
'SET THIS TO PUT THE CURRENT FOLDER BACK TO WHERE IT HAS STARTED.
.RestoreDirectory = True
'SET THE TITLE OF THE DIALOG BOX.
.Title = "Select a file to open"
'ACCEPT ONLY THE VALID WIN32 FILE NAMES.
.ValidateNames = True
If .ShowDialog = DialogResult.OK Then
Try
PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
Catch fileException As Exception
Throw fileException
End Try
End If
End With
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Exclamation, Me.Text)
End Try
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
conexion()
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
End Sub
Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click
End Sub
Private Sub BtnBuscar_Click(sender As Object, e As EventArgs) Handles BtnBuscar.Click
Dim arrimage() As Byte
Dim conn As New OleDb.OleDbConnection
Dim Myconnection As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\geral\source\repos\BD de imagenes\BD de imagenes\DBImagenes.mdb"
conn.ConnectionString = Myconnection
conn.Open()
sql = "Select * from TBImg where Nombre=" & (TBBuscar.Text)
Dim cmd As New OleDbCommand
With cmd
.Connection = conex
.CommandText = sql
End With
Dim publictable As New DataTable
Try
da.SelectCommand = cmd
da.Fill(publictable)
TextBox1.Text = publictable.Rows(1).Item("Nombre").ToString
arrimage = publictable.Rows(1).Item("Imagen")
Dim mstream As New System.IO.MemoryStream(arrimage)
PictureBox1.Image = Image.FromStream(mstream)
Catch ex As Exception
MsgBox(ex.Message)
Finally
da.Dispose()
conn.Close()
End Try
End Sub
End Class
the relevant part is at Private Sub BtnBuscar_Click.
I'm trying to search in a textbox for the name that I saved the image with. but I haven't had success all I get is the error of the title.
this is how my database looks like the images are saved as an ole object
This is the error I get
I was following this tutorial https://www.youtube.com/watch?v=zFdjp39mfhQ
but he didn't quite explain how to use the:
TextBox1.Text = publictable.Rows(0).Item(1)
arrimage = publictable.Rows(0).Item(1)'
don't know if it's the cause of the issue.
instructions. The reason why my code looks different is that I was trying to stuff to see if I could make it work.
I have tried to search for answers and people suggest that I may have put the table name wrong or the column but I copied the name exactly how it is in the table with ctrl + c and ctrl + v.
what I want is that when I type the name in the column name of the database that it brings the designated picture stored as ole object onto my desired picture box on my form app.
Needless to say, I'm not that experienced with vb.net and SQL, Acces. I'm just following tutorials for being able to complete the project.
Do not declare connections or commands or datareaders at the class level. They all need to have their Dispose methods called. Using blocks will have the declare, closing and disposing even if there is an error. Streams also need Using blocks.
Defaults for an OpenFiledialog
Multiselect is False
CheckFileExists is True
CheckPathExists is True
DereferenceLinks is True
ValidateNames is True
FileName is ""
Unless you are getting paid by the line, it is unnecessary to reset these values to their defaults.
I have alerted your Filter to exclude All Files. You also had jpg appearing twice.
I declared a variable to hold the file extension, PictureFormat, of the image file so you could provide the proper parameter for ImageFormat.
When you retrieve the image field from the database it comes as an Object. To get the Byte() a DirectCast should work.
Private PictureFormat As String
Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click
FillPictureBoxFromFile()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles BTNGuardar.Click
Try
saveimage()
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
MsgBox("Image has been saved in the database")
End Sub
Private cnStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\geral\source\repos\BD de imagenes\BD de imagenes\DBImagenes.mdb"
Private Sub saveimage()
Dim arrimage() As Byte
Using mstream As New System.IO.MemoryStream
If PictureFormat.ToLower = ".png" Then
PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Png)
ElseIf PictureFormat.ToLower = ".jpg" Then
PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg)
End If
arrimage = mstream.GetBuffer()
Dim Filesize As Long
Filesize = mstream.Length
End Using
Using con As New OleDbConnection(cnStr),
cmd As New OleDbCommand("Insert into TBImg (Imagen, Nombre) Values (#Imagen, #Nombre)", con)
With cmd
.Parameters.Add("#Imagen", OleDbType.Binary).Value = arrimage
.Parameters.Add("#Nombre", OleDbType.VarChar).Value = TextBox1.Text
con.Open()
.ExecuteNonQuery()
End With
End Using
End Sub
Private Sub BtnExaminar_Click(sender As Object, e As EventArgs) Handles BtnExaminar.Click
FillPictureBoxFromFile()
End Sub
Private Sub BtnBuscar_Click(sender As Object, e As EventArgs) Handles BtnBuscar.Click
Dim dt As DataTable
Try
dt = GetDataByName(TBBuscar.Text)
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
TextBox1.Text = dt(0)("Nombre").ToString
Dim arrimage = DirectCast(dt(0)("Imagen"), Byte())
Dim mstream As New System.IO.MemoryStream(arrimage)
PictureBox1.Image = Image.FromStream(mstream)
End Sub
Private Function GetDataByName(name As String) As DataTable
Dim dt As New DataTable
Using conn As New OleDb.OleDbConnection(cnStr),
cmd As New OleDbCommand("Select * from TBImg where Nombre= #Buscar", conn)
cmd.Parameters.Add("#Buscar", OleDbType.VarChar).Value = TBBuscar.Text
conn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Private Sub FillPictureBoxFromFile()
With OpenFileDialog1
.Filter = "(*.jpg)|*.jpg|(*.png)|*.png"
.RestoreDirectory = True
.Title = "Select a file to open"
If .ShowDialog = DialogResult.OK Then
PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
End If
PictureFormat = Path.GetExtension(OpenFileDialog1.FileName)
End With
End Sub
I have a DataGridView where some of the cells only allow values from an AutoCompleteStringCollection. When I enter the cell and begin to type a value, a drop-down window appears with viable options. If I finish typing it out and hit enter or tab, I go to the next cell. However, if I start typing and then select an option from the drop-down menu, it moves one row down in the same column. I’d like it to move to the next cell/next column SAME row after selecting from the drop-down box. Any idea how I go about doing this. Thanks in advance for your help!!
Private Sub getData(ByVal DataCol As AutoCompleteStringCollection)
Dim comm As SqlCommand
Dim adapt As New SqlDataAdapter
Dim ds As New DataSet
Dim sql As String = "SELECT DISTINCT ValueOption From HR.dbo.RecruitVal WHERE ColumnName = 'Source'"
Try
If SqlConn.State = ConnectionState.Broken Then SqlConn.Close()
If SqlConn.State = ConnectionState.Closed Then SqlConn.Open()
comm = New SqlCommand(sql, SqlConn)
adapt.SelectCommand = comm
adapt.Fill(ds)
adapt.Dispose()
comm.Dispose()
For Each row As DataRow In ds.Tables(0).Rows
DataCol.Add(row(0).ToString())
Next
Catch ex As Exception
MessageBox.Show("Error")
End Try
End Sub
Private Sub RAppSrc(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles RAppGrid.EditingControlShowing
Dim titleText As String = RAppGrid.Columns(RAppGrid.CurrentCell.ColumnIndex).HeaderText
If titleText.Equals("Source") Then
Dim autoText As TextBox = TryCast(e.Control, TextBox)
If autoText IsNot Nothing Then
autoText.AutoCompleteMode = AutoCompleteMode.SuggestAppend
autoText.AutoCompleteSource = AutoCompleteSource.CustomSource
Dim dataCol As New AutoCompleteStringCollection()
getData(dataCol)
autoText.AutoCompleteCustomSource = dataCol
End If
End If
End Sub
Cell - Validating
If (appCol.Name = "Source") Then
Dim sql As String = " SELECT 1 FROM Hr.dbo.RecruitVal WHERE ColumnName = 'Source'AND ValueOption = #Source "
Dim sql2 As String = "SELECT DISTINCT ValueOption from HR.dbo.RecruitVal WHERE ColumnName = 'Source' "
Dim com As New SqlCommand(sql, SqlConn)
Dim com2 As New SqlCommand(sql2, SqlConn)
Dim reader As SqlDataReader
Dim val As String
Dim val2 As String
com.Parameters.Add("#Source", SqlDbType.VarChar).Value = e.FormattedValue
val = com.ExecuteScalar()
reader = com2.ExecuteReader()
If reader.HasRows Then
While reader.Read()
val2 += reader.GetValue(0) & "," & Space(3)
End While
End If
If String.IsNullOrEmpty(e.FormattedValue) Then
'Do Nothing
ElseIf val = Nothing Then
MessageBox.Show(" Please Enter a valid Source Option" & vbCrLf & vbCrLf & "Valid Options are as Follows:" & vbCrLf & vbCrLf + val2.ToString(), "VALIDATION ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
RAppGrid.EndEdit()
End If
End If
I've tested few scenarios and found out, that the Enter key wouldn't work (all but Enter works). I found this answer on MSDN:
For the enter key, ProcessDataGridViewKey will return true meaning that it has handled the key so you won't get a KeyDown event for it.
If you override ProcessDataGridViewKey and handle the enter key making it return false, you will get the key events you are expecting.
{
Keys key = (e.KeyCode & Keys::KeyCode); //removes control, alt modifiers
if(key == Keys.Enter)
{
//Still do the default processing for enter so it will move down to the next row
Base.ProcessDataGridViewKey(e);
return false; //say we have *not* handled the key
}
else
{
return Base.ProcessDataGridViewKey(e);
}
}
The above code is in C#, obvously.
The move function then may look like this (tested only VB.NET version bellow and only with other keys than Enter):
Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
If IsNothing(TryCast(e.Control, DataGridViewTextBoxEditingControl)) = False Then
Dim tb As DataGridViewTextBoxEditingControl = e.Control
AddHandler e.Control.KeyDown, AddressOf DataGridView1_Keydown
End If
End Sub
Private Sub DataGridView1_Keydown(sender As Object, e As KeyEventArgs) ' Handles DataGridView1.KeyDown
Dim dgv As DataGridView = DataGridView1
Dim tb As TextBox = CType(sender, TextBox)
If e.KeyCode = Keys.Enter Then
e.SuppressKeyPress = True
dgv.EndEdit()
If IsNothing(dgv.CurrentCell) = False Then
Dim cc As DataGridViewCell = dgv.CurrentCell
If cc.ColumnIndex < dgv.Columns.Count - 2 Then ' if there's a cell to the right of the current one
dgv.CurrentCell = dgv.Rows(cc.RowIndex).Cells(cc.ColumnIndex + 1)
ElseIf cc.RowIndex < dgv.Rows.Count - 1 Then ' if there's a row bellow
dgv.CurrentCell = dgv.Rows(cc.RowIndex + 1).Cells(0)
Else
' do nothing, stay where you are
End If
dgv.CurrentCell.Selected = True
End If
End If
End Sub
I have a .NET project that includes an UltraWinGrid to display data from a database table. On the form with the UWG, I have 3 buttons; 'New Data', 'Edit Data' and 'Delete Data'. The first two open new forms with controls through which to enter/edit the data to be saved. The save function works fine, however when I close the form to see the initial form (with the UWG), the data has not refreshed, and only does so when I close and re-open it.
So, is there any way that I can make the UWG refresh when I press the save button on the new form? (I have already tried calling the function again which loads the UWG, but this doesn't work as I cannot make it a Shared method due to the connections)
Save function code:
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim m_cn As New OleDbConnection
m_cn = m_database.getConnection()
If txtFirstName.Text = "" Then
MsgBox("First name cannot be blank")
ElseIf txtLastName.Text = "" Then
MsgBox("Last name cannot be blank")
ElseIf txtAge.Text = "" Then
MsgBox("Age cannot be blank")
ElseIf txtPostCode.Text = "" Then
MsgBox("Postcode cannot be blank")
Else
Dim personID As Integer = database.SaveNewPerson(txtFirstName.Text, txtLastName.Text, txtAge.Text, txtPostCode.Text, m_cn)
MsgBox("Save successful")
txtFirstName.Text = ""
txtLastName.Text = ""
txtAge.Text = ""
txtPostCode.Text = ""
End If
End Sub
Code that loads the UWG:
Public Sub getPeople()
Try
Dim sql As String = "SELECT * FROM tblPerson"
Dim cm As New OleDbCommand(sql, m_database.getConnection())
Dim da As New OleDbDataAdapter(cm)
Dim dt As New DataTable()
da.Fill(dt)
ugData.DataSource = dt
Catch Ex As Exception
MsgBox("Could not load people")
End Try
End Sub
You should call the getPeople function in the calling form, not in the saving form.
You just need to know if the saving form has terminated correctly or not and this information is available as the return value for the call to ShowDialog. Your button that saves the person data should have the DialogResult property set to OK and then this code should work for you
' Open the form that inserts a new person
' Change that name to your actual form class name...
Using fp = new frmPerson()
' If the user presses the button to save and everything goes well
' we get the DialogResult property from the button pressed
if fp.ShowDialog() = DialogResult.OK Then
ugData.DataSource = Nothing
getPeople()
End If
End Using
Notice the point if all goes well. This means that if, in your button save procedure something does not go well, you should block the form closing changing the DialogResult property to None.
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim m_cn As New OleDbConnection
m_cn = m_database.getConnection()
If txtFirstName.Text = "" Then
MsgBox("First name cannot be blank")
Me.DialogResult = DialogResult.None
ElseIf txtLastName.Text = "" Then
MsgBox("Last name cannot be blank")
Me.DialogResult = DialogResult.None
ElseIf txtAge.Text = "" Then
MsgBox("Age cannot be blank")
Me.DialogResult = DialogResult.None
ElseIf txtPostCode.Text = "" Then
MsgBox("Postcode cannot be blank")
Me.DialogResult = DialogResult.None
Else
Dim personID As Integer = database.SaveNewPerson(txtFirstName.Text, txtLastName.Text, txtAge.Text, txtPostCode.Text, m_cn)
MsgBox("Save successful")
txtFirstName.Text = ""
txtLastName.Text = ""
txtAge.Text = ""
txtPostCode.Text = ""
End If
End Sub
Good morning,
I've been up all night trying to figure this out on my own without bugging anybody else, but I can't.
I've been successful in querying my MySQL database and gotten a set of records into a DataTable (dbTable). During debugging, I can see its contents so I know the data is there. Initially, the DataTable is used to populate a ListView control I have on my form.
When I select a record, I want the contents of the DataTable (or the query I just ran) to be assigned to some TextBox controls. I can't seem to figure out how to do this. Any help would be greatly appreciated.
UPDATE TO ADD IMAGES:
I'm hoping these screenshots will give an idea of what I'm looking to do. The first image shows what happens after an account number has been entered. The second box shows a Groupbox expanded to reveal the form fields after a record has been selected in the ListView.
The control names are: TextBoxCustomer, TextBoxLastName, TextBoxFirstName, ComboBoxSalutation, ComboBoxCardType, TextBoxCard.Text, TextBoxExpireMonth, TextBoxExpireYear, TextBoxCVV2.
The field names in the DataTable (dbTable) are: nameCOMPANY, nameLAST, nameFIRST, nameSALUTATION, ccType, ccNumber, ccExpireMonth, ccExpireYear, ccCode.
IMAGE 1:
IMAGE 2:
Have you tried this?
TextBox1.Text = dbTable.Rows(0)("ColumnName").ToString()
TextBox2.Text = dbTable.Rows(1)("OtherColumnName").ToString()
You can also do this:
Dim row as DataRow = dbTable.Rows(0)
TextBox1.Text = row("ColumnName").ToString()
row = dbTable.Rows(1)
TextBox2.Text = row("OtherColumnName").ToString()
You could also DataBind to a DataGrid (or similar control) using dbTable as the DataSource and then set the DataGrid.EditMode to True. This would create the textbox controls for you.
UPDATE:
Try something like this to bind your textboxes to the selected values of your ListView:
Private Sub ListView1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListView1.SelectedIndexChanged
Dim item As ListViewItem = Nothing
Dim tb As TextBox = Nothing
Dim i As Integer = 0
For Each item In ListView1.SelectedItems
tb = Me.Controls.Find("TextBox" & i.ToString, True)(0)
If tb IsNot Nothing Then
tb.Text = item.Text
End If
i += 1
Next
End Sub
UPDATE:
This is a little more error-proof, but this routine will only work if your textboxes are named TextBox1, TextBox2, TextBox3, etc.:
Private Sub ListView1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListView1.SelectedIndexChanged
Dim item As ListViewItem = Nothing
Dim found() As Control = Nothing
Dim tb As TextBox = Nothing
Dim i As Integer = 0
For Each item In ListView1.SelectedItems
found = Me.Controls.Find("TextBox" & i.ToString, True)
If found.Length > 0 Then
tb = TryCast(found(0), TextBox)
Else
tb = Nothing
End If
If tb IsNot Nothing Then
tb.Text = item.Text
End If
i += 1
Next
End Sub
UPDATE:
Okay, thanks to the screenshots, I am assuming that your ListView.MultiSelect = False, so only one item can be selected at a time. Given that, the following should work as long as the textboxes and ListView columns are named correctly:
Private Sub ListView1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListView1.SelectedIndexChanged
Dim item As ListViewItem = Nothing
If ListView1.SelectedItems.Count = 1 Then
item = ListView1.SelectedItems(0)
txtCardNumber.Text = item.SubItems("CARD NUMBER")
txtCardExpirationMonth.Text = item.SubItems("EXP MO")
txtCardExpirationYear.Text = item.SubItems("EXP YEAR")
End If
End Sub
Hello guys/gals,
With tremendous assistance from Pete, I was able to modify the suggested answer and I achieved the desired solution. To prevent the horizontal scrollbars from displaying, I didn't add columns to the Listview (from the Designer). Instead, I added the fields to the Listview programatically - this way they were available for selection.
The main trouble I ran into was figuring out the Index numbers of the fields. I had to debug several times to figure out what the numbers were - so if anybody knows of a better way please do share.
Here're the two codes I used (thanks Pete):
Private Sub loadCard()
Try
'FOR MySQL DATABASE USE
Dim dbQuery As String = ""
Dim dbCmd As New MySqlCommand
Dim dbAdapter As New MySqlDataAdapter
Dim dbTable As New DataTable
Dim i As Integer
If dbConn.State = ConnectionState.Closed Then
dbConn.ConnectionString = String.Format("Server={0};Port={1};Uid={2};Password={3};Database=accounting", FormLogin.ComboBoxServerIP.SelectedItem, My.Settings.DB_Port, My.Settings.DB_UserID, My.Settings.DB_Password)
dbConn.Open()
End If
dbQuery = "SELECT *" & _
"FROM cc_master INNER JOIN customer ON customer.accountNumber = cc_master.customer_accountNumber " & _
"WHERE customer.accountNumber = '" & TextBoxAccount.Text & "'"
With dbCmd
.CommandText = dbQuery
.Connection = dbConn
End With
With dbAdapter
.SelectCommand = dbCmd
.Fill(dbTable)
End With
ListViewCard.Items.Clear()
For i = 0 To dbTable.Rows.Count - 1
With ListViewCard
.Items.Add(dbTable.Rows(i)("ccID"))
With .Items(.Items.Count - 1).SubItems
.Add(dbTable.Rows(i)("ccNumber"))
.Add(dbTable.Rows(i)("ccExpireMonth"))
.Add(dbTable.Rows(i)("ccExpireYear"))
.Add(dbTable.Rows(i)("ccCode"))
.Add(dbTable.Rows(i)("ccType"))
.Add(dbTable.Rows(i)("ccAuthorizedUseStart"))
.Add(dbTable.Rows(i)("ccAuthorizedUseEnd"))
.Add(dbTable.Rows(i)("nameCOMPANY"))
.Add(dbTable.Rows(i)("nameSALUTATION"))
.Add(dbTable.Rows(i)("nameLAST"))
.Add(dbTable.Rows(i)("nameFIRST"))
End With
End With
Next
If dbTable.Rows.Count = 0 Then
LabelNoCard.Visible = True
LabelNoCard.Focus()
TextBoxAccount.Focus()
Me.Refresh()
Else
If dbTable.Rows.Count > 1 Then
LabelNoCard.Visible = False
LabelMultipleCards.Visible = True
ListViewCard.Visible = True
Me.Refresh()
End If
End If
Catch ex As MySqlException
MessageBox.Show("A DATABASE ERROR HAS OCCURED" & vbCrLf & vbCrLf & ex.Message & vbCrLf & _
vbCrLf + "Please report this to the IT/Systems Helpdesk at Ext 131.")
End Try
dbConn.Close()
End Sub
Here's the second one:
Private Sub ListViewCard_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListViewCard.SelectedIndexChanged
GroupBox2.Visible = True
Dim item As ListViewItem = Nothing
If ListViewCard.SelectedItems.Count = 1 Then
item = ListViewCard.SelectedItems(0)
TextBoxCustomer.Text = item.SubItems(8).Text
TextBoxLastName.Text = item.SubItems(10).Text
TextBoxFirstName.Text = item.SubItems(11).Text
ComboBoxSalutation.Text = item.SubItems(9).Text
ComboBoxCardType.Text = item.SubItems(5).Text
TextBoxCard.Text = item.SubItems(1).Text
TextBoxExpireMonth.Text = item.SubItems(2).Text
TextBoxExpireYear.Text = item.SubItems(3).Text
TextBoxCVV2.Text = item.SubItems(4).Text
DateTimePickerStartDate.Text = item.SubItems(6).Text
DateTimePickerEndDate.Text = item.SubItems(7).Text
End If
End Sub