For loop through function - vb.net

I tried to draw 64 button(8 rows and 8 columns) to make a game, but for some reason my code does not work. I hope someone can help me with this.
Public Class Form1
Dim AMOUNTOF_COLUMNS As Integer = 8
Dim AMOUNTOF_ROWS As Integer = 8
Public Function setNew(row As Integer, column As Integer) As Button
Dim newButton As New Button()
newButton.Width = 40
Me.Controls.Add(newButton)
newButton.Left = 0
newButton.Top = 0
newButton.Height = newButton.Width
newButton.Text = ""
newButton.Tag = (column + (row * AMOUNTOF_COLUMNS))
AddHandler newButton.MouseDown, AddressOf Klik
Return newButton
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For value1 As Integer = 0 To AMOUNTOF_ROWS Step 1
For value2 As Integer = 0 To AMOUNTOF_COLUMNS Step 1
Me.setNew(value1, value2)
Next
Next
End Sub
If I execute this code, it only draws me one button.

You're drawing 64 buttons but they are all on top of each other. You will need to offset them correctly. Particularly these lines should be modified so that every button gets the correct position.
newButton.Left = 0
newButton.Top = 0
EDIT:
newButton.Tag = "Column x - row y"
Public Sub Klik(sender as Object, e As EventArgs)
Dim b as Button = sender
Dim value as String = b.Tag
If value = "Column 1 - row 1" Then
' Do action for col 1 row 1
Else If value = "Column 2 row 1" Then
' Do action for col 2 row 1
Else If ...
Else If ...
End If
End Sub

You need to modify you method to draw your buttons next to each other, and set their Left and Top properties accordingly:
Public Function setNew(row As Integer, column As Integer) As Button
Dim newButton As New Button()
newButton.Width = 40
newButton.Height = newButton.Width
Me.Controls.Add(newButton)
newButton.Left = column * newButton.Width ' you may need some offset here too
newButton.Top = row * newButton.Height ' you may need some offset here too
newButton.Text = ""
newButton.Tag = (column + (row * AMOUNTOF_COLUMNS))
AddHandler newButton.MouseDown, AddressOf Klik
Return newButton
End Function
Also, you need to draw one less column and row as you're currently creating 9 rows and columns
For value1 As Integer = 0 To AMOUNTOF_ROWS - 1 Step 1
For value2 As Integer = 0 To AMOUNTOF_COLUMNS -1 Step 1
Me.setNew(value1, value2)
Next
Next

Related

How to freeze merged columns in data grid view when scrolling vertically?

