Nested Loop Not Working vb.net - vb.net

I am trying to read file names from source directory and then read a separate file to rename and move files to target directory. Below code reads the file names but the problem is it only reading the contents of app.ini file only once i.e. for first file name. Code is not looping app.ini as soon as for loops switches to second file name.
Dim di As New IO.DirectoryInfo("D:\Transcend")
Dim diar1 As IO.FileInfo() = di.GetFiles()
Dim dra As IO.FileInfo
If (di.GetFiles.Count > 0) Then
Dim a As Integer = 1
Dim b As Integer = 1
For Each dra In diar1
ComboBox1.Items.Add(dra.FullName.ToString)
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
Do While reader2.Peek() >= 0
Dim line2 = reader2.ReadLine
Do Until line2 Is Nothing
'line2 = reader2.ReadLine()
'ComboBox1.Items.Add(line2.ToString)
'Label1.Text = line2
If line2 <> Nothing Then
If line2.Contains("filename" + a.ToString) Then
Dim values() As String = line2.Split(CChar(":")).ToArray
Dim values2() As String = values(1).Split(CChar(";")).ToArray() 'full filename
Dim values3() As String = values(2).Split(CChar(";")).ToArray() 'keyword to be replaced in filename
Dim values4() As String = values(3).Split(CChar(";")).ToArray() 'fullname in place of keyword
Dim values5() As String = values(4).Split(CChar(";")).ToArray 'destination drive letter
Dim values6() As String = values(5).Split(CChar(";")).ToArray 'destination path after drive letter
ComboBox1.Items.Add(values2(0))
ComboBox1.Items.Add(values3(0))
ComboBox1.Items.Add(values4(0))
ComboBox1.Items.Add(values5(0) + ":" + values6(0))
'Label1.Text = dra.Name.ToString
If dra.Name.ToString.Contains(values2(0)) Then
Dim n As String = dra.Name.Replace(values3(0), values4(0))
File.Copy(dra.FullName, values5(0) + ":" + values6(0) + n)
End If
End If
End If
Exit Do
Loop
a = a + 1
Loop
reader2.Close()
End Using
b = b + 1
Next
Label1.Text = b
Else
MsgBox("No files!")
End
End If
ouput image:
Above image is to show the output and error, first line is the filename1 and the next 8 lines are the output of the app.ini file. As you can see as soon as the filename1 changes to the next file name i.e. Autorun.inf in the 9th line of the above image the same 8 lines of app.ini(line 2nd to 9th in the above image) should be reiterated after Autorun.inf file name but app.ini is not getting to read after file name increments to Autorun.inf and then to FreeSoftware(JF).htm.

The only difference between the first and the second file are the a and b values.
On the first run a will start from 1 and it will be incremented for each line in the app.ini file. After reading 8 lines, the final value of a will be 9.
For the second file, the value a isn't reset so it's value will still be 9. This means that the following condition will never be true because the first run only found value from 1 to 8 *.
If line2.Contains("filename" + a.ToString) Then
To fix your issue, you must set the a variable value back to 1 between each file:
Using reader2 As New IO.StreamReader("D:\Transcend\test\app.ini")
a = 1
Do While reader2.Peek() >= 0
* I'm assuming that the filename in your .ini file are sorted (i.e. line containing filename9 isn't listed before filename2) and that no external process changed the content of your .ini file between the first and the second file.

Related

VB.net Read Specific Lines From a Text File That Start With and Stop Reading When Start With

I'm looking to read lines from a text file that start with certain characters and stop when the line starts with other characters. So in my example I would like to start reading at line AB and stop at line EF however not all lines will contain the CD line. There will always be a AB line and EF line, however the number of lines in between is unknown.
Here is an example of the lines in a text file I would be reading. You can see that this will create two rows in the DataGridView however the first row is missing the CD line and should be blank.
AB-id1
EF-address1
AB-id2
CD-name1
EF-address2
Here is the code I have so far:
Dim lines() As String = File.ReadAllLines(textfile)
For i As Integer = 0 To lines.Length - 1
If lines(i).StartsWith("AB") Then
Dim nextLines As String() = lines.Skip(i + 1).ToArray
Dim info As String = nextLines.FirstOrDefault(Function(Line) Line.StartsWith("CD"))
Dim name As String = "Yes"
Dim info2 As String = nextLines.FirstOrDefault(Function(Line) Line.StartsWith("EF"))
Dim address As String = "Yes"
End If
DataGridView.Rows.Add(name,address)
Next
Now the output I currently get is:
|Yes|Yes|
|Yes|Yes|
And I should be getting:
||Yes|
|Yes|Yes|
It looks like it's reading too far down the text file and I need it to stop reading at EF. I've tried Do while and Do Until with no success. Any suggestions?
You could use the Array.FindIndex function to get the index of the next line starting with your prefix. This way you don't have to skip lines and create a new array each time.
Try this out instead:
Dim lines() As String = File.ReadAllLines(textFile)
For i As Integer = 0 To lines.Length - 1
If lines(i).StartsWith("AB") Then
Dim addressIndex As Integer = Array.FindIndex(lines, i + 1, Function(Line) Line.StartsWith("EF"))
Dim address As String = If(addressIndex <> -1, lines(addressIndex).Substring(3), "") ' Get everything past the "-"
Dim name As String = ""
If addressIndex <> -1 Then
Dim nameIndex As Integer = Array.FindIndex(lines, i + 1, addressIndex - i, Function(line) line.StartsWith("CD"))
If nameIndex <> -1 Then
name = lines(nameIndex).Substring(3) ' Get everything past the "-"
End If
End If
DataGridView.Rows.Add(name, address)
End If
Next

