I would like to retrieve the picture from access database when the user login to the system.
Firstly, the user will type his/her Staff ID and Password to login.
Secondly, if the user granted to login the system, it will show another form.
Thirdly, that another form will show the user's first name and last name.
Furthermore, I would like to show the picture that saved in Access Database too. Could any senior help me?
This is my code:
Private Sub ShowStaffData(ByVal CurrentRow)
txtFirstName.Text = DTS.Tables("Staff").Rows(CurrentRow)("User's_First_Name")
txtLastName.Text = DTS.Tables("Staff").Rows(CurrentRow)("User's_Last_Name")
End Sub
Private Sub RetrieveStaffInformation()
Dim StaffID As String
Dim i, j As Integer
Dim Command As New OleDbCommand("SELECT Picture FROM Staff WHERE Staff_ID ='" & txtStaff_ID.Text & "'", Connection)
Command.Parameters.AddWithValue("#Staff_ID", txtStaff_ID.Text)
Connection.Open()
Dim PictureData As Byte() = DirectCast(Command.ExecuteScalar(), Byte())
Connection.Close()
Command.Dispose()
Dim Stream As New IO.MemoryStream(PictureData)
picStaff.Image = Image.FromStream(Stream)
txtStaff_ID.Text = Login.txtStaff_ID.Text
Stream.Dispose()
StaffID = txtStaff_ID.Text
j = DTS.Tables("Staff").Rows.Count - 1
i = 0
While i <> j + 1
If StaffID = DTS.Tables("Staff").Rows(i)("Staff_ID") Then
ShowStaffData(i)
End If
i += 1
End While
End Sub
Check you OleDbCommand. Maybe your select statement is not findind the Staff_ID because your where clause is comparing Staff_ID against a string, and in most cases this ID is a numeric value stored as integer.
Dim Command As New OleDbCommand("SELECT Picture FROM Staff WHERE Staff_ID = ?", Connection)
Command.Parameters.AddWithValue("#Staff_ID", CInt(txtStaff_ID.Text))
Anyway, you should provide some error details, if you got any errors...
Related
I have a (Household) table which have two columns: firstname and lastname. The second table (Complaints) also has two columns: respondents and remarks. Now im trying to check when the selected row in (household) has the same name values to the respondents column and has "UNSETTLED" value in remarks column. Then it will show household has records. If the value of respondents has a match but the remarks is = SETTLED then then the household has no records.
This is where to select the household
and when i select a row and click the button use selected
This form will open and the household has/no records, will show up in the black panel
I dont know what im doing wrong here so here's my code
Dim i As Integer
i = DataGridView1.CurrentRow.Index
Dim householdid = DataGridView1.Item(0, i).Value
Dim GLOBALid = DataGridView1.CurrentRow.Cells(0).Value
If con.State = ConnectionState.Closed Then
con.Open()
End If
Try
Dim command As New OleDbCommand("SELECT * FROM Household WHERE ID=#id", con)
Dim da As New OleDbDataAdapter(command)
With command
.Parameters.Add("#id", OleDb.OleDbType.VarChar).Value = GLOBALid
End With
command.ExecuteNonQuery()
Dim cmd1 As New OleDbCommand("SELECT count(*) FROM Complaint WHERE respondents LIKE '% #lastname %' OR respondents LIKE '% #firstname %' AND remarks=UNSETTLED ", con)
Dim da1 As New OleDbDataAdapter(cmd1)
With cmd1
.Parameters.Add("#lastname", OleDb.OleDbType.VarChar).Value = DataGridView1.Item(1, i).Value
.Parameters.Add("#firstname", OleDb.OleDbType.VarChar).Value = DataGridView1.Item(2, i).Value
End With
'Dim numrows As Integer = 0
'numrows = cmd.ExecuteScalar()
Dim rowcount = Convert.ToInt32(command.ExecuteScalar())
If rowcount >= 1 Then
BrgyclearanceWithRecords.Label17.ForeColor = Color.Red
BrgyclearanceWithRecords.Label17.Text = "Resident's Name has a match with an Existing unsettled complain!"
ElseIf rowcount = 0 Then
'BrgyclearanceWithRecords.Panel1.Visible = True
BrgyclearanceWithRecords.Label17.ForeColor = Color.Green
BrgyclearanceWithRecords.Label17.Text = "Resident's Name has no match with an Existing unsettled complain!"
End If
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
BrgyclearanceWithRecords.Show()
BrgyclearanceWithRecords.BringToFront()
End Sub
I don't guarantee it solves every problem but..
WHERE respondents LIKE '% #lastname %'
it doesn't work like this; that will literally just search for any rows where the respondents field contains the text " #lastname "
WHERE respondents LIKE #lastname
and if you want to put wildcards you put them in the value
Parameters.Add("#lastname", OleDb.OleDbType.VarChar).Value = "Smith%"
I would think your database should look something like this.
Where the ID in the Households table is the Primary Key and has a one to many relationship to the HouseholdID Foreign Key in the Complaints table.
I am guessing that DataGridView1 contains the Households and the first column contains the ID column.
The Using block includes the connection and the command. Both need to be disposed. End Using also closes the connection.
When you are using a literal string in the Where criteria, it needs to be surrounded by single quotes.
Since you are only retrieving a single value from the database you can use ExecuteScalar() which returns an Object, thus the CInt().
Once the connection is safetly closed and disposed with the End Using, you can check your returned value, count, and take the required actions.
Private OPConStr As String = "Your connection string."
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim count As Integer
Dim i = DataGridView1.CurrentRow.Index
Dim householdid = CInt(DataGridView1.Item(0, i).Value)
Try
Using con As New OleDbConnection(OPConStr),
cmd As New OleDbCommand("SELECT count(*) FROM Complaints WHERE HouseholdID = #ID AND Remarks = 'UNSETTLED';", con)
cmd.Parameters.Add("#id", OleDbType.Integer).Value = householdid
con.Open()
count = CInt(cmd.ExecuteScalar())
End Using
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
If count >= 1 Then
BrgyclearanceWithRecords.Label17.ForeColor = Color.Red
BrgyclearanceWithRecords.Label17.Text = "Resident's Name has a match with an Existing unsettled complain!"
Else
BrgyclearanceWithRecords.Label17.ForeColor = Color.Green
BrgyclearanceWithRecords.Label17.Text = "Resident's Name has no match with an Existing unsettled complain!"
End If
BrgyclearanceWithRecords.Show()
BrgyclearanceWithRecords.BringToFront()
End Sub
I'm quite new to VB .Net and Databases in general so I'm not sure which SQL Version I am using. I did most of my coding until now with VBA.
I added a "Service Based Database" to my "WinFormsApp" Project and created a Table with 3 Columns:
CREATE TABLE [dbo].[employees] (
[id] INT IDENTITY (1, 1) NOT NULL,
[nr] VARCHAR (MAX) NULL,
[name] TEXT NULL,
PRIMARY KEY CLUSTERED ([id] ASC)
);
Afterwards I added a Dataset for the created Table.
Following this, I added a new Form to my Project and added a few controls to it including two TextBoxes for Dataentry and a DataGridView to show the saved data. On Form_Load I fill the DataGridView using the following code:
Private Sub UpdateGridView()
'Loading the data into the GridView
'---------------------------------------
Dim Conn As SqlConnection = New SqlConnection
Dim ADP As SqlDataAdapter
Dim DS As DataSet = New DataSet
Conn.ConnectionString = My.Settings.DBConnEmployees
ADP = New SqlDataAdapter("SELECT * FROM employees", Conn)
ADP.Fill(DS)
Me.DataGridView_Employees.DataSource = DS.Tables(0)
'---------------------------------------
'Hidding the ID Col
Me.DataGridView_Employees.Columns(0).Visible = False
End Sub
Also in the Form_Load I set a few unrelated variables and TextBoxes (as I'm not able to find the errors after several hour of trial and error, I include this. Maybe I'm overlooking something):
Private Sub NewEmployee()
'Reseting the Variables
DataGridIndex = -1
EmployeeId = 0
EmployeeNr = String.Empty
EmployeeName = String.Empty
'Writing to TBs
Me.tbNr.Text = EmployeeNr
Me.tbName.Text = EmployeeName
'Select Nothing
Me.DataGridView_Employees.CurrentCell = Nothing
'Changing Btn Desc
Me.btnSaveEmployee.Text = "Neuen Mitarbeiter speichern"
End Sub
The testing data I entered into the table by hand fills in without a problem. Inserting, updating an deleting into/from the table by code works perfect.
On DataGrivView_CellDoubleClick I read some data of the the GridView into the TextBoxes to edit them:
Private Sub DataGridView_Employees_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView_Employees.CellDoubleClick
If e.RowIndex <> -1 Then
'Loading selected Data
DataGridIndex = e.RowIndex
EmployeeId = Me.DataGridView_Employees.Rows(DataGridIndex).Cells(0).Value
EmployeeNr = Me.DataGridView_Employees.Rows(DataGridIndex).Cells(1).Value
EmployeeName = Me.DataGridView_Employees.Rows(DataGridIndex).Cells(2).Value
'Write to TBs
Me.tbNr.Text = EmployeeNr
Me.tbName.Text = EmployeeName
'Changing btn
Me.btnSaveEmployee.Text = "Ă„nderungen speichern"
End If
End Sub
To prevent the User from using the nr twice I wanted to check if the nr is already saved in the Table. However this is where the problems begin. The SQLCommand only finds the row which i double clicked in the GridView. Which is strange as there should be no connection between them. Hereafter my try at checking for the nr:
Private Function EmployeeNrInUse(id As Integer, nr As String) As Boolean
Dim Query As String = String.Empty
Dim Result
Dim Response As Boolean = True
'Checking for nr
'---------------------------------------
Query = "SELECT * FROM employees WHERE nr=#nr"
Using Conn = New SqlConnection(My.Settings.DBConnEmployees)
Using Comm = New SqlCommand()
With Comm
.Connection = Conn
.CommandType = CommandType.Text
.CommandText = Query
.Parameters.AddWithValue("#nr", nr)
End With
Try
Conn.Open()
Result = Comm.ExecuteScalar
Response = Not IsNothing(Result)
Catch ex As SqlException
MsgBox(ex.Message.ToString, vbOKOnly + vbCritical)
End Try
End Using
End Using
'---------------------------------------
'Return
Return Response
End Function
The Result is always returning nothing, unless I double clicked a dataentry before, then it finds it's own row (if the nr matches) but only that, no other matching nr is found.
If I forgot to mention crucial data, please inform me as this is my first question ever in a forum :) (Also please excuse any spelling mistakes etc. as English isn't my native language) Thanks in Advance for your help!
Edit:
This is how the Function EmployeeNrInUse is called (Called on Button_Clicked):
Private Sub SaveEmployeeToDB(id As Integer, nr As String, name As String)
Dim Query As String = String.Empty
'Adding new Employee / Editing existing
'---------------------------------------
If EmployeeNrInUse(id, nr) Then
MsgBox("Nr. bereits in verwendung.", vbOKOnly + vbExclamation)
Exit Sub
End If
If EmployeeId = 0 Then
Query = "INSERT INTO employees (nr, name) VALUES (#nr, #name)"
Else
Query = "UPDATE employees SET nr=#nr, name=#name WHERE id=#id"
End If
Using Conn As New SqlConnection(My.Settings.DBConnEmployees)
Using Comm As New SqlCommand()
With Comm
.Connection = Conn
.CommandType = CommandType.Text
.CommandText = Query
.Parameters.AddWithValue("#id", id) 'Wird nur bei änderung verwendet
.Parameters.AddWithValue("#nr", nr)
.Parameters.AddWithValue("#name", name)
End With
Try
Conn.Open()
Comm.ExecuteNonQuery()
UpdateGridView()
If EmployeeId = 0 Then
MsgBox("Neuen Mitarbeiter gespeichert.", vbOKOnly + vbInformation)
Else
MsgBox("Bestehenden Mitarbeiter aktualisiert.", vbOKOnly + vbInformation)
End If
NewEmployee()
Catch ex As SqlException
MsgBox(ex.Message.ToString, vbOKOnly + vbCritical)
End Try
End Using
End Using
'---------------------------------------
End Sub
The problem was caused by entering the values into the Database by hand. While copying the nr, a linebreak sneaked itself into the values so a check just for the nr instead the nr and the linebreak resulted in nothing. Properly entering the data has fixed the problem.
I've search a lot of resources and couldn't fix it.
My problem is when I click the button event the next form doesn't show and also I want to close my login form at the same time.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim firstname As String = ""
Dim lastname As String = ""
Dim ara As Boolean = False
cn = New OleDbConnection(con)
cn.Open()
Dim user As String
Dim pass As String
user = TextBox1.Text
pass = TextBox2.Text
With cmd
.Connection = cn
.CommandText = "Select * from users WHERE username='" & user & "' AND password='" & pass & "'"
.ExecuteNonQuery()
rdr = cmd.ExecuteReader
If rdr.HasRows Then
ara = True
While rdr.Read()
firstname = rdr("firstname").ToString
lastname = rdr("lastname").ToString
lib_name = firstname + lastname
End While
If ara = True Then
Form2.Show()
Me.Close()
x = True
Else
MsgBox(" Access Denied!" + Environment.NewLine + "Sorry, username or password is incorrect!")
End If
End If
End With
cn.Close()
cmd.Dispose()
1 : You are opening the gates of SQL INJECTION. Read more . Instead of passing values directly in your query, pass parameters first and use them later(For unknown reason, the code formatting is not working below) :
Dim cmd as New OleDbCommand("Select * from users WHERE username=#user AND password=#pass" , con)
With cmd
.Parameters.Add("#user", OleDbType.Varchar).Value = user
.Parameters.Add("#user", OleDbType.Varchar).Value = password
End With
2 : Your If statement will only work IDateReader.HasRows returns true and if ara=True which is unnecessary. .HasRows is a boolean, you don't need to create another boolean and pass the value to it. However, the rest of your code will only execute if your conditions match
3 : Form1.Close and AnotherForm.Show will never work if in your Project Proerties , Shutdown Mode is set to On main window close(by default). Either change it to On Explicit window close or On last window close or change
Me.CLose To
Me.Hide
4 : In order to reduce too much code , you can use Using Statement :
Using cmd as New SqlCommand("Select * from users WHERE username=#user AND password=#pass" , con)
'''codes here
End Using
''Now no need to call cmd.Dispose
Hope this helps :)
Assume that i have a login table that stores 3 attributes:
USERNAME
PASSWORD
USERTYPE
Note that i am using Access Database
In my login.vb form, there is 2 textboxes for the user to enter their username and password. And one Login button to validate the login.
My question is how to redirect the windows form based on userType.
Below is my codes for login.vb.
Private Sub btn_login_Click(sender As System.Object, e As System.EventArgs) Handles btn_login.Click
Dim mysql As String = "SELECT COUNT(*) AS NUM_MATCHES FROM TABLE WHERE USERNAME='" & username.Text & "' and PASSWORD ='" & password.Text & "'"
Dim mydatatable As New DataTable
Dim myreader As New OleDb.OleDbDataAdapter(mysql, myconnection)
myreader.Fill(mydatatable)
Dim num_matches As String = mydatatable.Rows(0).Item("NUM_MATCHES")
If num_matches = 1 Then
If userType = "CUSTOMER" Then
username = username.Text
form_customer.Show()
Me.Hide()
ElseIf userType = "STAFF" Then
form_staff.Show()
Me.Hide()
End If
Else
txt_username.Text = ""
txt_password.Text = ""
MsgBox("Incorrect Username or Password")
End If
End Sub
I have set userType as Public userType As String in the module so that the whole application can access. But when i debug the application, there is no error and when i click the login button, nothing happened.
There is one possible case where the code posted will not throw an error but will not open a form or display a message box either: when num_matches is 1 but userType is neither "CUSTOMER" nor "STAFF".
As pointed out in the comments, your code does not assign a value to userType. I'm assuming that it needs to do so here. I don't use MS Access myself, but I do use MySQL, and your current query is only returning the count of matches, not any other column value such as USERTYPE. You need to modify your query or add a second one to get information into your VB userType variable. Perhaps this will work:
Dim mysql As String = "SELECT COUNT(*) AS NUM_MATCHES, USERTYPE..."
...
userType = mydatatable.Rows(0).Item("USERTYPE")
That's just a guess on my part, since I use MySql.Data.MySqlClient classes for queries, but you should still get the idea.
You really should read all the answers.... Irene has basically given you all you needed... here is a rewrite of your code.
Private Sub btn_login_Click(sender As System.Object, e As System.EventArgs) Handles btn_login.Click
Dim mysql As String = "SELECT * FROM TABLE WHERE USERNAME='" & username.Text & "' and PASSWORD ='" & password.Text & "'"
Dim mydatatable As New DataTable
Dim myreader As New OleDb.OleDbDataAdapter(mysql, myconnection)
myreader.Fill(mydatatable)
If mydatatable.Rows.Count = 1 Then
'we have a row
'assign userType
userType = mydatatable.Rows(0).Item("USERTYPE")
If userType = "CUSTOMER" Then
username = username.Text
form_customer.Show()
Me.Hide()
ElseIf userType = "STAFF" Then
form_staff.Show()
Me.Hide()
End If
Else
txt_username.Text = ""
txt_password.Text = ""
MsgBox("Incorrect Username or Password")
End If
End Sub
Note that the above code does not address the issue of sql injection.
I sort of wonder why you are counting matches in your select statement but then checking for the number of matches by looking at how many rows there are in the datatable.
The way your logic is set up, as long as the user name and password are found, you have a match. Therefore the code in the if clause is executed. As others have noted, you are not assigning anything to userType here. You can prove to yourself that this is the problem by adding an ELSE clause to the code like this:
If num_matches = 1 Then
If userType = "CUSTOMER" Then
username = username.Text
form_customer.Show()
Me.Hide()
ElseIf userType = "STAFF" Then
form_staff.Show()
Me.Hide()
Else
MsgBox("Incorrect user type.")
End If
Else
txt_username.Text = ""
txt_password.Text = ""
MsgBox("Incorrect Username or Password")
End If
If I were writing this code, I would change the SQL statement to select the userType based on user name and password. You don't need to use count(*) then and can simply test the number of rows in the datatable and act accordingly.
By the way, if it is at all possible that the same username/password combination could be included in the table twice with different user types, then your test should be If num_matches >= 1 Then instead of If num_matches = 1 Then as well because in the situation where there is more than one match, execution will jump to the Else portion of the statement with the message "Incorrect Username or Password."
I have a form where i want to enter Sr. Nos for machines.it have a combo box where i have to choose the invoice no saved in another table along with its corresponding qty of machines.
When i am entering machine details it should say me as "enter Sr no. for X'th/Y'th machine where y is the total qty saved in db and x is the no. of sr no. i have saved+1 "
It should also allow me to save the no. some where.. i mean in any variable so that if i pause my work in between and after word if continue it should say me "enter detail for X'th/Y'th" not "1'st/Y'th"
I am using this code:
Private Sub get_qty()
Dim qtySql As String = "SELECT * FROM invoice1 where chalan_no='" & cmbChal_no.Text & "'"
cnnOLEDB.Open()
Dim cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand(qtySql, cnnOLEDB)
Dim dr As OleDb.OleDbDataReader = cmd.ExecuteReader
If dr.Read = True Then
qnty = dr("qty")
End If
cnnOLEDB.Close()
End Sub
Private Sub Srno_enter()
Dim noSql As String = "SELECT count(sr_no) FROM Vendor_machine GROUP BY(chalan_no) having chalan_no='" & cmbChal_no.Text & "'"
cnnOLEDB.Open()
Dim cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand(noSql, cnnOLEDB)
' Suggest code retrieve count(sr_no) <--------------------------
cnnOLEDB.Close()
End Sub
private sub show()
lblMachine= 'Result of count(sr_no)' "/" qnty
end sub
Please suggest me the code for same.. thank you..
Just use an Identity column in your database and let the database engine do the work of creating the next free number.
If you wrote a stored procedure to do the insert, you could return the serial number as an output parameter