i'm puzzled in the logic of shuffling the questions that i'll display from my database.
my current code displays random questions to the textbox but it also display empty and duplicate entries.
Dim r As MySqlDataReader
Dim i As Integer = 0
Dim temp() As Integer = {}
Dim txtQ() As TextBox = {txtQ1, txtQ2, txtQ3, txtQ4, txtQ5, txtQ6, txtQ7, txtQ8, txtQ9, txtQ10}
Dim cbA() As CheckedListBox = {cbA1, cbA2, cbA3, cbA4, cbA5, cbA6, cbA7, cbA8, cbA9, cbA10}
con.Open()
cmd = New MySqlCommand("select * from tbexam", con)
r = cmd.ExecuteReader
While r.Read
If i <= 9 Then
Randomize()
Dim j As Integer = CInt(Int(9 * Rnd()))
txtQ(j).Text = r.GetString("exam_question")
cbA(j).Items.Clear()
cbA(j).Items.Add("a) " & r.GetString("exam_ans_a"))
cbA(j).Items.Add("b) " & r.GetString("exam_ans_b"))
cbA(j).Items.Add("c) " & r.GetString("exam_ans_c"))
cbA(j).Items.Add("d) " & r.GetString("exam_ans_d"))
i = i + 1
End If
End While
When you place a random number in j, it is (very nearly) a random number between 0 and 9. This is equivalent to rolling a ten-sided dice. What do you think the chances are that if you were to roll it ten times you would get exactly one of each of the values 0 to 9? Pretty low. What you will actually get is something like: 2, 0, 8, 2, 5, 1, 7, 6, 1, 4. This sequence contains duplicates of 2 and 1 and the values 3, and 9 do not appear. This is where your duplicates and gaps come from.
One option you could try is to fill the array sequentially and then shuffle it.
Dim r As MySqlDataReader
Dim i As Integer = 0
Dim temp() As Integer = {}
Dim txtQ() As TextBox = {txtQ1, txtQ2, txtQ3, txtQ4, txtQ5, txtQ6, txtQ7, txtQ8, txtQ9, txtQ10}
Dim cbA() As CheckedListBox = {cbA1, cbA2, cbA3, cbA4, cbA5, cbA6, cbA7, cbA8, cbA9, cbA10}
con.Open()
cmd = New MySqlCommand("select * from tbexam", con)
r = cmd.ExecuteReader
' Read the Q&As into the arrays in the order they appear in the DB
While r.Read
If i <= 9 Then
txtQ(i).Text = r.GetString("exam_question")
cbA(i).Items.Clear()
cbA(i).Items.Add("a) " & r.GetString("exam_ans_a"))
cbA(i).Items.Add("b) " & r.GetString("exam_ans_b"))
cbA(i).Items.Add("c) " & r.GetString("exam_ans_c"))
cbA(i).Items.Add("d) " & r.GetString("exam_ans_d"))
i = i + 1
End If
End While
' Re-order the arrays by swapping each element with another, randomly selected element.
' Start with i at the count of the elements read in the last loop and work down.
Dim n as Integer = i - 1
While i > 0
Dim j As Integer = CInt(Int(n * Rnd()))
i = i - 1
' Swap elements i and j of the arrays
Dim tmpQ As TextBox = txtQ(i)
txtQ(i) = txtQ(j)
txtQ(j) = tmpQ
Dim tmpA() As CheckedListBox = cbA(i)
cbA(i) = cbA(j)
cbA(j) = tmpA
End While
This could be simplified and abstracted but you get the idea.
It is hard to avoid duplicate entry using random number generation, but you can avoid empty entries. You get empty entries because you generates random number and fetch question with that id, and unfortunately that id is not available in database always. SO first, fetch all the ids from database in an array and generate random number from 0 to array length. and select id value of array key.
Related
A multi-level WBS the users were able to delete some tasks that are not applicable to their project. Goal is to renumber the entire WBS so that no numbers are skipped. Example: 1.1.1, 1.1.2, 1.1.4 - number 1.1.3 was deleted. Each WBS element may or may not have child elements that need to be renumbered as well.
I have the data in a datatable, fields: WBS_ID, WBSNo, ParentID, ParentNo, SortKey(the original WBS Number) and Notes. WBS_ID is the UID, ParentID is the WBS_ID of the parent WBS element. First element of the WBS has a null value in the ParentID field.
I cannot seem to grasp how to make an iterative function call to create the WBS number.
Dim dTb As New DataTable
Using Conn
Conn.Open()
Using dad As New SqlClient.SqlDataAdapter(vSqlStr, Conn)
dad.SelectCommand.Parameters.Add("#ProjectID", SqlDbType.Int)
dad.SelectCommand.Parameters.Add("#Revision", SqlDbType.Int)
dad.SelectCommand.Parameters("#ProjectID").Value = vProjectID
dad.SelectCommand.Parameters("#Revision").Value = vRevision
dad.Fill(dTb) 'Now we have a table with all the elements .
End Using
Conn.Close()
End Using
'Now work with the datatable
'WBS_ID, WBSNo, WBSLevel, ParentID, ParentNo, SortKey, Notes
dTb.DefaultView.Sort = "SortKey ASC"
dTb = dTb.DefaultView.ToTable
Dim vRowCount As Int16
vRowCount = dTb.Rows.Count
Dim vCurRow As Int16 = 0
For x = 0 To vRowCount - 1
If Not IsDBNull(dTb.Rows(x)("ParentID")) Then
Else
dTb.Rows(x)("WBSNo") = "1"
End If
dTb.Rows(x)("Notes") = dTb.Rows(x)("Notes") & vbCrLf & "<<< Old WBS No. = " & dTb.Rows(x)("SortKey")
Next
Renumber the WBS, starting with "1", each child of an element would be numbered with the parent number, plus a period (.) then sequentially starting with 1; each child could have children.
I wrote a recursive sub-routine to update the datatable, then another routine to update the database.
Sub RenumberChildren(vParentID As Int16, vParentWBSNo As String)
Dim ChildCount As Int16 = 0
For x = 0 To dTb.Rows.Count - 1
If Not IsDBNull(dTb.Rows(x)("ParentID")) Then
If dTb.Rows(x)("ParentID") = vParentID Then
ChildCount += 1
dTb.Rows(x)("WBSNo") = vParentWBSNo & "." & ChildCount
RenumberChildren(dTb.Rows(x)("WBS_ID"), dTb.Rows(x)("WBSNo"))
End If
End If
Next
End Sub
So I am currently trying to read values from an access database and write them to an array of labels in VB.NET. This is for a little quiz program I am making where the previous scores they got in the 14 categories are written to the screen. The issue I am having is when writing to Label7 (column 20 in the database) I get the error 'specified cast is not valid'. I have checked my txt file and database thoroughly to see what is wrong with this specific value and I cannot see a difference. It is still written as a 32 bit integer like all the others, for which the code has no issues.
Dim LabelArray() As Control = {Label1, Label2, Label3, Label4, Label5, Label6, Label7, Label8, Label9, Label10, Label11, Label12, Label13, Label14}
Dim x As Integer = 2
'starting at the the 3rd column in the database
Dim QArray(13) As String 'reading names of the columns from a txt file into the array
FileOpen(1, Application.StartupPath & "\sqlscores.txt", OpenMode.Input) 'load files
Dim j As Integer = 0
Do While Not EOF(1)
QArray(j) = LineInput(1) 'input into array
j = j + 1
Loop
FileClose(1)
Dim tbl As New DataTable
Dim conn1 = MyConnection2() 'connects to microsoft access database
Dim temp As String
For i = 0 To 13 'for each item in the array
Dim command = New OleDbCommand("Select * From Users Where Username='" & usernames & "' and " & QArray(i) & " >= 0", conn) 'look for that column in the database where their username and score is more than 0
Dim reader = command.ExecuteReader()
While reader.Read()
temp = (reader.GetInt32(x)).ToString 'read value and convert to string
LabelArray(i).Text = temp 'assign temp to label text
x = x + 3 'increment by 3 as correct column is in every third column
End While
Next i
Below is a screenshot of the database (the specific column) that is causing the issue.
The first field is the section that is playing up
As you can see, it has the same properties as a section that does work compared to a section that does
I have tried deleting the column and adding it again, which makes no difference. I have also checked the label (and re-added it) in VB to see if that was the issue, which it was not. It appears to think that the value in that column, which is just currently the 32 bit integer "4" cannot be converted to a string. I am only interested in the practice scores in the db which can be seen in the column names.
Am I missing something obvious?
Dim X As String
Dim V, Q, Y As Double
DGV.ColumnCount = 3
con.Open()
cmd = New SqlCommand("select Name,Price from Items where Name ='" & ListItems.SelectedItem & "'", con)
DR = cmd.ExecuteReader
While DR.Read()
' Q = Val(Qty.Text)
X = (DR("Name").ToString())
Y = Val((DR("Price").ToString()))
V = Q * Y
Dim row As String() = New String() {Q, X, V}
DGV.Rows.Add(row)
i am using visual basic.net and if i have similar items in datagridview as below
for example
1 hot dog 5 $
2 hot dog 10 $
5 hot dog 20 $
how can we consolidate them in one line as
8 hot dog 40 $
So you have columns "Name" and "Price". From your text under your code I see that name is going to be "5 hotdog" and Price to be "20$". I don't know if they are formatted that way, but I am going to assume so.
So what you want to do first is calculate the values you want in your "total" row. Since you have "hot dog" or a string after your initial number, we want to just get that number for each value. We'll loop through, evaluate that number, and sum it up. We'll do the same with the price column, but instead we'll remove the "$" in the string. Again, I'm doing a lot of assuming here.
Dim nameTotal As Integer = 0
Dim priceTotal As Integer = 0
'loop through each row of the DGV
For Each row As DataRow In DGV.Rows
'evaluate value in current row
Dim str_nameValue As String = row.Item("Name").ToString()
str_nameValue = str_nameValue.Remove(" hot dog")
'or if there are other string attached, remove those from the str_nameValue here to get an integer
'processing stringcode here...
'add to name total
nameTotal += CInt(str_nameValue)
'do the same for the other column
Dim str_priceValue As String = row.Item("Price").ToString()
str_priceValue = str_priceValue.Remove("$")
'sum
priceTotal += CInt(str_priceValue)
Next
'for loop is finished, add a new row with the values
'add row to table with a parameter of total values, and an empty one for the second column
DGV.Rows.Add(nameTotal & " hot dog " & priceTotal & "$", " ")
You should be in charge of formatting your strings to meet your needs.
I am developing an application using Visual Basic 2010 for hydraulic calculations of a pipe network.
This application uses a lot of iterations and loops, depending on the user input and size of network. Most of the results have to be saved temporarily to be used for the next step of calculations.
Firstly, I used a DataGridView to save the results but as the number of iterations increased, the application became very slow.
Now I am trying to create a DataTable, then populate it with some initial results (this part was successful). The obtained DataTable has some columns that are not populated like so:
22 24 10
3 16 22 9 15
16 12 24 13
14 21 10 23 12 1
24 18 23 2 1
Other calculations are performed and a certain value (X) is obtained.
Now I am trying to loop through the columns of a specific row to check if the calculated value (X) equals to one of the values in those columns.
My question is: How can I loop through only the columns that have values (avoiding the columns containing NULL values) for a specific row?
I am a beginner in VB.net. I hope my question is clear as I didn't provide any code.
Thanks in advance for you help.
This is the initial code I used:
Results.DGVInitial.Rows.Clear()
Results.DGVFinal.Rows.Clear()
For m As Integer = 0 To NetworkLayout.DGVNetworkLayout.Rows.Count - 1
Results.DGVInitial.Rows.Add()
Next
Dim I As Integer = NetworkLayout.DGVNetworkLayout.Rows.Count - 1
Dim Sec(I), Ini(I) As Integer
Dim Hyd(I), Dia(I), Len(I) As Single
Dim Qsec(I), Qini(I), Vsec(I) As Single
Dim U(I), Y(I) As Single
Do
I = I - 1
Sec(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(0).Value
Ini(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(1).Value
Hyd(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(6).Value
Dia(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(4).Value
Len(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(3).Value
Dim V As Integer
V = Results.DGVRandomGen.Rows(TotalNum_Runs - 1).Cells(I).Value
Qsec(I) = 0
Dim q As Single = 0
For n As Integer = 0 To Results.DGVInitial.Rows.Count - 1
If Results.DGVInitial.Rows(n).Cells(1).Value = Sec(I) Then
q = Results.DGVInitial.Rows(n).Cells(0).Value
Qsec(I) = Qsec(I) + q
Else
Qsec(I) = Qsec(I)
End If
Next
If V = 1 Then ' if the hydrant is open
Qini(I) = Hyd(I) + Qsec(I)
Else ' if the hydrant is close
Qini(I) = Qsec(I)
End If
Results.DGVInitial.Rows(I).Cells(0).Value = Qini(I)
Results.DGVInitial.Rows(I).Cells(1).Value = Ini(I)
Results.DGVSectionDischarges.Rows(TotalNum_Runs - 1).Cells(I).Value = ini(I).ToString("F2")
Now instead of using
V = Results.DGVRandomGen.Rows(TotalNum_Runs - 1).Cells(I).Value
I would like to replace the "DGVRandomGen" with a DataTable called "DT_Random"
Like I said I am a beginner so I am not sure how to code it but it will be something like this:
For DT_Random.Rows (TotalNum_Runs - 1)
For Each col As DataColumn In DT_Random.Columns
If DT_Random.Rows(TotalNum_Runs - 1).Item(col) = I Then
Qini(I) = Hyd(I) + Qsec(I)
Else
Qini(I) = Qsec(I)
End If
Next
But I want to avoid Null values as not all columns are populated
Thanks
Maybe this will help you:
Dim myXvalue = 24
Dim myDataTable As New DataTable
myDataTable.Columns.Add("Col1")
myDataTable.Columns.Add("Col2")
myDataTable.Columns.Add("Col3")
myDataTable.Columns.Add("Col4")
myDataTable.Rows.Add(22, 24, 10, DBNull.Value)
myDataTable.Rows.Add(3, 16, 22, DBNull.Value)
myDataTable.Rows.Add(24, 18, DBNull.Value, 24)
For Each column As DataColumn In myDataTable.Columns
If IsDBNull(myDataTable.Rows(0).Item(column)) Then
MsgBox("DB Null Found At: " & column.ColumnName)
Continue For
End If
If myDataTable.Rows(0).Item(column) = myXvalue Then
MsgBox("Match: " & myDataTable.Rows(0).Item(column) & " found at " & column.ColumnName)
End If
Next column
Just a quick example, you may need to restructure it a bit, but at least it shows you how to access the values in your datatable by columns. I would do a function that passes a row index as a parameter and returns a boolean. Create two booleans inside the sub, one for dbnull existing in the row, and one for finding a matching value. If dbnull bool is false, and match value is true, then return true. Just make sure you loop all the columns and dont exit early.
If you need me to elaborate let me know.
I'm trying to make a calendar in vb.net and I have come across this problem. I want to append some text into an existing datatable row. When I watch my debugger it says:"In order to evaluate an indexed property, the property must be qualified and the arguments must be explicitly supplied by the user.".
Dim aantalRijen As Integer = 1
For x = 0 To 6
Dim dttopdrachten As New DataTable
dttopdrachten = opdrachtendao.getOpdrachtenByDate(Today.AddDays(x))
If dttopdrachten.Rows.Count > aantalRijen Then
aantalRijen = dttopdrachten.Rows.Count
End If
Next
For z = 0 To aantalRijen - 1
Dim r As DataRow
r = dttAgenda.NewRow()
dttAgenda.Rows.InsertAt(r, z)
Next
For i = 0 To 6
Dim aantalItems As Integer = 0
Dim dttopdrachten As New DataTable
dttopdrachten = opdrachtendao.getOpdrachtenByDate(Today.AddDays(i))
aantalItems = dttopdrachten.Rows.Count
For j = 0 To aantalItems - 1
Dim info As String = dttopdrachten.Rows(j).Item(0).ToString & vbCrLf & dttopdrachten.Rows(j).Item(2).ToString & vbCrLf & dttopdrachten.Rows(j).Item(3).ToString & vbCrLf & dttopdrachten.Rows(j).Item(4).ToString & vbCrLf & dttopdrachten.Rows(j).Item(5).ToString & vbCrLf & dttopdrachten.Rows(j).Item(6).ToString
dttAgenda.Rows(j).Item(i) = info
Next
Next
dgvAgenda.DataSource = dttAgenda
In the code above, I first count how many rows I have to make. Afterwards I add the amount of rows to the datatable (columns are added before). Until here it works, but then when I keep debugging I get the error. I tried googling but nothing could help me so far.
Seem problem has been solved without changing anything. So if someone want to make a calendar. Here's the solution ;)