My Access DataBase has few Rows under single person. Some Person's row count is 1, but another person's row count more than 1.
I want create Tab Pages to insert that person's details.
When Creating Tab Pages,
Tab Pages count must be equal to Row Count. (If that person has 04 rows - 04 tab pages must be created.
Separate MS-Access DB row data (Column) put in to that tab Pages
If click 1st Tab Page : -----> 1st Rows of that Person Details (Field Data / Column) should be there with TextBoxes or Labels.
If Click 4th Tab Page : ------> 4th Row of that Person Details (Field Data / Column) should be there with TextBoxes or Labels.
I already created tab Pages according to row count with this code
Dim newPage As New TabPage()
Dim RecCount As Integer
While QReaderQ.Read()
RecCount = RecCount + 1 ' Count How many Rows
End While
TabControl1.TabPages.Clear()
For xXx = RecCount To 1 Step -1 ' to Desending Order ---->3,2,1
newPage = New TabPage 'create new instance
If xXx = 1 Then
newPage.Text = "Repeat - 1"
Else
newPage.Text = "Repeat - " & xXx.ToString
End If
TabControl1.TabPages.Add(newPage)
Next
I want put details from Database in to Tab Pages.
Example:
1st time repeat data to 1st Tab Page (repeat Data mean DB Column).
4th time repeat data to 4th Tab Page (repeat Data mean DB Column).
Since you're using Access, I'm going to assume you're using OleDb. You don't indicate what QReaderQ is, but based on the name it sounds like it's an OleDbDataReader.
Since (again, according to your posted code) you want to go in descending order, I'd suggest you use the OleDbDataAdapter instead - DataReaders are forward-only, so you can't go in reverse order.
I'd also suggest moving your code to create each tab page to its own function, and calling that function from within your For loop.
Putting this all together it might look something like this:
Dim TabContent As DataTable
' Pass in your selection string and your connection object
Dim Adapter As New OleDbDataAdapter("SELECT * FROM table", con)
Dim newPage As TabPage
' Fill the DataTable TabContent with the result from your select command
Adapter.Fill(TabContent)
TabControl1.TabPages.Clear()
For xXx As Integer = TabContent.Rows.Count To 1 Step -1
' Pass in the current row - use xXx - 1 since the row collection is 0 based
newPage = InitializeTabPage(TabContent.Rows(xXx - 1))
newPage.Text = "Repeat - " + xXx.ToString()
TabControl1.TabPages.Add(newPage)
Next
InitializeTabPage is a function that returns a TabPage. You'll need to create the controls on this page.
Public Function InitializeTabPage(ByVal Row As DataRow) As TabPage
Dim newPage As New TabPage()
' Create the control and bind the data from the row to them
Return newPage
End Function
In the InitializeTabPage function, you're taking a DataRow from the table. You'll need to create the TextBoxes and Labels on each tab page and then bind the appropriate data to them from the row.
For example, if you have a label called lblName, and a column in your row Name, you could do this:
lblName.Text = Row("Name").ToString()
Some helpful links:
OleDbDataAdapter Class
A Really Simple Database - Tutorial on VB.NET and Access
Related
I have been attempting many ways to retrieve 2 collections together, while the first collection holds a comma-separated value in a column, we can not find a solution to passing the first collection value to the second For Each.
This code simply retrieves database rows and adds each result to our list control using the Add() method.
Dim transferstable As New DataTable
count = 0
For Each row As DataRow In transferstable.Rows
Dim name = Truncate(row.Item("name"), 42)
ListControl1.Add(name, row.Item("username")", row.Item("added"), avatars, row.Item("online"), images(count), 0)
count += 1
Next
Problem
We need to nest the loops, so we get the value from the first collection from the "avatars" column (image1,image2,image3) and call it from Add() - 4th parameter.
We only get always 1 string result into the view, while the actual query reports many rows with 2 strings (image1, image2) so I tried this:
Dim lst As New List(Of String) From {
transferstable.Rows(0).Item(8)
}
count = 0
For Each item As String In lst
For Each row As DataRow In transferstable.Rows
Dim name = Truncate(row.Item("name"), 42)
ListControl1.Add(name, row.Item("username")", row.Item("added"), item, row.Item("online"), images(count), 0)
count += 1
Next
Next
And the still the same single result! (8) is the GROUP_CONCAT column for "avatars" How do we pass this list over to the 4th parameter?
We want to retrieve these as URL remote images and render them to view with Bitmap.
Expected result:
A list of 15x15 pictures that represent each split result from GROUP_CONCAT(avatars)
I've been at all different ways to do this for most of the day, I know nesting is the right direction but I can't figure out why only 1 result is coming back (image1 - not image1,image2, etc.)
Some physical image files do not exist anymore, so rendering that to view also has it halt after a few single string results, so it quits and gives an error, like a 404 but does not proceed with the 180 other rows.
https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/for-each-next-statement
Each time a user changes a value in one of the editable columns within my DataGridView, it triggers a recalculation of up to 8 fields. This means the event CellValueChanged Event on the DataGridView will trigger more than 1 time.
I want to create a row in a DataSet.DataTable which will include the new values for all columns after the user has changed a value.
The issue I am having is that the code below creates a row for each column that has had its value changed due to the recalculated columns.
Private Sub PL_DGV_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles PL_DGV.CellValueChanged
If isLoaded Then
Dim grid_row As DataRow = Me.DataSet.PL.Rows(e.RowIndex)
Dim unsaved_row As DataRow = grid_row
Me.DataSet.PL_UnsavedChanges.ImportRow(unsaved_row)
unsaved_changes = True
End If
End Sub
How could I make it so that if a row already exists, it will just update the values within it each time?
There is no PrimaryKeys assigned to the DataTable within the DataSet, but there are 3 columns which would be used as unique values per row.
[UPDATE BASED ON COMMENTS]
With the code shown above what will happen is that the user will update a value in column 1 >
Event is triggered and new row is created which will include the new value in Column 1 >
Column 2 is recalculated based on changes in Column 1 >
Event is triggered and new row is created which will include the new value in Column 1 and Column 2 >
Column 3 is recalculated based on changes on either of the previously mentioned columns >
Event is triggered and new row is created which will include new value in Column 1, Column 2 and Column 3.
What I want to achieve is to have 1 row which will have all the new values, no need to generate any other rows but one which includes the changes from the user action and any recalculations based on that.
After the discussion within the comments the solution to my issue, or rather what I did to overcome it was the below:
Dim grid_row As DataRow = Me.DataSet.PL.Rows(e.RowIndex)
Dim Column1 = Variable1
Dim Column2 = grid_row.Item("Column2").ToString().Trim()
Dim Column3 = grid_row.Item("Column3").ToString().Trim()
Dim Updated_column_name = Me.DataSet.PL.Columns(e.ColumnIndex).ColumnName
Dim Updated_value = grid_row.Item(Updated_column_name).ToString()
Dim row As DataRow = Me.DataSet.PL_ChangesLog.NewRow()
row("price_list") = Price_list
row("warehouse") = Warehouse
row("product_code") = Product
row("column_name") = Updated_column_name
row("updated_value") = Updated_value
row("timestamp") = DateTime.Now()
row("username") = Environment.UserName()
Me.DataSet.PL_ChangesLog.Rows.Add(row)
unsaved_changes = True
This allows me to create a DataTable holding a row of data for each cell that has had its value updated, whether recalculated via code or by user action.
Based on that I can pick out the last audit and use that as the "Save Changes" to commit the changes to the SQL Database.
Where I work we receive electronic meters from customers and try to solve the errors they have. We will receive 4-8 meters at a time that all have the same problem, same specs, same everything, the only thing different between each meter is the Serial Number. I want to be able to enter every serial number, and the common specs all in one form to create multiple records.
Here's a pic of what I have for the form. I was able to create records for just one serial number at a time, but I would like to do it all at once to make data entry quicker and easier.
Meter Entry Form
So summary, Multiple Meters, all identical specs, different serial numbers. I want to enter it all into a form and have multiple records created. Thanks for any help or insight you can provide me.
-Chris
You could bind a subform to the table that stores your meter records and then have some unbound fields on your main form that allows you to enter the information that would be repeated in your batch of records. You could also put another unbound text box on the main form to specify the number of records you want that will have this repeated information.
So in the mock-up below, you'd specify how many records you want (red box), e.g. 10 records:
Then you'd supply the data that would be repeated for these 10 records (blue boxes):
You'd then click a button that would create the number of records specified with the repeated information given:
It would then just be a case completing the unique serial number for each of the records in the batch you have generated.
Here's the VBA I used on the Add button:
Private Sub cmdAddRecords_Click()
batchAdd Me.txtRecords
Me.tblMeters_sub.Requery
End Sub
...and the batchAdd sub routine it calls:
Public Sub batchAdd(records As Integer)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim i As Integer
Set db = CurrentDb
Set rs = db.OpenRecordset("tblMeters")
i = 1
Do While i <= records
rs.AddNew
rs!SerialNumber = ""
rs!MeterFirmware = Me.MeterFirmware
rs!MeterCatalog = Me.MeterCatalog
rs!Customer = Me.Customer
rs!MeterKh = Me.MeterKh
rs!MeterForm = Me.MeterForm
rs!MeterType = Me.MeterType
rs!MeterVoltage = Me.MeterVoltage
rs.Update
i = i + 1
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Here's a link to the mock-up (if you want a closer look).
Update
In response to your query about whether the subform could be filtered so it doesn't just become a big list of all meters, you could add another field to the tblMeters table that will take the date and time that you added records to the table:
You'd then need to add another line to the batchAdd sub that will put the system time and date in this new field:
...
Do While i <= records
rs.AddNew
rs!SerialNumber = ""
rs!MeterFirmware = Me.MeterFirmware
rs!MeterCatalog = Me.MeterCatalog
rs!Customer = Me.Customer
rs!MeterKh = Me.MeterKh
rs!MeterForm = Me.MeterForm
rs!MeterType = Me.MeterType
rs!MeterVoltage = Me.MeterVoltage
rs!DateAdded = Now ' <-- HERE!
rs.Update
i = i + 1
Loop
...
You'll then need to change the subform's Record Source property (Design View > select subform > Property Sheet > Data tab > Record Source):
Put the following SQL in there:
SELECT TOP 15 tblMeters.SerialNumber, tblMeters.MeterFirmware, tblMeters.MeterCatalog,
tblMeters.Customer, tblMeters.MeterType, tblMeters.MeterForm, tblMeters.MeterKh,
tblMeters.MeterVoltage, tblMeters.DateAdded
FROM tblMeters
ORDER BY tblMeters.DateAdded DESC;
... which will order the records by the date/time field (most recent at the top) and then show only the first 15 of these records. If you want a different number of records change the TOP 15 bit to a different number of your choosing.
When you click "Add", your new batch of records should be added to the top of the list and the list should stay at a maximum of 15 records (or whatever number you specify in TOP ...)
Be aware that when I was testing this, clicking the "Add" button rapidly a few times seemed to cause the sql to not bother with the TOP ... filter, but as long there's like a second or more between each "Add" click it seemed to work fine.
Hope this helps.
I have a database table which contains a list of usernames and their current active location, an integer called SEQUENCE.
I get this list of sequence numbers into a datatable with a single column (e.g. "SELECT SEQUENCE FROM TABLE"):
dtUsers = CLS_USERS.GetUsers(User)
It excludes the current user, which is why I parse in User.
What I then do is loop through the datatable and for each number I want to set the matching row in a datagridview (which also has a SEQUENCE column) to a different colour. This is my current code:
For Each row As DataRow In dtUsers.Rows
intSeq = row("SEQUENCE")
For Each dgv_row As DataGridViewRow In dgvCandList.Rows
If dgv_row.Cells("CURRENT_SQ").Value = intSeq Then
dgv_row.DefaultCellStyle.BackColor = Color.Cyan
Else
dgv_row.DefaultCellStyle.BackColor = Color.Grey
End If
Next
Next
However, all rows are highlighted rather than just those where dgv_row.Cells("SV_CURRENT_CAND_SQ").Value = intSeq is True... I've verified that this loop is working correctly, so it must be dgv_row.DefaultCellStyle.BackColor = Color.Cyan which is incorrect?
If so, how should I correctly be assigning the row back colour of specific DataGridRow?
EDIT: This code works correctly, my issue was related to bug outside this loop causing the BackColor to be sent for everything, and then never setback to default if where BackColor wasn't being set back to the default if it wasn't in dtUsers.
I have a SQL database with a table "Employees" in it (with large number of rows). By using DataGridView, I want to search for specific "Employee's Name" and change it's "Job". How can I achieve that. I'm using VB.net. Please Help Me.
Not sure if this will help but write a loop that goes through all the values if it finds a match its true if not it is false ,if found the item can be displayed in a textbox and edited
if not a message is displayed saying "no match found"
the editing part can be done using a procedure that will update the value in your grid with what is entered
i can supply code for this if need be but i am unsure if this is what you wish
and there is most likely a better way of doing it
you can loop through your grid, and check if the data you wish to edit exists using the For loop:
Supposing you are using a textbox as the input, and you use a label to hold the employee ID:
Dim EmpIDColumn as Integer = 'array number of your EmpID Column
Dim EmpNameColumn as Integer = 'The array number of the column where your EmpName is
Dim JobColumn as Integer = 'The array number of your job column
For each dr as Datagridviewrow in Datagridview1.Rows
If dr.cells(EmpNameColumn).value = TxtSearchBox.text Then
txtEmpJob.text = dr.cells(JobColumn).value
lblEmpID.Text = dr.cells(EmpIDColumn).value
End if
Next
Okay, so you've searched the record successfully. Next step (after editing the job, and even other details like the name) would be to update the record in the grid. Remember you set the lblEmpID's text to empID in the column? Use it to find the
Record you wish to change in the grid using the same technique above!
Dim EmpIDColumn as Integer = 'array number of your EmpID Column
Dim EmpNameColumn as Integer = 'The array number of the column where your EmpName is
Dim JobColumn as Integer = 'The array number of your job column
For each dr as Datagridviewrow in Datagridview1.Rows
If dr.cells(EmpIDColumn).value = lblEmpID.text Then
dr.cells(JobColumn).value = txtEmpJob.text
dr.cells(EmpNameColumn).value = txtEmpName.text
'then, type in here your SQL Query Update!
End if
Next