VB 2010 compare string within directory and store latest revision letter of the file name - vb.net

My application currently extracts data from an excel document, putting the data into a listview. I then am able to open each of the strings/items within the listview (which are pdf files in a given directory). However the pdf files within the given directory have revision letters at the end of their file names, starting with 'A' for the first revision and 'B' for the second revision...and so on.
So I am trying to approach it like comparing the string to the files in the directory and then once it's found, check what the latest rev letter is if any.
So if there is 07010302A.pdf file in the directory and there's also a 07010302B.pdf in the directory, I want to store that file name (07010302B.pdf) to a new string in my vb application. Any help on this would be much appreciated.
Here's what I am working with:
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
Dim range As Excel.Range
Dim rCnt As Integer
Dim cCnt As Integer
Dim Obj As Object
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Open("C:\Users\Admin\Desktop\Exp_Master.xlsm")
xlWorkSheet = xlWorkBook.Worksheets("Sheet1")
range = xlWorkSheet.Range("H1:H100") 'xlWorkSheet.UsedRange
For rCnt = 1 To range.Rows.Count
For cCnt = 1 To range.Columns.Count
Obj = CType(range.Cells(rCnt, cCnt), Excel.Range)
If IsNumeric(CType(range.Cells(rCnt, cCnt), Excel.Range).Value) Then
'MsgBox(Obj.value)
ListView1.Items.Add(Obj.value)
ListView1.View = View.List
End If
Next
Next
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
'Kill Excel Process that wouldn't close
Process.Start("C:\Users\Admin\Desktop\batch archive\EXCEL_KILLER.bat")
'MsgBox("Total Item(s) in ListView:" & ListView1.Items.Count)
Dim i As Integer = 0
Dim n As Integer = 0
Dim str As String
For i = 1 To (ListView1.Items.Count)
Dim strng As String = "R:\"
n = (i - 1)
str = strng & (ListView1.Items.Item(n).Text) & (".pdf")
MsgBox(str)
'----
'System.Diagnostics.Process.Start(str)
'Here I want to check the R:\ directory and compare it with each string to see
'what the latest revision letter of the filename is and store it in another string to add to
'a pdf merging list later in this for loop
'----
Next
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class

