VBScript opening text file but it's showing up as empty - windows

I have a text file with some numbers, like so:
123456789
987654321
The file is called numbers.txt
I am trying to open the file and read it line by line and compare it another separate number
'Create the file system object
Set fso = CreateObject("Scripting.FileSystemObject")
identify = "123456789"
WScript.Echo identify
numfile = fso.OpenTextFile("C:\numbers.txt", ForReading)
WScript.Echo numfile.ReadLine
WScript.Echo "test2"
Do Until numfile.AtEndOfStream
cell = numfile.ReadLine
WScript.Echo cell
If identify = cell Then
count = 1
End If
Loop
WScript.Echo "end of loop"
However my code is getting stuck in an infinite loop with the AtEndOfStream loop. Furthermore,
WScript.Echo cell
is always an empty dialog box, and
WScript.Echo numfile.ReadLine
doesn't Echo anything, it just skips right to echo-ing "test 2". Where am I going wrong? The directory of the file is right, and it exists with the numbers
Edit: I tried
WScript.Echo numfile.ReadAll
and was just greeted with an empty dialog box
I also tried to open it as Unicode, but it didn't make any difference

Define ForReading:
Const ForReading = 1
, get rid of any "On Error Resume Next", and try again.
If you'd disabled the the evil OERN, you'd have seen an error message for
numfile = fso.OpenTextFile("C:\numbers.txt", ForReading)
which should be
Set numfile = fso.OpenTextFile("C:\numbers.txt", ForReading)

Related

How to Check if a File does NOT exist and display one overall response using a For Loop

