For each... Next not looping - vba

I have a macro that uses a string in the filename to identify the folder to move the file to. It looks up the string in column A and builds the folder name using the country name retrieved from the adjacent cell in column B.
The If statement executes correctly (moves the file correctly). However, the For each... Next looping through the files doesn't work and I cannot see why not.
Thanks in advance for the help.
Sub MoveFiles_SpecificFolders_Loop()
Dim SrepFSO As FileSystemObject
Dim Srep As File
Dim fso As New FileSystemObject
Dim HoldingFolder As String
Dim TargetFolder As String
Dim HldFolder As Folder
Dim i As Integer
HoldingFolder = "C:\Users\xyz\Holding\"
TargetFolder = "C:\Users\xyz\Countries\"
Set fso = CreateObject("Scripting.FileSystemObject")
Set SrepFSO = New Scripting.FileSystemObject
Set HldFolder = SrepFSO.GetFolder(HoldingFolder)
For Each Srep In HldFolder.Files
For i = 2 To 50
If InStr(Srep, Sheet2.Cells(i, 1)) <> 0 Then
SrepFSO.MoveFile Source:=SrepFSO.GetFile(Srep), _
Destination:=TargetFolder & Sheet2.Cells(i, 1).Offset(, 1) & "\" & Srep.Name
End If
Next i
Next Srep
End Sub

You need to exit the inner for loop once the file has been moved.
Try this
Sub MoveFiles_SpecificFolders_Loop()
Dim SrepFSO As FileSystemObject
Dim Srep As File
Dim fso As New FileSystemObject
Dim HoldingFolder As String
Dim TargetFolder As String
Dim HldFolder As Folder
Dim i As Integer
HoldingFolder = "C:\Users\xyz\Holding\"
TargetFolder = "C:\Users\xyz\Countries\"
Set fso = CreateObject("Scripting.FileSystemObject")
Set SrepFSO = New Scripting.FileSystemObject
Set HldFolder = SrepFSO.GetFolder(HoldingFolder)
For Each Srep In HldFolder.Files
For i = 2 To 50
If InStr(Srep, Sheet2.Cells(i, 1)) <> 0 Then
If Not SrepFSO.FolderExists(TargetFolder & Sheet2.Cells(i, 2)) then
SrepFSO.CreateFolder TargetFolder & Sheet2.Cells(i, 2)
End if
SrepFSO.MoveFile Source:=SrepFSO.GetFile(Srep), _
Destination:=TargetFolder & Sheet2.Cells(i, 2) & "\" & Srep.Name
Exit For
End If
Next i
Next Srep
End Sub

Related

opening html file with vba

