Does not enable a menustrip item when the folder has files with - vb.net

My form's Load event handler checks if a folder is available (if not, it creates it) and if available checks if there are files with a specific extension. If there's at least one file with that extension, it will enable an option on a MenuStrip (referred to as QuickLoadMenuStripItem).
The problem is when it checks a folder when it's on the user's folder, it does not work, regardless if there is or not. It executes the code normally, but it always gives false. Here's the code:
Public Class BaseForm1
Private Sub BaseForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ImportFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\Immortal Sins\Saves\"
If (Not Directory.Exists(ImportFolder)) Then
Directory.CreateDirectory(ImportFolder)
QuickStartToolStripMenuItem.Enabled = False
Else
Directory.GetFiles(ImportFolder)
For Each tempstring As String In ImportFolder
If tempstring.Contains(".isgsf") Then
QuickStartToolStripMenuItem.Enabled = True
Else
QuickStartToolStripMenuItem.Enabled = False
End If
Next
End If
End Sub
End Class
For reference, it checks on C:\Users\\Immortal Sins\Saves. The files have the .isgsf extension.

You could just do:
Private Sub BaseForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ImportFolder As String = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Immortal Sins\Saves\")
If (Not Directory.Exists(ImportFolder)) Then
Directory.CreateDirectory(ImportFolder)
QuickStartToolStripMenuItem.Enabled = False
Else
QuickStartToolStripMenuItem.Enabled = (Directory.GetFiles(ImportFolder, "*.isgsf").Length > 0)
End If
End Sub

You're not storing the file list on ImportFolder when retrieving the content at Directory.GetFiles(ImportFolder)
Also, you're not checking the file extension. You're checking if the file contains a certain string.
Try this instead
Dim ImportFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\Immortal Sins\Saves\"
If (Not Directory.Exists(ImportFolder)) Then
Directory.CreateDirectory(ImportFolder)
QuickStartToolStripMenuItem.Enabled = False
Else
Dim fileEntries As String() = Directory.GetFiles(ImportFolder)
For Each file As String In fileEntries
Dim extension As String = System.IO.Path.GetExtension(file)
If extension = "isgsf" Then
QuickStartToolStripMenuItem.Enabled = True
Exit For 'Once a .isgsf is found the next files should't be checked
Else
QuickStartToolStripMenuItem.Enabled = False
End If
Next
End If

Related

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

Limited Multiselect in open file dialog?

I want the user to have the option to select multiple files through openfiledialog which I have in my code, but then if the user selects a file from one folder he is then restricted to select another file only from this specific folder. What is the best way to approach to this problem?
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim openfiledialog1 As New OpenFileDialog
With openfiledialog1
.Title = "Select your models"
.Filter = "Solidworks Files|*.sldprt;"
.Multiselect = True
End With
If OpenFileDialog1.ShowDialog = DialogResult.OK Then
For Each mfile As String In openfiledialog1.FileNames
'' Add all filenames in a txt file, in a column
Next
End If
End Sub
As far as I know, OpenFileDialog doesn't offer a way to prevent the user from navigating to another directory.
One approach would be to create a class-level variable that holds the value of the recently used directory path. Then, whenever a new file is selected, you check its directory path against the one previously stored. If it matches, continue. If not, break the operation and report to the user.
Here's a complete example:
Private openFileDialog1 As New OpenFileDialog
Private modelsDirectory As String = Nothing
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
With openFileDialog1
.Title = "Select your models"
.Filter = "Solidworks Files|*.sldprt;"
.Multiselect = True
.FileName = Nothing
' Open the dialog and navigate to the previous direcoty by default.
.InitialDirectory = modelsDirectory
End With
If openFileDialog1.ShowDialog <> DialogResult.OK Then Exit Sub
Dim dirPath As String = IO.Path.GetDirectoryName(openFileDialog1.FileName)
If modelsDirectory IsNot Nothing AndAlso
Not dirPath.Equals(modelsDirectory, StringComparison.OrdinalIgnoreCase) Then
MessageBox.Show("Models must be selected from the following directory:" &
vbNewLine & modelsDirectory, "Restricted Directory")
Exit Sub
End If
' Store the value of the current directory path.
modelsDirectory = dirPath
For Each filePath As String In openFileDialog1.FileNames
' TODO: use the selected files as you see fit.
Next
End Sub
You might want to remove this restriction at some point (e.g., if you clear the list of selected files). You can achieve that by simply setting modelsDirectory to Nothing:
Private Sub ClearFilesList
' TODO: clear the files.
modelsDirectory = Nothing
End Sub

