VBA Error 52 to read last line of log file - excel

I am using this code to open a log file, and read the last line, to see if the file was correctly closed last time or not. If not, it will add a line in the log specifying a "Fatal Error". But, when the code runs, I get an Error 52 message. I already read a lot of posts here and other foruns, changed my code and used some posted here to make it work, but nothing worked.
Edited to better MCVE:
Public Function WriteLogFile(strMsg As String)
Const LogFileName As String = "\log\FrenteCaixa.log"
Dim FileNum As Integer, strLogMsg As String, strAddFatalError As String
FileNum = FreeFile
If Right(strMsg, 6) = "aberto" Then
Open ThisWorkbook.Path & LogFileName For Input Access Read Lock Read As #FileNum
Dim lngCounter As Long, strLastLine As String
lngCounter = 0
Do Until EOF(lngCounter) **--> THE ERROR IS HERE!**
Line Input #FileNum, strLastLine
If Left(strLastLine, 8) <> "<!-- EoF" Then strAddFatalError = "<!-- FATAL ERROR -->"
lngCounter = lngCounter + 1
Loop
Close #FileNum
End If
Open ThisWorkbook.Path & LogFileName For Append As #FileNum
If strAddFatalError <> "" Then Print #FileNum, strAddFatalError
Print #FileNum, strLogMsg
Close #FileNum
End Function

Your usage of EOF(lngCounter) is wrong. From its documentation, this function expects a file number:
Function EOF(FileNumber As Integer) As Integer
You are feeding it with a line counter, which is 0 at the start. This might be the reason for the error you are seeing.
Try replacing EOF(lngCounter) with EOF(FileNum) and see if it works.
Also, if I'm not mistaken, you don't need that line counter lngCounter at all here. Reading a line via Line Input will advance the line pointer so that the next time the statement is executed, it will read the next line.
Public Sub WriteLogFile(strMsg As String)
Const LogFileName As String = "\log\FrenteCaixa.log"
Dim FileNum As Integer, strLogMsg As String, strAddFatalError As String
FileNum = FreeFile
If Right(strMsg, 6) = "aberto" Then
Open ThisWorkbook.Path & LogFileName For Input Access Read Lock Read As #FileNum
Dim strLastLine As String
Do Until EOF(FileNum) '**--> THE ERROR IS HERE!**
Line Input #FileNum, strLastLine
If Left(strLastLine, 8) <> "<!-- EoF" Then strAddFatalError = "<!-- FATAL ERROR -->"
Loop
Close #FileNum
End If
Open ThisWorkbook.Path & LogFileName For Append As #FileNum
If strAddFatalError <> "" Then Print #FileNum, strAddFatalError
Print #FileNum, strLogMsg
Close #FileNum
End Sub
I've also made it a Sub as you're not assigning any return value, so having it as a function would be somewhat misleading.

Related

Changing a number in a txt.file with VBA

Text file
I am new here and I want t know how to change the value of a number in a text file.
This is for a project I am working on for the company I work for.
The number is used to create new project numbers by clicking a single button.
With the code in the file below I can read the text from the file on my desktop and put it in a cell in Excel. But after that I want the number to increase by 10.
Can somebody please help me.
Thanks alot in advance.
Sub Hallo()
Dim X As Double
Dim TXT As String
Open "C:\Users\Leon\Desktop\Project nummer.txt" For Input As #1
Do While Not EOF(1)
Line Input #1, TXT
Sheets("Blad1").Range("C2") = TXT
Loop
Close #1
End Sub
Write back to the file
Option Explicit
Sub Hallo()
Const FOLDER = "C:\Users\Leon\Desktop\"
Const FILENAME = "Project nummer.txt"
Const INC = 10
Dim s As String, ff
ff = FreeFile()
Open FOLDER & FILENAME For Input As #ff
Line Input #ff, s
Close #ff
If IsNumeric(s) Then
Sheets("Blad1").Range("C2") = Format(s, 0)
' save new number
ff = FreeFile()
Open FOLDER & FILENAME For Output As #ff
Write #ff, Val(s) + INC
Close #ff
Else
MsgBox s & " not valid number", vbCritical
End If
End Sub

"File already open" when trying to open a text file