I have some .html files which I want to read with vba. I wrote this codes to do what I want but I get
object variable or with block variable not set
error.
Dim arrListATA() As String
Dim arrListTaskNo() As String
Dim arrListDesc() As String
Dim arrIssueNo() As String
Dim arrIssueDate() As String
Dim arrPartNo() As String
Dim arrDMC() As String
Dim arrApplicability() As String
Dim arrDMCModelCode() As String
Dim DMCs As String
Dim arrSubTask() As String
Dim subTasks As String
Dim subs() As Variant
Dim subs1 As String
k = 0
Dim objFile As Scripting.File
Dim objFolder As Scripting.Folder
Set objFSO = CreateObject("Scripting.FileSystemObject")
w = 0
m = 0
b = 0
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
With fd
fd.Filters.Clear
If fd.Show = -1 Then
myTopFolderPath = fd.SelectedItems(1)
Set objFolder = objFSO.GetFolder(myTopFolderPath)
Dim arrSplitedDMC As Variant
Dim arrSubTasks As Variant
For Each objFile In objFolder.Files
Debug.Print myTopFolderPath & "\" & objFile.Name
If Right(objFile.Name, 4) = "html" And Len(objFile.Name) = 33 And Left(objFile.Name, 8) <> "V2500-00" Then
Debug.Print myTopFolderPath & "\" & objFile.Name
Workbooks.Open Filename:=myTopFolderPath & "\" & objFile.Name
Debug.Print "Opened"
lastrow = Cells(Rows.Count, 1).End(xlUp).Row
taskCheckFlag = False
myTemp = ""
partNoFlag = False
mySubTask = ""
For i = 1 To lastrow
txt = Cells(i, 1)
Next i
My folder path and my object names like this
C:\Users\ftk1187\Desktop\V2500 - Copy\V2500-00-70-72-02-00A-363A-D.html
It's not opening my .html files. How can I solve this problem?
The code below actually runs.
Option Explicit
Private Sub Test()
Dim arrListATA() As String
Dim arrListTaskNo() As String
Dim arrListDesc() As String
Dim arrIssueNo() As String
Dim arrIssueDate() As String
Dim arrPartNo() As String
Dim arrDMC() As String
Dim arrApplicability() As String
Dim arrDMCModelCode() As String
Dim DMCs As String
Dim arrSubTask() As String
Dim subTasks As String
Dim subs() As Variant
Dim subs1 As String
Dim objFSO As FileSystemObject
Dim Fd As FileDialog
Dim objFile As Scripting.File
Dim objFolder As Scripting.Folder
Dim arrSplitedDMC As Variant
Dim arrSubTasks As Variant
Dim myTopFolderPath As String
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set Fd = Application.FileDialog(msoFileDialogFolderPicker)
' k = 0
' w = 0
' m = 0
' b = 0
With Fd
.Filters.Clear
If .Show = -1 Then
myTopFolderPath = .SelectedItems(1)
Set objFolder = objFSO.GetFolder(myTopFolderPath)
For Each objFile In objFolder.Files
Debug.Print myTopFolderPath & "\" & objFile.Name
Debug.Print myTopFolderPath
Debug.Print objFile.Name
Debug.Print Right(objFile.Name, 4), Len(objFile.Name), Left(objFile.Name, 8)
' If Right(objFile.Name, 4) = "html" And Len(objFile.Name) = 33 And Left(objFile.Name, 8) <> "V2500-00" Then
' Debug.Print myTopFolderPath & "\" & objFile.Name
' Workbooks.Open Filename:=myTopFolderPath & "\" & objFile.Name
' Debug.Print "Opened"
'
' lastrow = Cells(Rows.Count, 1).End(xlUp).Row
' taskCheckFlag = False
' myTemp = ""
' partNoFlag = False
' mySubTask = ""
'
' For i = 1 To lastrow
' txt = Cells(i, 1)
' Next i
Next objFile
End If
End With
End Sub
You will see that I added Option Explicit at the top and a few declarations that were missing. The variables k, w, m and b are also not declared but if they are numbers their value should already be 0 at that point of the code. According to my research, Excel should be able to open an HTML file but I wonder what it might show.
As a general piece of advice, I would recommend that you construct your code as one Main subroutine which calls other subs and functions, each of them no larger than 10 to 25 lines of code. In your code you already exceed that number in your declarations. The effect is a construct that you can't control.

Issue in looping through various subfolders of folder and each files of these subfolders