Select text between key words

This is a follow on question to Select block of text and merge into new document
I have a SGM document with comments added and comments in my sgm file. I need to extract the strings in between the start/stop comments so I can put them in a temporary file for modification. Right now it's selecting everything including the start/stop comments and data outside of the start/stop comments.
Dim DirFolder As String = txtDirectory.Text
Dim Directory As New IO.DirectoryInfo(DirFolder)
Dim allFiles As IO.FileInfo() = Directory.GetFiles("*.sgm")
Dim singleFile As IO.FileInfo
Dim Prefix As String
Dim newMasterFilePath As String
Dim masterFileName As String
Dim newMasterFileName As String
Dim startMark As String = "<!--#start#-->"
Dim stopMark As String = "<!--#stop#-->"
searchDir = txtDirectory.Text
Prefix = txtBxUnique.Text
For Each singleFile In allFiles
If File.Exists(singleFile.FullName) Then
Dim fileName = singleFile.FullName
Debug.Print("file name : " & fileName)
' A backup first
Dim backup As String = fileName & ".bak"
File.Copy(fileName, backup, True)
' Load lines from the source file in memory
Dim lines() As String = File.ReadAllLines(backup)
' Now re-create the source file and start writing lines inside a block
' Evaluate all the lines in the file.
' Set insideBlock to false
Dim insideBlock As Boolean = False
Using sw As StreamWriter = File.CreateText(backup)
For Each line As String In lines
If line = startMark Then
' start writing at the line below
insideBlock = True
' Evaluate if the next line is <!Stop>
ElseIf line = stopMark Then
' Stop writing
insideBlock = False
ElseIf insideBlock = True Then
' Write the current line in the block
sw.WriteLine(line)
End If
Next
End Using
End If
Next
This is the example text to test on.
<chapter id="Chapter_Overview"> <?Pub Lcl _divid="500" _parentid="0">
<title>Learning how to gather data</title>
<!--#start#-->
<section>
<title>ALTERNATE MISSION EQUIPMENT</title>
<para0 verdate="18 Jan 2019" verstatus="ver">
<title>
<applicabil applicref="xxx">
</applicabil>Three-Button Trackball Mouse</title>
<para>This is the example to grab all text between start and stop comments.
</para></para0>
</section>
<!--#stop#-->
Things to note: the start and stop comments ALWAYS fall on a new line, a document can have multiple start/stop sections
I thought maybe using a regex on this
(<section>[\w+\w]+.*?<\/section>)\R(<\?Pub _gtinsert.*>\R<pgbrk pgnum.*?>\R<\?Pub /_gtinsert>)*
Or maybe use IndexOf and LastIndexOf, but I couldn't get that working.
You can read the entire file and split it into an array using the string array of {"<!--#start#-->", "<!--#stop#-->"} to split, into this
Element 0: Text before "<!--#start#-->"
Element 1: Text between "<!--#start#-->" and "<!--#stop#-->"
Element 2: Text after "<!--#stop#-->"
and take element 1. Then write it to your backup.
Dim text = File.ReadAllText(backup).Split({startMark, stopMark}, StringSplitOptions.RemoveEmptyEntries)(1)
Using sw As StreamWriter = File.CreateText(backup)
sw.Write(text)
End Using
Edit to address comment
I did make the original code a little compact. It can be expanded out into the following, which allows you to add some validation
Dim text = File.ReadAllText(backup)
Dim split = text.Split({startMark, stopMark}, StringSplitOptions.RemoveEmptyEntries)
If split.Count() <> 3 Then Throw New Exception("File didn't contain one or more delimiters.")
text = split(1)
Using sw As StreamWriter = File.CreateText(backup)
sw.Write(text)
End Using

File.Exists Is Not Adding File Number to Existing File in Directory Before Saving