I have a data grid view where I need the columns to be frozen or fixed when scrolling vertically.
I have a data grid view control in vb.net windows application which displays the data in a parent-child hierarchy(as shown below). The first column displays the parent data and the second column displays all its child data. The child data in the second column can be as much as 100 rows or even more. So when scrolling down through the grid, the value in the first column does not remain there as it is while the values in the second column(i.e. the child data) scrolls down. So if the user wants to check to which parent, the current child info belongs to, then again he will have to scroll up to the starting of the column to find the name of the parent. I want the values in the first column to be displayed or frozen till it reaches the end of the list of its child values in the grid or at least till the next row where the next parent data starts. I have suggested the client to go with a tree view but they are not agreeing and need it in a data grid view itself. Is there anyway to achieve this in a data grid view?
Thanks in advance.
You can't freeze a row (in runtime, on dgv scrolling) with index greater than zero because all those before are frozen and at that point you can't scroll your datagridview.
If I understood correctly what you want I wrote this class quickly (probably should be optimized). Usage is simple.
1 - First create your own datagridview.
2 - then add your columns and rows (IMPORTANT: Put a “X” in the Tag in each row is a Parent or is considered as title for other rows as you seen in TestPopulate method) .
3 - Call the class I made by passing the datagridview (you created first) as a parameter. At this point this control takes its size, placement and REPLACE YOUR DATAGRIDVIEW .
Private Class CustomDgv
Inherits Panel
Dim WithEvents TopDgv As DataGridView = New DataGridView
Dim WithEvents DownDgv As DataGridView = New DataGridView
Dim Cols As Integer
' This variable is in case you have more rows as "headrow"
' In TestPopulate you can see how to get those
Dim listOfOwnerRows As List(Of Integer) = New List(Of Integer)
Dim currentTopRow As Integer = -1
Protected Overloads Property Height As Integer
Get
Return MyBase.Height
End Get
Set(value As Integer)
MyBase.Height = value
TopDgv.Height = TopDgv.RowTemplate.Height - 1
DownDgv.Height = value - TopDgv.Height - 1
End Set
End Property
Protected Overloads Property Width As Integer
Get
Return MyBase.Width
End Get
Set(value As Integer)
MyBase.Width = value
TopDgv.Width = value - 1
DownDgv.Width = value - 1
End Set
End Property
Sub New(dgvOriginal As DataGridView)
DownDgv = dgvOriginal
Dim parentCtrl As Control = dgvOriginal.Parent
parentCtrl.Controls.Remove(dgvOriginal)
parentCtrl.Controls.Add(Me)
Me.Location = DownDgv.Location
Me.Size = DownDgv.Size
Me.BorderStyle = DownDgv.BorderStyle
TopDgv.Width = Width - 2 - SystemInformation.VerticalScrollBarWidth
TopDgv.Height = TopDgv.RowTemplate.Height
TopDgv.ScrollBars = ScrollBars.None
TopDgv.ColumnHeadersVisible = False
TopDgv.BorderStyle = BorderStyle.None
DownDgv.ColumnHeadersVisible = False
DownDgv.BorderStyle = BorderStyle.None
TopDgv.Left = 0
DownDgv.Left = 0
DownDgv.Width = Width - 2
DownDgv.Height = Height - 2
For Each Col As DataGridViewColumn In DownDgv.Columns
Dim cIndex As Integer = TopDgv.Columns.Add(Col.Clone)
If Col.Frozen Then
TopDgv.Columns(cIndex).Frozen = True
End If
Cols += 1
Next
DownDgv.Top = 0
Me.Controls.Add(TopDgv)
Me.Controls.Add(DownDgv)
If DownDgv.Rows.Count > 0 Then
listOfOwnerRows = (From R As DataGridViewRow In DownDgv.Rows
Where R.Tag = "X"
Select R.Index).ToList
If listOfOwnerRows.Count > 0 Then
SetFrosenRow(listOfOwnerRows(0))
End If
End If
End Sub
Protected Sub SetFrosenRow(index As Integer)
If DownDgv.Rows.Count > index Then
TopDgv.Rows.Clear()
TopDgv.Rows.Add()
Dim currentRIndex As Integer = DownDgv.FirstDisplayedScrollingRowIndex
'If you want onlly the base row
For i As Integer = 0 To Cols - 1
TopDgv.Rows(0).Cells(i).Value = DownDgv.Rows(index).Cells(i).Value
Next
'Or else get the diplayed on top row
TopDgv.Rows(0).DefaultCellStyle = New DataGridViewCellStyle With {
.BackColor = Color.Bisque
}
currentTopRow = index
End If
End Sub
Protected Sub SetChildValuesInTopRow(index As Integer)
For i As Integer = 1 To Cols - 1
TopDgv.Rows(0).Cells(i).Value = DownDgv.Rows(index).Cells(i).Value
Next
End Sub
Private Sub DownDgv_Scroll(sender As Object, e As ScrollEventArgs) Handles DownDgv.Scroll
Try
If e.ScrollOrientation = ScrollOrientation.VerticalScroll Then
Dim topR As Integer = DownDgv.FirstDisplayedScrollingRowIndex
'If you want in top row the current value that is in the top uncomment this
SetChildValuesInTopRow(topR)
If listOfOwnerRows.Count > 0 Then
Dim rToSetAsOwner As Integer = listOfOwnerRows(listOfOwnerRows.Count - 1)
For i As Integer = listOfOwnerRows.Count - 1 To 0 Step -1
If listOfOwnerRows(i) <= topR Then
rToSetAsOwner = listOfOwnerRows(i)
Exit For
End If
Next
If rToSetAsOwner <> currentTopRow Then
SetFrosenRow(rToSetAsOwner)
End If
Console.WriteLine("rToSetAsOwner: " & rToSetAsOwner)
End If
Else
TopDgv.HorizontalScrollingOffset = DownDgv.HorizontalScrollingOffset
End If
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
End Class
Usage:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
' first populate you grid putting a tag in each row which is a header/parent/title for other rows
TestPopulate()
Dim customControl As Control = New CustomDgv(DataGridView1)
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
Sub TestPopulate()
For i As Integer = 0 To 100
DataGridView1.Rows.Add()
If i = 0 Then
DataGridView1.Rows.Item(0).Cells(0).Value = "Owner 0"
DataGridView1.Rows(0).Tag = "X"
End If
If i = 50 Then
DataGridView1.Rows.Item(50).Cells(0).Value = "Owner 50"
DataGridView1.Rows(50).Tag = "X"
End If
If i = 70 Then
DataGridView1.Rows.Item(70).Cells(0).Value = "Owner 70"
DataGridView1.Rows(70).Tag = "X"
End If
DataGridView1.Rows.Item(i).Cells(1).Value = "child_" & i.ToString & "_1"
DataGridView1.Rows.Item(i).Cells(2).Value = "child_" & i.ToString & "_2"
Next
End Sub
I hope I have been helpful

