How To Clear CheckedListBox From Previous Selection - VB.NET - vb.net

Okay so I have a checkedlistbox that when a user selects a item it will print out that item into word. That works perfect. However, I want to give the user the option to not select anything at all, but when the user does not select an item in the checkboxlist, it still prints out the previous selected item into MS word.
Below is my code:
Private Sub ExportContactOkButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExportContactOkButton.Click
Dim i As Integer
Dim array_Counter_Contacts As Integer
Dim array_size_Contacts As Integer
array_Counter_Contacts = 0
For i = 0 To ExportContactCheckedListBox.Items.Count() - 1
If ExportContactCheckedListBox.GetItemCheckState(i) = CheckState.Checked Then
array_size_Contacts = UBound(SelectedContacts)
ReDim Preserve SelectedContacts(array_size_Contacts + 1)
SelectedContacts(array_Counter_Contacts) = ExportContactCheckedListBox.Items(i)
If Search.debugging = True Then
MsgBox(ExportContactCheckedListBox.Items(i))
End If
array_Counter_Contacts += 1
ExportContactCheckedListBox.Items(i) = ExportContactCheckedListBox.Items(i).ToString.Replace("'", "''")
If array_Counter_Contacts = 1 Then
ContactNames = "" & ExportContactCheckedListBox.Items(i) & ""
Else
ContactNames = String.Concat(ContactNames & "', '" & ExportContactCheckedListBox.Items(i) & "")
End If
End If
Next
If Search.debugging = True Then
MsgBox(ContactNames)
End If
sConnection.Close()
Dispose()
Me.Close()
End Sub
I have tried remove, clear, and I even tried this
Dim i As Integer
For i = 0 To ExportContactCheckedListBox.CheckedIndices.Count - 1
ExportContactCheckedListBox.SetItemChecked(ExportContactCheckedListBox.CheckedIndices(0), False)
Next i
But nothing is working. Can anyone help me? All I want is to be able to have the checkedlistbox forget or clear the checked item after the "OK" button is pressed and the text has already been printed into word.

Use a List(Of String) to store the selection and, of course remember, to reinitialize the list when you hit the ExportContactOkButton
' Declared at the form level....
Dim SelectedContacts as List(Of String)
.....
Private Sub ExportContactOkButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExportContactOkButton.Click
Dim i As Integer
SelectedContacts = new List(Of String)()
For i = 0 To ExportContactCheckedListBox.Items.Count() - 1
If ExportContactCheckedListBox.GetItemCheckState(i) = CheckState.Checked Then
SelectedContacts.Add(ExportContactCheckedListBox.Items(i))
.....
End If
Next
End Sub
In this way, every time you hit the ExportContactOKButton you reinitialize your list of contacts, loop through the checked items, add the checked one to your list.
A List(Of String) is better because you don't need to know in advance how many items your user selects in the CheckedListBox and continuosly resize the array. You simply add new items to it. And you could always use it like an array
Dim Dim array_Counter_Contacts = SelectedContacts.Count
For i = 0 to array_Counter
Console.WriteLine(SelectedContacts(i))
Next

Related

Read and write below a precise cell in a CSV