I'm trying to check if the file exists in the directory in which the application was saved and if so, to add a number at the end -1, -2. -3 - based on whether a file with the same name already exists. My code is below:
Dim FileName, FilePath As String
Dim FileNumber As Integer
FileName = ProjectName
FilePath = Path.Combine(CurrentDirectory, FileName)
If File.Exists(FilePath) = True Then
Do While File.Exists(FilePath)
FileNumber = FileNumber + 1
FileName = FileName & "-" & FileNumber
FilePath = Path.Combine(CurrentDirectory, FileName)
Loop
End If
NewWorkbook.SaveAs(FilePath)
When I run this code and the file is saving the first time, it works as intended but if I try saving the file with the same name a second time, there is no iterated FileNumber added to it, so the file name stays the same and it cannot save without replacing the original file.
Why is the File.Exists not recognizing that this file already exists and how can I fix this?
There is a logical problem in your code. You continue to modify the same variable and building continuosly new names.
For example. Suppose to have initially a file with the name "Project.vb". At the first iteration inside the loop you check for a file named "Project.vb1", if your loop continues at the second iteration you check for a file named "Project.vb12" and so on.
A more correct way could be
Dim FileName, FileWithoutExtension, FileExtension, FilePath As String
Dim FileNumber As Integer = 1
Dim currentDirectory As String = "E:\temp" ' as an example
FileName = "test.txt" ' as an example
FileExtension = Path.GetExtension(FileName)
FileWithoutExtension = Path.GetFileNameWithoutExtension(FileName)
FilePath = Path.Combine(CurrentDirectory, FileName)
' No need of additional if to test file existance.
Do While File.Exists(FilePath)
FileNumber = FileNumber + 1
' Rebuild the Filename part wtih all the info
FileName = FileWithoutExtension & "-" & FileNumber.ToString("D3") + FileExtension
FilePath = Path.Combine(CurrentDirectory, FileName)
Loop
NewWorkbook.SaveAs(FilePath)

Is it possible to rename the files after copying from source folder?

I copy some test images from source folder.. but i want to make their image name become "001,002" .. and so on.
For Each path As ListViewItem In listbat1.Items
For Each Ftif As String In Directory.GetFiles(path.SubItems(0).Text, "*.tif")
'For n As Integer = 0 To listbat1.Items.Count - 1
Dim Finfo As New FileInfo(Ftif)
My.Computer.FileSystem.CopyFile(Ftif, txtdirectory.Text & imgdir & Finfo.Name & ".tif")
'Next
Next
Next
Is it possible ? if so, can you help me? pls ..
If you want to rename your file using a progressive counter, then you could easily do it using the ToString with a formatting expression. In this example D3 means convert the input number to a string using three numbers and padding with zero if the number is not converted to enough character.
Dim counter as Integer = 0
For Each path As ListViewItem In listbat1.Items
For Each Ftif As String In Directory.GetFiles(path.SubItems(0).Text, "*.tif")
Dim Finfo As New FileInfo(Ftif)
Dim destFile = Path.Combine(txtDirectory.Text, imgdir, counter.ToString("D3") + ".tif")
My.Computer.FileSystem.CopyFile(Ftif, destFile)
Counter = Counter + 1
Next
Next
Notice also that building a path should always be done using the Path class

How to insert a text into text file using VBA

I want to insert a string at a particular position in text file of "utf-8" format.
let say the content in the file is "12367890"
now i want to insert "45" after "3" i.e at position 3,
now the content in the file becomes "1234567890"
I wrote some piece of but it is not working
dim str as string
Dim binaryObj As Object
str = "12367890"
Set binaryObj = CreateObject("adodb.stream")
binaryObj.Open
binaryObj.Charset = "UTF-8"
binaryObj.Type = 2
h = 0
For h = 0 To length
jpByte = Mid(jpString, h + 1, 1)
binaryObj.WriteText jpByte
Next
binaryObj.WriteText ChrW(0)
binaryObj.Position = 6
binaryObj.WriteText "4"
binaryObj.Position = 7
binaryObj.WriteText "5"
binaryObj.SaveToFile "D:\A4\Message_tool\withBom.bin", adSaveCreateOverWrite
Instead of inserting 4 and 5, these are gettin replaced with 6 & 7.
output = "12345890"
As you may have guessed, "WriteText" overwrites the text at that position, rather than inserting. Instead, write everything up until the new character insertion point (after the "3"), write the "4" and "5", then output the rest.
You may find it easier to read the file into a string, then manipulate the string with the built-in string functions, then output to the file, instead of manipulating text files.
You can create a temp file with the modified text and replace this existing file. Here is a proof of concept.
Public Sub TextFileModify()
Dim fso As New FileSystemObject
Dim text As String, line As String, temp As String
Dim path As String, fs As TextStream, fs2 As TextStream
'First create a text file with original content
path = fso.BuildPath(fso.GetSpecialFolder(2), "textfile.txt")
Set fs = fso.CreateTextFile(path, True)
fs.WriteLine "12367890"
fs.WriteLine "other stuff"
fs.Close
'Now open the file to replace a line of text
temp = fso.BuildPath(fso.GetSpecialFolder(2), fso.GetTempName())
Set fs = fso.OpenTextFile(path, ForReading)
Set fs2 = fso.CreateTextFile(temp)
While Not fs.AtEndOfStream
If fs.line = 1 Then
line = fs.ReadLine
fs2.WriteLine Left(line, 3) & "45" & Mid(line, 4)
Else
fs2.WriteLine fs.ReadLine
End If
Wend
fs.Close
fs2.Close
'New delete old file and replace with new file
fso.DeleteFile path
fso.MoveFile temp, path
' textfile.txt now contains "1234567890" in the first line and the rest of the file is identical
End Sub
Notes:
You have to add a reference to the Microsoft Scripting Runtime (per. Example here)
fso.GetSpecialFolder(2) returns the path to your temp folder.
fso.GetTempName() returns a filename like radA5FC8.tmp