Do code in VB.net on text input before text being shown

I have this code in VB6:
Private Sub t_Change(Index As Integer)
Iznos = 0
For i = 1 To 4
Iznos = Iznos + t(i).Text
Next
If CDbl(Iznos) > Label13.Caption Then
t(Index).Text = 0
Iznos = 0
t(Index).SelStart = 0
t(Index).SelLength = 1
For i = 1 To 4
Iznos = Iznos + t(i).Text
Next
End If
t(0).Text = Format(Label13.Caption - CDbl(Iznos), "#,##0.00")
End Sub
This code works for my textboxes (4 of them named: t(0),t(1),t(2),t(3)).
I am trying to achieve the same with VB.net but i can't seem to wrap my head around it.
This is my code in VB.Net:
Public Function izracunaj(ByVal s As Object)
Dim ukupniIznos As Decimal = Decimal.Parse(maticnavalutatbox.Text)
Dim poslaniIznos As Decimal = Decimal.Parse(s.text)
Dim iznos As Decimal
Dim allTextboxesPayment() As TextBox = {gotovinaTbox, karticeTbox, ostaloTbox, ziralnoTbox}
For Each kontrola As TextBox In allTextboxesPayment
iznos = iznos + Decimal.Parse(kontrola.Text)
Next
If CDbl(iznos) > ukupniIznos Then
s.Text = 0
iznos = 0
For Each kontrola As TextBox In allTextboxesPayment
iznos = iznos + Decimal.Parse(kontrola.Text)
Next
End If
gotovinaTbox.Text = Format(ukupniIznos - CDbl(iznos), "#,##0.00")
End Function
But if I call my function like this:
Private Sub ziralnoTbox_TextChanged(sender As Object, e As TextChangedEventArgs) Handles ziralnoTbox.TextChanged
izracunaj(sender)
End Sub
It does not work because my izracunaj function already has the input value of ziralnoTbox. How can i achieve same functionality with vb.net as in vb6
If I'm looking at this correctly, you could make use of the TextChanged event.
Private Sub TextBox1_TextChanged(sender As Object,
e As EventArgs) Handles gotovinaTbox.TextChanged,
karticeTbox.TextChanged,
ostaloTbox.TextChanged,
ziralnoTbox.TextChanged
Dim ukupniIznos As Decimal = Decimal.Parse(maticnavalutatbox.Text)
Dim poslaniIznos As Decimal = Decimal.Parse(s.text)
Dim iznos As Decimal
Dim allTextboxesPayment() As TextBox = {gotovinaTbox, karticeTbox, ostaloTbox, ziralnoTbox}
'gotovinaTbox, quita esto?
For Each kontrola As TextBox In allTextboxesPayment
iznos = iznos + Decimal.Parse(kontrola.Text)
Next
If CDbl(iznos) > ukupniIznos Then
s.Text = 0
iznos = 0
For Each kontrola As TextBox In allTextboxesPayment
iznos = iznos + Decimal.Parse(kontrola.Text)
Next
End If
gotovinaTbox.Text = Format(ukupniIznos - CDbl(iznos), "#,##0.00")
End Sub