I'm trying to write a VBScript that will check whether a file exists in a folder or not based on a partial number. If anything in the folder has this number in the string it can continue, if not an error needs to display saying it's not in the system. I've gotten a code that lets me know that the file DOES exist, but I can't get a NOT version to work. Any ideas?
Dim FSO, str1, fileName
str1 = "001234"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = FSO.GetFolder("C:\Users\GDoe\Desktop\FolderA\")
For Each objFile In objFolder.Files
fileName = objFile.Name
If InStr(fileName, str1) Then
MsgBox("Proceed")
Exit For
End If
Next
Unfortunately the FileSystemObject's FileExists method does not support wildcards, so the straightforward approach is not possible here.
The code you posted in your question is basically how one would check for the existence of a file with a partial name with VBScript and the FileSystemObject. You can modify that code into a check for the absence of a file with some minor changes. Define a variable before the loop and set it to False, then instead of displaying a message box set that vriable to True when you find a matching file:
fileFound = False
For Each objFile In objFolder.Files
fileName = objFile.Name
If InStr(fileName, str1) Then
fileFound = True
Exit For
End If
Next
If fileFound Then
MsgBox("Proceed")
Else
MsgBox("File doesn't exist.")
End If
Alternatively, you could shell out and check the exit code of the dir command:
Function FileExists(path, namepart)
Set sh = CreateObject("WScript.Shell")
rc = sh.Run("cmd /c dir ""*" & path & "\" & namepart & "*""", 0, True)
FileExists = Not CBool(rc)
End Function
dir returns 0 if it finds matching file(s) and 1 if it doesn't. CBool() converts the integer return code into a boolean value (0 → False, 1 → True). The negation then corrects the logic from "false if found" to "true if found".
Of course you could also name the function FileMissing and remove the negation, so that the function returns True if no matching file is found. That's just a matter of what logic works best in your code.
Note that you need to run the command with cmd /c, because dir is a cmd.exe builtin command, not an executable.
I actually just found a way to answer my own question but if there's a better way I'd also love to know.
Dim FSO, str1, fileName
str1 = "-001239"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = FSO.GetFolder("C:\Users\GDoe\Desktop\FolderA\")
For Each objFile In objFolder.Files
fileName=objFile.Name
If InStr(fileName, str1) Then
MsgBox("Proceed")
Exit For
End If
Next
If InStr(fileName, str1) = 0 Then
MsgBox("File doesn't Exist")
End If
I took the rule that if string2 is not found in an InStr command it returns 0. Setting the result = 0 shows if I don't have the file.

MS Access 2016 File Browse Button Issues

I am using the script listed below (I honestly stole this probably from this very site) for a browse button on a form. The task is simply to start up MS File Dialog box so that a file (in this case an image file) can be selected. Once you select the record and click ok it then pastes the file name and location into a field.
Viewing the table the file name and location is pasted just as it should be. The problem comes in with a report I built. I have an image set to display with the control source linked back to that file address field. It will not display the image though.
However, if I manually type the same address character for character or even “copy”, delete, and then “paste” the same exact entry into the field the image then displays just fine on the report.
I have checked to make sure there are no spaces or characters anywhere there shouldn’t be. I am at a loss here.
Any help would be greatly appreciated and I will gladly give you my first born. Ok maybe not the first I like him but you can have the second one, she’s hell.
Private Sub Command67_Click()
On Error GoTo SubError
'Add "Microsoft Office 14.0 Object Library" in references
Const msoFileDialogFilePicker As Long = 3
'Dim FD As Office.FileDialog
Dim FDialog As Object
Dim varfile As Variant
Set FDialog = Application.FileDialog(msoFileDialogFilePicker)
EmployeePicture = ""
' Set up the File Dialog
Set FDialog = Application.FileDialog(msoFileDialogFilePicker)
With FDialog
.Title = "Choose the spreadsheet you would like to import"
.AllowMultiSelect = False
.InitialFileName = "C:\Users\" 'Folder picker needs trailing slash
.Filters.Clear
.Filters.Add "All", "*.*"
If .Show = True Then
If .SelectedItems.Count = 0 Then
'User clicked open but didn't select a file
GoTo SubExit
End If
'An option for MultiSelect = False
'varFile = .SelectedItems(1)
'EmployeePicture = varFile
'Needed when MultiSelect = True
For Each varfile In .SelectedItems
EmployeePicture = EmployeePicture & varfile & vbCrLf
Next
Else
'user cancelled dialog without choosing!
'Do you need to react?
End If
End With
SubExit:
On Error Resume Next
Set FDialog = Nothing
Exit Sub
SubError:
MsgBox "Error Number: " & Err.Number & " = " & Err.Description, vbCritical + vbOKOnly, _
"An error occurred"
GoTo SubExit
End Sub

Problems using array in VBScript

I modified this script so it would work over multiple directories. However when I run the script, I get an error message at line 6, char 3 "Invalid procedure call or argument". I'm new to VB scripting, but I would think that I can call a function with a variable as its argument.
Dim loc(2)
loc(0) = "C:\Users\Default\AppData\Local\Temp\"
for each path in loc
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(path)
' delete all files in root folder
for each f in folder.Files
On Error Resume Next
name = f.name
f.Delete True
If Err Then
'WScript.Echo "Error deleting:" & Name & " - " & Err.Description
Else
'WScript.Echo "Deleted:" & Name
End If
On Error GoTo 0
Next
' delete all subfolders and files
For Each f In folder.SubFolders
On Error Resume Next
name = f.name
f.Delete True
If Err Then
'WScript.Echo "Error deleting:" & Name & " - " & Err.Description
Else
'WScript.Echo "Deleted:" & Name
End If
On Error GoTo 0
Next
Next
You're declaring an array whose highest index is 2. That'll be an array with three items: zero, one, and two. Then you're initializing only one of the items in that array, item zero. The first time through the loop, it's fine. The second time, it takes the second item from the array and sets path equal to it. That second array item is equal to Nothing, because you never initialized it to anything else, so path then equals Nothing. fso.GetFolder(path) fails when path equals Nothing.
When I change the array declaration to loc(0), it has just one item, item zero. And then your code works fine for me.
Dim loc(0)
That declaration looks surreally counterintuitive to me, but the compiler likes it.
Alternatively, you could initialize all three items in your original array:
loc(0) = "C:\Users\Default\AppData\Local\Temp\"
loc(1) = "C:\Users\Default\AppData\Local\Temp\blah"
loc(2) = "C:\Users\Default\AppData\Local\Temp\foobar"
...or whatever. But those paths should be real directories, otherwise fso.GetFolder() will fail because they don't exist. That error would look like this:
path.vbs(8, 3) Microsoft VBScript runtime error: Path not found

vbscript find last line of a text file that does not contain the text "Ack"

I have a log file that I would like to read with vbscript, the file has two lines for each command, e.g. the command itself and following that on the next like an Acknowledgement of the previous line.
So I get:
xxx,xxx,xxx, ,Blah - some more blah
xxx,xxx,xxx, ,Blah Ack
I want to go right to the bottom of the log file, and then read back up line by lane until I get to the first line that does not have an "Ack" in it, then put that line in a variable and write it out.
I can get most of it working, I just can figure out how to read back up line by line until I see a line that doesnt have an Ack?
Does anyone have any ideas?
This is what I'm sing to get to the bottom of the file:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("Y:\Selcall\logs\DEC-20130929.LOG", ForReading)
Do Until objFile.AtEndOfStream
strNextLine = objFile.ReadLine
If Len(strNextLine) > 0 Then
strLine = strNextLine
End If
Loop
objFile.Close
Wscript.Echo strLine
Wscript.Echo Right(strLine, Len(strLine) - 35)
Technically you can't read a file back to front, so you must read the file from the beginning and remember the last line that doesn't contain the keyword Ack:
Do Until objFile.AtEndOfStream
strNextLine = objFile.ReadLine
If InStr(strNextLine, "Ack") = 0 Then strLine = strNextLine
Loop
After the loop terminates, the variable strLine contains the line you're looking for.
You can't move/read backwards with the FSO's TextStream object. You must read the file from top to bottom and store/overwrite each candidate line(s); after the .Close, the storage will contain the last/desired candidate.

How can I determine if a file is locked using VBS?

I am writing a VB Script to update some files on the network. Before beginning, I want to know if any of the files are locked. I'd like to do this before I actually do any updates.
I am aware that I can handle the error if the file is locked when I try to replace it, but I really want to know if any files are locked before I start updating any files.
Is there any way to see that a file is locked using VBS (apart from trying to replace it)?
This function determines whether a file of interest can be accessed in 'write' mode. This is not exactly the same as determining whether a file is locked by a process. Still, you may find that it works for your situation. (At least until something better comes along.)
This function will indicate that 'write' access is not possible when a file is locked by another process. However, it cannot distinguish that condition from other conditions that prevent 'write' access. For instance, 'write' access is also not possible if a file has its read-only bit set or possesses restrictive NTFS permissions. All of these conditions will result in 'permission denied' when a 'write' access attempt is made.
Also note that if a file is locked by another process, the answer returned by this function is reliable only at the moment the function is executed. So, concurrency problems are possible.
An exception is thrown if any of these conditions are found: 'file not found', 'path not found', or 'illegal file name' ('bad file name or number').
Function IsWriteAccessible(sFilePath)
' Strategy: Attempt to open the specified file in 'append' mode.
' Does not appear to change the 'modified' date on the file.
' Works with binary files as well as text files.
' Only 'ForAppending' is needed here. Define these constants
' outside of this function if you need them elsewhere in
' your source file.
Const ForReading = 1, ForWriting = 2, ForAppending = 8
IsWriteAccessible = False
Dim oFso : Set oFso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Dim nErr : nErr = 0
Dim sDesc : sDesc = ""
Dim oFile : Set oFile = oFso.OpenTextFile(sFilePath, ForAppending)
If Err.Number = 0 Then
oFile.Close
If Err Then
nErr = Err.Number
sDesc = Err.Description
Else
IsWriteAccessible = True
End if
Else
Select Case Err.Number
Case 70
' Permission denied because:
' - file is open by another process
' - read-only bit is set on file, *or*
' - NTFS Access Control List settings (ACLs) on file
' prevents access
Case Else
' 52 - Bad file name or number
' 53 - File not found
' 76 - Path not found
nErr = Err.Number
sDesc = Err.Description
End Select
End If
' The following two statements are superfluous. The VB6 garbage
' collector will free 'oFile' and 'oFso' when this function completes
' and they go out of scope. See Eric Lippert's article for more:
' http://blogs.msdn.com/b/ericlippert/archive/2004/04/28/when-are-you-required-to-set-objects-to-nothing.aspx
'Set oFile = Nothing
'Set oFso = Nothing
On Error GoTo 0
If nErr Then
Err.Raise nErr, , sDesc
End If
End Function
The script below tries to write to a file for 30 seconds and gives up after that. I needed this when all our users had to click on a script. Chances are that multiple users try to write at the same time. OpenCSV() tries to open the file 30 times with a delay of 1 second in between.
Const ForAppending = 8
currentDate = Year(Now) & "-" & Month(Now) & "-" & Day(Now) & " " & Hour(Now) & ":" & Minute(Now) & ":" & Second(Now)
filepath = "\\network\path\file.csv"
Set oCSV = OpenCSV( filepath )
oCSV.WriteLine( currentDate )
oCSV.Close
Function OpenCSV( path )
Set oFS = CreateObject( "Scripting.FileSystemObject" )
For i = 0 To 30
On Error Resume Next
Set oFile = oFS.OpenTextFile( path, ForAppending, True )
If Not Err.Number = 70 Then
Set OpenCSV = oFile
Exit For
End If
On Error Goto 0
Wscript.Sleep 1000
Next
Set oFS = Nothing
Set oFile = Nothing
If Err.Number = 70 Then
MsgBox "File " & filepath & " is locked and timeout was exceeded.", vbCritical
WScript.Quit
End If
End Function
Or, more simply:
Assuming you already have a variable in your VBS named FileName, which contains the full filepath you want to test:
Dim oFso, oFile
Set oFso = CreateObject("Scripting.FileSystemObject")
Set oFile = oFso.OpenTextFile(FileName, 8, True)
If Err.Number = 0 Then oFile.Close
Line 3 tries to open the file you want to test with append permissions enabled. e.g. it attempts to open the file with a write lock.
If opening the file with a write lock generates an error, then your VBS will error on the third line and not continue. At that point your error handling from wherever you called the VBS should kick in. The error message will be "Permission Denied" if you couldn't get a write lock.
If opening the file with a lock doesn't result in an error, then line 4 closes it again. You can now open the file or do whatever you want with it, confident that it doesn't have a write lock on it.

Resources