Purpose is to move files in their specified folders, from which they were in IF the date is at least a day old from today. I'm having some trouble moving the file since I don't see it archived. I'm assuming it's parsing the date from a filename. VS2005 .Net 2.0
Sub CopytoArchive(ByVal mydirpath)
'mydirpath = "C:\UTResults\"
'T:\UTResults\Press3\sv70206655\data07012015.txt is an example of txtFileList
Dim txtFileList As String() = Directory.GetFiles(mydirpath, "*.txt", SearchOption.AllDirectories) 'Search all files in the given path with .txt type
For Each txtName As String In txtFileList
Dim pressname As String = txtName.Substring(0, txtName.LastIndexOf("\")) 'take out the file extension
pressname = pressname.Substring(0, pressname.LastIndexOf("\")) 'take out the folder after the press folder for a clean "PRESS" look
pressname = pressname.Remove(0, 13)
Dim folderexists As String = Path.Combine("C:\writetest\", pressname)
Dim filename = txtName.Remove(0, 4)
filename = filename.Substring(0, filename.LastIndexOf("."))
filename = Convert.ToDateTime(filename)
If filename < Date.Now Then
If My.Computer.FileSystem.DirectoryExists(folderexists) Then
My.Computer.FileSystem.MoveFile(txtName, folderexists)
Else
My.Computer.FileSystem.CreateDirectory(folderexists)
My.Computer.FileSystem.MoveFile(txtName, folderexists)
End If
End If
Next
End Sub
Sub CopytoArchive(ByVal mydirpath As String)
'mydirpath = "C:\UTResults\"
'T:\UTResults\Press3\sv70206655\data07012015.txt is an example of txtFileList
Dim dir As New DirectoryInfo(mydirpath)
Dim fileInfos = dir.EnumerateFiles("*.txt", SearchOption.AllDirectories)
fileInfos = fileInfos.
Where(Function(fi) DateTime.ParseExact(RegEx.Replace(fi.Name, "[^0-9]", ""), "MMddyyyy", Nothing) < DateTime.Now.AddDays(-1))
'The magic is here ------^^^
For Each info In fileInfos
Dim pressname As String = _
Path.GetDirectoryName(info.DirectoryName).Replace(mydirpath, "C:\writetest\")
'Better/more efficient to just call CreateDirectory() every time
My.Computer.FileSystem.CreateDirectory(pressname)
My.Computer.FileSystem.MoveFile(info.FullName, pressname)
Next
End Sub
Date strings are usually a problem, here is basic approach:
Dim s As String = "data07012015.txt"
s = s.Substring(4)
s = s.Substring(0, s.LastIndexOf("."))
' convert to valid en date string
s = s.Insert(2, "/").Insert(5, "/")
Dim dt As Date = s
If dt < Now.AddDays(-1) Then
Stop
Else
Stop
End If
Related
I have a file location and I need to check if it exists.
The way I wan't to do it is like this:
Dim route As String = ("C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt")
If System.IO.File.Exists(route) Then
MsgBox("BESTAAT HET WERKT!")
Else
Dim subroute() As String = route.Split("\"c)
Dim counting As Integer = route.Split("\"c).Length - 1
For count2 As Integer = 0 To counting - 1
Dim firstbackslash As Integer = route.IndexOf("\")
Dim backslash As Integer = route.IndexOf("\", firstbackslash + 1)
Dim firstPart As String = route.Substring(0, backslash)
MsgBox(firstPart)
Next
What I try to accomplisch is that I fist check if folder "C:" exists then "C:\testing1" then "C:\testing1\testing2" etc.
But I cant find something like this on the internet nor with some messing around...
Here is an algorithm that that will give you all the paths starting from the root and building up to the final path including the filename. You can use this to check for each folder and create them as you go if they don't exist:
Sub Main()
Dim route As String = ("C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt")
Dim fi As New System.IO.FileInfo(route)
If Not fi.Exists Then
Dim fileName As String = Path.GetFileName(route)
Dim di As DirectoryInfo = fi.Directory
Dim pathStack As New Stack(Of String)()
pathStack.Push(di.Name)
While Not IsNothing(di.Parent)
di = di.Parent
pathStack.Push(di.Name)
End While
Dim curPath As String = ""
While pathStack.Count > 0
curPath = Path.Combine(curPath, pathStack.Pop)
' ... do something with "curPath" in here ...
' ... like check for existence and create it ...
Console.WriteLine(curPath)
End While
curPath = Path.Combine(curPath, fileName)
' ... do something with "curPath" in here ...
' ... this is the full path including the file on the end ...
Console.WriteLine(curPath)
End If
Console.Write("Press Enter to quit...")
Console.ReadLine()
End Sub
Output:
C:\
C:\testing1
C:\testing1\testing2
C:\testing1\testing2\testing3
C:\testing1\testing2\testing3\testing4
C:\testing1\testing2\testing3\testing4\testing5
C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt
Press Enter to quit...
Don't use string mnaipulation to work with file or folder paths. use the Path class.
One option:
Private Function GetExistingSubPath(fullPath As String) As String
If Directory.Exists(fullPath) OrElse File.Exists(fullPath) Then
Return fullPath
End If
Dim subPath = Path.GetDirectoryName(fullPath)
If subPath Is Nothing Then
Return Nothing
End If
Return GetExistingSubPath(subPath)
End Function
Sample usage:
Dim fullPath = "C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt"
Dim existingSubPath = GetExistingSubPath(fullPath)
Console.WriteLine(existingSubPath)
What I try to accomplisch is that I fist check if folder "C:" exists then "C:\testing1" then "C:\testing1\testing2" etc.
Noooooooooooo!
That's not how to do it at all! The file system is volatile: things can change between each of those checks. Moreover, file existence is only one of many things that can stop file access.
It's much better practice to try to access the file in question, and then handle the exception if it fails. Remember, because of the prior paragraph you have to be able to handle exceptions here anyway. .Exists() doesn't save you from writing that code. And each check is another round of disk access, which is about the slowest thing it's possible to do in a computer... even slower than unrolling the stack for an exception, which is the usual objection to this idea.
I fixed it, know I can check if multiple text files are at the locations I need, if there not I place the Textfiles at the location I need them. Then I can add something in it. (I need to put a Location of something else in it.)
Dim een As String = "C:\testing1\testing2\testing7\testing1\testing1\text.txt"
Dim twee As String = "C:\testing1\testing2\testing7\testing2\testing1\text.txt"
Dim drie As String = "C:\testing1\testing2\testing7\testing3\testing1\text.txt"
Dim vier As String = "C:\testing1\testing2\testing7\testing4\testing1\text.txt"
Dim Files As String() = {een, twee, drie, vier}
For Each route As String In Files
If System.IO.File.Exists(route) Then
MsgBox("BESTAAT HET WERKT!")
Else
Dim subroute() As String = route.Split("\"c)
Dim counting As Integer = route.Split("\"c).Length - 1
Dim tel As Integer = route.Substring(route.LastIndexOf("\") + 1).Count
Dim bestandnaam As String = route.Substring(route.LastIndexOf("\") + 1)
For count2 As Integer = 0 To route.Length - tel - 1
Dim firstbackslash As Integer = route.IndexOf("\", count2)
Dim backslash As Integer = route.IndexOf("\", count2)
Dim Mapnaam As String = route.Substring(0, backslash)
count2 = firstbackslash
If System.IO.Directory.Exists(Mapnaam) Then
Else
System.IO.Directory.CreateDirectory(Mapnaam)
End If
Next
If System.IO.File.Exists(route) Then
Else
Dim objStreamWriter As System.IO.StreamWriter
objStreamWriter = New System.IO.StreamWriter(route)
Dim label As String
Select Case route
Case een
label = "een"
Case twee
label = "twee"
Case drie
label = "drie"
Case vier
label = "vier"
End Select
Dim value As String = InputBox("Route invullen naar " & label)
'Dim objStreamWriter As New System.IO.StreamWriter(route)
objStreamWriter.Write(value)
objStreamWriter.Close()
'Using sw As System.IO.StreamWriter = System.IO.File.AppendText(route)
' sw.WriteLine(value)
'End Using
End If
End If
Next route
I have a ListBox with a certain amount of items in it.
For each item in the ListBox a corresponding text file exists in the file directory.
I need to search each text file (based on what's in the ListBox) for a persons name. Each text file may contain the name or it may not.
I would then like a return which text file contains the name.
I have tried this as a way to search a text file: it works, but I'm not sure how to get this to repeat based on whats in a ListBox.
Dim sFileContents As String = String.Empty
If (System.IO.File.Exists((Application.StartupPath) & "\Project_Green.txt")) Then
sFileContents = (System.IO.File.ReadAllText((Application.StartupPath) & "\Project_Green.txt"))
End If
If sFileContents.Contains(TextBox4.Text) Then
MessageBox.Show("yup")
Else
MessageBox.Show("nope")
End If
Also, if it would be possible to ignore case that would be great.
If you have a bunch of files in a directory and you have their names in a ListBox, and you want to search their contents for something.
One liner query:
Imports System.IO
'...
Sub TheCaller()
Dim dir = My.Application.Info.DirectoryPath
Dim ext = ".txt" ' If the extensions are trimmed in the list.
Dim find = TextBox4.Text
Dim files = Directory.EnumerateFiles(dir).Where(Function(x) ListBox1.Items.Cast(Of String).
Any(Function(y) String.Concat(y, ext).
Equals(Path.GetFileName(x),
StringComparison.InvariantCultureIgnoreCase) AndAlso File.ReadLines(x).
Any(Function(z) z.IndexOf(find, StringComparison.InvariantCultureIgnoreCase) >= 0))).ToList
ListBox2.Items.Clear()
ListBox2.Items.AddRange(files.Select(Function(x) Path.GetFileNameWithoutExtension(x)).ToArray)
End Sub
Or if you prefer the For Each loop:
Sub Caller()
Dim dir = My.Application.Info.DirectoryPath
Dim find = TextBox4.Text
Dim files As New List(Of String)
For Each f As String In ListBox1.Items.Cast(Of String).
Select(Function(x) Path.Combine(dir, $"{x}.txt"))
If File.Exists(f) AndAlso
File.ReadLines(f).Any(Function(x) x.IndexOf(find,
StringComparison.InvariantCultureIgnoreCase) <> -1) Then
files.Add(f)
End If
Next
ListBox2.Items.Clear()
ListBox2.Items.AddRange(files.Select(Function(x) Path.GetFileNameWithoutExtension(x)).ToArray)
End Sub
Either way, the files list contains the matches if any.
Plus a pseudo-parallel async method, for the very heavy-duty name searches.
The Async Function SearchNameInTextFiles returns a named Tuple:
(FileName As String, Index As Integer)
where FileName is the file parsed and Index is the position where the first occurrence of the specified name (theName) was found.
If no matching sub-string is found, the Index value is set to -1.
The caseSensitive parameter allows to specify whether the match should be, well, case sensitive.
You can start the search from a Button.Click async handler (or similar), as shown here.
Imports System.IO
Imports System.Threading.Tasks
Private Async Sub btnSearchFiles_Click(sender As Object, e As EventArgs) Handles btnSearchFiles.Click
Dim filesPath = [Your files path]
Dim theName = textBox4.Text ' $" {textBox4.Text} " to match a whole word
Dim ext As String = ".txt" ' Or String.Empty, if extension is already included
Dim tasks = ListBox1.Items.OfType(Of String).
Select(Function(f) SearchNameInTextFiles(Path.Combine(filesPath, f & ext), theName, False)).ToList()
Await Task.WhenAll(tasks)
Dim results = tasks.Where(Function(t) t.Result.Index >= 0).Select(Function(t) t.Result).ToList()
results.ForEach(Sub(r) Console.WriteLine($"File: {r.FileName}, Position: {r.Index}"))
End Sub
Private Async Function SearchNameInTextFiles(filePath As String, nameToSearch As String, caseSensitive As Boolean) As Task(Of (FileName As String, Index As Integer))
If Not File.Exists(filePath) then Return (filePath, -1)
Using reader As StreamReader = New StreamReader(filePath)
Dim line As String = String.Empty
Dim linesLength As Integer = 0
Dim comparison = If(caseSensitive, StringComparison.CurrentCulture,
StringComparison.CurrentCultureIgnoreCase)
While Not reader.EndOfStream
line = Await reader.ReadLineAsync()
Dim position As Integer = line.IndexOf(nameToSearch, comparison)
If position > 0 Then Return (filePath, linesLength + position)
linesLength += line.Length
End While
Return (filePath, -1)
End Using
End Function
You can do these simple steps for your purpose:
First get all text files in the application's startup directory.
Then iterate over all names in the ListBox and for each one, search in all text files to find the file that contains that name.
To make the process case-insensitive, we first convert names and text file's contents to "lower case" and then compare them. Here is the full code:
Private Sub findTextFile()
'1- Get all text files in the directory
Dim myDirInfo As New IO.DirectoryInfo(Application.StartupPath)
Dim allTextFiles As IO.FileInfo() = myDirInfo.GetFiles("*.txt")
'2- Iterate over all names in the ListBox
For Each name As String In ListBox1.Items
'Open text files one-by-one and find the first text file that contains this name
Dim found As Boolean = False 'Changes to true once the name is found in a text file
Dim containingFile As String = ""
For Each file As IO.FileInfo In allTextFiles
If System.IO.File.ReadAllText(file.FullName).ToLower.Contains(name.ToLower) Then 'compares case-insensitive
found = True
containingFile = file.FullName
Exit For
End If
Next
'Found?
If found Then
MsgBox("The name '" + name + "' found in:" + vbNewLine + containingFile)
Else
MsgBox("The name '" + name + "' does not exist in any text file.")
End If
Next
End Sub
I have the following code to create a directory, the task accepts a recordcount and every time the recordcount reaches the required number, say 1000 records, a new directory is created. If the task is run a second time it will add another 1000 records to the existing directories, I want it to skip these existing directories and create a new one. I've tried adding various ifexists, but mess it up all the time, any help would be appreciated
Public Sub Main()
Dim SourceDirectory As String = "E:\Data"
Dim TargetDirectory As String = "E:\CN"
Dim FileExtensionsToProcess As String = "CON*.pdf"
Dim FileCounter As Integer = 0
Dim FolderName As Integer = 1
Dim recordcount As Integer
recordcount = CInt(Dts.Variables("RecordCount").Value)
For Each FileName As String In System.IO.Directory.GetFiles(SourceDirectory, FileExtensionsToProcess)
Dim FileOnly As String = System.IO.Path.GetFileName(FileName)
Try
If Not IO.Directory.Exists(IO.Path.Combine(TargetDirectory, FolderName.ToString())) Then
IO.Directory.CreateDirectory(IO.Path.Combine(TargetDirectory, FolderName.ToString()))
End If
IO.File.Move(FileName, IO.Path.Combine(TargetDirectory, IO.Path.Combine(FolderName.ToString(), FileOnly)))
Catch
End Try
FileCounter += 1
If (FileCounter Mod recordcount) = 0 Then
FolderName += 1
End If
Next
Dts.TaskResult = ScriptResults.Success
End Sub
Okay. The full solution is shown below and then I will explain some of it.
Public Sub Main()
Dim SourceDirectory As String = "E:\Data"
Dim TargetDirectory As String = "E:\CN"
Dim FileExtensionsToProcess As String = "CON*.pdf"
Dim FileCounter As Integer = 0
Dim FolderName As Integer = 1
Dim recordcount As Integer = CInt(Dts.Variables("RecordCount").Value)
Dim targetDir As String = SetOutputFolder(TargetDirectory, FolderName, recordcount)
For Each FileName As String In Directory.GetFiles(SourceDirectory, FileExtensionsToProcess)
Dim FileOnly As String = Path.GetFileName(FileName)
'Try - Leave this out to observe any exceptions, then add handling when you see any
' Check for file name conflicts before moving
File.Move(FileName, Path.Combine(targetDir, FileOnly))
'Catch
'End Try
FileCounter += 1
If FileCounter >= recordcount Then
FolderName += 1
targetDir = SetOutputFolder(TargetDirectory, FolderName, recordcount)
FileCounter = Directory.GetFiles(targetDir).Count
End If
Next
End Sub
Private Function SetOutputFolder(baseDir As String, ByRef folderName As Integer, ByRef recordCount As Integer) As String
Dim targetDir = Path.Combine(baseDir, folderName.ToString())
Dim filecounter = 0
While Directory.Exists(targetDir)
filecounter = Directory.GetFiles(targetDir).Count
If filecounter >= recordCount Then
folderName += 1
targetDir = Path.Combine(baseDir, folderName.ToString())
Else
Exit While
End If
End While
If Not Directory.Exists(targetDir) Then
Directory.CreateDirectory(targetDir)
End If
Return targetDir
End Function
The additional function I created solves a few problems. Note that it is passing the folder counter and the record count as references ByRef folderName As Integer, ByRef recordCount As Integer, so it can continue with correct values after getting the right directory. It will search for the target directory, starting at 1, and for each directory it finds it will check to see if it is full or not. If it is, then it will carry on, otherwise it will select that directory.
Within this it also checked if the directory exists and if not, creates it before exiting, this removes the extra If statements that are needed throughout and puts them in one place.
I am saving a .csv file in my directory by giving the path with StreamWriter. Now i want to give the option to user to save that file desired path. how can it. help me somebody.
Dim objStreamWriter = New IO.StreamWriter("c:\FaultTypesByMonth.csv")
Dim Str As String
Dim i As Integer
Dim j As Integer
Dim headertext1(rsTerms.Columns.Count) As String
Dim k As Integer = 0
Dim arrcols As String = Nothing
For Each column As DataColumn In TempTab.Columns
headertext1(k) = column.ColumnName
arrcols += column.ColumnName.ToString() + ","c
k += 1
Next
objStreamWriter.WriteLine(arrcols)
For i = 0 To (TempTab.Rows.Count - 1)
For j = 0 To (TempTab.Columns.Count - 1)
'this IF statement stops it from adding a comma after the last field
If j = (TempTab.Columns.Count - 1) Then
Str = (TempTab.Rows(i)(j).ToString)
Else
Str = (TempTab.Rows(i)(j).ToString & ",")
End If
objStreamWriter.Write(Str)
Next
objStreamWriter.WriteLine()
Next
objStreamWriter.Close()
' After save the file in C:/ I want to save the same file in any other Path for my convenience.
'------------------------------------------------------------------------------------------------
Dim sd As New SaveFileDialog
sd.Filter = "CSV Files (*.csv)|*.csv"
sd.FileName = "FaultTypesByMonth"
If sd.ShowDialog = Windows.Forms.DialogResult.OK Then
'save the file here
Debug.WriteLine("Save file location:" + sd.FileName)
End If
If it's a console application you could read a path argument from the command line.
If it's a GUI application you can show a save file dialog box, in WinForms use the SaveFileDialog class.
To save a file to different locations put the writer code in a function which takes the file path as an argument:
Sub SaveFile(filePath As String)
Dim objStreamWriter = New IO.StreamWriter(filePath)
' ... your code here
End Sub
Sub ButtonClick
SaveFile("c:\FaultTypesByMonth.csv")
' ... SaveFileDialog code
SaveFile(sd.Filename)
End Sub
To copy a file use File.Copy:
' ... SaveFileDialog code
File.Copy("c:\FaultTypesByMonth.csv", sd.Filename)
Use the SaveFileDialog class
Simple example:
Private Sub SaveFile()
Dim sd As New SaveFileDialog
sd.Filter = "CSV Files (*.csv)|*.csv"
If sd.ShowDialog = Windows.Forms.DialogResult.OK Then
'save the file here
Debug.WriteLine("Save file location:" + sd.FileName)
End If
End Sub
I'm currently using the following to read the contents of all text files in a directory into an array
Dim allLines() As String = File.ReadAllLines(txtfi.FullName)
Within the text files are only 6 lines that all follow the same format and will read something like
forecolour=black
I'm trying to then search for the word "forecolour" and retrieve the information after the "=" sign (black) so i can then populate the below code
AllDetail(numfiles).uPath = ' this needs to be the above result
I've only posted parts of the code but if it helps i can post the rest. I just need a little guidance if possible
Thanks
This is the full code
Dim numfiles As Integer
ReDim AllDetail(0 To 0)
numfiles = 0
lb1.Items.Clear()
Dim lynxin As New IO.DirectoryInfo(zMailbox)
lb1.Items.Clear()
For Each txtfi In lynxin.GetFiles("*.txt")
Dim allLines() As String = File.ReadAllLines(txtfi.FullName)
ReDim Preserve AllDetail(0 To numfiles)
AllDetail(numfiles).uPath = 'Needs to be populated
AllDetail(numfiles).uName = 'Needs to be populated
AllDetail(numfiles).uCode = 'Needs to be populated
AllDetail(numfiles).uOps = 'Needs to be populated
lb1.Items.Add(IO.Path.GetFileNameWithoutExtension(txtfi.Name))
numfiles = numfiles + 1
Next
End Sub
AllDetail(numfiles).uPath = Would be the actual file path
AllDetail(numfiles).uName = Would be the detail after “unitname=”
AllDetail(numfiles).uCode = Would be the detail after “unitcode=”
AllDetail(numfiles).uOps = Would be the detail after “operation=”
Within the text files that are being read there will be the following lines
Unitname=
Unitcode=
Operation=
Requirements=
Dateplanned=
For the purpose of this array I just need the unitname, unitcode & operation. Going forward I will need the dateplanned as when this is working I want to try and work out how to only display the information if the dateplanned matches the date from a datepicker. Hope that helps and any guidance or tips are gratefully received
If your file is not very big you could simply
Dim allLines() As String = File.ReadAllLines(txtfi.FullName)
For each line in allLines
Dim parts = line.Split("="c)
if parts.Length = 2 andalso parts(0) = "unitname" Then
AllDetails(numFiles).uName = parts(1)
Exit For
End If
Next
If you are absolutely sure of the format of your input file, you could also use Linq to remove the explict for each
Dim line = allLines.Where(Function(x) (x.StartsWith("unitname"))).SingleOrDefault()
if line IsNot Nothing then
AllDetails(numFiles).uName = line.Split("="c)(1)
End If
EDIT
Looking at the last details added to your question I think you could rewrite your code in this way, but still a critical piece of info is missing.
What kind of object is supposed to be stored in the array AllDetails?
I suppose you have a class named FileDetail as this
Public class FileDetail
Public Dim uName As String
Public Dim uCode As String
Public Dim uCode As String
End Class
....
numfiles = 0
lb1.Items.Clear()
Dim lynxin As New IO.DirectoryInfo(zMailbox)
' Get the FileInfo array here and dimension the array for the size required
Dim allfiles = lynxin.GetFiles("*.txt")
' The array should contains elements of a class that have the appropriate properties
Dim AllDetails(allfiles.Count) as FileDetail
lb1.Items.Clear()
For Each txtfi In allfiles)
Dim allLines() As String = File.ReadAllLines(txtfi.FullName)
AllDetails(numFiles) = new FileDetail()
AllDetails(numFiles).uPath = txtfi.FullName
Dim line = allLines.Where(Function(x) (x.StartsWith("unitname="))).SingleOrDefault()
if line IsNot Nothing then
AllDetails(numFiles).uName = line.Split("="c)(1)
End If
line = allLines.Where(Function(x) (x.StartsWith("unitcode="))).SingleOrDefault()
if line IsNot Nothing then
AllDetails(numFiles).uName = line.Split("="c)(1)
End If
line = allLines.Where(Function(x) (x.StartsWith("operation="))).SingleOrDefault()
if line IsNot Nothing then
AllDetails(numFiles).uOps = line.Split("="c)(1)
End If
lb1.Items.Add(IO.Path.GetFileNameWithoutExtension(txtfi.Name))
numfiles = numfiles + 1
Next
Keep in mind that this code could be really simplified if you start using a List(Of FileDetails)