Scripting FileSystemObject creates Runtime 429 error on Windows - excel

Am I missing a reference object? Trying to retrieve a list of files in a directory and have them show in a sheet.
Also, would it be possible to get the directory location from a specific cell in the file?
Sub LoopThroughFiles()
Dim oFSO As Object
Dim oFolder As Object
Dim oFile As Object
Dim i As Integer
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder("C:\VBA Folder")
For Each oFile In oFolder.Files
Cells(i + 1, 1) = oFile.Name
i = i + 1
Next oFile
End Sub
Here:
Set oFSO = CreateObject("Scripting.FileSystemObject")
Runtime error 429 on a Windows machine.

There's little to no reason at all to late-bind the Scripting library - it's present (same identical version) on every single Windows box out there, and won't work on a Mac whether you late-bind it or not.
Tools/References, add the "Microsoft Scripting Runtime" library to your project, and then declare the actual data types for your object variables; you'll get compile-time validation and intellisense/autocompletion (good-bye error 438!) for all member calls.
Early binding is your friend. Declare As Scrpiting.FileSystemObject, and then just New up the object instead of hitting the registry to resolve the "Scripting.FileSystemObject" ProgID with CreateObject:
Set fso = New Scripting.FileSystemObject
Or have a With block whithold the object reference, and then you don't even need a local variable for it:
With New Scripting.FileSystemObject
'....
End With

Related

VBA Early Binding to Late Binding