I'm stuck on a basic problem. What I want is to parse through a CSV in order to compare some string and write below if I find it.
Precisely, I have a programe where I can drag and drop some button, when I drop this button I want to save it's new location on the first empty cells below the corresponding column.
Here's a sample of my CSV :
So I substring the .x/.y from my CSV and compare the name from the drop button with each cell with the help of textFieldParser. It seems to work my loop stopped when it find an equal expression.
But here's the problem I don't know how to say to my program to write below it. The first reason I can figured it out is because my parser go until the endOfData and I want it to go until the endOfDat + one row.
The second one is because I don't know if I can use a fieldwriter into textFieldParser, I mean I tried to create a variable with row+1 and write below but nothing happen when I use fileWriter.
now a sample of my code :
Private Sub manageCsv(ByVal sender As Button)
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("..\..\Pic\csvPic.csv")
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim currentRow As String()
Dim rowPlusOne As String()
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
rowPlusUn = MyReader.ReadFields()
Dim currentField As String
Dim str As String = btnSender.Name.Substring(3)
Dim nameDelimited As String
Dim x As Integer
For Each currentField In currentRow
''Search the corresponding field''
x = InStr(currentField, ".")
If Not (currentField.Equals("imagefile")) Then ''imagefile is the first index of my csv''
nameDelimited = currentField.Substring(0, x) ''substr the extension''
If nameDelimited.Equals(str) Then
writeCsv("..\..\Image\csvPic.csv", nameDelimited, ",")
''Ofc the "+1" does not work but that was the idea''
currentRow(+1) = lblImgName.Text
currentRow(+1) = btnSender.Location.ToString
Exit For
End If
End If
Next
Catch ex As _
Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & "is not valid and will be skipped.")
End Try
End While
End Using
End Sub
I hope it's clear enough, if not i'll try to elaborate more. Thanks for your help
Show your teacher that there are better ways to do this with a simple text file. The file will only exist if buttons have been moved before in the application. See in line comments.
Private ButtonLocation As New Dictionary(Of Button, Point)
Private MouseIsDown As Boolean
Private ptX, ptY As Integer 'Starting point of mouse relative to the button
Private btn As Button 'The button being moved
Private ButtonPath As String = "C:\Users\maryo\Desktop\Code\DroppedButtons.txt"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Reposition the buttons to where they were dropped in the previous session.
If File.Exists(ButtonPath) Then
Dim lines = File.ReadAllLines(ButtonPath) 'returns an array of strings (each line)
For Each line In lines 'loop though each line in the file
Dim fields = line.Split(","c) 'The three values on the line are separated by a comma
Dim b = DirectCast(Controls(fields(0)), Button) 'Change the string Button.Name
'to an actual Button object by finding it in the controls collection
'Set the location with the next 2 values on the line
b.Location = New Point(CInt(fields(1)), CInt(fields(2)))
'Add the Button and Location to the list
ButtonLocation.Add(b, b.Location)
Next
End If
End Sub
'These three Event procedures are the normal code to Drag and Drop a control
Private Sub Button_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown, Button2.MouseDown
btn = DirectCast(sender, Button)
ptX = e.Location.X
ptY = e.Location.Y
MouseIsDown = True
End Sub
Private Sub Button_MouseMove(sender As Object, e As MouseEventArgs) Handles Button1.MouseMove, Button2.MouseMove
If MouseIsDown Then
'e.X and e.Y are the coordinates of the Mouse relative to the control (the Button)
'not the Form or the Screen.
btn.Location = New Point(btn.Location.X + e.X - ptX, btn.Location.Y + e.Y - ptY)
End If
End Sub
Private Sub Button_MouseUp(sender As Object, e As MouseEventArgs) Handles Button1.MouseUp, Button2.MouseUp
MouseIsDown = False
'When we drop the button with the MouseUp event we record the new location in the list
RecordButtonLocation(btn, btn.Location)
btn = Nothing
End Sub
Private Sub RecordButtonLocation(Sender As Button, Location As Point)
'Check if the Button is already in the list
If ButtonLocation.ContainsKey(Sender) Then
'Record its new location
ButtonLocation.Item(Sender) = Location
Else
'If it is not in the list add it.
ButtonLocation.Add(Sender, Location)
End If
End Sub
Private Sub Form1_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles Me.Closing
SaveDictionary()
End Sub
Private Sub SaveDictionary()
If ButtonLocation.Count > 0 Then
'If there is anything in the list we will create or overwrite the file
Dim sb As New StringBuilder
For Each kv As KeyValuePair(Of Button, Point) In ButtonLocation
sb.AppendLine($"{kv.Key.Name},{kv.Value.X},{kv.Value.Y}")
Next
File.WriteAllText(ButtonPath, sb.ToString)
End If
End Sub

vb.NET You are not allowed to perform an operation across different threads

