Vb.Net - Copy files based on pattern - vb.net

I have got table named FILELISTS
Table Name - Filelists
Field - FileNames
Data Value
File1.txt
File2.csv
File3*.csv
I'm struggling to write the code, as per above if it has a file name (like file1.txt and file2.txt) it needs to copy from source to destination. If file name is pattern (like File3*.csv) then copy all files that matches this pattern from source to destination.
I'm enumerating through above row in Vb.net using data reader.

You can use Directory.EnumerateFiles and File.Copy, for example:
var filePatterns = database.GetFileNamePattern(); // your method that returns the list of files
// assuming you've stored the source- and dest.-directories in the app-settings
string sourceFolder = Properties.Settings.Default.SourceFolder;
string destFolder = Properties.Settings.Default.DestinationFolder;
foreach (string pattern in filePatterns)
{
var files = Directory.EnumerateFiles(
sourceFolder,
pattern,
SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
File.Copy(file, Path.Combine(destFolder, Path.GetFileName(file)), true);
}
}
Edit: Sorry, here the VB.NET version:
' your method that returns the list of files:
Dim filePatterns = database.GetFileNamePattern()
' assuming you've stored the source- and dest.-directories in the app-settings
Dim sourceFolder As String = My.Settings.SourceFolder
Dim destFolder As String = My.Settings.DestinationFolder
For Each pattern As String In filePatterns
Dim files = Directory.EnumerateFiles(sourceFolder, pattern, SearchOption.TopDirectoryOnly)
For Each file As String In files
IO.File.Copy(file, IO.Path.Combine(destFolder, IO.Path.GetFileName(file)), True)
Next
Next