What I want to do: I have an Log.txt where special values from an Excel-Sheet are listed. Anytime the Macro is executed, it checks for new special values. Before adding them to the Log.txt via a Sub, the same Sub checks if the corresponding value (they are unambigous) is already on the Log-List. If this is not the case, the value should be added to the list.
My approach: You can see my current approach in the code example below.
Dim FileNum as Integer
dim DataLine as String
Dim strPath as String
Dim strEntry as String
strPath = [Path to Log.txt]
strEntry = [Special Value]
'In this first part the Log.txt is opened for Input and each line is saved in DataLine
'to be compared to the special value in strEntry. If it is already in the Log.txt, the Sub to
'create a new Log-Entry is exited and is started again, once the next special value from another cell is
'obtained (from another Sub).
FileNum = FreeFile()
Open strPath For Input As #FileNum
Do While Not EOF(FileNum)
Line Input #FileNum, DataLine
'The value strEntry should start at position 2 of the Entry in the Log.txt (due to the quotation marks [""] in the
'Log.txt line.
If InStr(DataLine, strEntry) = 2 Then Exit Sub
Loop
Close #FileNum
'After it could be verified, that strEntry is not already in the Log.txt, the txt-File should be opened
'again, this time for Append. Then, the strEntry should be written to the txt-File, the Log.txt should close and
'Sub is finished.
FileNum = FreeFile()
Open strPath For Append As #FileNum
Write #FileNum, strEntry
Close #FileNum
The Problem: I observed, that the first part of the Sub is working fine. If strEntry is already in the Log.txt, the Sub is exited and the whole Macro is jumping to the next special value. If this value is not already in the txt-File, the first part of the Sub does not exit the Sub and it jumps to the second part, where it should append the value to the Log.txt.
This is where the problem is. If I exclude the first part of the Sub, I could verify, that the second part is also working fine (as he simply appends all values to the txt-File). But once I have the first part included, I get the Error-Message
File already open.
I can not figure out, why this is happening, as I Close #FileNum at the end of part one.
I thank in advance for your ideas and solutions.
The problem is If InStr(DataLine, strEntry) = 2 Then Exit Sub You are not closing the file in this case as it is exiting the Sub. In this case file remains open. Use Exit Sub judiciously. Try and have one entry point and one exit point so that you can dispose objects/variables and do relevant cleanup correctly.
One way: Using a Boolean Variable
'
'~~> Rest of your code
'
Dim continue As Boolean: continue = True
'
'~~> Rest of your code
'
Do While Not EOF(FileNum)
Line Input #FileNum, DataLine
If InStr(DataLine, strEntry) = 2 Then
continue = False
Exit Do
End If
Loop
Close #FileNum
If continue = True Then
FileNum = FreeFile()
Open strPath For Append As #FileNum
Write #FileNum, strEntry
Close #FileNum
End If
Another way: Using GOTO
FileNum = FreeFile()
Open strPath For Input As #FileNum
Do While Not EOF(FileNum)
Line Input #FileNum, DataLine
'The value strEntry should start at position 2 of the Entry in the Log.txt (due to the quotation marks [""] in the
'Log.txt line.
If InStr(DataLine, strEntry) = 2 Then GoTo CleanupAndExit
Loop
Close #FileNum
'After it could be verified, that strEntry is not already in the Log.txt, the txt-File should be opened
'again, this time for Append. Then, the strEntry should be written to the txt-File, the Log.txt should close and
'Sub is finished.
FileNum = FreeFile()
Open strPath For Append As #FileNum
Write #FileNum, strEntry
CleanupAndExit:
Close #FileNum

modifying csv file using vba

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

EXCEL VBA Write - Read File - BUG?

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.

Read/Parse text file line by line in VBA

I'm trying to parse a text document using VBA and return the path given in the text file. For example, the text file would look like:
*Blah blah instructions
*Blah blah instructions on line 2
G:\\Folder\...\data.xls
D:\\AnotherFolder\...\moredata.xls
I want the VBA to load 1 line at a time, and if it starts with a * then move to the next line (similar to that line being commented). For the lines with a file path, I want to write that path to cell, say A2 for the first path, B2 for the next, etc.
The main things I was hoping to have answered were:
What is the best/simple way to read through a text file using VBA?
How can I do that line by line?
for the most basic read of a text file, use open
example:
Dim FileNum As Integer
Dim DataLine As String
FileNum = FreeFile()
Open "Filename" For Input As #FileNum
While Not EOF(FileNum)
Line Input #FileNum, DataLine ' read in data 1 line at a time
' decide what to do with dataline,
' depending on what processing you need to do for each case
Wend
#Author note - Please stop adding in close #FileNum - it's addressed in the comments, and it's not needed as an improvement to this answer
I find the FileSystemObject with a TxtStream the easiest way to read files
Dim fso As FileSystemObject: Set fso = New FileSystemObject
Set txtStream = fso.OpenTextFile(filePath, ForReading, False)
Then with this txtStream object you have all sorts of tools which intellisense picks up (unlike using the FreeFile() method) so there is less guesswork. Plus you don' have to assign a FreeFile and hope it is actually still free since when you assigned it.
You can read a file like:
Do While Not txtStream.AtEndOfStream
txtStream.ReadLine
Loop
txtStream.Close
NOTE: This requires a reference to Microsoft Scripting Runtime.
For completeness; working with the data loaded into memory;
dim hf As integer: hf = freefile
dim lines() as string, i as long
open "c:\bla\bla.bla" for input as #hf
lines = Split(input$(LOF(hf), #hf), vbnewline)
close #hf
for i = 0 to ubound(lines)
debug.? "Line"; i; "="; lines(i)
next
You Can use this code to read line by line in text file and You could also check about the first character is "*" then you can leave that..
Public Sub Test()
Dim ReadData as String
Open "C:\satheesh\myfile\file.txt" For Input As #1
Do Until EOF(1)
Line Input #1, ReadData 'Adding Line to read the whole line, not only first 128 positions
If Not Left(ReadData, 1) = "*" then
'' you can write the variable ReadData into the database or file
End If
Loop
Close #1
End Sub
The below is my code from reading text file to excel file.
Sub openteatfile()
Dim i As Long, j As Long
Dim filepath As String
filepath = "C:\Users\TarunReddyNuthula\Desktop\sample.ctxt"
ThisWorkbook.Worksheets("Sheet4").Range("Al:L20").ClearContents
Open filepath For Input As #1
i = l
Do Until EOF(1)
Line Input #1, linefromfile
lineitems = Split(linefromfile, "|")
For j = LBound(lineitems) To UBound(lineitems)
ThisWorkbook.Worksheets("Sheet4").Cells(i, j + 1).value = lineitems(j)
Next j
i = i + 1
Loop
Close #1
End Sub

Resources