I am running code to read text from pdf files and than create a WordCloud. To inform the user the process is on going I add a BackgroundWorker to my form that shows an image saying Loading. I get an error for operating across different threads.
Private Sub ButtonCreate_Click(sender As Object, e As EventArgs) Handles ButtonCreate.Click
bTextEmpty = False
ListView1.Items.Clear()
ResultPictureBox.Image = Nothing
If ListBox1.SelectedIndex > -1 Then
For Each Item As Object In ListBox1.SelectedItems
Dim ItemSelected = CType(Item("Path"), String)
Dim myTempFile As Boolean = File.Exists(ItemSelected + "\Words.txt")
If myTempFile = False Then
'when we load the form we first call the code to count words in all files in a directory
'lets check if the folder exists
If (Not System.IO.Directory.Exists(ItemSelected)) Then
Dim unused = MsgBox("The archive " + ItemSelected.Substring(ItemSelected.Length - 5, Length) + " was not found",, Title)
Exit Sub
Else
Call CreateWordList(ItemSelected)
End If
End If
'if the words file is empty we cant create a cloud so exit the sub
If bTextEmpty = True Then Exit Sub
'then we fill the wordcloud and Listview from the created textfile
Call CreateMyCloud(ItemSelected + "\Words.txt")
Next
Else
Dim unused = MsgBox("You have to choose an Archive to create the Word Cloud",, Title)
End If
Size = New Drawing.Size(1400, 800)
End Sub
I put above code in a Private Sub and called it from my BackgroundWorker. The error occured at this line: If ListBox1.SelectedIndex > -1 Then
After trying the suggested code I get the same error again:
Public Sub CreateMyCloud(ByVal sourcePDF As String)
Dim WordsFreqList As New List(Of WordsFrequencies)
For Each line As String In File.ReadLines(sourcePDF)
Dim splitText As String() = line.Split(","c)
If splitText IsNot Nothing AndAlso splitText.Length = 2 Then
Dim wordFrq As New WordsFrequencies
Dim freq As Integer
wordFrq.Word = splitText(0)
wordFrq.Frequency = If(Integer.TryParse(splitText(1), freq), freq, 0)
WordsFreqList.Add(wordFrq)
End If
Next
If WordsFreqList.Count > 0 Then
' Order the list based on the Frequency
WordsFreqList = WordsFreqList.OrderByDescending(Function(w) w.Frequency).ToList
' Add the sorted items to the listview
WordsFreqList.ForEach(Sub(wf)
error -> ListView1.Items.Add(New ListViewItem(New String() {wf.Word, wf.Frequency.ToString}, 0))
End Sub)
End If
Dim wc As WordCloudGen = New WordCloudGen(600, 400)
Dim i As Image = wc.Draw(WordsFreqList.Select(Function(wf) wf.Word).ToList, WordsFreqList.Select(Function(wf) wf.Frequency).ToList)
ResultPictureBox.Image = i
End Sub
Should look something more like:
Private Sub ButtonCreate_Click(sender As Object, e As EventArgs) Handles ButtonCreate.Click
If ListBox1.SelectedItems.Count > 0 Then
Dim data As New List(Of Object)
For Each Item As Object In ListBox1.SelectedItems
data.Add(Item)
Next
bTextEmpty = False
ListView1.Items.Clear()
ResultPictureBox.Image = Nothing
BackgroundWorker1.RunWorkerAsync(data)
Else
MessageBox.Show("You have to choose an Archive to create the Word Cloud",, Title)
End If
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim data As List(Of Object) = DirectCast(e.Argument, List(Of Object))
For Each Item As Object In data
Dim ItemSelected = CType(Item("Path"), String)
Dim myTempFile As Boolean = File.Exists(ItemSelected + "\Words.txt")
If myTempFile = False Then
'when we load the form we first call the code to count words in all files in a directory
'lets check if the folder exists
If (Not System.IO.Directory.Exists(ItemSelected)) Then
MessageBox.Show("The archive " + ItemSelected.Substring(ItemSelected.Length - 5, Length) + " was not found",, Title)
Exit Sub
Else
Call CreateWordList(ItemSelected)
End If
End If
'if the words file is empty we cant create a cloud so exit the sub
If bTextEmpty = True Then Exit Sub
'then we fill the wordcloud and Listview from the created textfile
Call CreateMyCloud(ItemSelected + "\Words.txt")
Next
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Size = New Drawing.Size(1400, 800)
End Sub
To fix the error in your second, edited post:
WordsFreqList.ForEach(Sub(wf)
ListView1.Invoke(Sub()
ListView1.Items.Add(New ListViewItem(New String() {wf.Word, wf.Frequency.ToString}, 0))
End Sub)
End Sub)
You cannot simply access controls outside of the current thread. You first need to call the Invoke method on the target control and then pass a delegate containing the instructions intended to modify the control outside of the current thread. See this article on MSDN on how to do this: https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls?view=netframeworkdesktop-4.8