DirectoryInfo, FileInfo - - You deleted your other question before I could click post... but this works with .net framework 2.0, like you asked
Option Strict On
Imports sO = System.IO.SearchOption
Imports dI = System.IO.DirectoryInfo
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each F In (New dI("C:\")).GetFiles("*.*", sO.TopDirectoryOnly)
MsgBox(F.FullName)
'Do your copy here
Next
End Sub
End Class

Related

How can I ignore a new line character when reading CSV file in VB.NET?

I wrote a utility in VB.NET that reads an input CSV file, does some processing (specifically it ignores the first 5 lines of the input file and replaces them with a header row saved in another file) and writes the information from the input file into a new output CSV file.
Where my program fails is when the input data includes new line characters within one column value within the CSV.
I would like to ignore the new line character within a CSV data row when I load it into my string array.
Here is my code (its embedded in a form)
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim incsvPath = strFileName
Dim outcsvPath = fi.DirectoryName & "\" & outfilename
Dim headerPath = fi.DirectoryName & "\ACTIVITY_HISTORY_HEADER.csv"
Dim fileP As String = incsvPath
Dim fileheader As String = headerPath
Dim CSVheaderIn As New ArrayList
Dim CSVlinesIn As New ArrayList
Dim CSVout As New List(Of String)
CSVheaderIn.AddRange(IO.File.ReadAllLines(fileheader))
CSVlinesIn.AddRange(IO.File.ReadAllLines(fileP))
messageTB.AppendText(vbCrLf & vbCrLf)
For Each line As String In CSVheaderIn
Dim nameANDnumber As String() = line.Split(",")
messageTB.AppendText("csv file header row = " & line & vbCrLf & vbCrLf & "csv file contents follow ..." & vbCrLf)
CSVout.Add(line)
Next
Dim mySubAL As ArrayList = CSVlinesIn.GetRange(5, CSVlinesIn.Count - 5)
For Each line As String In mySubAL 'CSVlinesIn
messageTB.AppendText(line & vbCrLf)
CSVout.Add(line)
Next
IO.File.WriteAllLines(outcsvPath, CSVout.ToArray)
End Sub
This is fairly hard work actually; it'll be easier to use a library that knows how to read and write CSV with newlines in the data than roll your own - not saying you couldn't, but it's a wheel that has already been invented so why do it again?
I used Steve Hansen's Csv - right click your project in solution explorer, choose Manage Nuget Packages, click Browse, Search csv, install the right one
Imports System.Text
Imports Csv
Imports System.IO
Module Module1
Sub Main(args As String())
'open the headers file
Using hIn = File.OpenText("C:\temp\h.csv")
'setup instruction to the csv reader with headersabsent flag so we can get the first line as data
Dim hOptions = New CsvOptions With {.HeaderMode = HeaderMode.HeaderAbsent}
'take the first line into an array - these are our headers
Dim headers = CsvReader.Read(hIn, hOptions)(0).Values
'open the data file,
Using fIn = File.OpenText("C:\temp\a.csv")
'setup instruction for the reader to skip 5 rows, treat first row as data, and allow newlines in quoted fields
Dim fOptions = New CsvOptions With {.RowsToSkip = 5, .HeaderMode = HeaderMode.HeaderAbsent, .AllowNewLineInEnclosedFieldValues = True}
Using fOut = File.CreateText("C:\temp\a_out.csv")
'convert the ICsvLine rows in the reader to rows of String() that the writer will accept, and write them under the headers
CsvWriter.Write(fOut, headers, CsvReader.Read(fIn, fOptions).Select(Function(line) line.Values))
End Using
End Using
End Using
End Sub
End Module
You don't have to use this lib to read the headers; you could just file.ReadText().ReadLine().Split(","c) it
If you want to perform per-line processing on the elements, do this:
CsvWriter.Write(fOut, headers, CsvReader.Read(fIn, fOptions).Select(Function(line) ProcessLine(line.Values)))
...
Function ProcessLine(input As String()) As String()
'Note: If(input(8), "") returns input(8) unless it is nothing in which case "" is returned instead
If If(input(8), "").Length > 10 Then input(8) = input(8).Remove(10) 'Trim if over 10
If If(input(14), "").Length > 10 Then input(14) = input(14).Remove(10)
Return input 'Always return
End Function

VB.Net Search for text and replace with file content

This is a follow on question to a post I made. Append one file into another file
I need to search the master document for entities "&CH1.sgm" to "&CH33.sgm",
mark where they are in the master document and replace the entity call with the matching file "Chapter1.sgm" found in "fnFiles". I can change the file names and entities to anything if that will help.
My code copies the text of a file and appends it to the bottom of the master_document.sgm. But now I need it to be more intelligent. Search the Master document for entity markers, then replace that entity marker with that file contents match. The file number and entity number match up. e.g.(&CH1; and Bld1_Ch1.sgm)
Private Sub btnImport_Click(sender As Object, e As EventArgs) Handles btnImport.Click
Dim searchDir As String = txtSGMFile.Text 'Input field from form
Dim masterFile = "Bld1_Master_Document.sgm"
Dim existingFileMaster = Path.Combine(searchDir, masterFile)
'Read all lines of the Master Document
Dim strMasterDoc = File.ReadAllText(existingFileMaster) '// add each line as String Array.
'?search strMasterDoc for entities &Ch1.sgm
'?replace entity name "&Ch1.sgm" with content of file "Bld1_Ch1.sgm" this content if found below
'? do I use a book mark? Replace function?
'Get all the sgm files in the directory specified
Dim fndFiles = Directory.GetFiles(searchDir, "*.sgm")
'Set up the regular expression you will make as the condition for the file
Dim rx = New Regex(".*_Ch\d\.sgm")
Dim ch1 = New Regex(".*_Ch[1]\.sgm")
'Use path.combine for concatenatin directory together
'Loop through each file found by the REGEX
For Each fileNo In fndFiles
If rx.IsMatch(fileNo) Then
If ch1.IsMatch(fileNo) Then
Dim result = Path.GetFileName(fileNo)
'Use path.combine for concatenatin directory together
Dim fileToCopy = Path.Combine(searchDir, result)
'This is the file we want to copy into MasterBuild but at specific location.
'match &ch1.sgm inside strMasterDoc
Dim fileContent = File.ReadAllText(fileToCopy)
'Search master file for entity match then append all content of fileContent
File.AppendAllText(existingFileMaster, fileContent)
MessageBox.Show("File Copied")
End If
End If
Next
Close()
End Sub
If I understand correctly (big if), you want to replace the the text of the abbreviated chapter name in the master file with the contents of the file it refers to at the spot where the abbreviation is found.
I made a class to handle the details.
Private Sub btnImport_Click(sender As Object, e As EventArgs) Handles btnImport.Click
'Add a FolderBrowseDialog to your form designer
FolderBrowserDialog1.ShowDialog()
Dim searchDir As String = FolderBrowserDialog1.SelectedPath
Dim existingFileMaster = Path.Combine(searchDir, "Bld1_Master_Document.sgm")
Dim lstFileChanges = CreateList(searchDir)
'The following method does NOT return an array of lines
Dim strMasterDoc = File.ReadAllText(existingFileMaster)
For Each fc In lstFileChanges
strMasterDoc = strMasterDoc.Replace(fc.OldString, fc.NewString)
Next
File.WriteAllText(existingFileMaster, strMasterDoc)
End Sub
Private Function CreateList(selectedPath As String) As List(Of FileChanges)
Dim lstFC As New List(Of FileChanges)
For i = 1 To lstFC.Count
Dim fc As New FileChanges
fc.OldString = $"&CH{i}.sgm"
fc.FileName = $"Chapter{i}.sgm"
fc.NewString = File.ReadAllText(Path.Combine(selectedPath, fc.FileName))
lstFC.Add(fc)
Next
Return lstFC
End Function
Public Class FileChanges
Public Property OldString As String '&CH1.sgm
Public Property FileName As String 'Chapter1.sgm
Public Property NewString As String 'Contents of Chapter1.sgm, the string to insert
End Class
Testing .Replace
Dim s As String = "The quick brown fox jumped over the lazy dogs."
s = s.Replace("fox", "foxes")
MessageBox.Show(s)

Export data to Excel file from SQL Server database

I want to create a program that can export data from sql server database to
excel file and the file name must be auto generated and auto incremented.
I query data from server using date time picker as below:
`command.CommandText = ("Select * from ComponentCheckerSystem where
Last_Update between #FromDate AND #ToDate;")
command.Parameters.Add("#FromDate", SqlDbType.Date).Value =
DateTimePicker1.Value.Date
command.Parameters.Add("#ToDate", SqlDbType.Date).Value =
DateTimePicker2.Value.Dat`
'set final path
Dim fileName As String = "\Summary of Operator Scan Wrong Items"
+ ".xls" 'just set the file Name
Dim finalPath = f.SelectedPath + fileName
txtPath.Text = finalPath
oSheet.Columns.AutoFit()
Please help me to make a function to auto generate file name.
thank you.
To create a place in Settings for your data:
1.Project Menu > Properties (all the way at the bottom)
2. Choose the Settings tab (on the left)
3. File out the boxes Name: LastFile, Type: Integer, Scope: User Value: will be set for you to 0
Actually, you could store your LastFile variable value in a text file or a database but I chose App.config for convenience.
You already know how to set your directory and the following code will get you a new file name.
Private Function GetNewFileName() As String
Dim FileSuffix As Integer = My.Settings.LastFile
FileSuffix += 1
Dim NewFileName As String = String.Format("\Summary of Operator Scan Wrong Items{0}.xls", FileSuffix)
My.Settings.LastFile = FileSuffix
Return NewFileName
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim file As String = GetNewFileName()
Debug.Print(file)
End Sub

How to zip the folders and its sub-folders in vb.net 2.0?

I have folder in the name of Main1. And inside that folders, i have multiple folders. Like
Folders1
Folders2
Folders3
Folders4
Each folders have their own files. My requirement is to zip "Main1" folder including all the sub-folders and their files.
I dont want to use any third part tools. I'm planning to use namespace System.Compression with Gzip. Please guys advice.
ZipFile.CreateFromDirectory() can easily do this for you. Just pass it the path of your Day1 folder and it will zip the entire folder to a zip file. You can iterate over all the Day folders using System.IO.Directory class.
(Just realized that you want to stick to .NET Fx 2.0. There is no direct way of doing this in that version. You must either use 3rd-party lib, which you don't want to, or do low-level stuff).
Edit
If you're really inclined towards doing it by hand, here is a crude way:
Get the list of all directories (recursive) in your Day directory; call it DirList.
Get the list of all files (recursive) in your Day directory; call it FilesList.
Create a Dictionary(Of String, String) and store the name of each file in FilesList and the BASE64 representation of its contents; name as Key, content as Value.
Save the Dictionary to an XML file using .NET's built-in XML serialization.
At the very start of the file, inject the contents of DirList.
Save the file again. (you could do steps 4-6 in a single step too).
Read this file as binary and use GZip to compress the entire content.
Write it to a zip file.
To uncompress this file:
Open the file and use GZip to decompress and get your entire content.
Grab the list of directories from the top and create all recursively.
Read the remaining section in its entirety and use XML Serialization to create your Dictionary object from it.
Iterate through the Dictionary and create files using the Key part and then inject contents into the files by converting their Value from BASE64 back to binary.
Let me know if you have questions about any of these steps.
Edit 2
The following code is compiled against .NET 2.0 and will compress and decompress a directory:
Public Function ZipDirectory(DirPath As String) As Byte()
If Not Directory.Exists(DirPath) Then Return Nothing
Dim Directories = Directory.GetDirectories(DirPath, "*", SearchOption.AllDirectories)
Dim Files = Directory.GetFiles(DirPath, "*", SearchOption.AllDirectories)
Dim X As New XmlDocument
Dim RootNode = X.CreateElement("Content")
Dim DirsNode = X.CreateElement("Directories")
Dim FilesNode = X.CreateElement("Directories")
X.AppendChild(RootNode)
RootNode.AppendChild(DirsNode)
RootNode.AppendChild(FilesNode)
For Each d In Directories
Dim DirNode = X.CreateElement("Directory")
Dim PathAttrib = X.CreateAttribute("Path")
PathAttrib.Value = d.Replace(DirPath & "\", "") 'Create relative paths
DirNode.Attributes.Append(PathAttrib)
DirsNode.AppendChild(DirNode)
Next
For Each f In Files
Dim FileNode = X.CreateElement("File")
Dim PathAttrib = X.CreateAttribute("Path")
PathAttrib.Value = f.Replace(DirPath & "\", "") 'Create relative paths
FileNode.Attributes.Append(PathAttrib)
FileNode.InnerText = Convert.ToBase64String(File.ReadAllBytes(f))
FilesNode.AppendChild(FileNode)
Next
Using Mem As New MemoryStream()
X.Save(Mem)
Dim AllContentsAsByteArray = Mem.ToArray()
Dim CompressedContent = CompressArray(AllContentsAsByteArray)
Return CompressedContent
End Using
End Function
Public Sub UnzipDirectory(compressed() As Byte, outputPath As String)
If Not Directory.Exists(outputPath) Then Directory.CreateDirectory(outputPath)
Dim Uncompressed = DecompressArray(Compressed)
Dim X As New XmlDocument
Using Mem As New MemoryStream(Uncompressed)
X.Load(Mem)
Dim RootNode = X.FirstChild
Dim DirsNode = RootNode.FirstChild
Dim FilesNode = RootNode.FirstChild.NextSibling
For Each ChildDir In DirsNode.ChildNodes
Directory.CreateDirectory(Path.Combine(outputPath, DirectCast(ChildDir, XmlNode).Attributes.Item(0).Value))
Next
For Each ChildFile In FilesNode.ChildNodes
Dim FilePath = Path.Combine(outputPath, DirectCast(ChildFile, XmlNode).Attributes.Item(0).Value)
Dim Content = Convert.FromBase64String(DirectCast(ChildFile, XmlNode).InnerText)
File.WriteAllBytes(FilePath, Content)
Next
End Using
End Sub
Private Function CompressArray(ByVal content() As Byte) As Byte()
Using outFile As New MemoryStream()
Using Compress As New GZipStream(outFile, CompressionMode.Compress)
Compress.Write(content, 0, content.Length)
End Using
Return outFile.ToArray()
End Using
End Function
Private Function DecompressArray(ByVal content() As Byte) As Byte()
Using outFile As New MemoryStream()
Using inFile As New MemoryStream(content)
Using Compress As New GZipStream(inFile, CompressionMode.Decompress)
Dim buffer(1023) As Byte
Dim nRead As Integer
Do
nRead = Compress.Read(buffer, 0, buffer.Length)
outFile.Write(buffer, 0, nRead)
Loop While nRead > 0
End Using
End Using
Return outFile.ToArray()
End Using
End Function
The code should be used like this:
'To zip a directory
Dim Compressed = ZipDirectory("C:\SomeDir")
File.WriteAllBytes("C:\somedir.zip", Compressed)
'To unzip a zipped file
Dim Compressed = File.ReadAllBytes("C:\somedir.zip")
UnzipDirectory(Compressed, "C:\SomeDir2")
Below code is using System.IO.Compression
Example from MSDN site:
Link
Imports System
Imports System.Collections.Generic
imports System.IO
imports System.IO.Compression
Public Class CompressionSnippet
Public Shared Sub Main()
Dim path As String = "test.txt"
' Create the text file if it doesn't already exist.
If Not File.Exists(path) Then
Console.WriteLine("Creating a new test.txt file")
Dim text() As String = {"This is a test text file.", _
"This file will be compressed and written to the disk.", _
"Once the file is written, it can be decompressed", _
"imports various compression tools.", _
"The GZipStream and DeflateStream class use the same", _
"compression algorithms, the primary difference is that", _
"the GZipStream class includes a cyclic redundancy check", _
"that can be useful for detecting data corruption.", _
"One other side note: both the GZipStream and DeflateStream", _
"classes operate on streams as opposed to file-based", _
"compression data is read on a byte-by-byte basis, so it", _
"is not possible to perform multiple passes to determine the", _
"best compression method. Already compressed data can actually", _
"increase in size if compressed with these classes."}
File.WriteAllLines(path, text)
End If
Console.WriteLine("Contents of {0}", path)
Console.WriteLine(File.ReadAllText(path))
CompressFile(path)
Console.WriteLine()
UncompressFile(path + ".gz")
Console.WriteLine()
Console.WriteLine("Contents of {0}", path + ".gz.txt")
Console.WriteLine(File.ReadAllText(path + ".gz.txt"))
End Sub
Public Shared Sub CompressFile(ByVal path As String)
Dim sourceFile As FileStream = File.OpenRead(path)
Dim destinationFile As FileStream = File.Create(path + ".gz")
Dim buffer(sourceFile.Length) As Byte
sourceFile.Read(Buffer, 0, Buffer.Length)
Using output As New GZipStream(destinationFile, _
CompressionMode.Compress)
Console.WriteLine("Compressing {0} to {1}.", sourceFile.Name, _
destinationFile.Name, False)
output.Write(buffer, 0, buffer.Length)
End Using
' Close the files.
sourceFile.Close()
destinationFile.Close()
End Sub
Public Shared Sub UncompressFile(ByVal path As String)
Dim sourceFile As FileStream = File.OpenRead(path)
Dim destinationFile As FileStream = File.Create(path + ".txt")
' Because the uncompressed size of the file is unknown,
' we are imports an arbitrary buffer size.
Dim buffer(4096) As Byte
Dim n As Integer
Using input As New GZipStream(sourceFile, _
CompressionMode.Decompress, False)
Console.WriteLine("Decompressing {0} to {1}.", sourceFile.Name, _
destinationFile.Name)
n = input.Read(buffer, 0, buffer.Length)
destinationFile.Write(buffer, 0, n)
End Using
' Close the files.
sourceFile.Close()
destinationFile.Close()
End Sub
End Class
Truly you would be better off using SharpLibZip

How do I get just the filename and just the path separately in a DragDrop in VB.net?

Title says it all. I just need to get the File's name that is dragged into the form by itself and the file's path (without name) into separate variables.
Code:
Private Sub Form1_DragDrop(sender As System.Object, e As System.Windows.Forms.DragEventArgs) Handles Me.DragDrop
Dim files() As String = e.Data.GetData(DataFormats.FileDrop)
Dim theFiles() As String = CType(e.Data.GetData("FileDrop", True), String())
Dim tep As Integer = 0
For Each path As String In files
If e.Data.GetDataPresent(DataFormats.FileDrop) Then
' Assign the files to an array.
Dim MyFiles As String() = DirectCast(e.Data.GetData(DataFormats.FileDrop), String())
' Display the file Name
MessageBox.Show(MyFiles(tep))
tep += 1
End If
Next
It gives me the path WITH the name from "MessageBox.show(MyFiles(tep))". I don't want that. I only want the path. I also do want the name, but just not with the path. I want them separate.
You can use the System.IO namespace to separate your path and file name.
The Path.GetDirectoryName() method will give you the parent directory's path of the specified file or directory, and the Path.GetFileName() method will give you the name and extension of the specified file.
Dim FilePath As String = IO.Path.GetDirectoryName(MyFiles(tep))
Dim FileName As String = IO.Path.GetFileName(MyFiles(tep))
MessageBox.Show(FilePath)
MessageBox.Show(FileName)
The code will produce for example:
C:\Users\Vincent\Desktop
and
Open me.txt
Read more:
MSDN - Path.GetDirectoryName()
MSDN - Path.GetFileName()