Moving files into new folder using VB

I have one Log file that keep a full path for *.docx extension every time it's created. The problem is I don't know how to split the file's name from the full path. Before move it, I can select which Path that have been created using CheckedListBox and move it to target folder.
For example in my Log File I store (file has been created: C:\Users\AsrahLim\Desktop\New Microsoft Word Document.docx), all I need is the file's name "New Microsoft Word Document.docx" and move it to new folder .
This is my target folder: C:\Users\AsrahLim\Google Drive. Below is my code.
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CheckedListBox1.Items.Add("Select/UnSelect All")
CheckedListBox1.CheckOnClick = True
Dim FILE_NAME As String = "C:\Users\AsrahLim\Desktop\LogFile.txt"
If System.IO.File.Exists(FILE_NAME) Then
Dim objReader As New System.IO.StreamReader(FILE_NAME)
Do While objReader.Peek() <> -1
CheckedListBox1.Items.Add(objReader.ReadLine())
btnSave.Enabled = True
Loop
Else
MessageBox.Show("File Does Not Exist")
Close()
End If
End Sub
Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles btnSave.Click
If CheckedListBox1.CheckedItems.Count <> 0 Then
For i As Integer = 0 To CheckedListBox1.CheckedItems.Count - 1
Dim SourcePath As String = CheckedListBox1.SelectedItem
Dim MoveLocation As String = "C:\Users\AsrahLim\Google Drive"
SourcePath = SourcePath.Substring(SourcePath.LastIndexOf("- ") + 1)
If File.Exists(SourcePath) = True Then
File.Move(SourcePath, MoveLocation)
MsgBox("File Moved")
Else
MsgBox("File Not move")
End If
Next
End If
End Sub
Private Sub btnCancel_Click(sender As System.Object, e As System.EventArgs) Handles btnCancel.Click
Close()
End Sub
End Class
Don't try to implement your own logic for path manipulations. Use the shared Path class in System.IO instead.
Dim filename As String = Path.GetFileName(SourcePath)
Then you can construct the new path name with
Dim destinationPath As String = Path.Combine(MoveLocation, filename)
Also, test if the file exists in the destination location as well and delete it if it exists.
If File.Exists(SourcePath) Then
Dim filename As String = Path.GetFileName(SourcePath)
Dim destinationPath As String = Path.Combine(MoveLocation, filename)
If File.Exists(destinationPath) Then
File.Delete(destinationPath)
End If
File.Move(SourcePath, destinationPath)
MsgBox("File Moved")
Else
MsgBox("File Not move")
End If
A side note: I don't like statements like If File.Exists(SourcePath) = True Then. Often people think that an If-statement requires a comparison. This is not true. All it needs is a Boolean expression, i.e. an expression returning either True or False. File.Exists(SourcePath) is an expression which does exactly this. The additional = True doesn't change anything and is superfluous, because if File.Exists(SourcePath) returns True then True = True is True and if File.Exists(SourcePath) returns False then False = True is False. = True is a neutral operation as is * 1 for numbers. You don't say Foo(1 * x), you just say Foo(x).
Very simple in your log you could store with a delimiter for instance:
New File Created*C:\test.docx
The star symbol is a banned character in file name so you can be sure it wont be in the path. After this you can just do
Dim data() As String
data = Split(File.ReadAllText(LogFile.txt), StringSplitOptions.RemoveEmptyEntries)
File.Move(data(1), Path.Combine(MoveLocation , Path.GetFileName(data(1)))
Ideally you just shouldn't store files a bit everywhere on your computer and use distinct folders.

Object returns null when it is not

I basically i have two forms, one named 'frmSettings' and another names 'frmXLExternalFile', 'frmXLExternalFile' is created from 'frmSettings', there is data passed between these two forms and when i return it using a property it returns as null. Ive tried returning it by settings it to public but that still doesnt seem to work some strange reason. I've set breakpoints and traced the variable ( actually a structure ) and it is certainly not 'null'
frmXLExternalFile
Dim XL_File As frmMain.XLSheetData
Public ReadOnly Property XLFile As frmMain.XLSheetData
Get
Return XL_File
End Get
End Property
Private Sub frmXLExternalFile_formClosing(sender As Object, e As EventArgs) Handles MyBase.FormClosing
If txtFilepath.Text <> "" And cmboName.Text <> "" Then
XL_File = New frmMain.XLSheetData
XL_File.name = cmboName.Text
XL_File.filePath = txtFilepath.Text
frmMain.settings.setXLFile()
frmMain.settings.cmboXLSheets.Text = txtFilepath.Text
End If
frmMain.settings.Enabled = True
End Sub
frmMain (This is where the structure is declared)
Public Structure XLSheetData
Dim name As String
Dim filePath As String
End Structure
frmSettings
Dim XL_FileList As List(Of frmMain.XLSheetData)
Sub setXLFile()
Dim file As frmMain.XLSheetData = frmXLExternalFile.XLFile
XL_FileList.Add(file)
cmboXLSheets.Items.Add(file.filePath)
End Sub
basically, The top form calls this the bottom method once the field - XL_File - is filled, this then uses the property - 'XLFile' - to 'Get' the object and put it in the 'frmSettings' class. As I have said, i have tried setting 'XL_File' to public and tried accessing it directly but the same exception is thrown. It is null, the combo box and text box that are used to fill the object are not null. Any help would be appreciated. Thanks.
Here's one way to do it with Show(), by passing in the "Owner" form:
In frmSettings:
Dim frmX As New frmXLExternalFile
' ... pass some data to frmX ...
frmX.Show(Me) ' <-- pass this form in as the "Owner"
In frmXLExternalFile:
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
If txtFilepath.Text <> "" And cmboName.Text <> "" Then
XL_File = New frmMain.XLSheetData
XL_File.name = cmboName.Text
XL_File.filePath = txtFilepath.Text
Dim main As frmSettings = DirectCast(Me.Owner, frmSettings) ' <-- use the instance passed in as the owner via Show()
' ... use "main" somehow ...
main.settings.setXLFile()
main.settings.cmboXLSheets.Text = txtFilepath.Text
main.settings.Enabled = True
Else
' ... possibly do something else ...
End If
End Sub
This example demonstrates a ShowDialog() approach:
In frmSettings:
Dim frmX As New frmXLExternalFile
' ... pass some data to frmX ...
If frmX.ShowDialog() = Windows.Forms.DialogResult.OK Then ' <-- execution in this Form STOPS until "frmX" is dismissed
' Retrieve the value from out "frmX" instance:
Dim file As frmMain.XLSheetData = frmX.XLFile
' ... do something with "file" ...
XL_FileList.Add(file)
cmboXLSheets.Items.Add(file.filePath)
cmboXLSheets.Text = file.filePath
End If
In frmXLExternalFile:
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
If txtFilepath.Text <> "" And cmboName.Text <> "" Then
XL_File = New frmMain.XLSheetData
XL_File.name = cmboName.Text
XL_File.filePath = txtFilepath.Text
' Set DialogResult, returning execution to the ShowDialog() line:
Me.DialogResult = Windows.Forms.DialogResult.OK
Else
' ... possibly do something else ...
End If
End Sub

Folder name to combobox in VB.NET

I wanted my combo box to fill in runtime by checking all directory name in a directory.
Here is my code :
Private Sub EDITFORM_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Call CLEAR()
End Sub
Private Sub CLEAR()
qtytb.Enabled = False
parttb.Clear()
qtytb.Clear()
DTCB.Items.Clear()
MTHCB.SelectedIndex = ""
YRCB.SelectedIndex = ""
RadioButton2.Checked = True
RadioButton1.Checked = True
TextBox1.Clear()
TextBox2.Clear()
>> Dim di As New DirectoryInfo("D:\DATABASE\" & Pick_Item.deptlbl.Text)
If di.Exists = True Then
For Each subDirectory As DirectoryInfo In di.GetDirectories()
YRCB.Items.Add(CInt(subDirectory.Name.ToString))
Next
End If<<
End Sub
That is my complete code to the combobox and load form
But when i debug, it just appear a messagebox with error so i dont know where exactly is my error in the code
"Conversion from "" string to integer is not valid"
Some thing like this. So, how can i add the folder name to my combobox? Exactly my Directories name are using Integer (Cause name it by year), if i add Directories by name(Not integer) it can. Any help would be appreciated
Your problem is in the TOP line
Dim folders() As String = IO.Directory.GetDirectories("D:\DATABASE\")
For Each folder As String In folders
Combobox1.Items.Add(folder)
Next
Update
Is there any other code which is present in the subroutine/event but is not included above? I tried it and it works fine even if the folder names are numbers
I think the problem is in these lines
MTHCB.SelectedIndex = ""
YRCB.SelectedIndex = ""
change them to
MTHCB.SelectedIndex = -1
YRCB.SelectedIndex = -1