increment text box name by 1 in a loop

ok so I've done numerous searches and come up with the following code to increment up the text box name, but it just does not work. The text box is within a tab control does this matter? I've tried to reference it within the tab control but no joy.
Public Cpv_Coeffs As New List(Of Decimal)
Dim i As Integer
For i = 0 To 6
'Cpv_Coeffs.Add(txt_Cp_Coef_A1.Text) 'this line works fine
Cpv_Coeffs.Add(Me.Controls("txt_Cp_Coef_A" & 1).Text)
Next i
i just get a null reference exception
where am I going wrong?
If you want it to work, no matter which container the control is in, then use the Controls.Find() fucntion. It can recursively search for the control no matter how deeply nested it is:
Public Cpv_Coeffs As New List(Of Decimal)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ctlName As String
For i As Integer = 0 To 6
ctlName = "txt_Cp_Coef_A" & i
Dim ctl As Control = Me.Controls.Find(ctlName, True).FirstOrDefault
If Not IsNothing(ctl) AndAlso TypeOf ctl Is TextBox Then
Dim tb As TextBox = DirectCast(ctl, TextBox)
Dim dcml As Decimal
If Decimal.TryParse(tb.Text, dcml) Then
Cpv_Coeffs.Add(dcml)
Else
MessageBox.Show("Value: " & tb.Text, "Invalid Decimal")
End If
Else
MessageBox.Show("Name: " & ctlName & vbCrLf & "Could Not Find Control, or it was not a TextBox.", "Error")
End If
Next i
End Sub
The above example is verbose, but it shows you exactly where all the failure points could occur.

Why is gridview.selectedColumns nothing?

I want to run a code like this, but it always jumps over the loop, so I see no line in the console.
That means that selectedColumns is empty. My assumption was that I (or the user) select a cell from a Column and then, selectedColummns are +1. But as it looks, it doesnt work. Then I tried to set proberties of selectionMode to select full columns, but then an exception is thrown:
"System.InvalidOperationException" Additional Information: the SortMode cannot be Automatic, if full Column selection is selected.
I don't know what SortMode is.
For Each col As DataGridViewColumn In datagridview2.SelectedColumns
Console.Write(datagridview2.SelectedColumns.Count)
Console.Write("1")
Next
Any Ideas how to get that the columns into selectedColumns?
Here my code that solved my problem, but I guess it is not the smartest one:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim body As String = ""
Dim myWriter As New StreamWriter("H:\downloads\test.csv", True)
Dim list As List(Of Integer) = New List(Of Integer)
For Each cell As DataGridViewCell In datagridview2.SelectedCells
If list.Contains(cell.ColumnIndex) = False Then
list.Add(cell.ColumnIndex)
End If
Next
For i = 0 To datagridview2.Rows.Count - 1
For ix = 0 To datagridview2.Columns.Count - 1
If list.Contains(ix) Then
If datagridview2.Rows(i).Cells(ix).Value IsNot Nothing Then
body = body + datagridview2.Rows(i).Cells(ix).Value.ToString + ";"
Else
body = body + ";"
End If
End If
Next
myWriter.WriteLine(body)
body = ""
Next
myWriter.Close()
End Sub
You need to do this after the selected changed event has fired.
For example:
Private Sub Mydg_ColSelected(sender As Object, e As SelectionChangedEventArgs) Handles datagridview2.SelectionChanged
For Each col As DataGridViewColumn In datagridview2.SelectedColumns
Console.Write(datagridview2.SelectedColumns.Count)
Console.Write("1")
Next
End Sub
Or if this isn't what you are after, then try handling the ColumnHeaderMouseClick event instead. I'm not sure what technology you are using, e.g Winforms, WPF, silverlight

