I have the following code.
Surely there must be a better way of coding this using a for/next or something, but I just don't get it to work
If CheckBox1.CheckState Then bin(1) = "1" Else bin(1) = "0"
If CheckBox2.CheckState Then bin(2) = "1" Else bin(2) = "0"
If CheckBox3.CheckState Then bin(3) = "1" Else bin(3) = "0"
..
..
..
If CheckBox20.CheckState Then bin(20) = "1" Else bin(20) = "0"
OK, This should work, but bear in mind, it assumes that you have 20 CheckBoxes and that number will never change, and that the bin array will also never change the number of elements.
Private Sub SyncCheckBoxestoBinValue()
For i As Integer = 1 To 20
bin(i) = Math.Abs(CInt(CType(Me.Controls("CheckBox" & i), CheckBox).Checked)).ToString
Next
End Sub
An explanation might be in order here. Working from the inside out, here goes..
Me.Controls("CheckBox" & i)
This will refer to the control that matches CheckBox1 when i=1, CheckBox2 when i=2 etc. However, because that bit of code is designed to work with all kinds of control, it can only return it as an Object type rather than the specific type of control you're searching for.
To be able to do anything significant with that result, we need to tell the compiler that it's a CheckBox. So now we need to wrap that last bit of code in to this.
CType(Me.Controls("CheckBox" & i), CheckBox)
Now we have something that the compiler recognises as a CheckBox, we can work with it. So you want to find out of the CheckBox is checked or not. You've usedCheckstate, but personally I think it's a bit easier to useChecked` for this purpose. So ...
CType(Me.Controls("CheckBox" & i), CheckBox).Checked
This returns a result of True or False. In VB.Net this can also be seen as -1 (true) or 0 (false). although you want a 1 or 0 so that you can assign this value to your bin array. How we do this is as below
Math.Abs(CInt(CType(Me.Controls("CheckBox" & i), CheckBox).Checked)).ToString
Finally, your result of 1 or 0 is assigned to the element of bin that corresponds to the CheckBox number
That "should" do it.
Maybe make the check boxes a list and query the result by linq? For the sake of using linq for everything better readability, I mean.
Dim cbList = New List(Of CheckBox) From {checkBox1, checkBox2, checkBox3}
Dim binTmp As List(Of String) = cbList.Select(Function(chk) If(chk.checkState, "1", "0")).ToList()
bin = binTmp
You may also want to store the result as Boolean instead of "1","0" for further processing.
I am comparing the splitted Source_Doc_No_P of PER MAP to PER SAWT then if it matched it will color the BackColor of DataGridview into yellow but there is something wrong in my code when the split value of Source_Doc_No_P is inside the If condition it only get 1 value of splitted string. Please see the screen-shot and code to help you understand my problem.
For x As Integer = 0 To Me.DataGridView4.Rows.Count - 1
Dim sdoc_map As String = DataGridView4.Rows(x).Cells("Source_Doc_No_P").Value.ToString
Dim split_sdoc() As String = sdoc_map.Split("/")
For Each part As String In split_sdoc
'Output of split_doc after For each loop
'BS091
'BS092
'BS093
If part = Me.DataGridView4.Rows(x).Cells("Source_Doc_No").Value.ToString Then
'Output of split_doc after If condition
'BS091
'It should be
'BS091
'BS092
'BS093A
'-------Will automatically color the yellow of mathced Source Document----------'
Me.DataGridView4.Rows(x).Cells(0).Style.BackColor = Color.Yellow
Me.DataGridView4.Rows(x).Cells("Source_Doc_No").Style.BackColor = Color.Yellow
Me.DataGridView4.Rows(x).Cells("ATC").Style.BackColor = Color.Yellow
Me.DataGridView4.Rows(x).Cells("Prepaid_Tax").Style.BackColor = Yellow
Me.DataGridView4.Rows(x).Cells("Source_Doc_No_P").Style.BackColor = Color.Yellow
Me.DataGridView4.Rows(x).Cells("ATC_P").Style.BackColor = Color.Yellow
Me.DataGridView4.Rows(x).Cells("Tax_Withheld_P").Style.BackColor = Color.Yellow
'-----------------------------------End---------------------------------------'
End If
Next
Next
Current Result
What should be the result
Dim sdoc_map As String = DataGridView4.Rows(x).Cells("Source_Doc_No_P").Value.ToString
check Here.. I think just Confused With Cell Name . because Cells("Source_Doc_No_P") not Present here. Check the cell Name and then Proceed.
I am an amateur in Visual Basic. I am attempting to recreate the game of Go, and I have created the board and am able to place stones on the intersections of the grid.
I now want to start capturing stones which are surrounded. I have looked online and found that flood fill is the best way to go about this. However, I have looked online for days, and I can't find anything that I can use, or manipulate to create this. I do not understand any other programming language, so I cannot use bits of code from Java, etc. And the bits of information for Visual Basic I have found do not make much sense to me as I am still a beginner.
I have attempted to start it by myself, starting off small with the situation of "If one stone were to be captured". I have two representations for the board, one is declared as "grid", and the other as "placed_stone".
"Grid" is the actual board where the users click to place their stones. placed_stone is a copy of this board, but I have used "0", "1" and "2" to represent empty, black and white respectively. I am using Windows Forms to recreate this game. This is the segment of code I have written for capturing the stones:
Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
Dim board As Panel = DirectCast(sender, Panel)
' Figure out where the user clicked: min = 0, max = (gridsize - 1)
Dim pt As Point = board.PointToClient(Cursor.Position)
Dim colWidth As Integer = (1 / (GridSize + 1)) * board.Size.Width
Dim rowHeight As Integer = (1 / (GridSize + 1)) * board.Size.Height
Dim gridPosition As New Point(Math.Min(Math.Max((pt.X / colWidth) - 1, 0), GridSize - 1), Math.Min(Math.Max((pt.Y / rowHeight) - 1, 0), GridSize - 1))
Dim newcoordsx As Integer
Dim newcoordsy As Integer
' Now do something with gridPosition:
If Not Grid(gridPosition.X)(gridPosition.Y).HasValue Then 'If gird(x,y) is empty
illegalmovelbl.Hide() ' Hides the "Illegal Move" Label
If cp = True Then ' If current player is Black
This is the part where I got stuck and realised that the coding for every situation will take too long. I managed to write up the code for one situation:
newcoordsx = gridPosition.X + 1
If placed_stone(newcoordsx, gridPosition.Y) = 2 Then
newcoordsy = gridPosition.Y + 1
If placed_stone(newcoordsx, newcoordsy) = 1 Then
newcoordsy = gridPosition.Y - 1
If placed_stone(newcoordsx, newcoordsy) = 1 Then
newcoordsx = gridPosition.X + 2
If placed_stone(newcoordsx, gridPosition.Y) = 1 Then
newcoordsx = gridPosition.X + 1
Grid(gridPosition.X)(gridPosition.Y) = True 'Place a black stone at Grid(x,y)
Grid(newcoordsx)(gridPosition.Y) = Nothing
placed_stone(newcoordsx, gridPosition.Y) = 0
pass = False
cp = False
passbtn.BackColor = Color.White 'The passbutton changes colour to white
passbtn.ForeColor = Color.Black 'The passbutton font changes colour to black
End If
End If
End If
End If
'Grid(gridPosition.X)(gridPosition.Y) = True ' Place a black stone at Grid(x,y)
'placed_stone(gridPosition.X, gridPosition.Y) = 1
'pass = False
'cp = False
'passbtn.BackColor = Color.White ' The passbutton changes colour to white
'passbtn.ForeColor = Color.Black ' The passbutton font changes colour to black
ElseIf cp = False Then ' If current player is White
Grid(gridPosition.X)(gridPosition.Y) = False ' Place a white stone at Grid(x,y)
placed_stone(gridPosition.X, gridPosition.Y) = 2
pass = False
cp = True
passbtn.BackColor = Color.Black ' The passbutton changes colour to black
passbtn.ForeColor = Color.White ' The passbutton font changes colour to white
End If
ElseIf Grid(gridPosition.X)(gridPosition.Y).HasValue Then ' If gird(x,y) isn't empty
illegalmovelbl.Show() ' Shows the "Illegal Move" Label
MsgBox("Place your stone in a vacant point") ' Displays error message
End If
board.Invalidate() ' Force the board to redraw itself
End Sub
I have tried to use Wikipedia's algorithm on flood fill, and I understand the logic of how it works, but I just don't know how to program it in Visual Basic.
Flood-fill (node, target-color, replacement-color):
1. If target-color is equal to replacement-color, return.
2. If the color of node is not equal to target-color, return.
3. Set the color of node to replacement-color.
4. Perform Flood-fill (one step to the south of node, target-color, replacement-color).
Perform Flood-fill (one step to the north of node, target-color, replacement-color).
Perform Flood-fill (one step to the west of node, target-color, replacement-color).
Perform Flood-fill (one step to the east of node, target-color, replacement-color).
5. Return.
Of course, in Go, instead of colouring in the area, you have to remove the stones when capturing, and you don't start the flood fill from the stone you just placed to capture, you start from the closest stone you wish to capture.
Can you please explain how to use flood fill in Visual Basic in an easy way and how to implement it to this game of Go?
If anyone would like to look at the whole code, please let me know. I would appreciate any suggestions!
I'm not familiar with the rules/game-play of the game Go, so I'm not sure exactly what you are attempting to accomplish, but if you believe that a flood-fill type of algorithm is what you need, then I can at least offer some advice in how you could do that. The primary thing that your code needs is to be broken down into more granular methods. What are the steps that you are attempting to perform when the panel is clicked? Surely it's not just one thing. There are many different things going on--each of which could be performed by a separate dedicated method. For instance, if you had a method like this:
Private Function GetGridPosition(board As Panel, cursorPosition As Point) As Point
Dim pt As Point = board.PointToClient(Cursor.Position)
Dim colWidth As Integer = (1 / (GridSize + 1)) * board.Size.Width
Dim rowHeight As Integer = (1 / (GridSize + 1)) * board.Size.Height
Return New Point(Math.Min(Math.Max((pt.X / colWidth) - 1, 0), GridSize - 1), Math.Min(Math.Max((pt.Y / rowHeight) - 1, 0), GridSize - 1))
End Function
Then, in the Panel1_Click event handler, you could simplify the beginning of the code considerably, like this:
Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
Dim board As Panel = DirectCast(sender, Panel)
Dim gridPosition As Point = GetGridPosition(board, Cursor.Position)
' ...
Sure, that makes the code more organized and easier to read, but that doesn't get you any closer to a flood fill algorithm, right? Well, yes, that's mostly true, but organization and readability are worthy goals in their own right, so lets continue anyway... The next step we need to perform is to make the player's move, and then, if the move was successful, we need to switch to the other player. So, let's first create the method to switch players:
Private Sub SwitchPlayer()
pass = False
cp = Not cp
passbtn.BackColor = GetPlayerForeColor(cp)
passbtn.ForeColor = GetPlayerBackColor(cp)
End Sub
Private Function GetPlayerForeColor(player as Boolean) As Color
If player Then
Return Color.White
Else
Return Color.Black
End If
End Function
Private Function GetPlayerBackColor(player as Boolean) As Color
If player Then
Return Color.Black
Else
Return Color.White
End If
End Function
You'll notice that I snuck (Chrome auto-spell tells me that isn't a word, but my American upbringing begs to differ) a couple other methods in there while I was at it. I'm sure their purpose is obvious. But stop right there. It's obvious? You'll notice that the comments are gone, yet the meaning of the code is still obvious. That's what we mean by self-documenting code. Comments are great when they're necessary, but it's even better when they aren't necessary at all.
So, pretend for now we have a method like this:
Private Function MakeMove(gridPosition As Grid, player As Boolean) As Boolean
' return true if the move was successful
End Function
Then the whole Panel1_Click event handler could look like this:
Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
Dim board As Panel = DirectCast(sender, Panel)
Dim gridPosition As Point = GetGridPosition(board, Cursor.Position)
If MakeMove(gridPosition, cp) Then
SwitchPlayer()
Else
ShowIllegalMoveMessage()
End If
End Sub
Private Sub ShowIllegalMoveMessage()
illegalmovelbl.Show() 'Shows the "Illegal Move" Label
MsgBox("Place your stone in a vacant point") 'Displays error message
End Sub
Ok, so now we're getting to the meat of it. So, what are the steps that need to be taken when a move is being made? Well, I don't know, because I don't know the game. I leave that exercise up to you, but, if your inclinations are correct, and you need some kind of flood fill algorithm, then that probably means that you need some kind of PlaceStone action which can be repeated over and over again, so that should be its own method:
Private Sub PlaceStone(gridPosition As Point, player As Boolean)
' Do something
End Sub
Obviously the Do something is the key part of all this, and it's the one part that I can't help you with. But, if it's going to be a flood fill algorithm, I can give you a really big hint. Among all the other stuff it's going to do in there, it's going to be calling PlaceStone again, passing it a different grid position (one of the surrounding positions). So for instance, something like this:
Private Sub PlaceStone(gridPosition As Point, player As Boolean)
Dim north As Position = GetNorthPosition(gridPosition)
If Floodable(north, player) Then
PlaceStone(north, player)
End If
' ...
End Sub
When a method calls itself, like that, we call it recursion. But, until you start splitting your code up into dedicated little methods, each with its own encapsulated task, then you can't really add recursion. So, first get organized, then add recursion.
I want to ask for a letter color in an If conditional:
string="asdfghjkl"
for i=1 to len(string)
letter = mid(string, i, 1)
input_letter = inputbox("Write a letter")
if letter = input_letter 'and letter.Font.Color = RGB(31,78,120)
'my code here
endif
next
The and letter.Font.Color = RGB(31,78,120) is not working. It says i need an object.
Is there any similar way to ask this? This RGB color is blue, and I am using this code to transform the entire sentence to blue (with the record macro excel setting)
With Selection.Font
.ThemeColor = xlThemeColorAccent1
.TintAndShade = -0.499984740745262
End With
Thanks
Regarding your question's problem:
The .Font.Color is a property of the class Range, but in your line of code:
if letter = input_letter 'and letter.Font.Color = RGB(31,78,120)
... you're trying to access this property in the variable letter, which is a String (you don't explicitly declare it as such, but it gets automatically declared when you execute letter = mid(string, i, 1) just above).
That is why you get an Object required exception: you're trying to access the property .Font.Color on something that is not a Range object (actually, not an Object at all).
Regarding your real need:
I'm not sure to understand what you're trying to do. Are you trying to reach a multi-colored text into a single cell in Excel? If I've got it right, you'll have a string:
string="asdfghjkl"
(please note: you can't call your variable String, that's a reserved keyword for the code. Think of calling it something else, though I guess you already do that in your real code or you wouldn't be able to execute it at all).
... and, for each letter of that string,
for i=1 to len(string)
... you want the user to give you a color. In that case, you can't do it in Excel. If not that, could you please express better your real need?
The code below comes closest to your OP logic and comment using the .Characters property of a cell Range (B11) containing your string value:
Code
Option Explicit
Sub test()
Dim blue As Long: blue = RGB(31, 78, 120)
Dim s As String: s = "asdfgh"
Dim letter As String
Dim input_letter As String
Dim i As Integer
Dim rng As Range
Set rng = ThisWorkbook.Worksheets("MySheet").Range("B11")
With rng
.Value = s
' color whole string
.Characters(1, Len(s)).Font.Color = blue
For i = 1 To Len(s)
letter = Mid(s, i, 1)
input_letter = InputBox("Write a letter")
If letter = input_letter And .Characters(i, 1).Font.Color = blue Then
'color found character
.Characters(i, 1).Font.Color = vbWhite
ElseIf input_letter = "" Then Exit For
End If
Next
End With
End Sub
Notes
Always use Option Explicitin your modules declaration head. So you would see that String isn't allowed as variable name as it's a function.
The extra color check in the If condition seems redundant, as characters so long a r e blue.
You seem to prefer repeated InputBoxes within the For - Next loop, could be reduced to a single call.
I am relatively new to vb.net coding.
I am looking to write a code that will modify the label (calculation result output) color based on some criteria. I have a drop down menu with 2 options, Dust and Metal.
The color is not changing and i am not sure why.
This is the code;
Dim concentrationcheck As String = Form8.materialType.SelectedIndex
Select Case concentrationcheck
Case "Dust"
If Val(concentrationValue.Text) < 4 Then
concentrationValue.BackColor = Color.Red
MsgBox("Add more suppressant or contact factory")
Else
concentrationValue.BackColor = Color.Green
End If
Case "Metal"
If Val(concentrationValue.Text) < 20 Then
concentrationValue.BackColor = Color.Red
MsgBox("Add more suppressant, or contact factory")
Else
concentrationValue.BackColor = Color.Green
End If
End Select
SelectedIndex is a number, not the SelectedItem
Dim concentrationcheck As String = Form8.materialType.SelectedItem.ToString
Your Form8 name sounds like the name of the form, and not the instance. My guess would be to change it to me if this is all running in the one form:
Dim concentrationcheck As String = Me.materialType.SelectedItem.ToString
If nothing is selected, an exception will be thrown, so you might have to do a simple check:
If materialType.SelectedIndex > -1 Then
code here
End If
I guess your drop down menu is combobox .. Try this ..
Dim concentrationcheck As String = Form8.materialType.Text
I'm suspicious of SelectedIndex in your original post.
SelectedIndex is an integer, not the value at that integer location.
SelectedValue might get you what you need.