I use this code to convert PDF Files to Excel.
Private Sub CommandButton2_Click()
Dim setting_sh As Worksheet
Set setting_sh = ThisWorkbook.Sheets("Tabelle1")
Dim pdf_path As String
Dim excel_path As String
pdf_path = setting_sh.Range("E11").Value
excel_path = setting_sh.Range("E12").Value
Dim fso As New FileSystemObject
Dim fo As Folder
Dim f As File
Set fo = fso.GetFolder(pdf_path)
Dim wa As Object
Dim doc As Object
Dim wr As Object
Set wa = CreateObject("word.application")
'Dim wa As New Word.Application
wa.Visible = True
'Dim doc As Word.Document
Dim nwb As Workbook
Dim nsh As Worksheet
'Dim wr As Word.Range
For Each f In fo.Files
Set doc = wa.documents.Open(f.Path, False, Format:="PDF Files")
Set wr = doc.Paragraphs(1).Range
wr.WholeStory
Set nwb = Workbooks.Add
Set nsh = nwb.Sheets(1)
wr.Copy
nsh.Paste
nwb.SaveAs (excel_path & "\" & Replace(f.Name, ".pdf", ".xlsx"))
doc.Close False
nwb.Close False
Next
wa.Quit
MsgBox "Done"
End Sub
The problem is, other people also want to use this function, but they don't understand to how to add the Microsoft Scripting Runtime Reference in your VBA project. I tried to convert it to late binding, but it fails all the time. Can someone help me?
Thanks.
Change this:
Dim fso As New FileSystemObject
Dim fo As Folder
Dim f As File
to this:
Dim fso As Object
Dim fo As Object
Dim f As Object
Set fso = CreateObject("Scripting.FileSystemObject")
The next code will automatically add the necessary reference:
Sub addScrRunTimeRef()
'Add a reference to 'Microsoft Scripting Runtime':
'In case of error ('Programmatic access to Visual Basic Project not trusted'):
'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
' check "Trust access to the VBA project object model"
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\SysWOW64\scrrun.dll"
End Sub
The above code may fail if Trust access to the VBA project object model check box is gray out, being disabled by restricted administrative security policies. In such a case, the following solution should be recommended:
To declare and set variables in Late binding way, declare and assign the objects in the next way:
Dim fso As Object, fo as Object, f as Object
set fso =CreateObject("Scripting.FileSystemObject")
It is also good to be known that Early binding is operationally faster than Late during run-time, and the programmer may benefit of intellisense suggestions, automatic capitalization of method names etc.

Read File From Sharepoint

I'm writing a script where I wish to write an HTML doc to a string from sharepoint.
Dim Content As String
Dim strShare As String: strShare = "\\link\to\share.html"
Dim iFile As Integer: iFile = FreeFile
Open strShare For Input As #iFile
Content = Input(LOF(iFile), iFile)
Close #iFile
However, I find I get a "path/file access error" every time I run the script for the first time upon boot. Once I visit "\link\to\share.html" in IE for the first time, the path begins to resolve in the VBA script.
My only thought is that IE is performing some sort of "DNS Cache" that VBA can't do. Currently my workaround is to catch the error and force the URL to open in IE the first time the script is run. After that, every other HTML file under that share loads fine.
As a test, I tried switching between from what I understand is http:// formatting (forward slash) and WebDAV formatting (\\ formating), and only the backslash separated paths ever work. I also tried to resolve the share to an IP and try it that way, but that never worked.
My last thought is to try mapping the share to a drive letter name and then specifically accessing the share with G:\link\to\mapped\share.html. But I don't see this as an elegant solution, and wonder if it will receive the same error any way.
Is there something blatant that I do not understand about WebDAV, Windows file handling, and VBA file inputs? There's something weird going on under the hood with resolving that shared domain, and I can't seem to debug it.
See if this helps here and an example below that I used.
2 things though: I only worked with Excel files on Sharepoint and I was already logged in there.
Dim oFSO As Object
'Dim oFolder As Object 'if needed
'Dim oFile As Object 'if needed
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder("\\sharepoint.site.com#SSL\DavWWWRoot\sites\")
'For Each oFolder In oFolder.SubFolders 'loops through folders
' For Each oFile In oFolder.Files 'loops through files
' 'do stuff
' Next oFile
'Next oFolder
I'm a bit confused about what you want to do. Do you want to check out files from SP and check files back into SP?
Sub testing()
Dim docCheckOut As String
'docCheckOut = "//office.bt.com/sites/Training/Design Admin/Training Plan/adamsmacro.xlsm"
docCheckOut = "http://your_path_here/ExcelList.xlsb"
Call UseCheckOut(docCheckOut)
End Sub
Sub UseCheckOut(docCheckOut As String)
' Determine if workbook can be checked out.
If Workbooks.CanCheckOut(docCheckOut) = True Then
Workbooks.CheckOut docCheckOut
Else
MsgBox "Unable to check out this document at this time."
End If
End Sub
Or...do you want to list files in a SP folder?
Sub ListFiles()
Dim folder As Variant
Dim f As File
Dim fs As New FileSystemObject
Dim RowCtr As Integer
Dim FPath As String
Dim wb As Workbook
RowCtr = 1
FPath = "http://excel-pc:43231/Shared Documents"
For Each f In FPath
'Set folder = fs.GetFolder("C:\Users\Excel\Desktop\Ryan_Folder")
'For Each f In folder.Files
Cells(RowCtr, 1).Value = f.Name
RowCtr = RowCtr + 1
Next f
End Sub
Sub test()
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\Users\Excel\Desktop\Ryan_Folder")
'Set colSubfolders = objFolder.SubFolders
'For Each objSubfolder In colSubfolders
Cells(RowCtr, 1).Value = f.Name
RowCtr = RowCtr + 1
'Next
End Sub

VBA - select the first file from a specific folder and reply all

I saved multiple outlook msg on a specific folder named "email temp folder" and would to reply on the first msg in the folder.
However there is an error: type mismatch occur in the below lines.
Could you somebody help me on this please?
Sub outlookActivate1()
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim fso As New FileSystemObject
Dim objFolder As Object
Dim objFile As Object
Dim FileItemToUse As Outlook.MailItem
Dim i As Long
Set OutApp = CreateObject("Outlook.Application")
strPath = "C:\Users\admin\Desktop\email temp folder" & "\"
strFiles = Dir(strPath & "*.*")
Set objFolder = fso.GetFolder(strPath)
For Each objFile In objFolder.Files
If i = 0 Then
Set FileItemToUse = objFile // error: type mismatch
End If
Next objFile
With FileItemToUse
.ReplyAll
.BCC = ""
.Subject = "Hi"
.HTMLBody = "testing"
.BodyFormat = olFormatHTML
.display
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
It means that objFile is not of type Outlook.MailItem as you declared on top of your code.
Relying on the fact that your email template will always be the first item in the Files collection of the folder is not really stable, as the file might change position (probably is already not there, since you get the type mismatch error - you're probably trying to cast another type into a variable that is supposed to be a Outlook.MailItem type).
My suggestion is to reference directly to the file object; which means, in your code:
Set objFile = fso.GetFile("C:\...\mytemplate.msg")
and keep on running the code without the need to neither getFolder() nor looping For Each objFile in the Files collection, hoping that your file will be the first one.
However, best way to understand these kind of errors is to run the code in debug mode (press F8 and run line by line) and, by adding some watchers, figuring out what is what at run-time.
The Outlook object model doesn't provide any direct methods for opening .msg files on the disk. However, you can use the following workarounds to get the job done:
The CreateItemFromTemplate method of the Application class which allows to create a new Microsoft Outlook item from an Outlook template (.oft) or just a message file (.msg) and returns the new item. See How To: Create a new Outlook message based on a template for more information.
Use the ShellExecute method to open the file programmatically. Be aware, only one instance of the Outlook Application can be run at the same time. Thus, the message file will be opened in a new inspector window.
Sub CreateFromTemplate()
Dim MyItem As Outlook.MailItem
Set MyItem = Application.CreateItemFromTemplate("D:\message.msg")
MyItem.Display
End Sub

VBA Excel get first file name from the files collection returned by GetFolder.Files

I'm trying to get the first file of a directory. I don't care that "first" is not well defined in this case, and I don't care if I'll get a different file each time I call my sub.
I try to use:
Dim FSO As Object
Dim SourceFolder As Object
Dim FileItem As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
Set SourceFolder = FSO.GetFolder(SourceFolderName)
Set FileItem = SourceFolder.Files.Item(0)
but this returns a compiler error ("Invalid procedure call or argument")
Could you please tell me how to make this work?
Thanks,
Li
You may use the bulit in Dir function
Below is the sample code which returns the first file found name from Test folder.
Sub test()
Dim strFile As String
strFile = Dir("D:Test\", vbNormal)
End Sub
It looks to me like SourceFolder.Files will only accept a string as the key, just like you noted with Scripting.Folders. I think Santosh's answer is the way to go, but here's a kludgy modification of your code that returns the "first" file in the folder:
Sub test()
Dim FSO As Object
Dim SourceFolder As Object
Dim FileItem As Object
Dim FileItemToUse As Object
Dim SourceFolderName As String
Dim i As Long
SourceFolderName = "C:\Users\dglancy\Documents\temp"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set SourceFolder = FSO.GetFolder(SourceFolderName)
For Each FileItem In SourceFolder.Files
If i = 0 Then
Set FileItemToUse = FileItem
Exit For
End If
Next FileItem
Debug.Print FileItemToUse.Name
End Sub
It’s true that VBA has a limitation (a bug or design flaw in my opinion) in which a file system object's Files collection cannot be accessed by item-index number, only by each item’s file-path string value. The original question posted here is about accessing only the first item in the Files collection but it touches on a general problem for which there are two reasonable workarounds: creation and use of either a File object meta-collection or a File object array to provide indexed access to a Files collection. Here’s a demo routine:
Sub DemoIndexedFileAccess()
'
'Demonstrates use of both a File object meta-collection and a File object array to provide indexed access
'to a Folder object's Files collection.
'
'Note that, in both examples, the File objects being accessed refer to the same File objects as those in
'the Folder object's Files collection. (i.e. if one of the physical files gets renamed after the creation
'of the Folder object's Files collection, all three sets of File objects will refer to the same, renamed
'file.)
'
'IMPORTANT: This technique requires a reference to "Microsoft Scripting Runtime" be set.
'
'**********************************************************************************************************
'File-selector dialog contsants for msoFileDialogFilePicker and msoFileDialogOpen:
Const fsdCancel As Integer = 0 'File dialog Cancel button
Const fsdAction As Integer = -1 'File dialog Action button, and its aliases...
Const fsdOpen As Integer = fsdAction
Const fsdSaveAs As Integer = fsdAction
Const fsdOK As Integer = fsdAction
Dim FD As FileDialog
Dim File As Scripting.File
Dim FileArr() As Scripting.File
Dim FileColl As New Collection
Dim Folder As Scripting.Folder
Dim FSO As Scripting.FileSystemObject
Dim Idx As Integer
'Get a folder specification from which files are to be processed
Set FD = Application.FileDialog(msoFileDialogFolderPicker) 'Create the FolderPicker dialog object
With FD
.Title = "Select Folder Of Files To Be Processed"
.InitialFileName = CurDir
If .Show <> fsdOK Then Exit Sub
End With
'Use the folder specification to create a Folder object.
Set FSO = New Scripting.FileSystemObject
Set Folder = FSO.GetFolder(FD.SelectedItems(1))
'A Folder object's Files collection can't be accessed by item-index number (only by each item's file-path
'string value), so either...
'1. Create a generic "meta-collection" that replicates the Files collection's File objects, which allows
' access by collection-item index:
For Each File In Folder.Files
FileColl.Add File
Next File
'"Process" the files in (collection) index order
For Idx = 1 To FileColl.Count
Debug.Print "Meta-Collection: " & FileColl(Idx).Name
Next Idx
'2. Or, create an array of File objects that refer to the Files collection's File objects, which allows
' access by array index:
ReDim FileArr(1 To Folder.Files.Count)
Idx = 1
For Each File In Folder.Files
Set FileArr(Idx) = File
Idx = Idx + 1
Next File
'"Process" the files in (array) index order
For Idx = LBound(FileArr) To UBound(FileArr)
Debug.Print "File Object Array: " & FileArr(Idx).Name
Next Idx
End Sub
I solve the problem in this Way:
Private Function GetFirstFile(StrDrive as String) As String
'Var Declarations
Dim Fso As Object, Drive As Object, F As File
'Create a reference to File System Object and Drive
Set Fso = New Scripting.FileSystemObject
Set Drive = Fso.GetDrive(StrDrive)
If Not Drive Is Nothing Then
'Scan files in RootFolder.files property of then drive object
For Each F In Drive.RootFolder.Files
Exit For
Next
'if there are any file, return the first an get then name
If Not F Is Nothing Then FirstFile = F.Name: Set F = Nothing
Set Drive = Nothing
End If
Set Fso = Nothing
End Function
Don´t forget add Reference to Microsoft Scripting Runtime in your project
It works to me... I hope this Help you guys.
Why don't you just use a function to iterate through the files in the folder until you get to the one that you want? Assuming you're using the fso as detailed in other posts above, just pass the Folder, and the Index of the file you want, it could be #1 or any other file in the folder.
Function GetFile(oFolder As Folder, Index As Long) As File
Dim Count As Long
Dim oFile As File
Count = 0
For Each oFile In oFolder.Files
Count = Count + 1
If Count = Index Then
Set GetFile = oFile
Exit Function
End If
Next oFile
End Function

How do I use FileSystemObject in VBA?

Is there something that I need to reference? How do I use this:
Dim fso As New FileSystemObject
Dim fld As Folder
Dim ts As TextStream
I am getting an error because it does not recognize these objects.
Within Excel you need to set a reference to the VBScript run-time library.
The relevant file is usually located at \Windows\System32\scrrun.dll
To reference this file, load the
Visual Basic Editor (ALT+F11)
Select Tools > References from the drop-down menu
A listbox of available references will be displayed
Tick the check-box next to 'Microsoft Scripting Runtime'
The full name and path of the scrrun.dll file will be displayed below the listbox
Click on the OK button.
This can also be done directly in the code if access to the VBA object model has been enabled.
Access can be enabled by ticking the check-box Trust access to the VBA project object model found at File > Options > Trust Center > Trust Center Settings > Macro Settings
To add a reference:
Sub Add_Reference()
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\System32\scrrun.dll"
'Add a reference
End Sub
To remove a reference:
Sub Remove_Reference()
Dim oReference As Object
Set oReference = Application.VBE.ActiveVBProject.References.Item("Scripting")
Application.VBE.ActiveVBProject.References.Remove oReference
'Remove a reference
End Sub
In excel 2013 the object creation string is:
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
instead of the code in the answer above:
Dim fs,fname
Set fs=Server.CreateObject("Scripting.FileSystemObject")
These guys have excellent examples of how to use the filesystem object http://www.w3schools.com/asp/asp_ref_filesystem.asp
<%
dim fs,fname
set fs=Server.CreateObject("Scripting.FileSystemObject")
set fname=fs.CreateTextFile("c:\test.txt",true)
fname.WriteLine("Hello World!")
fname.Close
set fname=nothing
set fs=nothing
%>
After adding the reference, I had to use
Dim fso As New Scripting.FileSystemObject
After importing the scripting runtime as described above you have to make some slighty modification to get it working in Excel 2010 (my version). Into the following code I've also add the code used to the user to pick a file.
Dim intChoice As Integer
Dim strPath As String
' Select one file
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
' Show the selection window
intChoice = Application.FileDialog(msoFileDialogOpen).Show
' Get back the user option
If intChoice <> 0 Then
strPath = Application.FileDialog(msoFileDialogOpen).SelectedItems(1)
Else
Exit Sub
End If
Dim FSO As New Scripting.FileSystemObject
Dim fsoStream As Scripting.TextStream
Dim strLine As String
Set fsoStream = FSO.OpenTextFile(strPath)
Do Until fsoStream.AtEndOfStream = True
strLine = fsoStream.ReadLine
' ... do your work ...
Loop
fsoStream.Close
Set FSO = Nothing

Resources