So I'm pretty new to VBA.
The below code works fine in 2007 for listing all of the PDF files in a particular folder. However, this code doesn't seem to work when I try it in excel 2010 (it throws an error on Set fold = fso.GetFolder(folderPath))
Any Ideas What I'm doing wrong?
I do have Scripting Runtime checked. My code is below:
Sub List_files()
Dim fso As FileSystemObject
Dim fold As Folder
Dim f As File
Dim folderPath As String
Dim i As Integer
folderPath = "S:\Academic Affairs\Academic Operations Reporting\CV's"
Set fso = New FileSystemObject
Set fold = fso.GetFolder(folderPath)
i = 2
For Each f In fold.Files
If LCase(Right(f.Name, 3)) = "pdf" Then
Range("A" & i).Value = f.Name
i = i + 1
End If
Next
End Sub
I think you need a "\" on the folderPath variable... so that it is
folderPath = "S:\Academic Affairs\Academic Operations Reporting\CV's\"
If that doesn't fix it, post the error you're getting.
Here is a procedure that I use for listing files:
Function GetFileList(pDirPath As String) As Variant
On Error GoTo GetFileList_err
' Local constants / variables
Const cProcName = "GetFileList"
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim c As Double ' upper bound for file name array
Dim i As Double ' iterator for file name array
Dim vFileList() As String ' array for file names
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(pDirPath)
c = objFolder.Files.Count
i = 0
ReDim vFileList(1 To c) ' set bounds on file array now we know count
'Loop through the Files collection
For Each objFile In objFolder.Files
'Debug.Print objFile.Name
i = i + 1
vFileList(i) = objFile.Name
Next
'Clean up!
Set objFolder = Nothing
Set objFile = Nothing
Set objFSO = Nothing
GetFileList = vFileList
GetFileList_exit:
Exit Function
GetFileList_err:
Debug.Print "Error in ", cProcName, " Err no: ", Err.Number, vbCrLf, "Err Description: ", Err.Description
Resume Next
End Function
Sub PrintFileList(pDirPath As String, _
Optional pPrintToSheet = False, _
Optional pStartCellAddr = "$A$1", _
Optional pCheckCondition = False, _
Optional pFileNameContains)
On Error GoTo PrintFileList_err
' Local constants / variables
Const cProcName = "PrintFileList"
Dim vFileList() As String ' array for file names
Dim i As Integer ' iterator for file name array
Dim j As Integer ' match counter
Dim c As String
vFileList = GetFileList(pDirPath)
c = pStartCellAddr
j = 0
For i = LBound(vFileList) To UBound(vFileList)
If pPrintToSheet Then
If pCheckCondition Then
' if pFileNameContains not in filename go to next iteration of loop
If InStr(1, vFileList(i), pFileNameContains, vbTextCompare) = 0 Then
GoTo EndLoop
End If
End If
Range(c).Offset(j, 0).Value = vFileList(i)
j = j + 1
End If
'Debug.Print vFileList(i)
i = i + 1
EndLoop:
Next
PrintFileList_exit:
Exit Sub
PrintFileList_err:
Debug.Print "Error in ", cProcName, vbCrLf, "Err no: ", Err.Number, _
vbCrLf, "Err Description: ", Err.Description
Resume Next
End Sub
The function is just for internal use, you call the procedure. Here is an example call (in this case using the userprofile windows environment variable as the path rather than a hard coded path):
call PrintFileList(environ("userprofile"), True, "$A$1", True, ".pdf")
Whenever things are not working as they "should" it's very productive to start with a minimal approach that works and build from there.
Try this that works in Excel 2016:
Option Explicit
Sub File_renaming2()
Dim objFSO As FileSystemObject
Dim mySource As Folder
Dim myFolder As File
Set objFSO = New FileSystemObject
Set mySource = objFSO.GetFolder("S:\Academic Affairs\Academic Operations Reporting\CV's\")
For Each myFolder In mySource.Files
Debug.Print myFolder.Name
Next myFolder
End Sub
Use this:
Set fso = New Scripting.FileSystemObject
Don't know how to explain:
But we need to make the full reference to the object type
CHANGE
"Dim mySource As Folder "
TO
"Dim mySource As Scripting.Folder" 'OR "Dim mySource As object"
Why ?
In my case the working code stopt from working
=> I added the "microsoft outlook object library" => it has a "Folder" type to
=> so nothing worked for me aftherwards
Related
I want to open a text file from my directory to find emails from a text.
I use this code:
Public Sub makeEmailList()
Fname = Application.GetOpenFilename(MultiSelect:=True)
If Not IsArray(Fname) Then MsgBox "No File Selected", vbMsgBoxRtlReading, "": Exit Sub
Dim wbkExport As Workbook
Set wbkExport = Application.Workbooks.Add
wbkExport.Worksheets(1).Cells(1, 1).Select
Selection = "EMail"
r = 1
For K = LBound(Fname) To UBound(Fname)
If Right(Fname(K), 4) = ".txt" Then
Open Fname(K) For Input Access Read As #1
While Not EOF(1)
Line Input #1, WholeLine
If InStr(WholeLine, "#") > 0 Then
S = InStr(WholeLine, "<th>")
e = InStr(WholeLine, "</th>")
r = r + 1
wbkExport.Worksheets(1).Cells(r, "A") = Mid(WholeLine, S + 4, e - S - 4)
End If
Wend
End If
Next K
Close #1
End Sub
when the name of all folders and sub folders that contains the text file, are English, everything is ok. but when I choose a file from a path that has a folder that it's name contains Persian characters (just this two characters: "ی" and "ک") it returns Error 76: path not Found.
In Persian we type "ی" as ChrW(1740) but vba uses arabic "ي" with ChrW(1610) instead and we type ChrW(1705) for "ک" but VBA Uses ChrW(1603). this is the reason.
The error occurs here:
Open Fname(K) For Input Access Read As #1
I used the replace function, above this line, to change characters but it did'nt work.
Fname(K) = Replace(Replace(Fname(K), ChrW(1610), ChrW(1740)), ChrW(1603), ChrW(1705))
I checked the windows language and location setting on windows And Language setting in excel options, and it is ok.
thank you for your help.
Open File When Non-English Letters in Path
Instead of the Open statement, use the OpenTextFile method of the FileSystemObject object.
Public Sub MakeEmailList()
' Needs a reference to VBE->Tools->References->Microsoft Scripting Runtime
Dim fPaths As Variant: fPaths = Application.GetOpenFilename(MultiSelect:=True)
If Not IsArray(fPaths) Then MsgBox "No File Selected", vbMsgBoxRtlReading, "": Exit Sub
Dim wbkExport As Workbook: Set wbkExport = Workbooks.Add(xlWBATWorksheet)
Dim wsExport As Worksheet: Set wsExport = wbkExport.Worksheets(1)
wsExport.Range("A1").Value = "EMail"
Dim r As Long: r = 1
' Early binding needs a reference and has IntelliSense to easily learn.
Dim fso As Scripting.FileSystemObject: Set fso = New Scripting.FileSystemObject
' Or: Late binding needs no reference; no IntelliSense though.
'Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
Dim fsoTextStream As Scripting.TextStream ' early binding...
'Dim fsoTextStream As Object ' ... or late binding
Dim fPath As String
Dim fExtension As String
Dim WholeLine As String
Dim sPos As Long
Dim ePos As Long
Dim n As Long
For n = LBound(fPaths) To UBound(fPaths)
fPath = fPaths(n)
'Debug.Print "Path: " & fPath
fExtension = fso.GetExtensionName(fPath)
If StrComp(fExtension, "txt", vbTextCompare) = 0 Then
Set fsoTextStream = fso.OpenTextFile(fPaths(n), ForReading)
Do While Not fsoTextStream.AtEndOfStream
'DoEvents
WholeLine = fsoTextStream.ReadLine
'Debug.Print "Line: " & WholeLine
If InStr(WholeLine, "#") > 0 Then
sPos = InStr(WholeLine, "<th>")
ePos = InStr(WholeLine, "</th>")
r = r + 1
wsExport.Cells(r, "A") = Mid(WholeLine, sPos + 4, ePos - sPos - 4)
End If
Loop
fsoTextStream.Close
End If
Next n
End Sub
This is the first week I learn vba so bear with me if I have a lot of questions;-)
So I have two folders, one folder contains the templates I need to update, the other contains the reports that the updates will be copied from. Cell A1 in each template contains the code that is specific to that BU. I need vba to find the code in the file names in the report folder and open that report. The problem is that the report names have different lengths, eg. it's named as XXX region_code_XXXXXXXXXXX, there can be any number of "X" before and after the code.
Sub Macro1()
Set fso = CreateObject("scripting.filesystemobject")
Set ff = fso.getfolder("C:\Users\35264\summary\test")
For Each file In ff.Files
Workbooks.Openfile
Set wbk2 = ActiveWorkbook
Sheets("Summary").Select
Range("A1").Select
rngX = Range("A1").Value
Now I need to find rngX in the file names in the report folder... I can't figure out how. Let me know if anyone can help! Thank you!
I am learning how to use dir function. I think it will be helpful to get the names of the reports first.
Combine the FileSystemObject Object With the Dir Function
Dir cannot be used in nested Do...Loops.
Using the FileSystemObject object, it opens files in one folder and uses the information in it to open specific files in another folder by using the Dir function. For each combination, it prints their names to the immediate window and closes each file without saving changes.
A better way to do this would be to write the file paths of the first folder to an array by using the Dir function and then loop through the elements of the array to open each file... etc.
Option Explicit
Sub PrintTemplatesAndReports()
' Templates
Const tFolderPath As String = "C:\Users\35264\summary\templates\"
Const tWorksheetName As String = "Summary"
Const rFilePatternAddress As String = "A1"
Const tFileExtensionLeft As String = "xls"
' Reports
Const rFolderPath As String = "C:\Users\35264\summary\reports\"
Const rFileExtensionPattern As String = ".xls*"
' 1st Worbook (ThisWorkbook)
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(tFolderPath) Then Exit Sub
If Not fso.FolderExists(rFolderPath) Then Exit Sub
Dim fsoFolder As Object: Set fsoFolder = fso.Getfolder(tFolderPath)
' Templates (using the FileSystemObject object)
Dim fsoFile As Object
Dim twb As Workbook, tws As Worksheet
Dim tExtension As String, tFilePath As String
' Report (using Dir)
Dim rwb As Workbook
Dim rFilePattern As String, rFileName As String, rFilePath As String
' Counters
Dim ttCount As Long, tCount As Long, rCount As Long
For Each fsoFile In fsoFolder.Files
ttCount = ttCount + 1
tExtension = fso.GetExtensionName(fsoFile)
If InStr(1, tExtension, tFileExtensionLeft, vbTextCompare) = 1 Then
tCount = tCount + 1
tFilePath = tFolderPath & fsoFile.Name
' 2nd Workbook (Template)
Set twb = Workbooks.Open(tFilePath)
On Error Resume Next
Set tws = twb.Worksheets(tWorksheetName)
On Error GoTo 0
If Not tws Is Nothing Then
rFilePattern = CStr(tws.Range(rFilePatternAddress).Value)
rFileName = Dir(rFolderPath, "*" & rFilePattern _
& "*" & rFileExtensionPattern)
Do Until Len(rFileName) = 0
rCount = rCount + 1
rFilePath = rFolderPath & rFileName
' 3rd Workbook (Report)
Set rwb = Workbooks.Open(rFolderPath, rFileName)
' Do your thing, e.g.:
Debug.Print twb.Name, rwb.Name
rwb.Close SaveChanges:=False
rFileName = Dir ' next report
Loop
Set tws = Nothing
End If
twb.Close SaveChanges:=False
End If
Next fsoFile ' next template
MsgBox "Template files processed: " & tCount & "(" & ttCount & ")" _
& vbLf & "Report files processed: " & rCount & "(" & tCount & ")", _
vbInformation
End Sub
in the Range A1:A2 I stored the file name.
The files are stored in three different folders.
And the file name start with the search criteria in A1 but is not always match 100 %.
A1 = "test1"
But the pdf documents, which I am looking for call
"test1-e"
, but this is the right one which I need.
After finding the correct pdf in the three folders, I need to copy it to the Source Path.
My approach looks like this:
Sub copyFile()
Dim objFSO As Object, rng As Range
Dim strFileToCopy, strOldPath As String, strOldPath2 As String, strOldPath3 As String, strNewPath As String
strOldPath = "" 'Verzeichnis Nr. 1 in dem die Datei liegt
strOldPath2 = "" 'Verzeichnis Nr. 2 in dem die Datei liegt
strOldPath3 = "" 'Verzeichnis Nr. 3 in dem die Datei liegt
strNewPath = ""
With ActiveSheet
For Each rng In Range("A1:A2")
'strFileToCopy = .Range("A2") 'Zelle mit dem Namen
If strFileToCopy Like rng Then
strFileToCopy = rng
strFileToCopy = strFileToCopy & ".pdf" 'Suffix anhängen
Set objFSO = CreateObject("Scripting.FileSystemObject")
OldPath = objFSO.BuildPath(strOldPath, strFileToCopy)
If objFSO.FileExists(OldPath) Then
objFSO.copyFile OldPath, objFSO.BuildPath(strNewPath, strFileToCopy)
End If
End If
Next
'If Dir(strOldPath & strFileToCopy, vbNormal) <> "" Then
' Set objFSO = CreateObject("Scripting.FileSystemObject")
'objFSO.copyFile strOldPath & strFileToCopy, strNewPath & strFileToCopy
'End If
End With
Set objFSO = Nothing
End Sub
But my problem is, how can search in different folders and how can I search with "Like-Expression", because my solution didn't work out. Thanks a lot for the support.
Something along these lines I would use. This returns an array of files.
Function ReturnFiles(strSourceFolder As String, strSearch As String) As Scripting.File()
Dim a() As File
Dim fso As Scripting.FileSystemObject
Dim f As Scripting.Folder
Dim fl As Scripting.File
On Error GoTo eHandle
Set fso = New Scripting.FileSystemObject
If fso.FolderExists(strSourceFolder) Then
Set f = fso.GetFolder(strSourceFolder)
For Each fl In f.Files
If Left(fl.Name, Len(strSearch)) = strSearch Then ' Or instr here for example
Set a(UBound(a)) = fl
ReDim Preserve a(UBound(a) + 1)
End If
Next fl
Else
End If
ReturnFiles = a
HouseKeeping:
Set fl = Nothing
Set f = Nothing
Set fso = Nothing
Erase a
Exit Function
eHandle:
If Err.Number = 9 Then
ReDim a(0)
Resume
Else
GoTo HouseKeeping
End If
End Function
Below is code that should let me select a folder, then find and replace periods in the word documents within the folder and replace them with a space.
I got the code to work, my computer crashed, and now I don't remember what I did, and I'm getting a 'user-defined type' error.
I'm not quite sure how to fix this.
I'm also trying to get this to work from excel (not just from word) so any help there would be appreciated.
Sub Step_1() 'select folder with raw files to clean up
Dim wordApp As Word.Application
Dim objDocument As Word.Document
Dim intResult As Integer
Dim strPath As String
Dim arrFiles() As String
Dim i As Integer
'box will open where user can pick folder with raw files
intResult = Application.FileDialog(msoFileDialogFolderPicker).Show
'checks if user has cancelled the dialog
If intResult <> 0 Then
'display folder search box
strPath = Application.FileDialog( _
msoFileDialogFolderPicker).SelectedItems(1)
arrFiles() = GetAllFilePaths(strPath)
For i = LBound(arrFiles) To UBound(arrFiles)
Call ModifyFile(arrFiles(i))
Next i
End If
End Sub
Private Sub ModifyFile(ByVal strPath As String)
Dim wordApp As Word.Application
Dim objDocument As Word.Document
Set objDocument = wordApp.Documents.Open(strPath)
objDocument.Activate
For Each objDocument In strPath
With Selection.Find
.Text = "."
.Replacement.Text = " "
.Find.Execute Replace:=wdReplaceAll
'there's a much longer list of things to replace
End With
objDocument.Close (True)
Next
Next
End Sub
Private Function GetAllFilePaths(ByVal strPath As String) _
As String()
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim i As Integer
Dim arrOutput() As String
ReDim arrOutput(1 To 1)
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the folder object
Set objFolder = objFSO.GetFolder(strPath)
i = 1
'loops through each file in the directory and
'prints their names and path
For Each objFile In objFolder.Files
ReDim Preserve arrOutput(1 To i)
'print file path
arrOutput(i) = objFile.Path
i = i + 1
Next objFile
GetAllFilePaths = arrOutput
End Function
Cleaned up:
Sub ProcessFiles()
Dim wordApp As Word.Application
Dim wdDoc As Word.document
Dim strPath As String, allfiles As Collection, fPath
strPath = GetFolderPath()
If Len(strPath) = 0 Then Exit Sub
Set allfiles = GetAllFiles(strPath, "*.doc*")
If allfiles.Count = 0 Then
MsgBox "No Word files found"
Exit Sub
End If
Set wordApp = New Word.Application
wordApp.Visible = True
'loop over found files
For Each fPath In allfiles
Debug.Print "Processing " & fPath
Set wdDoc = wordApp.documents.Open(fPath)
ReplaceDocContent wdDoc, ".", " "
ReplaceDocContent wdDoc, ",", " "
ReplaceDocContent wdDoc, "~", " "
'etc.....
wdDoc.Close True 'close and save changes
Next fPath
MsgBox "done"
End Sub
'replace text in a Word document with some other text
Private Sub ReplaceDocContent(doc As Word.document, findWhat, replaceWith)
With doc.Range.Find
.Text = findWhat
.Replacement.Text = replaceWith
.Execute Replace:=wdReplaceAll
End With
End Sub
'collect all files under folder `strPath` which match `pattern`
Private Function GetAllFiles(ByVal strPath As String, pattern As String) As Collection
Dim objFile As Object, col As New Collection
'Create an instance of the FileSystemObject and list all files
For Each objFile In CreateObject("Scripting.FileSystemObject").GetFolder(strPath).Files
If objFile.Path Like pattern Then col.Add objFile.Path
Next objFile
Set GetAllFiles = col
End Function
'return selected folder path or empty string
Function GetFolderPath() As String
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show <> 0 Then GetFolderPath = .SelectedItems(1)
End With
End Function
I have script to scan a folder for files with a file name containing a certain text. The script works but it stops after sometime without finishing the scan of the complete folder (I reached 16663 scans, is there a limit?). I can't figure out why the script stops. Any help is greatly appreciated.
I initially used the code posted in this post Get list of sub-directories in VBA
Update: The drive I'm scanning is a network drive. My assumption now is that due to a hick-up in the connection the script stops. At the moment I'm trying different approaches to work around this...
Sub LoopThroughFilePaths()
Application.StatusBar = True
Application.ScreenUpdating = False
Counter = 1
Dim strPath As String
strPath = "V:\50" ' folder to scan
Dim myArr
myArr = GetSubFolders(strPath)
Application.StatusBar = False
Application.ScreenUpdating = True
End Sub
Used Function GetSubFolders
Function GetSubFolders(RootPath As String)
Application.ScreenUpdating = False
Dim fso As Object
Dim fld As Object
Dim sf As Object
Dim myArr
Dim output As String
Dim StrFileOut As String
VAR_01_output = "D:\output" 'Location to copy found files to
Set fso = CreateObject("Scripting.FileSystemObject")
Set fld = fso.GetFolder(RootPath)
Dim StrFile As String
StrFile = Dir(fld + "\*labsuite*") 'wild card search for files
Do While Len(StrFile) > 0
StrFileOut = Format(Now(), "hh-mm-ss") & "_" & StrFile ' rename files
FileCopy fld + "\" + StrFile, VAR_01_output + "\" + StrFileOut 'copy found files to output folder
StrFile = Dir
Loop
For Each sf In fld.SubFolders
ReDim Preserve Arr(Counter)
Arr(Counter) = sf.Path
Counter = Counter + 1
On Error Resume Next
myArr = GetSubFolders(sf.Path)
On Error Resume Next
'ActiveWorkbook.Sheets(1).Cells(1, 1).Value = Counter
Application.StatusBar = sf.Path
DoEvents
Next
GetSubFolders = Arr
Set sf = Nothing
Set fld = Nothing
Set fso = Nothing
End Function