What has to be done to show a marquee output with a scroll menu?

Today i continue my work, Building a menu with a vb.net console application. I found more samples to build with Windows forms. Still i try to get Basic Knowledge with the console surface.I was not able to put the following marquee text in a scroll menu, the second Code past the marquee text.
Module Module1
Dim aTimer As New System.Timers.Timer
Const marqueeText As String = "The quick brown fox... "
Dim sb As New System.Text.StringBuilder
Dim direction As Boolean = False
Sub Main()
aTimer.AutoReset = True
aTimer.Interval = 100 '1/10 second
AddHandler aTimer.Elapsed, AddressOf tick
aTimer.Start()
Console.ReadKey()
End Sub
Private Sub tick(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
Console.Clear()
If sb.Length = 0 Then sb.Append(marqueeText)
If direction Then
sb.Insert(0, sb(sb.Length - 1))
sb.Remove(sb.Length - 1, 1)
Else
sb.Append(sb(0))
sb.Remove(0, 1)
End If
Console.CursorLeft = 10 'no visible change
Console.CursorTop = 10 'visible change
Console.Write("{0}{1}", vbCr, sb.ToString)
End Sub
End Module
The marquee text Output from above is not easy to manage with the console.cursorleft command. I have no clue how to move it to the right or to put the marquee Output in the following Code, a scroll menu, on the third line.
Module Module1
Dim MenuList As New List(Of String)
Sub PrintMenu(highlight As Integer, left As Integer, top As Integer)
Dim Nickvektor() As Integer = {1, 2, 3, 4, 5}
For I = 0 To MenuList.Count - 1
Console.CursorLeft = left
Console.CursorTop = top + I
If I = highlight Then
Console.Write("{0}", "[" & Nickvektor(I) & "]")
Else
Console.Write(MenuList(I))
End If
Next
End Sub
Sub Main()
Console.CursorVisible = False
Dim x As Integer = 0
Dim Nickvektor() As String = {" "}
For counter As Integer = 0 To 0
Do
For Each s In Nickvektor
MenuList.Add(s)
Next
x += 1
Loop Until x = 5
Next
Console.SetCursorPosition(10, 16)
Console.Write("[ ]")
Dim CurrentItem As Integer = 0
Dim CurrentKey As ConsoleKey
While CurrentKey <> ConsoleKey.Enter
PrintMenu(CurrentItem, 10, 10)
CurrentKey = Console.ReadKey(True).Key
Select Case CurrentKey
Case ConsoleKey.DownArrow
CurrentItem += 1
Case ConsoleKey.UpArrow
CurrentItem -= 1
End Select
CurrentItem = (CurrentItem + MenuList.Count) Mod MenuList.Count
End While
End Sub
End Module
The menu Frame for the above Code can be used with the up and down arrows on the Keyboard.
Maybe it is to much work but i have no clue how to continue.
The first Solution for the marquee Output is an easy change of the original code. The wrap, vbCr, was the main Problem to move the text output toward the right edge oft he screen. The following code can be used to change the cursorTop Positon and also the cursorLeft Position of the Text.
Console.CursorVisible = False
Console.CursorLeft = 30
Console.CursorTop = 10
Console.Write("{0}", sb.ToString)
The heavy part are the Menu code Lines. To answer my own question some additional help was necessary.
I posted my question on the MS developer Network written in german language. With the following link it can be viewed.
For the case the link should be broken or other cases i post the code on this site.
Module Module1
Dim MenuList As New List(Of String)
Dim aTimer As New System.Timers.Timer
Const marqueeText As String = "The quick brown fox... "
Dim sb As New System.Text.StringBuilder
Dim direction As Boolean = False
Sub PrintMenu(highlight As Integer, left As Integer, top As Integer)
Dim Nickvektor() As Integer = {1, 2, 3, 4, 5}
For I = 0 To MenuList.Count - 1
Console.CursorLeft = left
Console.CursorTop = top + I
If I = highlight Then
Console.Write("{0}", "[" & Nickvektor(I) & "]")
Else
Console.Write(MenuList(I))
End If
Next
End Sub
Sub Main()
Console.CursorVisible = False
aTimer.AutoReset = True
aTimer.Interval = 100 '1/10 second
AddHandler aTimer.Elapsed, AddressOf tick
Dim x As Integer = 0
Dim Nickvektor() As String = {" "}
For counter As Integer = 0 To 0
Do
For Each s In Nickvektor
MenuList.Add(s)
Next
x += 1
Loop Until x = 5
Next
Console.SetCursorPosition(10, 16)
Console.Write("[ ]")
Dim CurrentItem As Integer = 0
Dim CurrentKey As ConsoleKey
While CurrentKey <> ConsoleKey.Enter
If CurrentItem = 2 Then ' Zero can be used to show the marquee output prompt
aTimer.Start() ' With a change to two or four the timer can be stoped:
'Else
'If aTimer.Enabled Then
' aTimer.Stop()
'End If
End If
PrintMenu(CurrentItem, 10, 10)
CurrentKey = Console.ReadKey(True).Key
Select Case CurrentKey
Case ConsoleKey.DownArrow
CurrentItem += 1
Case ConsoleKey.UpArrow
CurrentItem -= 1
End Select
CurrentItem = (CurrentItem + MenuList.Count) Mod MenuList.Count
End While
End Sub
Private Sub tick(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
If sb.Length = 0 Then sb.Append(marqueeText)
If direction Then
sb.Insert(0, sb(sb.Length - 1))
sb.Remove(sb.Length - 1, 1)
Else
sb.Append(sb(0))
sb.Remove(0, 1)
End If
Console.CursorVisible = False
Console.CursorLeft = 20
Console.CursorTop = 12 ' For the first Element CursorTop=10, fort he third 12
Console.Write("{0}", sb.ToString)
End Sub
End Module
To learn an other language like English i have to search a lot. Visual Basic Code is mostly written with English key words for the commands. I think it is easier to look up the maintainable changes for your self. To search is not every day funny.

How can I put an extra value?

I have a table (DataGridView) like this :
Col1 | Col2 | Col3
3 | Mars | Regular
Here is my code:
For a As Integer = 0 To Form3.DataGridView1.Rows.Count - 1
For b As Integer = 0 To Form3.DataGridView1.Rows.Count - 1
For c As Integer = 0 To Form3.DataGridView1.Rows.Count - 1
If Form3.DataGridView1.Rows(c).Cells(2).Value = "Regular" Then
If Form3.DataGridView1.Rows(b).Cells(1).Value = Form3.MetroComboBox7.Items(0) Then
fair = 7 * Form3.DataGridView1.Rows(a).Cells(0).Value
Label1.Text += fair
End If
End If
Next
Next
Next
I want to set that if Regular is selected on Col3 and Mars on Col2 then the value is 7 and it will multiply by row Col1 and it will be the same every row.
I think you should use the event dtgv.CellMouseClick.
Then you create conditions that you want. I give you an example here :
Public Sub event_select() Handles dtgv.CellMouseClick
Dim row As Integer = dtgv.CurrentRow.Index()
' If the column 2 and 3 are selected
If dtgv.Rows(row).Cells(1).Selected = True And dtgv.Rows(row).Cells(2).Selected = True Then
' If the value of the 2nd column is Mars and the value of the 3rd column is Regular
If dtgv.Rows(row).Cells(1).Value = "Mars" And dtgv.Rows(row).Cells(2).Value = "Regular" Then
Label1.Text = 7 * dtgv.Rows(row).Cells(0).Value
End If
End If
End Sub
You should also check that no other rows have cells selected.
One loop for all rows is enough to calculate "fair" for all rows
Const REGULAR_VALUE As String = "Regular"
Const FAIR_COEFFICENT As Integer = 7
Dim fairSum As Integer = 0
For Each row As DataGridViewRow in DataGridView1.Rows
If REGULAR_VALUE.Equals(row.Cells(2).Value.ToString()) = False Then Continue For
If Equals(MetroComboBox7.Items(0), row.Cells(1).Value) = False Then Continue For
Dim col1Value As Integer = Integer.Parse(row.Cells(1).Value)
Dim fair As Integer = col1Value * FAIR_COEFFICENT
fairSum += fair
Next
Label1.Text = fairSum.ToString()
And set Option Strict On in your project or at least in the code file(first line of file).
This will save you time by giving fast feedback about possible type converting errors during compile time.
Create class which represent your data in strongly typed manner
Public Class Ticket
Public Property Passenger As Integer
Public Property Destination As String
Public Property Status As String
End Class
Then you can add rows to the DataGridView in easy way in your form
Public Class YourForm
Private _tickets As New BindigList(Of Ticket)()
Public Sub New()
InitializeComponent() ' Forms required method
DataGridView1.DataSource = _tickets
End Sub
Private Sub Populate(passenger As Integer, destination As String, Status As String)
Dim newTicket As New Ticket With
{
.Passenger = passenger,
.Destination = destination,
.Status = Status,
}
_ticket.Add(newTicket)
End Sub
'Then you can loop all rows with correct types
Private Sub Calculate()
Dim fairSum As Integer = 0
For Each ticket As Ticket in _tickets
If REGULAR_VALUE.Equals(ticket.Status) = False Then Continue For
If ticket.Destination.Equals(MetroComboBox7.Items(0)) = False Then Continue For
Dim fair As Integer = ticket.Passenger * FAIR_COEFFICENT
fairSum += fair
Next
Label1.Text = fairSum.ToString()
End Sub
End Class

Visual Basic: How can i display the prime numbers between 1 and the inputted number

Hello everyone so i'm trying to find the prime numbers of any input. I want them to be in a listbox and the input in a text box. I would like to use two arguments but i don't know how to. this is the code i have i need dire help. I am not the best at visual basic i just need some guidance. My code isn't working but display a drop down box when i press display.
Public Class Form1
Private Sub Button3_Click_1(sender As Object, e As EventArgs) Handles Button3.Click
Dim prim As Integer
Dim test As Integer
Dim imPrime As Boolean = False
prim = CInt(txtNum.Text)
test = prim
If prim = 1 Then
imPrime = False
MessageBox.Show("Enter a number greater than one please")
Else
Do While prim >= 2
For i As Integer = 2 To prim
If prim Mod i = 0 Then
imPrime = False
Exit For
Else
imPrime = True
lstPrime.Items.Add(prim)
End If
Next
Loop
End If
If imPrime = True Then
lstPrime.Items.Add(prim)
End If
End Sub
End Class
This is my fastest VBA code to generate prime numbers between two numbers.
The generated prime numbers are put in clipboard. You will need to open
your ms office word and type Ctrl+V to view all the generated prime numbers.
Sub generateprimenumbersbetween()
Dim starting_number As Long
Dim last_number As Long
Dim primenumbers As Variant
Dim a As Long
Dim b As Long
Dim c As Long
starting_number = 1 'input value here
last_number = 1000000 'input value here
primenumbers = ""
For a = starting_number To last_number
c = Round(Sqr(a)) + 1
For b = 2 To c
If a = 1 Or (a Mod b = 0 And c <> b) Then
Exit For
Else
If b = c Then
primenumbers = primenumbers & " " & a
Exit For
End If
End If
Next b
Next a
Dim answer As DataObject
Set answer = New DataObject
answer.SetText primenumbers
answer.PutInClipboard
End Sub
I think the while loop is not working as you intend. You need two loops, the first one counting up to the possible prime, and an inner one counting up to the counter in the outer loop.
You can find examples everywhere... here's one implemented in C#, but since your question was specifically about a listbox, I've translated it to VB.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
calculatePrimes()
End Sub
Private Sub calculatePrimes()
Dim prim As Integer
Dim count As Integer = 0
prim = CInt(Me.TextBox1.Text)
If prim < 3 Then
MsgBox("Please enter a bigger number")
Return
End If
Me.ListBox1.Items.Clear()
For i As Integer = 1 To prim
Dim isPrime As Boolean = True
For j As Integer = 2 To i
If (i Mod j <> 0) Then count = count + 1
Next
If count = (i - 2) Then Me.ListBox1.Items.Add(i)
count = 0
Next
End Sub
End Class
(This assumes you have a textbox for input called TextBox1 and a listbox for display called ListBox1)