I want to access each subfolder of my current folder(number of subfolders in each sub folder may vary) and then want to perform some operations in each excel workbook of all these subfolders.
Below mentioned is the code and code is not throwing compile time error but not working. Kindly help me
option explicit
Sub LoopFolders()
Dim strFolder As String
Dim strSubFolder As String
Dim strFile As String
Dim colSubFolders As New Collection
Dim varItem As Variant
Dim wbk As Workbook
' Parent folder including trailing backslash
strFolder = "C:\Users\Yashika Vaish\Desktop\yashika\"
' Loop through the subfolders and fill Collection object
strSubFolder = Dir(strFolder & "*", vbDirectory)
Do While Not strSubFolder = ""
Select Case strSubFolder
Case ".", ".."
' Current folder or parent folder - ignore
Case Else
' Add to collection
colSubFolders.Add Item:=strSubFolder, Key:=strSubFolder
End Select
' On to the next one
strSubFolder = Dir
Loop
' Loop through the collection
For Each varItem In colSubFolders
' Loop through Excel workbooks in subfolder
strFile = Dir(strFolder & varItem & "\*.xls*")
Do While strFile <> ""
' Open workbook
Set wbk = Workbooks.Open(FileName:=strFolder & _
varItem & "\" & strFile, AddToMRU:=False)
MsgBox "I am open"
strFile = Dir
Loop
Next varItem
End Sub
All the required references in tools settings have already been added in this VBA Project. Kindly help me with this code.
The method below writes the file names from the subfolders too to the workbook. So it finds them.
Sub Program()
Dim i As Integer
i = 1
listFiles "D:\Folder 1", i
End Sub
Sub listFiles(ByVal sPath As String, ByRef i As Integer)
Dim vaArray As Variant
Dim oFile As Object
Dim oFSO As Object
Dim oFolder As Object
Dim oFiles As Object
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder(sPath)
Set oFiles = oFolder.Files
If (oFiles.Count > 0) Then
ReDim vaArray(1 To oFiles.Count)
For Each oFile In oFiles
Cells(i, "A").Value = oFile.Name
Cells(i, "B").Value = oFile.Path
i = i + 1
Next
End If
listFolders sPath, i
End Sub
Sub listFolders(ByVal sPath As String, ByRef i As Integer)
Dim vaArray As Variant
Dim oFile As Object
Dim oFSO As Object
Dim oFolder As Object
Dim oFiles As Object
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder(sPath)
Set oFiles = oFolder.subfolders
If (oFiles.Count > 0) Then
ReDim vaArray(1 To oFiles.Count)
For Each oFile In oFiles
listFiles oFile.Path, i
i = i + 1
Next
End If
End Sub
This is what I use & it's a #WorksAtMyBox certified code ;)
Option Explicit
Dim fso As Scripting.FileSystemObject
Dim fsoMainDirectory As Scripting.folder
Dim fsoSubfolder As Scripting.folder
Dim fsoFile As Scripting.file
Dim strFilePath
Dim filecounter As Long
Dim foldercounter As Long
Public Sub FileFinder(fileorfolder As String)
If fso Is Nothing Then
Set fso = New Scripting.FileSystemObject
End If
Set fsoMainDirectory = fso.GetFolder(fileorfolder)
If fsoMainDirectory.SubFolders.Count > 0 Then
For Each fsoSubfolder In fsoMainDirectory.SubFolders
foldercounter = foldercounter + 1
Debug.Print "Folder: " & foldercounter & fsoSubfolder.Path
FileFinder (fsoSubfolder.Path)
Next fsoSubfolder
End If
If fsoMainDirectory.Files.Count > 0 Then
For Each fsoFile In fsoMainDirectory.Files
ProcessFile (fsoFile.Path)
Next fsoFile
End If
End Sub
Public Sub ProcessFile(file As String)
filecounter = filecounter + 1
Debug.Print "File: " & filecounter & ": " & file
End Sub
So, here is how I search through a folder looking for a specific file type. (early binding is your friend at this point in development). Make sure you have the Microsoft Scripting Runtime reference enabled.
Option Explicit
Sub test()
Dim fso As Scripting.FileSystemObject
Dim fsoMainDirectory As Scripting.Folder
Dim fsoSubfolder As Scripting.Folder
Dim fsoFile As Scripting.File
Dim strFilePath
Set fso = New Scripting.FileSystemObject
Set fsoMainDirectory = fso.GetFolder("Directory, with trailing \")
For Each fsoFile In fsoMainDirectory.Files
If fsoFile.Type = "Microsoft Excel 97-2003 Worksheet" Then '.xls file type
strFilePath = fsoFile.Path
Application.Workbooks.Open strFilePath
End If
Next fsoFile
End Sub
How deep do your sub folders go? Are you the only one will use this macro? Looping through n subfolders with an unknown number of subfolders is doable, but my method involves an array of counters. This array can lower performance, and as such don't want to do that if we don't need to.

VBA: How to open most recent two excel files in the folder

I have trying to open the most recent two excel file in the folder so far i did open the latest file in folder but i have to open 2nd latest file in folder. refer below code. please suggest how to open 2nd most recent file?
Sub findingdiff()
Dim FileSys, objFile, myFolder, c As Object
Dim wb1 As Workbook
Dim wb2 As Workbook
FolderName = ("C:\Users\ashokkumar.d\Desktop\Test\do\")
Set FileSys = CreateObject("Scripting.FileSystemObject")
Set myFolder = FileSys.GetFolder(FolderName)
dteFile = DateSerial(1900, 1, 1)
For Each objFile In myFolder.Files
If InStr(1, objFile.Name, ".xls") > 0 Then
If objFile.DateLastModified > dteFile Then
dteFile = objFile.DateLastModified
strFilename = objFile.Name
End If
End If
Next objFile
'opening of latest file in the folder
Set wb2 = Workbooks.Open(FolderName & Application.PathSeparator & strFilename)
End Sub
Here's another way to tackle the problem. Create a sorted list and then process the first 2 files:
Sub Lastest2Files()
Dim rs As ADODB.Recordset
Dim fs As FileSystemObject
Dim Folder As Folder
Dim File As File
'create a recordset to store file info
Set rs = New ADODB.Recordset
rs.fields.Append "FileName", adVarChar, 100
rs.fields.Append "Modified", adDate
rs.Open
'build the list of files and sort
Set fs = New FileSystemObject
Set Folder = fs.GetFolder("C:\aatemp")
For Each File In Folder.Files
rs.AddNew
rs("FileName") = File.Path
rs("Modified") = File.DateLastModified
Next
rs.Sort = "Modified DESC"
'process the first 2 files
rs.MoveFirst
Set wb2 = Workbooks.Open(rs.fields("FileName").value)
rs.MoveNext
Set wb2 = Workbooks.Open(rs.fields("FileName").value)
End Sub
You can do it in one pass
Sub findingdiff()
Dim FileSys, objFile, myFolder, c As Object
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim strFilename, strFilename2
FolderName = ("C:\Users\ashokkumar.d\Desktop\Test\do\")
Set FileSys = CreateObject("Scripting.FileSystemObject")
Set myFolder = FileSys.GetFolder(FolderName)
dteFile = DateSerial(1900, 1, 1)
For Each objFile In myFolder.Files
If InStr(1, objFile.Name, ".xls") > 0 Then
If objFile.DateLastModified > dteFile Then
dteFile = objFile.DateLastModified
strFilename2 = strFilename
strFilename = objFile.Name
End If
End If
Next objFile
'opening of latest file in the folder
Set wb1 = Workbooks.Open(FolderName & Application.PathSeparator & strFilename)
Set wb2 = Workbooks.Open(FolderName & Application.PathSeparator & strFilename2)
End Sub
I modified findingdiff when the first file it encounter is most recent; Otherwise findingdiff don't get the second most recent.
Hope this helps...
Private Sub SortDictionaryByKey() '220926
' http://www.xl-central.com/sort-a-dictionary-by-key.html
Dim ProcName As String: ProcName = Mod_Name & "SortDictionaryByKey" & Debug_Output_Seperator '220926
Debug.Print TimeStamp & ProcName
'Set a reference to Microsoft Scripting Runtime by using
'Tools > References in the Visual Basic Editor (Alt+F11)
'Declare the variables
Dim Dict As Scripting.Dictionary
Dim TempDict As Scripting.Dictionary
Dim KeyVal As Variant
Dim Arr() As Variant
Dim Temp As Variant
Dim Txt As String
Dim i As Long
Dim j As Long
'Create an instance of the Dictionary
Set Dict = New Dictionary
'Set the comparison mode to perform a textual comparison
Dict.CompareMode = TextCompare
Dim FileSys, objFile, myFolder, c As Object
Dim FolderName As Variant
Dim dteLatest As Variant
''''''''''''''''''''''''''''''''
FolderName = FolderSelect_Source_Destination '220922
Set FileSys = CreateObject("Scripting.FileSystemObject")
Set myFolder = FileSys.GetFolder(FolderName)
With myFolder
End With
dteLatest = DateSerial(1900, 1, 1)
For Each objFile In myFolder.Files
'220921
With objFile
If InStr(1, .name, PPT_Extension) > 0 Then
Dict.Add .DateLastModified, .Path
Debug.Print TimeStamp & ProcName & .Path
dteLatest = .DateLastModified
End If
End With
Next objFile
'Allocate storage space for the dynamic array
ReDim Arr(0 To Dict.Count - 1)
'Fill the array with the keys from the Dictionary
For i = 0 To Dict.Count - 1
Arr(i) = Dict.Keys(i)
Next i
'Sort the array using the bubble sort method
For i = LBound(Arr) To UBound(Arr) - 1
For j = i + 1 To UBound(Arr)
If Arr(i) > Arr(j) Then
Temp = Arr(j)
Arr(j) = Arr(i)
Arr(i) = Temp
End If
Next j
Next i
'Create an instance of the temporary Dictionary
Set TempDict = New Dictionary
'Add the keys and items to the temporary Dictionary,
'using the sorted keys from the array
For i = LBound(Arr) To UBound(Arr)
KeyVal = Arr(i)
TempDict.Add Key:=KeyVal, Item:=Dict.Item(KeyVal)
Next i
'Set the Dict object to the TempDict object
Set Dict = TempDict
'Build a list of keys and items from the original Dictionary
For i = 0 To Dict.Count - 1
Txt = Txt & Dict.Keys(i) & vbTab & Dict.Items(i) & vbCrLf
Next i
With Dict
str_Recent_FileFullName(1) = .Items(.Count - 1)
str_Recent_FileFullName(2) = .Items(.Count - 2)
Stop
'Display the list in a message box
End With
MsgBox Txt, vbInformation
Set Dict = Nothing
Set TempDict = Nothing
Set KeyVal = Nothing
Erase Arr()
Set Temp = Nothing
Set FileSys = Nothing
End Sub

How to take filename as input as create a file in VBA

Dim fso As Scripting.FileSystemObject
Dim ts As Scripting.TextStream
Dim c As Range
Dim filename As Variant
Dim colcount As Integer
colcount = 2
Worksheets("ShipmentTracker(AL3)").Activate
filename = InputBox("Enter File Name", "file name", Worksheets("ShipmentTracker(AL3)").Cells(3, 2).Value)
Set fso = New Scripting.FileSystemObject
Set ts = fso.OpenTextFile("C:\Users\soora\Desktop\Meng Project\Shipment Tracker" & filename, ForAppending, True)
For Each c In Range("A9", Range("A9").End(xlDown))
For i = 1 To colcount
ts.Write c.Offset(0, i - 1).Value
If i < colcount Then ts.Write vbTab
Next i
ts.WriteLine
Next c
ts.Close
Set fso = Nothing
I am taking filename as input and using that to create a new file into which I want to write data. But this does not work.
I want to create files with user input filename and write data to it.
Try using Environ
Option Explicit
Sub TEST()
Dim fso As Scripting.FileSystemObject
Dim ts As Scripting.TextStream
Dim c As Range
Dim I As Long
Dim filename As Variant
Dim colcount As Integer
Dim sPath As String
Application.ScreenUpdating = False
'// SaveAs Path
sPath = Environ("USERPROFILE") & "\Desktop\Meng Project\Shipment Tracker\"
colcount = 2
Worksheets("ShipmentTracker(AL3)").Activate
filename = InputBox("Enter File Name", "file name", _
Worksheets("ShipmentTracker(AL3)").Cells(3, 2).Value)
Set fso = New Scripting.FileSystemObject
Set ts = fso.OpenTextFile(sPath & filename, ForAppending, True)
For Each c In Range("A9", Range("A9").End(xlDown))
For I = 1 To colcount
ts.Write c.Offset(0, I - 1).Value
If I < colcount Then ts.Write vbTab
Next I
ts.WriteLine
Next c
Application.ScreenUpdating = True
ts.Close
Set fso = Nothing
End Sub
MSDN Environ Function

Find file and insert path into cell

I have a file name of a pdf that I want to search for in a folder on a shared network drive \\Share\Projects. The pdf will be in one of the subfolders under projects. I then want to return the entire file path of the pdf into a cell (eg \\Share\Projects\Subfolder\Another subfolder\thisone.pdf).
I have started the code but can't figure out how to search a file system:
Sub InsertPath()
Dim PONumber As String
PONumber = InputBox("PO Number:", "PO Number")
'search for order
Dim myFolder As Folder
Dim myFile As File
'This bit doesn't work
Set myFolder = "\\Share\Projects"
For Each myFile In myFolder.Files
If myFile.Name = "PO" & PONumber & ".pdf" Then
'I have absolutely no idea how to do this bit
End If
Next
End Sub
Am I on the right track or is my code completely wrong?
get list of subdirs in vba
slighly modified the above post.
Public Arr() As String
Public Counter As Long
Sub LoopThroughFilePaths()
Dim myArr
Dim i As Long
Dim j As Long
Dim MyFile As String
Const strPath As String = "C:\Personal\" ' change it as per your needs
myArr = GetSubFolders(strPath)
Application.ScreenUpdating = False
Range("A1:B1") = Array("text file", "path")
For j = LBound(Arr) To UBound(Arr)
MyFile = Dir(myArr(j) & "\*.pdf")
Do While Len(MyFile) <> 0
i = i + 1
Cells(i, 1) = MyFile
Cells(i, 2) = myArr(j)
MyFile = Dir
Loop
Next j
Application.ScreenUpdating = True
End Sub
Function GetSubFolders(RootPath As String)
Dim fso As Object
Dim fld As Object
Dim sf As Object
Dim myArr
Set fso = CreateObject("Scripting.FileSystemObject")
Set fld = fso.GetFolder(RootPath)
For Each sf In fld.SUBFOLDERS
Counter = Counter + 1
ReDim Preserve Arr(Counter)
Arr(Counter) = sf.Path
myArr = GetSubFolders(sf.Path)
Next
GetSubFolders = Arr
Set sf = Nothing
Set fld = Nothing
Set fso = Nothing
End Function
Well, your folder declaration isn't set against a filesystemobject so it can't find the folder. And because it's a network location, you may need to map a network drive first so that it's a secure link.
So here's an updated version of your code.
EDIT - to OP's conditions.
Dim PONumber As String
Sub InsertPath()
PONumber = InputBox("PO Number:", "PO Number")
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim Servershare As String
ServerShare = "S:\"
Dim Directory As Object
Set Directory = fso.GetFolder(ServerShare)
Subfolderstructure Directory
End Sub
Function Subfolderstructure(Directory As Object)
For Each oFldr in Directory.SubFolders
For Each FileName In oFldr.Files
If FileName.Name = "PO" & PONumber & ".pdf" Then
sheets("Sheet1").range("A1").value = ServerShare & "\PO" & PONumber & ".pdf"
Exit For
End If
Next
Dim sbfldrs : Set sbfldrs = ofldr.SubFolders
If isarray(sbfldrs) then
Subfolderstructure ofldr
End if
Next
'Cleanup
Set FileName = Nothing
Set Directory = Nothing
Set fso = Nothing
End Function
I have not tested this code. Try it out and let me know how it works.