I am getting my feet wet with VB .Net programming (total novice). I have a DataGridView with amongst other information, a file path to where a particular document is stored. I have added a DataGridViewButtonColumn to the DataGridView, but I cannot figure out how to get the button to open the file.
Sorry, I have no code to provide as starting point for where I get stuck.
Thanks in advance,
Sorry I didn't read the post clear enough the first time, and didn't explain my code enough so it got deleted. This uses the contentclick event.
Dim Filetext As String = "" 'At start of the class to make it available to the whole class
Private Sub DataGridView1_CellContentClick(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Dim FilePathColumn As Integer = 0 'File path is in Column 0
Dim ButtonColumn As Integer = 1 'Column buttons are in
Dim RowClicked As Integer = e.RowIndex 'This gets the row that you clicked the button in
If e.ColumnIndex = ButtonColumn Then 'Make sure you clicked a button
Dim FILE_PATH As String = DataGridView1.Rows(RowClicked).Cells(FilePathColumn).ToString 'Get the path to the file
If System.IO.File.Exists(FILE_PATH) Then 'Make sure file exists
Filetext = System.IO.File.ReadAllText(FILE_PATH) 'Save file to a variable
'OR
Process.Start(FILE_PATH) 'To open it
End If
End If
End Sub
You can get rid of most of those lines but I wrote it like that to explain how it worked
Related
im very new to vb.net. im making a piece of software and im very nearly finished (its my first piece of standalone software). i have a trackbar next to a button, which im trying to use to control how large a selection of this csv file should be, and then it can download it to a seperate file. my issue is im unsure how to parse the file itself and assign variables and do some variable maths and get the selection i need. ive written some pseudocode here to sort of show what im trying to do. any help or pointing in the right direction of what im looking for would be brilliant, thankyou.
Private Sub TrackBar4_Scroll(sender As Object, e As EventArgs) Handles TrackBar4.Scroll
Label44.Text = TrackBar4.Value
Dim MonthSelection As Integer = 3
MonthSelection = Label44.Text
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
If Label32.Text = "C:\" Then
MessageBox.Show("Please select Log from sign first")
Else
Dim fbd As FolderBrowserDialog = New FolderBrowserDialog()
If fbd.ShowDialog() = DialogResult.Cancel Then Exit Sub
Dim outputPath As String = IO.Path.Combine(fbd.SelectedPath, "selection log.txt")
'pseudocode
'parse file with date, time, direction, speed fields in each line
'dim SelectionRangeStart As String = LastLine.Date - MonthSelection(1,2,3,4,5,6)
'dim CSVSelectionRange As String = SelectionRangeStart to LastLine
IO.File.WriteAllText(outputPath, CSVSelectionRange)
MessageBox.Show("Success!")
End If
End Sub
ive searched for how to parse but its very complex and all forums and guides seem to be very specific and a bit difficult to understand. any help at all is greatly appreciated :)
Have a vb.net userform with a listbox set to multiselect. This is for personal use. The listbox populates itself when the form loads with all the subfolders, by name only, in a designated folder. I want to append a prefix to each selected folder in the listbox.
By default, all folders would have the prefix, let's say X. So, for example, Xfolder1 becomes folder1 if selected and the submit button is pressed (not on listbox change).
Here is my code and pseudocode so far. Getting string errors. Only the first sub, loading the form and populating the list works. Many thanks for any help. Health and safety to all during this pandemic.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each folder As String In System.IO.Directory.GetDirectories("D:\TestFolder\")
ListBox1.Items.Add(Path.GetFileName(folder))
Next
End Sub
This is ofc pseudocode
Private Sub RenameFolders(sender As Object, e As EventArgs) Handles Button1.Click
For i = 0 To ListBox1.Items.Count - 1
If Prefix Exists Then
FileIO.FileSystem.RenameDirectory(Prefix & FolderName, FolderName)
Else
FileIO.FileSystem.RenameDirectory(FolderName, Prefix & FolderName)
End If
Next
End Sub
What is above and lots of research. Issue might be with whether my strings are the full path or just the folder name. Listbox returns folder names, but is that what the code returns? Very confused.
Hi. Sorry for the lack of clarity. Because the listbox is populated on load, it will show the current state of the folders. This could be Xfolder1, folder2, xfolder3 etc. It will be the folder names as they currently exist.
Another way to look at it.
Selecting folders will remove any prefix from all selected when submit is hit.
Not selecting folders will add the prefix to all non-selected when submit is hit.
If xfolder1 appears in the listbox and is selected, it becomes folder1.
If xfolder1 appears in the listbox and is NOT selected, it remains xfolder1.
If folder1 appears in the listbox and it is selected, it remains folder1.
If folder1 appears in the listbox but is NOT selected, it changes to xfolder1
I hope that makes more sense?
Assuming that I'm understanding your question properly now, I would suggest that you use the DirectoryInfo class. You can create one for the parent folder and then get an array for the subfolders. You can then bind that array to the ListBox and display the Name property, which is just the folder name, while still having access to the FullName property, which is the full path. It also has an Exists property and a MoveTo method for renaming. Here is how I would do what you're asking for:
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim folderPath = Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Test")
Dim folder As New DirectoryInfo(folderPath)
Dim subFolders = folder.GetDirectories()
With ListBox1
.DisplayMember = "Name"
.DataSource = subFolders
End With
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Const prefix As String = "X"
For Each selectedSubFolder As DirectoryInfo In ListBox1.SelectedItems
'This is required to update the Exists property if the folder has been deleted since loading.
selectedSubFolder.Refresh()
If selectedSubFolder.Exists Then
Dim parentFolderPath = selectedSubFolder.Parent.FullName
Dim folderName = selectedSubFolder.Name
If folderName.StartsWith(prefix) Then
folderName = folderName.Substring(prefix.Length)
Else
folderName = prefix & folderName
End If
Dim folderPath = Path.Combine(parentFolderPath, folderName)
selectedSubFolder.MoveTo(folderPath)
End If
Next
End Sub
End Class
Note that this doesn't update the ListBox as it is. If you want that too, here's how I would do it with the addition of a BindingSource:
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim folderPath = Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Test")
Dim folder As New DirectoryInfo(folderPath)
Dim subFolders = folder.GetDirectories()
BindingSource1.DataSource = subFolders
With ListBox1
.DisplayMember = "Name"
.DataSource = BindingSource1
End With
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Const prefix As String = "X"
For Each selectedSubFolder As DirectoryInfo In ListBox1.SelectedItems
'This is required to update the Exists property if the folder has been deleted since loading.
selectedSubFolder.Refresh()
If selectedSubFolder.Exists Then
Dim parentFolderPath = selectedSubFolder.Parent.FullName
Dim folderName = selectedSubFolder.Name
If folderName.StartsWith(prefix) Then
folderName = folderName.Substring(prefix.Length)
Else
folderName = prefix & folderName
End If
Dim folderPath = Path.Combine(parentFolderPath, folderName)
selectedSubFolder.MoveTo(folderPath)
End If
Next
BindingSource1.ResetBindings(False)
End Sub
End Class
Note that this will still not resort the data but I'll leave that to you if you want it. The reason is that you could do a simple sort of the DirectoryInfo array on Name but that will do a straight alphabetic sort, which the ListBox can already do. If you want a logical sort like File Explorer does, where actual numbers in folder names are sorted numerically, then you need to use a Windows APi function too, which is beyond the scope of this question. If you want that, see here for more information.
I'm a complete rookie. I learned so much from here but this one I can't find the answer to. I'm using Visual Studio Pro 2015.
I have a windows form application that has a single column datagridview that is populated by reading a textfile, line by line at runtime. Each time the contents of the textfile will be different.
I want the user to be able to filter the list in the datagridview by entering characters in a textbox. The data is not "bound" to the datagridview, because at this point I don't know if that is necessary, and I don't completely understand it.
This is the code that I have for loading the datagridview, and the textbox is called txtFilter.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'read all lines from the file into a string array (one line per string)
Dim lines() As String = My.Computer.FileSystem.ReadAllText("c:\list_in.txt").Replace(vbLf, "").Split(vbCr)
Dim dgrow As DataGridViewRow
Dim dgcell As DataGridViewCell
'insert each line of input into a row in the datagrid
For Each line As String In lines
dgrow = New DataGridViewRow
dgcell = New DataGridViewTextBoxCell
If line <> "" Then
dgcell.Value = line
dgrow.Cells.Add(dgcell)
DataGridView1.Rows.Add(dgrow)
End If
Next
DataGridView1.Columns("ObjectName").ReadOnly = True
DataGridView1.ClearSelection()
End Sub
Edit:
Looking at your solution, I would advise you execute Dim lines() As String = My.Computer.FileSystem.ReadAllText("c:\list_in.txt").Replace(vbLf, "").Split(vbCr) outside of the txtFilter_TextChanged sub, as otherwise you are importing the entire list every time the user enters a key, which is unnecessary. If the list may change while the user is using the program, I'd instead recommend adding a 'refresh' button, especially if your text file could be a long one.
You also added a couple lines of code to remove the sound when the user presses the Enter key. If the user is expected to press the enter key to search, then you don't need to update the DataGridView every time the user enters a new character in the textbox. This would be easier on memory, and again very beneficial if you have a large text file.
I'm sure there's an easier way, but here's my approach.
Private Sub txtFilter_TextChanged(sender As Object, e As EventArgs) Handles txtFilter.TextChanged
Dim searchedlines(-1) As String 'create an array to fill with terms that match our search
If txtFilter.Text = Nothing Then
datapopulate(lines) 'just populate the datagridview with our text file array
Else
For Each line In lines
If line Like "*" & txtFilter.Text & "*" Then 'check if anything in our search matches any of our terms
ReDim Preserve searchedlines(UBound(searchedlines) + 1) 'resize the array to fit our needs
searchedlines(UBound(searchedlines)) = line 'add the matched line to our array
End If
Next
datapopulate(searchedlines) 'populate the datagrid with our matched terms array
End If
End Sub
Private Sub datapopulate(ByVal mylist)
Dim dgrow As DataGridViewRow
Dim dgcell As DataGridViewCell
DataGridView1.Rows.Clear() 'clear the grid
For Each line As String In mylist 'do the same thing here that we did on form load
dgrow = New DataGridViewRow
dgcell = New DataGridViewTextBoxCell
dgcell.Value = line
dgrow.Cells.Add(dgcell)
DataGridView1.Rows.Add(dgrow)
Next
End Sub
What I did is created a sub that handles whenever the text in txtFilter is changed. Alternatively, you could run that code in a sub that handles a button click. Given that, from what I know, ReDim can be a costly item in terms of memory usage, if your text document was hundreds of lines long, you might want it on a button click instead. You could probably use a list, but I haven't played around enough to know how to go about doing that.
An important note: in order for the sub txtFilter_TextChanged to be able to see lines(), I defined it outside of a sub but inside of your main class, so that all subs could access it, like so:
Public Class Form1
Dim lines() As String = My.Computer.FileSystem.ReadAllText("c:\list_in.txt").Replace(vbLf, "").Split(vbCr)
'...subs here...
End Class
I hope this helps you get started!
I have a solution working. Thank you very much.
Private Sub txtFilter_TextChanged(sender As Object, e As EventArgs) Handles txtFilter.TextChanged
'read all lines from the file into a string array (one line per string)
Dim lines() As String = My.Computer.FileSystem.ReadAllText("c:\list_in.txt").Replace(vbLf, "").Split(vbCr)
Dim dgrow As DataGridViewRow
Dim dgcell As DataGridViewCell
DataGridView1.Rows.Clear()
'insert each line of input into a row in the datagrid
For Each line As String In lines
dgrow = New DataGridViewRow
dgcell = New DataGridViewTextBoxCell
If line.Contains(txtFilter.Text) Then
dgcell.Value = line
dgrow.Cells.Add(dgcell)
DataGridView1.Rows.Add(dgrow)
End If
Next
DataGridView1.Columns("ObjectName").ReadOnly = True
DataGridView1.ClearSelection()
End Sub
And I also found this to eliminate the bell from ringing when the user pressed the enter key when entering the filter text.
Private Sub txtFilter_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtFilter.KeyPress
' this keeps the bell from ringing when the user presses the 'enter' key
If Asc(e.KeyChar) = 13 Then
e.Handled = True
End If
End Sub
Okay so I'm making a multiple-choice quiz game for an assignment and I have a form for the list of categories and the actual questions. Because I'm quite new at coding and don't really have a whole lot of time to totally restructure my code in a way that I probably wouldn't understand, instead of adding all the buttons to one buttons "Handles" I just made a sub for each click event.
This is an example of one of these subs:
Public Sub btnMusic_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMusic.Click
Questions.Show()
Me.Close()
Dim objReader As New System.IO.StreamReader("Music.txt")
End Sub
My text is read by the following structure:
Structure QuizQ
Dim Q As String
Dim A As String
Dim B As String
Dim C As String
Dim D As String
Dim Correct As String
End Structure
I then try to read the lines according to the structure with:
Dim I As Integer
For I = 0 To 5
MyQ(I).Q = objReader.ReadLine
MyQ(I).A = objReader.ReadLine
MyQ(I).B = objReader.ReadLine
MyQ(I).C = objReader.ReadLine
MyQ(I).D = objReader.ReadLine
MyQ(I).Correct = objReader.ReadLine
Next I
and then set the text for all of the buttons to the possible answers like so:
lblQuestion.Text = MyQ(qNum).Q
btnA.Text = MyQ(qNum).A
btnB.Text = MyQ(qNum).B
btnC.Text = MyQ(qNum).C
BtnD.Text = MyQ(qNum).D
But at this point the text isn't displayed on the buttons or where the question should be. I really have no idea what I could do from this point so any help really would be appreciated.
Thank you in advance!
I'm displaying data from a .txt file into a datagridview which works fine but once I press the button to display another line of data the datagridview row cell is skipping 7 lines. I don't know if this problem can be resolved in the datagridview properties or in the code itself. I have tried each way but have been unsuccessful in finding a solution
Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
Dim rowvalue As String
Dim cellvalue(0) As String
Dim streamReader As IO.StreamReader = NewIO.StreamReader("button1.txt")
'Reading CSV file content
While streamReader.Peek() <> -1
rowvalue = streamReader.ReadLine()
cellvalue = rowvalue.Split(","c) 'Separating
DataGridView1.Rows.Add(cellvalue)
End While
End Sub