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
Related
VBA: Is there a way to save a list of a combobox to a .txt file?
I did this one here that puts the information of a txt file into a combobox
Dim InFile As Integer
InFile = FreeFile
Open "MYFILE.txt" For Input As InFile
While Not EOF(InFile)
Line Input #InFile, NextTip
ComboBox1.AddItem NextTip
ComboBox1.ListIndex = 0
Wend
Close InFile
The following macro will print a list of items from the specified combobox to the specified text file. Change the name of the macro, and the path and file name for the destination file, accordingly.
'Force the explict declaration of variables
Option Explicit
Private Sub CommandButton1_Click()
'Declare the variables
Dim destFile As String
Dim fileNum As Long
Dim i As Long
'Assign the path and file name for the destination file (change accordingly)
destFile = "C:\Users\Domenic\Desktop\sample.txt"
'Get the next available file number
fileNum = FreeFile()
'Print list items from combobox to destination file
Open destFile For Output As #fileNum
With Me.ComboBox1
For i = 0 To .ListCount - 1
Print #fileNum, .List(i)
Next i
End With
Close #fileNum
MsgBox "Completed!", vbExclamation
End Sub
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.
I'm reading multiple csv files into excel for some number crunching. The file reads appear to work with each excel column having the csv file name inserted for confirmation. Odd thing. Each csv file name is correctly inserted into the sheet, but the data is all the same as the first file.
Is there a way to flush / reset ..... something, so the next read file data actually is the next file?
Excel VBA code snippet:
Public Const sRawFilePath As String = "\\server1\Sample.RAW.Files\"
----------------
Sub ImportCSV()
Dim sFullFilePath, sFile As String
fFIle = FreeFile()
sFile = Dir(sRawFilePath & "*.csv")
sFullFilePath = sRawFilePath & sFile
While sFile <> ""
Open sFullFilePath For Input As fFIle
While Not EOF(fFIle)
Line Input #fFIle, sLine
""
"take the sLine string and separate the comma delimited values for insertion into columns "
"This part works fine"
""
Wend
Close fFIle
sFile = Dir()
Wend
End Sub
Stepping through the code I can confirm the next file is in the queue, but the read data is not representing the next file, just the first file, ... and always the first file even though 20 more files are read.
PS - This forum has been an amazing resource.
The problem is you define sFullFilePath which locks in the file that you're opening. So even though you're successfully looping through the files with Dir, you will only open the first one because you locked it in. Don't use that variable at all:
'Change this line
Open sFullFilePath For Input As fFIle
'To be this instead
Open sRawFilePath & sFile For Input As fFIle
Rather than executing Dir(sRawFilePath & "*.csv") in every call, you should just execute Dir in subsequent calls. The error causes you to re-read the first file again and again.
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
I'm trying to write a file using VBA. My code is below. It worked the first time, but when i closed the excel file (.xlsm) and try to use it again, it doesn't work.
I do not get any errors when running the macro but the new file does not appear
Sub LogInformation(LogMessage As String)
Const LogFileName As String = "TEXTFILE.db"
Dim FileNum As Integer
FileNum = FreeFile ' next file number
Open LogFileName For Append As #FileNum ' creates the file if it doesn't exist
Print #FileNum, LogMessage ' write information at the end of the text file
Close #FileNum ' close the file
End Sub
Sorry guys. That was dumb.
The default relative path is in User/%MyUser%/Documents.
I need to use ChDir then open/write/close the file.
Chdir(ActiveWorkbook.Path)