I was able to use your Directory.getfiles suggestion and I added a for loop to display only the last of the files labeled within that criteria. Thanks a bunch, just took a little more playing with it to determine what I actually wanted and how to put it in code.
If anyone cares, here is the update that works and gets the last file name and path of the directory.getfiles group within a search criteria.
Cheers!
For i = 1 To (ListView1.Items.Count)
Dim strng As String = "R:\"
n = (i - 1)
str = strng & (ListView1.Items.Item(n).Text) & (".pdf")
'MsgBox(str)
Dim substr As String
substr = str.Substring(3, 8)
'MsgBox(substr)
'----
'System.Diagnostics.Process.Start(str)
' Only get files that begin with...
Dim dirs As String() = Directory.GetFiles("R:\", (substr & ("*.pdf")))
'MsgBox("The number of files starting with your string is {0}.", dirs.Length)
Dim dir As String
For Each dir In dirs
If dir Is dirs.Last Then
MsgBox(dir)
'do something with your last item'
End If
Next
'----
Next
End Sub

Related

Copy files from one folder to another automatically by today's date

I need to make a program in Visual Studio that copy files from one folder to another automatically by today's date. I've this code right here that a friends gives me but I don't know how to make it work. Could someone help me pls?
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lvCreationTime As Date
Dim lvStr_Diretoria As String = ""
lvStr_Diretoria = "C:\"
Dim ficheiros() As String = IO.Directory.GetFiles(lvCreationTime)
For Each file As String In ficheiros
' Do work, example
lvCreationTime = IO.File.GetCreationTime(file)
'Dim text As String = IO.File.ReadAllText(file)
If DateDiff(DateInterval.Day, lvCreationTime, Now) = 0 Then
'file to comunicate
End If
Next
'
'If Not IO.File.Exists() Then
'End If
you can use the code below
Dim folderA As String = "C:\FolderA"
Dim folderB As String = "C:\FolderB"
'read all files from folderA
Dim infoDir As New DirectoryInfo(folderA)
Dim files As FileInfo() = infoDir.GetFiles()
'use linQ to filter by date; below from Now but you can specify what you want
Dim filter As List(Of FileInfo) = (From f In files Where f.CreationTime.Date.ToShortDateString() = Now.ToShortDateString() Select f).ToList()
' and here you move from folderA to folderB
For Each i In filter
My.Computer.FileSystem.MoveFile(i.FullName, folderB & "\" & i.Name)
Next

Combine 2 pdfs in one using VBA

I'm currently working on a macro that creates a PDF from a SolidWorks file and then, if the Solidworks File is an assembly, it would merge the pdf with its BOM.
The problem is that I've coded the merge part of the macro, but I keep getting a "False" result on the merge line of my code and I can't find why...
Once it will be debugged, this will become a Function that will get 2 file paths to merge.
Can you help me make the macro actually merge the two files? I can't find anything about why it can return a false results.
So thank you for your help!
Here's my actual code:
Sub CombinePDFs() '(ByVal NewAsmPdf As String, ByVal OldAsmPdf As String)
' The function will combine the PDFs keeping the BOM of the older file merged (The one which is replaced)
Dim Adobe As AcroPDDoc
Dim PDF1 As Object
Dim PDF2 As Object
Dim PageNF As Long
Dim PageOF As Long
Dim b As Byte
Dim NewAsmPdf As String
Dim OldAsmPdf As String
NewAsmPdf = "Path.PDF"
OldAsmPdf = "Path_BOM.PDF"
' Defines the two PDFs to be merged
Set PDF1 = CreateObject("AcroExch.PDDoc")
PDF1.Open (NewAsmPdf)
Set PDF2 = CreateObject("AcroExch.PDDoc")
PDF2.Open (OldAsmPdf)
'Get the pages to be keep
PageNF = PDF1.GetNumPages
PageOF = PDF2.GetNumPages - PageNF
'Insert PDF2 BOM in PDF1
If PDF1.InsertPages(PageNF, PDF2, PageNF + 1, PageOF, 0) Then 'Here is my problem : Keep having false (No merge)
Kill (OldAsmPdf)
Else
MsgBox ("Could not merge the Old and New file")
End If
End Sub
SOLVED!
I found out that VBA counts from 0 (So page 1 is actually the page 0) so the false was returned due to impossible values in attributes.
Here's the code of the function that I've done:
Function CombinePDFs(ByVal NewAsmPdf As String, ByVal OldAsmPdf As String)
' The function will combine the 2 PDFs and replace the OldFile by the NewFile
Dim PDF1 As Object
Dim PDF2 As Object
Dim PageNF As Long
Dim PageOF As Long
Dim NewAsmPdf As String
Dim OldAsmPdf As String
' Defines the two PDFs to be merged
Set PDF1 = CreateObject("AcroExch.PDDoc")
PDF1.Open (NewAsmPdf)
Set PDF2 = CreateObject("AcroExch.PDDoc")
PDF2.Open (OldAsmPdf)
'Get the pages to be keep
PageNF = PDF1.GetNumPages
PageOF = PDF2.GetNumPages
' Insert PDF2 BOM in PDF1
If PDF1.InsertPages(PageNF - 1, PDF2, PageNF, PageOF-1, 0)
If Not PDF1.Save(PDSaveFill, NewAsmPdf) Then
MsgBox ("Not saved")
End If
' Delete "_BOM.PDF" file
PDF2.Close
Kill (OldAsmPdf)
Else
MsgBox ("Could not merge the Old and New file")
End If
' Clear memory
Set PDF1 = Nothing
Set PDF2 = Nothing
End Function
Have fun!

exclude header from csv in vb.net

I got a .csv and I want to load it into a datagridview. I have a button called button1 and I got a datagridview called datagridview1. I click the button and it appears... including the header, which I don't want.
Please:
How do I exclude the header from the .csv ?
code:
Imports System.IO
Imports System.Text
Public Class CSV_Reader
Private Sub CSV_Reader_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim filename As String = "C:\Users\Gaius\Desktop\meepmoop.csv"
Dim thereader As New StreamReader(filename, Encoding.Default)
Dim colsexpected As Integer = 7
Dim sline As String = ""
DataGridView1.Rows.Clear()
Do
sline = thereader.ReadLine
If sline Is Nothing Then Exit Do
Dim words() As String = sline.Split(";")
DataGridView1.Rows.Add("")
If words.Length = colsexpected Then
For ix As Integer = 0 To 6
DataGridView1.Rows(DataGridView1.Rows.Count - 2).Cells(ix).Value = words(ix)
Next
Else
DataGridView1.Rows(DataGridView1.Rows.Count - 2).Cells(0).Value = "ERROR"
End If
Loop
thereader.Close()
End Sub
End Class
meepmoop.csv:
alpha;bravo;charlie;delta;echo;foxtrot;golf
1;meep;moop;meep;moop;meep;moop
2;moop;meep;moop;meep;moop;meep
3;meep;moop;meep;moop;meep;moop
4;moop;meep;moop;meep;moop;meep
5;meep;moop;meep;moop;meep;moop
6;moop;meep;moop;meep;moop;meep
7;meep;moop;meep;moop;meep;moop
8;moop;meep;moop;meep;moop;meep
9;meep;moop;meep;moop;meep;moop
10;moop;meep;moop;meep;moop;meep
edit:
[...]
Dim sline As String = ""
DataGridView1.Rows.Clear()
Dim line As String = thereader.ReadLine()
If line Is Nothing Then Return
Do
sline = thereader.ReadLine
[...]
The above addition to the code works but I have no idea why. Nor do I understand why I have to -2 rather than -1. I can't rely on guesswork, I'm expected to one day do this professionally. But I just can't wrap my head around it. Explanation welcome.
edit:
Do
sline = thereader.ReadLine
If sline Is Nothing Then Exit Do
Dim words() As String = sline.Split(";")
If words.Count = 7 Then
DataGridView1.Rows.Add(words(0), words(1), words(2), words(3), words(4), words(5), words(6))
Else
MsgBox("ERROR - There are " & words.Count & " columns in this row and there must be 7!")
End If
Loop
I've shortened the Loop on the advice of a coworker, taking his word on it being 'better this way'.
Another method, using Enumerable.Select() + .Skip()
As noted in Ondřej answer, there's a specific tool for these operations: TextFieldParser
But, if there are no special requirements and the string parsing is straightforward enough, it can be done with the standard tools, as shown in Tim Schmelter answer.
This method enumerates the string arrays returned by the Split() method, and groups them in a list that can be then used in different ways. As a raw text source (as in this case) or as a DataSource.
Dim FileName As String = "C:\Users\Gaius\Desktop\meepmoop.csv"
Dim Delimiter As Char = ";"c
Dim ColsExpected As Integer = 7
If Not File.Exists(FileName) Then Return
Dim Lines As String() = File.ReadAllLines(FileName, Encoding.Default)
Dim StringColumns As List(Of String()) =
Lines.Select(Function(line) Split(line, Delimiter, ColsExpected, CompareMethod.Text)).
Skip(1).ToList()
DataGridView1.Rows.Clear()
'If the DataGridView is empty, add a `[ColsExpected]` number of `Columns`:
DataGridView1.Columns.AddRange(Enumerable.Range(0, ColsExpected).
Select(Function(col) New DataGridViewTextBoxColumn()).ToArray())
StringColumns.Select(Function(row) DataGridView1.Rows.Add(row)).ToList()
If you instead want to include and use the Header because your DataGridView is empty (it has no predefined Columns), you could use the Header line in the .csv file to create the control's Columns:
'Include the header (no .Skip())
Dim StringColumns As List(Of String()) =
Lines.Select(Function(line) Split(line, Delimiter, ColsExpected, CompareMethod.Text)).ToList()
'Insert the columns with the .csv header columns description
DataGridView1.Columns.AddRange(Enumerable.Range(0, ColsExpected).
Select(Function(col, idx) New DataGridViewTextBoxColumn() With {
.HeaderText = StringColumns(0)(idx)
}).ToArray())
'Remove the header line...
StringColumns.RemoveAt(0)
StringColumns.Select(Function(row) DataGridView1.Rows.Add(row)).ToList()
You can skip the header by calling ReadLine twice. Also use the Using-statement:
Using thereader As New StreamReader(filename, Encoding.Default)
Dim colsexpected As Integer = 7
Dim sline As String = ""
Dim line As String = thereader.ReadLine() ' header
if line is Nothing Then Return
Do
sline = thereader.ReadLine()
If sline Is Nothing Then Exit Do
Dim words() As String = sline.Split(";"c)
' ... '
Loop
End Using
You should use VB.NET class that is designed and tested for this purpose. It is Microsoft.VisualBasic.FileIO.TextFieldParser and you can skip header by calling ReadFields() once before you start parsing in loop.

Item pairing between two .txt

I have been trying to combine or pair two text files.
One file contains User:Key
The other file contains Key:Pass
I want a 3rd text file created containing the corresponding pairs of User:Pass based on the key matching.
Here is what Ive tried most recently
Private Sub Rotate()
Dim Cracked() As String = IO.File.ReadAllLines(TextBox1.Text)
For Each lineA In Cracked
TextBox5.Text = lineA
check()
Next
End Sub
Private Sub check()
Dim toCheck() As String = TextBox5.Text.Split(":")
Dim tHash As String = toCheck(0)
Dim tPass As String = toCheck(1)
Dim lines1() As String = IO.File.ReadAllLines(TextBox2.Text)
For Each line In lines1
If lines1.Contains(tHash) Then
Dim toAdd() As String = line.Split(":")
Dim uHash As String = toCheck(0)
Dim uUser As String = toCheck(1)
ListBox1.Items.Add(uUser + ":" + tPass)
End If
Next
End Sub
Public Sub CopyListBoxToClipboard(ByVal ListBox2 As ListBox)
Dim buffer As New StringBuilder
For i As Integer = 0 To ListBox1.Items.Count - 1
buffer.Append(ListBox1.Items(i).ToString)
buffer.Append(vbCrLf)
Next
My.Computer.Clipboard.SetText(buffer.ToString)
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
CopyListBoxToClipboard(ListBox1)
End Sub
The delimiter changes but for now the : works.
I tried splitting and matching but either the textbox5 does not rotate or it rotates through the list and thats all.
Something like this?
Dim KeyPassFile As String = "..."
Dim UserKeyFile As String = "..."
Dim UserPassFile As String = "..."
Dim KeyPass As New Hashtable
' Read Key:Pass file
For Each Line In IO.File.ReadAllLines(KeyPassFile)
Dim iStart = Line.IndexOf(":")
Dim Key = Line.Substring(0, iStart)
Dim Pass = Line.Substring(iStart + 1)
KeyPass.Add(Key, Pass)
Next
' Create User:Pass file
Dim OutFile = IO.File.CreateText(UserPassFile)
' Read User:Key file
For Each Line In IO.File.ReadAllLines(UserKeyFile)
Dim iStart = Line.IndexOf(":")
Dim User = Line.Substring(0, iStart)
Dim Key = Line.Substring(iStart + 1)
If KeyPass.ContainsKey(Key) Then
' We have a match for the key, write it to the file
OutFile.WriteLine(User & ":" & KeyPass(Key))
End If
Next
OutFile.Close()
This will probably not work for very large files that doesn't fit in memory, and there is no duplicate check for the key insertion in the hashtable, but I'll leave something for you to do.. :)
Also, in your code, you read the file specified in the TextBox2.Text as many times as there are lines in the TextBox1.Text file..

How do I create text file with 2 variable in it?

I have a program that saves a name and score. Currently it stores the name and score in 2 different files. I display them as high scores with 2 listboxes.
I know that it is possible to do something along the lines of ('score|name') and then call it back and split it with the pipe. I want to be able to save a number and name in that sort of format and then call it back in a listbox and have the largest number and the corresponding name show in a label as "Highscore held by {name} with {number}!"
Alternatively, as the project has 3 variables: type, mode and difficulty, along with the name and score. Would it be possible to save it as ('type|mode|diff|score|name') and then check for the correct mode etc. for each page on the high scores page.
I am not wording this too well, so I can upload the entire code to GitHub if need be. I have done this in a very round-about way.
I have posted the relevent code below.
Sub AA1()
Dim FILE_NAME As String = System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "calculator\addition\attack\1.txt")
Dim aryText(0) As String
aryText(0) = mdiparent1.overall
Dim objWriter As New System.IO.StreamWriter(FILE_NAME, True)
objWriter.WriteLine(aryText(0))
objWriter.Close()
MsgBox("Score and Name Saved")
End Sub
\\
Sub AAN1()
Dim FILE_NAME As String = System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "calculator\addition\attack\name\1.txt")
Dim aryText(0) As String
aryText(0) = mdiparent1.username
Dim objWriter As New System.IO.StreamWriter(FILE_NAME, True)
objWriter.WriteLine(aryText(0))
objWriter.Close()
'MsgBox("Score and Name Saved")
End Sub
\\
Sub file_createAA()
Dim filepath As String = System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "calculator\addition\attack\1.txt")
If Not System.IO.File.Exists(filepath) Then
System.IO.File.Create(filepath).Dispose()
End If
End Sub
\\
Sub file_createAAN()
Dim filepath As String = System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "calculator\addition\attack\name\1.txt")
If Not System.IO.File.Exists(filepath) Then
System.IO.File.Create(filepath).Dispose()
End If
End Sub
you can try this (VB.net code now)
Dim name As List(Of String)
Dim score As List(Of Integer)
Dim delimiter As String = "###"
Dim objWriter As New System.IO.StreamWriter(FILE_NAME, True)
For i As Integer = 0 To name.Count() Step 1
objWriter.WriteLine(name(i) + delimiter + score(i).ToString())
Next
objWriter.Close()