I have a code which opens a text file. It contains a number of rows that is more than the limit of Excel. When manually opening it, there is a prompt that says "File not loaded completely" but when in macro, I don't see a prompt.
What I want to do is to catch that error. Even when the display alerts of my macro is enabled, still no error is caught.
On Error Goto catch_err
...open text file here
On Error Goto 0
catch_err:
Msgbox err.description
That is the structure of my code.
Why don't you stream the file in and move to the next tab every time you hit 1M rows?
I threw this together for you, excuse the Citrix line in there (I needed it for testing, left it in in case you are on that environment).
Sub BigFile()
Dim myFile As String, textline As String, X As Long
'myFile = "\\Client\C$\Temp\YourBigFile.txt" 'Silly Citrix syntax
myFile = "C:\Temp\YourBigFile.txt" 'Normal syntax
Open myFile For Input As #1
Do Until EOF(1)
X = X + 1
If X = 1000000 + 1 Then
Sheets.Add
X = 1
End If
Line Input #1, textline
Range("A" & X).Formula = textline
Loop
Close #1
End Sub
This way you don't need to test for the error because there won't be one.
Related
So I have a text file with certain keywords, one on each line, which need to be imported into VBA. The keywords will be used in a find loop to check other documents. For this, I used this explanation: https://www.techrepublic.com/article/macro-trick-how-to-highlight-multiple-search-strings-in-a-word-document/ . However it is not robust as the words are hardcoded and the size of the list of keywords needs to be defined a priori.
So what I now have done is import the txt file in Word VBA, first counted all the lines, set the size of the keyword list and then looped again over the text file whilst trying to define each index of the keyword list. However the last bit fails. Using F8 I double checked that the code got the right word, but the "keywordlist(i) = textline" does not seem to actually parse the text string to the list.
What is going wrong here?
sub getkeywords
On Error Resume Next
MsgBox "Select text file with keywords."
On Error GoTo 0
Dim keyfile As String, textline As String
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Title = "Select Text Files"
.Filters.Clear
.Filters.Add "Text files", "*.txt"
.InitialView = msoFileDialogViewDetails
.Show
On Error Resume Next
keyfile = .SelectedItems(1)
Err.Clear
On Error GoTo 0
End With
Open keyfile For Input As #1
Dim i As Integer
Do Until EOF(1)
Line Input #1, textline
i = i + 1
Loop
Dim j As Integer
j = i - 1
Dim keywordlist() As String
ReDim keywordlist(0 To j) As String
i = 0
Do Until EOF(1)
Line Input #1, textline
keywordlist(i) = textline
i = i + 1
Loop
Close #1
end sub
I found the error. After the first Do Until loop, the code neglects the file and hence the second Do loop is not executed. A simple fix was to place Close #1 and Open #1 before the second loop. May not be pretty but it works.
When I try and open a CSV file, I get:
Error 53: File not found
I get the error on the 4th line, Open FilePath For Input As #1
What am I doing wrong?
It is my first time opening a CSV, please be indulgent with my code.
Sub opentextfile()
Dim FilePath As String
FilePath = "/Users/christinekelly/Desktop/authors.csv"
file1 = FreeFile
Open FilePath For Input As #file1
row_number = 0
Do Until EOF(1)
Line Input #file1, LineFromFile
LineItems = Split(LineFromFile, ",")
ActiveCell.Offset(row_number, 0).Value = LineItems(2)
ActiveCell.Offset(row_number, 1).Value = LineItems(1)
ActiveCell.Offset(row_number, 2).Value = LineItems(0)
Number = row_number + 1
Loop
Close #file1
End Sub
So from looking at #Rebekare's answer to this question this is what worked for me.
I went to the file in question test.csv and opened the immediate window and typed ?ThisWorkbook.Path and got HDD:Users:USER:Desktop.
I then used the suggested concatenatation of this path with Application.PathSeparator & filename i.e.
FilePath = "HDD:Users:USER:Desktop" & Application.PathSeparator & "test.csv"
This is a useful approach as you get the actual file path syntax and then yield the path separator decision to the Application.
Following on from #Mat'sMug suggestion, I found this, which opens the file dialog, and you select the file you want the full path of and it is returned via the message box.
Sub PathofFile()
OpenFile = Application.GetOpenFilename()
MsgBox OpenFile
End Sub
Within that same link was a suggestion for using the Dir function to test if the filepath is valid. If valid you get the filename back, if not you get an error which you can use to determine your next action e.g. the following returns "test.csv" if it exists at that filepath.
MsgBox Dir("HDD:Users:USER:Desktop:test.csv")
If you are doing other operations with the file you might want to add a test to to see if the file is open first, using Microsoft's IsFileOpen function. An example as follows:
Sub Test
If Not IsFileOpen(FilePath) Then
Set wb = Workbooks.Open(FilePath)
End If
End Sub
Function IsFileOpen(filename As String)
Dim filenum As Integer, errnum As Integer
On Error Resume Next ' Turn error checking off.
filenum = FreeFile() ' Get a free file number.
' Attempt to open the file and lock it.
Open filename For Input Lock Read As #filenum
Close filenum ' Close the file.
errnum = Err ' Save the error number that occurred.
On Error GoTo 0 ' Turn error checking back on.
' Check to see which error occurred.
Select Case errnum
' No error occurred.
' File is NOT already open by another user.
Case 0
IsFileOpen = False
' Error number for "Permission Denied."
' File is already opened by another user.
Case 70
IsFileOpen = True
' Another error occurred.
Case Else
Error errnum
End Select
End Function
I am checking if a file is open or not that is a .txt file
Private Sub CommandButton1_Click()
Dim strFileName As String
' Full path and name of file.
strFileName = "D:\te.txt"
' Call function to test file lock.
If Not FileLocked(strFileName) Then
' If the function returns False, open the document.
MsgBox "not open"
Else
MsgBox "open"
End If
End Sub
Function FileLocked(strFileName As String) As Boolean
On Error Resume Next
' If the file is already opened by another process,
' and the specified type of access is not allowed,
' the Open operation fails and an error occurs.
Open strFileName For Binary Access Read Write Lock Read Write As #1
Close #1
' If an error occurs, the document is currently open.
If Err.Number <> 0 Then
' Display the error number and description.
MsgBox "Error #" & Str(Err.Number) & " - " & Err.Description
FileLocked = True
Err.Clear
End If
End Function
It turns out .txt when opened using notepad doesn't lock the file, so it can not be known if a .txt file is open or not. And hence, if that .txt file is opened in Wordpad or Sakura, etc., your code should work or at least other code from the net should work.
I found that if a text file is opened using FileSystemObject, then the file is not locked and can still be edited by other users. As a potential workaround, you could make a file with a single bit to indicate when the other file is in use, and include checking that bit in your code. Here's my code as a rough example:
'FSO parameters
Const ForAppending = 8
Const ForReading = 1
Const ForWriting = 2
Sub WriteToFile()
Set fso = CreateObject("Scripting.FileSystemObject")
'Check the current lock bit (1 is locked, 0 is unlocked)
Set FileLock = fso.OpenTextFile("C:\FileLock.txt", ForReading)
Dim LockBit As Integer
LockBit = FileLock.ReadAll
FileLock.Close
'If the bit is 1 (file in use) then wait 1 second and try again (up to 10 times)
For try = 1 To 10
If LockBit = 1 Then
Application.Wait (Now + TimeValue("0:00:1"))
Set FileLock = fso.OpenTextFile("C:\FileLock.txt", ForReading)
LockBit = FileLock.ReadAll
FileLock.Close
Else: GoTo Line1 'when the bit is 0 (file available)
End If
If try = 10 Then
MsgBox "File not available"
Exit Sub
End If
Next try
Line1:
Call LockTheFile(fso, True) 'Change the lock bit to "1" to show the file's in use
Set WriteFile = fso.OpenTextFile("C:\WriteFile.txt", ForWriting)
'Do what you will with the file
MsgBox "Write Successful"
WriteFile.Close
Call LockTheFile(fso, False) 'Change the lock bit to "0" to show the file's available
End Sub
I made this sub separate to make the main code more streamlined
Sub LockTheFile(fso, SetLock As Boolean)
'Write "1" to a lock file to indicate the text file is in use, or "0" to indicate not in use
Set BitFile = fso.CreateTextFile("C:\FileLock.txt", True)
If SetLock = True Then
BitFile.WriteLine "1"
Else
BitFile.WriteLine "0"
End If
BitFile.Close
End Sub
To start off I have a function in VBA Excel that tells me if a Word Document is open or not open. For testing purposes I don't have the Word Document Open and expect 'False' to be returned.
Function IsFileOpen(filename As String) As Boolean
Dim filenum As Integer, errnum As Integer
On Error Resume Next ' Turn error checking off.
filenum = FreeFile() ' Get a free file number.
' Attempt to open the file and lock it.
Open filename For Input Lock Read As #filenum
Close filenum ' Close the file.
errnum = Err ' Save the error number that occurred.
On Error GoTo 0 ' Turn error checking back on.
' Check to see which error occurred.
Select Case errnum
' No error occurred.
' File is NOT already open by another user.
Case 0
IsFileOpen = False
' Error number for "Permission Denied."
' File is already opened by another user.
Case 70
IsFileOpen = True
' Another error occurred.
Case Else
Error errnum
End Select
End Function
Called Via:
...
If IsFileOpen("C:/Temp/test.docx") = True Then
MsgBox objWord.ActiveDocument.Name & " already open" 'ERROR FROM PIC HERE
Set objDoc = objWord.ActiveDocument
Else
Set objDoc = objWord.Documents.Open("C:/Temp/test.docx", Visible:=True)
End If
...
However when running the code I get that the Document is open (Returned True from the IsFileOpen function from case 70) yet I get an error on 'objWord.ActiveDocument.Name' that no Document is Open
On Windows 7 Task Manager this is what I have. Word Application is closed but it appears there are background processes open of Word. However I close all documents I don't use so these processes shouldn't be running
I think a better test to check to see if your Word File is open is to use the actual Word Documents collection
So for your example, use something like this:
With objWord
For Each doc In .Documents
If doc.Name = "test.docx" Then
found = True
Exit For
End If
Next doc
If found <> True Then
.Documents.Open FileName:="C:/Temp/test.docx"
Else
.Documents("test.docx").Activate
End If
End With
This question already has answers here:
Detect whether Excel workbook is already open [closed]
(7 answers)
Closed 8 years ago.
I'm having trouble working out why a bit of code that I found months and months ago (don't know originating website) is doing such a weird thing when trying to save the file...
In the main part of the code that is constantly looping it has the following:
Main Snippit
path = "C:/"
filename = "file.csv"
If Dir(path) = "" Then
FullPath = Environ("USERPROFILE") & "\Desktop\" & filename
Else
FullPath = path & filename
If Dir(FullPath) <> "" Then
isCsvOpen = IsFileOpen(FullPath)
If Not isCsvOpen Then Kill (FullPath)
End If
End If
If Not isCsvOpen Then outputtext delimiteddata, FullPath
It has the following two functions elsewhere in the code:
outputtext()
Function outputtext(text As String, path As String)
Dim MyFile As String, fnum As String
MyFile = path
fnum = FreeFile() ' Get a free file number.
Open MyFile For Output As fnum 'open file for output
Print #fnum, text ' Print when you want the string without quotation marks
Close #fnum
End Function
IsFileOpen()
Function IsFileOpen(filename As String)
Dim filenum As Integer, errnum As Integer
On Error Resume Next ' Turn error checking off.
filenum = FreeFile() ' Get a free file number.
' Attempt to open the file and lock it.
Open filename For Input Lock Read As #filenum
Close filenum ' Close the file.
errnum = Err
On Error GoTo 0 ' Turn error checking back on.
' Check to see which error occurred.
Select Case errnum
' No error occurred.
' File is NOT already open by another user.
Case 0
IsFileOpen = False
' Error number for "Permission Denied."
' File is already opened by another user.
Case 70
IsFileOpen = True
Case Else
Error errnum
End Select
End Function
What is the purpose of using IsFileOpen() and outputtext(), surely just saving with overwrite would be sufficient?
To me it looks like it's checking if the file is open, locking it open, then killing the file (unlocking it) and then saving...
Any explination would be much appreciated
A few reasons for such a design...
If the file is open elsewhere, it likely to be open in a non-Read-only mode (which is what is being checked, i.e. whether the file is locked or not). This is especially important over network drives.
If the file is open and your code tries to save it, it will throw an error. So you can either
try to handle the error once it's thrown, or
preempt the problem and throw a controlled error at the user or prompt for further action, etc.
This is a cleaner way to avoid file corruption especially over shared resources.