I have a text file with file addresses listed line by line.
Sometimes, however, the users go in there and accidentally add a space or a blank line between the addresses and that crashes the entire code.
How could I avoid this when reading the file using VBA?
This is the current block used to open the text file and read addresses line by line:
Set ActiveBook = Application.ActiveWorkbook
PathFile = ActiveWorkbook.Path & "\FilePaths.txt"
Open PathFile For Input As #1
Do Until EOF(1)
Line Input #1, SourceFile
Set Source = Workbooks.Open(SourceFile)
You will add two lines which will ignore blank lines and spaces like this:
Line Input #1, SourceFile
SourceFile = Trim(SourceFile) '~~> This will trim all the spaces
If Not SourceFile = "" Then '~~> This will check if lines is empty
Set Source = Workbooks.Open(SourceFile)
Suggest you add further code to
test if the file actually exists
test if the file is of a valid type for excel to open
code
Dim SourceFile As String
Dim PathFile As String
Set ActiveBook = Application.ActiveWorkbook
PathFile = ActiveWorkbook.Path & "\FilePaths.txt"
Open PathFile For Input As #1
Do Until EOF(1)
Line Input #1, SourceFile
SourceFile = Trim$(SourceFile)
If Len(Dir(ActiveWorkbook.Path & "\" & SourceFile)) > 0 Then
Select Case Right$(SourceFile, Len(SourceFile) - InStrRev(SourceFile, "."))
Case "xls", "xls*"
Set Source = Workbooks.Open(ActiveWorkbook.Path & "\" & SourceFile)
Case Else
Debug.Print "source not valid"
End Select
End If
Loop
Thanks for the code.
I did some small changes so I can reuse it in many different cases and call at any point of the code, using up to 3 different args (you may increase if you wish). like this below example.
note: you may change "totalBananas,EN2003" to anything you find impossible to exist in your files... I used it this way because I am not sure how to declare the args as optional :-p I don't think they are really possible to be optional anyway.
...
Call FixTextFile(file_name, "blabla", "0000", "")
...
Sub FixTextFile(inFile As Variant, fixArg1 As String, fixArg2 As String, fixArg3 As String)
Dim resArg1, resArg2, resArg3 As Long
Dim outFile As String
Dim data As String
If fixArg1 = "" Then fixArg1 = "totalBananas,EN2003"
If fixArg2 = "" Then fixArg2 = "totalBananas,EN2003"
If fixArg3 = "" Then fixArg3 = "totalBananas,EN2003"
Open inFile For Input As #1
outFile = inFile & ".alt"
Open outFile For Output As #2
Do Until EOF(1)
Line Input #1, data
resArg1 = InStr(1, data, fixArg1)
resArg2 = InStr(1, data, fixArg2)
resArg3 = InStr(1, data, fixArg3)
If Trim(data) <> "" And resArg1 < 1 And resArg2 < 1 And resArg3 < 1 Then
Print #2, data
End If
Loop
Close #1
Close #2
Kill inFile
Name outFile As inFile
MsgBox "File alteration completed!"
End Sub
Related
I need help in modifying the CSV file using VBA. I did research and came up with this solution. However, I can't get the expected output. So, for example, I have a CSV file:
ProductID,ProductName,SupplierName,CategoryID,Unit,Price
,,,,,
1,Chais,John Ray,1,10 boxes x 20 bags,18.00093483
2,Chang,Michael,1,24 - 12 oz bottles,19.66890343
I want to change all the values under the productname and suppliername. And change something like the combination of ProductID and the Column Name. My expected output should look like:
ProductID,ProductName,SupplierName,CategoryID,Unit,Price
,,,,,
1,1 ProductName,1 SupplierName,1,10 boxes x 20 bags,18.00093483
2,2 ProductName,2 SupplierName,1,24 - 12 oz bottles,19.66890343
It can occur multiple times and can change the column location. This is my code:
Sub test()
Dim FilePath As String, LineFromFile As Variant, LineItems() As String, strFile As Variant
FilePath = "C:\Users\mestrivo\Documents\Files\MyFirstProg\test.csv"
Open FilePath For Input As #1
Do Until EOF(1)
Line Input #1, LineFromFile
LinteItems = Split(LineFromFile, ",")
LineItems(1) = LineItems(0) & " ProductName"
LineItems(2) = LineItems(0) & " SupplierName"
strFile = Join(LineItems, ",")
Loop
Open "C:\Users\mestrivo\Documents\Files\MyFirstProg\test - 2.csv" For Output As #1
Print #1, strFile
Close #1
End Sub
Please help me check my code. I got an error on this part:
Open "C:\Users\mestrivo\Documents\Files\MyFirstProg\test - 2.csv" For Output As #1
it says that the file is already open.
NEVER hard-code file handles, they aren't for you to grab, they're for VBA to query what's available and give you a free, usable file handle. Use the FreeFile function to do this.
Dim fileHandle As Long
fileHandle = FreeFile
Then replace all hard-coded #1 handles with #fileHandle.
You cannot open two different files using the same handle. You've already opened the file for input:
Open FilePath For Input As #1
So when you try to use the same handle for output...
Open "C:\Users\mestrivo\Documents\Files\MyFirstProg\test - 2.csv" For Output As #1
That's when you get an error; you haven't closed the #1 handle yet, and now you're trying to reuse it to open another file - you can't do that.
You're dealing with two files, so either you open the first one, read it, then close it before you open the second one, write to it and then close it - or, you open both, and write to one as you read the other, then close both.
Either way, you shouldn't hard-code file handles. Use FreeFile to get a free file handle. Always.
Try this:
Sub test()
Dim FilePath As String, LineFromFile As Variant, _
LineItems() As String, strFile As Variant
FilePath = "mycsv.csv"
Open FilePath For Input As #1
Do Until EOF(1)
Line Input #1, LineFromFile
LineItems() = Split(LineFromFile, ",")
'I suggest to add the following 'If' statements
If LineItems(0) <> "" Then
LineItems(1) = LineItems(0) & " ProductName"
LineItems(2) = LineItems(0) & " SupplierName"
End If
If strFile <> "" Then strFile = strFile & Chr(10)
'-------------------------------------------------
strFile = strFile & Join(LineItems, ",")
Loop
'In the next 'Open' statement you are trying to
'assign an object over another that's already opened,
'therefore you must close the previous object first
'and / or declare the second one with another name
Close #1
Open "mycsv2.csv" For Output As #1
Print #1, strFile
Close #1
End Sub
I have the following code where I am trying to modify some Txt files in a specific folder. I first want to check that the Loop works. However when I run the macro the code can only read the first file and then there is a runtime 5 error at strFileName = Dir(). I am not sure what the problem is. The only issue I can think of is that I am moving the code between two module sheets. The folder location is being saved in a txt box in Sheet 1 of an excel workbook.
Sub Txt_File_Loop()
Public TextFile As String
Dim FolderLocation As String
Dim strFielName As String
Dim SaveLocation As String
'Location is present in a Text box
FolderLocation = Sheets(1).FolderLocationTXTBX.Text
strFileName = Dir(FolderLocation & " \ * ")
Do Until strFileName = ""
TextFile = FolderLocation & "\" & strFileName
Module2.Macro1
strFileName = Dir() 'ERROR is Here
Loop
End Sub
Sub Macro1()
Dim x As String
Open TextFile For Input As #1
Do Until EOF(1)
Line Input #1, textline
x = x & textline
Loop
Close #1
MsgBox x
End Sub
Have a look at these modifications. They seem to correct several things and run through well.
Option Explicit
Sub Txt_File_Loop()
Dim FolderLocation As String
Dim strFileName As String
Dim SaveLocation As String
'Location is present in a Text box
FolderLocation = Sheets(1).FolderLocationTXTBX.Text 'Environ("TMP")
strFileName = Dir(FolderLocation & "\*.txt")
Do Until strFileName = ""
Debug.Print FolderLocation & "\" & strFileName
Module2.Macro1 FolderLocation & "\" & strFileName
strFileName = Dir() 'ERROR is Here
Loop
End Sub
Sub Macro1(sFPFN As String)
Dim x As String, textline As String
Debug.Print sFPFN
Open sFPFN For Input As #1
Do Until EOF(1)
Line Input #1, textline
x = x & textline
Loop
Close #1
MsgBox x
End Sub
I passed the folder and filename name across as a string-type parameter. Also, I don't know why you had the extra spaces in (FolderLocation & " \ * " ; I tightened that up. There were a few misspellings and undeclared variables; these can be avoided with Option Explicit¹ at the top of the module code sheet. Get into the practise of standard indentation with your code. It certainly improves readability if nothing else.
¹ Setting Require Variable Declaration within the VBE's Tools ► Options ► Editor property page will put the Option Explicit statement at the top of each newly created code sheet. This will avoid silly coding mistakes like misspellings as well as influencing you to use the correct variable type in the variable declaration. Variables created on-the-fly without declaration are all of the variant/object type. Using Option Explicit is widely considered 'best practice'.
I would like to ask the community if there is anyway someone can store file directories path into a notepad or other word document and let VBA scan through each file directories and check if file exist.
Here's a commented code that uses dir to illustrate the comment above.
'This function will check if the file or the directory
'exists and returns a boolean.
Function ExistTest(Path As String) As Boolean
'The function default return is set to false
ExistTest = False
'Remove stream reader appending
Path = Replace(Path, "", "")
'Dir returns a 0-length string if the file or directory doesn't exist
If Len(Dir(Path)) > 0 Or Len(Dir(Path, vbDirectory)) > 0 Then
ExistTest = True
End If
End Function
Sub main()
'Defining the source file
Dim SourceFile As String: SourceFile = "d:/t.txt"
'Open a stream reader
Open SourceFile For Input As #1
'Read all line until the end of file
'Before we define a temporary string the path as we go through
'the sourcefile
Dim TempPath As String
Do Until EOF(1)
Line Input #1, TempPath
'Debug print the results
Debug.Print (TempPath & " " & ExistTest(TempPath))
Loop
Close #1
End Sub
Debug.Print will print in the immediate window. To enable that, go to View > Immediate Window
I've been wracking my brains with a file input problem, I've finally got it down to two problems, I can get past the error 62, "Read past End of file", but this one I can't get past.
Can someone tell me if I'm doing anything wrong / verify?
Basically the (this) code writes two lines#
?xml version="1.0"?
A Second Line
the debug statement in Part 1 (write file) prints the text as
?xml version="1.0"?
A Second Line
the debug statement in Part 2 (read file) prints the text as
ÿþ?xml version="1.0"?
A Second Line
As you can see, there are two extra characters being added to the either the input or
the output stream at the beginning of the file.
A second line has been added for completeness to show in more detail that it is only the first line that is being screwed.
When I look through Notepad there is nothing extra, what/where are these extras coming from?
Any thoughts, thanks in advance,
regards
Seán
Sub writeXMLTest()
'Part 1 - Write the file
Dim FSO As Object
Dim NewFile As Object
Dim FullPath As String
Dim XMLFileText As String
FullPath = "E:\TESTFILE.xml"
'On Error GoTo Err:
Set FSO = CreateObject("Scripting.FileSystemObject")
Set NewFile = FSO.CreateTextFile(FullPath, 1, 1)
XMLFileText = ""
XMLFileText = XMLFileText & "?xml version=" & Chr(34) & "1.0" & Chr(34) & "?" & vbNewLine
NewFile.Write (XMLFileText)
Debug.Print XMLFileText
XMLFileText = XMLFileText & "A Second Line" & vbNewLine
NewFile.Write (XMLFileText)
Debug.Print XMLFileText
NewFile.Close
'Part 1 - Complete
'Part 2 - Now to read the file
Dim FileNum As Integer, i As Integer
Dim s As String
' fpath = Application.GetOpenFilename
FileNum = FreeFile()
Open FullPath For Input As #FileNum
i = 1
While Not EOF(FileNum)
Line Input #FileNum, s ' read in data 1 line at a time
Debug.Print s
Wend
End Sub
Just a quick shot: Generally, xml-files use UTF8 encoding. But the FileSystemObject cannot handle UTF8. You can do this (read and write UTF8-Files in VBA) with an ADODB.Stream object - you'll find examples across the web.
I have data such as the following in a text file:
Member A
Diameter 60 in
Thickness 1 in
Yield Stress 50 ksi
Brace B
Diameter 54 in
Thickness 1 in
Yield Stress 50 ksi
I need to extract numerical diameter (or thickness, or yield stress) when a string of text "Member A" is found within a long text file. Data is always in same order.
I can extract data that is on the same line as the text I'm searching for using "Trim" / "Mid". I do not know how to refer to "the line below" the text I'm searching for.
My code:
Sub jtdtlextract()
Dim str, str1, strOutPut, strBrcAngle, strComnJt, strChrdDia As String
Dim FileToOpen, FileConverted, strRun, lngReturn, fs, f, s, ff
FileToOpen = Application.GetOpenFilename("All Files (*.*), *.*")
If FileToOpen <> False Then
MsgBox FileToOpen, 0, "Open File"
End If
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFile(FileToOpen)
FileConverted = UCase(f.ParentFolder.Path) & "\jt_dtls_extracted.txt"
Open FileToOpen For Input Access Read Shared As #1
Open FileConverted For Output Access Write Shared As #2
Do Until EOF(1)
Line Input #1, str
str1 = LTrim(str)
If Left(str1, 31) = "Detailed Review Report of Joint" Then
strComnJt = Trim(Mid(str1, 35, 4))
strOutPut = "Common_Jt" & Space(1) & strComnJt
Print #2, strOutPut
End If
'I have a lot more information to extract from the text file
'I was hoping to use a method similar to above since it's
'fairly simple and I have no coding experience, the code
'above only works when the information needed is on the
'same line as the information searched for. Was written
'by someone else.
Loop
Close #1
Close #2
strRun = "Notepad.exe " & FileConverted
lngReturn = Shell(strRun)
End Sub
You'll need some state-management code to keep track of where you are in the file.
If the file is not too big you don't need full-streaming and can use full-buffering in an array.
Then you can naturally scan this array using simple indexing :
name = lines(i)
diameter = parseDiameter(lines(i+1))
thickness = parseThickness(lines(i+2))
yieldStress = parseYieldStress(lines(i+3))
i = i + 5
Do Until EOF(1)
Line Input #1, str
str1 = LTrim(str)
If Left(str1, 31) = "Detailed Review Report of Joint" Then
strComnJt = Trim(Mid(str1, 35, 4))
strOutPut = "Common_Jt" & Space(1) & strComnJt
Print #2, strOutPut
Line Input #1, strDiscardThisLine
Line Input #1, str3rdLine
strOutPut = Trim(Mid(str3rdLine,35,4))
Print #2, strOutPut
End If