Reading from text file & displaying on form load

I have 2 text files named sQue.txt containing single words in each lines (each word in each line) and sObj.txt also containing single word in each line (but no. of entries are more in this file than in sQue.txt).
Now, I have a blank form in which I want to read both the above files & display them in a manner such that:
Each entry from sQue.txt file gets displayed in separate labels in the form
All the entries of file sObj.txt are put in a CheckedListBox & this CheckedListBox appears for each label displayed in point 1. above.
Example:
sObj.txt contains 3 entries aaa, bbb & ccc (vertically i.e each in new line).
sQue.txt contains 5 entries p,q,r,s & t (vertically i.e each in new line).
Now, when the form loads, 3 labels are seen with texts aaa, bbb & ccc. Also 3 CheckedListBoxes are seen containg p,q,r,s & t in each box.
Can it be done? I'm trying to find a solution with no luck yet.
Please help.
Till now all I have is
Private Sub Form7_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim queue As String() = IO.File.ReadAllLines("C:\temp\sQue.txt")
Dim objects As String() = IO.File.ReadAllLines("C:\temp\sObj.txt")
For i = 0 To queue.Count - 1
'create labels here
For j=0 to objects.Count - 1
'create CheckedListBoxes
Next
Next
End Sub
If you use a groupbox you can use the text property as your label, and add a checkedlistbox to the groupbox with the items you want. This code will do that:
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim NewForm2 As New Form2
NewForm2.Show()
Dim sObj() As String = File.ReadAllLines("sobj.txt")
Dim sQue() As String = File.ReadAllLines("sQue.txt")
For Each s As String In sObj
Me.Controls.Add(MakeNewGB(s, sQue))
Next
End Sub
End Class
Public Module Module1
Friend WithEvents NewGB As System.Windows.Forms.GroupBox
Friend WithEvents NewCLB As System.Windows.Forms.CheckedListBox
Public NextColumn As Integer = 0
Public Function MakeNewGB(lbl As String, clbItems() As String) As GroupBox
NewGB = New System.Windows.Forms.GroupBox()
NewCLB = New System.Windows.Forms.CheckedListBox()
NewGB.SuspendLayout()
'GroupBox1
'
NewGB.Controls.Add(NewCLB)
NewGB.Location = New System.Drawing.Point(NextColumn, 0)
NewGB.Name = lbl
NewGB.Size = New System.Drawing.Size(126, 210)
NewGB.TabIndex = 0
NewGB.TabStop = False
NewGB.Text = lbl
'
'CheckedListBox1
'
NewCLB.FormattingEnabled = True
NewCLB.Location = New System.Drawing.Point(6, 19)
NewCLB.Name = "clb" + lbl
NewCLB.Size = New System.Drawing.Size(103, 184)
NewCLB.TabIndex = 0
NewCLB.Items.AddRange(clbItems)
NextColumn += NewGB.Size.Width + 10
Return NewGB
End Function
End Module
I think your code should look like this. But i am not sure what the purpose of it is.
Private Sub Form7_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim queue As String() = IO.File.ReadAllLines("C:\temp\sQue.txt")
Dim objects As String() = IO.File.ReadAllLines("C:\temp\sObj.txt")
For i = 0 To queue.Count - 1
'create labels here
Dim label as new Label
label.Text = queue(i)
Dim chklst as new CheckedListBox
For j=0 to objects.Count - 1
'create CheckedListBoxes
chklst.Items.Add(object(j))
Next
Me.Controls.Add(label)
Me.Controls.Add(chklst)
Next
End Sub