I'm trying to make the following code work but am getting not getting the expected results.
The code recursively loops through all the folders and subfolders of where the file is located and joins all the PowerPoint documents into a single file.
The thing is that at times it seems to loop twice, duplicating the set of slides after the first pass of all the files.
What could be causing such behavior?
Sub loopAllSubFolderSelectStartDirectory()
Dim FSOLibrary As Object
Dim FSOFolder As Object
Dim folderName As String
folderName = ActivePresentation.Path
If Len(folderName) > 0 Then
MsgBox ActivePresentation.Name & vbNewLine & "saved under" & vbNewLine & folderName
Else
MsgBox "File not saved"
End If
'Set the reference to the FSO Library
Set FSOLibrary = CreateObject("Scripting.FileSystemObject")
'Another Macro must call LoopAllSubFolders Macro to start
LoopAllSubFolders FSOLibrary.GetFolder(folderName)
End Sub
Sub LoopAllSubFolders(FSOFolder As Object)
Dim FSOSubFolder As Object
Dim FSOFile As Object
'For each subfolder call the macro
For Each FSOSubFolder In FSOFolder.subfolders
LoopAllSubFolders FSOSubFolder
Next
On Error GoTo DoNext
'For each file, print the name
For Each FSOFile In FSOFolder.Files
'Insert the actions to be performed on each file
'This example will print the full file path to the immediate window
Debug.Print FSOFile.Path
With ActivePresentation
.Slides.Add Index:=.Slides.Count + 1, Layout:=ppLayoutCustom
With ActivePresentation.Slides(.Slides.Count)
.FollowMasterBackground = False
.Background.Fill.Solid
.Background.Fill.ForeColor.RGB = RGB(255, 0, 0)
.Shapes.Title.TextFrame.TextRange.Text = FSOFile.Path
.Shapes.Title.TextFrame.TextRange.Font.Color = RGB(255, 255, 255)
End With
.Slides.InsertFromFile FSOFile.Path, .Slides.Count
End With
DoNext:
Next
End Sub
Thanks in advance
You should skip active presentation file:
With ActivePresentation
...
If FSOFile.Path <> .FullName Then
.Slides.InsertFromFile FSOFile.Path, .Slides.Count
End If
End With
Related
I am getting a run-time error invalid procedure (error # 5) on this line:
afiles(countoflines).Delete True
I can't understand why. The save copy to the path works fine, and the assignation of the FSO to the folder files works , but I can't delete the 'x'th indexed item in the folder. Can someone assist with this?
Thanks
Option Explicit
Private Sub Workbook_Open()
Dim aFSO As New Scripting.FileSystemObject
Dim aFolder As Object
Dim aFiles As Object
Set aFolder = aFSO.GetFolder("R:\Groups\Finance\Ops Finance\Reporting\F18 Cost Analysis\Standard Costing\Std Cost Variances\Variance Master Back-Ups\")
If aFolder Is Nothing Then MsgBox "Directory not found!", vbExclamation: Exit Sub
Set aFiles = aFolder.Files
Application.StatusBar = "Saving back up copy"
ThisWorkbook.SaveCopyAs aFolder.Path & "\" & _
VBA.Replace(ThisWorkbook.Name, ".xlsm", "") & "_copy_" & _
VBA.Format$(Now, "m-d-yyyy hhmmss AM/PM") & ".xlsm"
Call CleanUpArchive(aFolder, aFolder.Path & Chr(92), aFiles.Count)
Set aFolder = Nothing
Set aFSO = Nothing
End Sub
'Cleans up archive file by deleting the 11th file (oldest copy)
Private Function CleanUpArchive(Folder As Object, Path As String, _
CountofFiles As Integer)
Dim aFiles As Scripting.Files
Set aFiles = Folder.Files
If CountofFiles > 10 Then
aFiles(CountofFiles).Delete True
End If
Set aFiles = Nothing
End Function
Untested, written on mobile. The below is not that different from your code, but might do what you need.
Option Explicit
Private Sub Workbook_Open()
Dim folderPath as string
folderPath = dir$("R:\Groups\Finance\Ops Finance\Reporting\F18 Cost Analysis\Standard Costing\Std Cost Variances\Variance Master Back-Ups\", vbdirectory)
If Len(folderPath) = 0 then
Msgbox("Could not locate folder")
Exit sub
Elseif strcomp(right(folderPath, 1),"\", vbbinarycompare) <> 0 then ' this might be unnecessary, depends if dir() on vbdirectory returns \ at end or not, cannot remember or test'
folderPath = folderPath & "\"
End if
Dim filenames() as string
Redim filenames(1 to 2, 1 to 1000) ' 1000 = magic number, change if needed.'
Dim fileIndex as long
Dim filename as string
Filename = dir$(folderPath & "*")
Do until Len(filename) = 0
Fileindex = fileindex +1
Filename(1, fileindex) = folderPath & filename
Filenames(2, fileindex) = filedatetime(Filename(1, fileindex))
Filename = dir$()
Loop
Redim preserve filenames(1 to 2, 1 to fileindex)
ThisWorkbook.SaveCopyAs folderPath & _
VBA.Replace(ThisWorkbook.Name, ".xlsm", "_copy_" & _
VBA.Format$(Now, "m-d-yyyy hhmmss AM/PM") & ".xlsm")
Dim Oldest as Date
Dim OldestIndex as long
Oldest = filenames(2,1) ' Initialise with first value'
' Might be better to store below in dictionary -- or any key-value/associative structure. But should work nonetheless.'
For fileindex = lbound(filenames,2) to ubound(filenames,2)
If filenames(2, fileindex) < oldest then
Oldest = filenames(2, fileindex)
OldestIndex = fileindex
End if
Next fileindex
Dim fileIsOpen as Boolean
On error resume next
Open filenames(1, OldestIndex) For Input Lock Read As #1
fileIsOpen = err.number <> 0
On error goto 0
Close #1
If fileIsOpen then
msgbox("Attempted to delete file at:" & filenames(1, OldestIndex) & " but file may be open elsewhere or by another user.")
Exit sub
Else
' In theory, the file could go from not-in-use to in-use between the check above and the delete below. Might be better just to try to kill without checking but with on error resume, and then checking if file still exists or is open.'
Kill filenames(1, OldestIndex)
End if
End sub
I am inserting a bunch of Word documents into one file for post-processing. When all the files are in one folder, I got my script to work. However to make it robust for future work, I'd like to insert Word files from all folders and subfolders (and possible futher subs) from a certain starting point. I followed this Youtube tutorial: https://www.youtube.com/watch?v=zHJPliWS9FQ to consider all folders and subfolders and of course amended it for my particular use.
Sub CombineDocs()
On Error Resume Next
MsgBox "Opening"
On Error GoTo 0
Dim foldername As String 'parent folder
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Show
On Error Resume Next
foldername = .SelectedItems(1)
Err.Clear
On Error GoTo 0
End With
Documents.Add
Selection.Style = ActiveDocument.Styles("Heading 1")
Selection.TypeText Text:="Opening text"
Selection.TypeParagraph
Selection.InsertNewPage
Selection.InsertBreak Type:=wdSectionBreakNextPage
ActiveDocument.GoTo(What:=wdGoToPage, Count:=2).Select
Dim fso As Scripting.FileSystemObject
Dim file As Scripting.file
getfolders foldername
End sub
Sub getfolders(foldername)
Set fso = New Scripting.FileSystemObject
Call pastedoc(foldername)
Set fso = Nothing
End Sub
Sub pastedoc(StartFolderPath as String)
Dim file As Scripting.file
Dim subfol As Scripting.folder
Dim mainfolder As Scripting.folder
Set mainfolder = fso.GetFolder(StartFolderPath )
For Each file In mainfolder.Files
If ((InStr(1, LCase(fso.GetExtensionName(file.Path)), "doc", vbTextCompare) > 0) Or _
(InStr(1, LCase(fso.GetExtensionName(file.Path)), "docx", vbTextCompare) > 0)) And _
(InStr(1, file.Name, "~$") = 0) Then
Selection.InsertFile FileName:= _
file.Path _
, Range:="", ConfirmConversions:=False, Link:=False, Attachment:=False
Selection.InsertBreak Type:=wdSectionBreakNextPage
End If
Next file
For Each subfol In mainfolder.SubFolders
pastedoc subfol.Path
Next subfol
End Sub
A difference between my code and the tutorial's is that I define the parent folder in the main code and the tutorial does it in the sub script. As a result I get an
'object required'
error in the 'set mainfolder' line. I tried defining all objects and names between the main code and calling the subs but I still can't get it to work. Any guidance what could fix the code?
One option: assuming the End Sub for CombineDocs was after the getfolders call, you can:
Remove getfolders entirely
In CombineDocs, say pastedoc foldername instead of getfolders foldername
Change the beginning of pastedoc to:
Sub pastedoc(StartFolderPath as String)
Dim fso As Scripting.FileSystemObject ' ** Added
Set fso = New Scripting.FileSystemObject ' ** Added
Dim file As Scripting.file
Dim subfol As Scripting.folder
Dim mainfolder As Scripting.folder
Set mainfolder = fso.GetFolder(StartFolderPath )
' ... (everything else the same)
In general, you need to Dim variables either in the Sub where they are used, or at the top of your module, outside any subs. Please put the Dims inside the Subs whenever you can, since that makes your code much easier to change and maintain.
I have a folder "test" containing several dbf files. I would like vba to open them in excel file and save them (in excel format) in another folder keeping the same dbf file names.
I found this code on the net and am trying to use this code for my needs but it won't work. Error message:
"sub of function not defined"
...please look into it.
Sub test()
Dim YourDirectory As String
Dim YourFileType As String
Dim LoadDirFileList As Variant
Dim ActiveFile As String
Dim FileCounter As Integer
Dim NewWb As Workbook
YourDirectory = "c:\Users\navin\Desktop\test\"
YourFileType = "dbf"
LoadDirFileList = GetFileList(YourDirectory)
If IsArray(LoadDirFileList) = False Then
MsgBox "No files found"
Exit Sub
Else
' Loop around each file in your directory
For FileCounter = LBound(LoadDirFileList) To UBound(LoadDirFileList)
ActiveFile = LoadDirFileList(FileCounter)
Debug.Print ActiveFile
If Right(ActiveFile, 3) = YourFileType Then
Set NewWb = Application.Workbooks.Open(YourDirectory & ActiveFile)
Call YourMacro(NewWb)
NewWb.SaveAs YourDirectory & Left(ActiveFile, Len(ActiveFile) - 4) & ".xlsx"
NewWb.Saved = True
NewWb.Close
Set NewWb = Nothing
End If
Next FileCounter
End If
End Sub
You missing the functions GetFileList and YourMacro. A quick search brought me to this website (I think you copied it from there). http://www.ozgrid.com/forum/printthread.php?t=56393
There are the missing functions. Copy those two also in your modul to make it run (I tested it with pdf-Files):
Function GetFileList(FileSpec As String) As Variant
' Author : Carl Mackinder (From JWalk)
' Last Update : 25/05/06
' Returns an array of filenames that match FileSpec
' If no matching files are found, it returns False
Dim FileArray() As Variant
Dim FileCount As Integer
Dim FileName As String
On Error GoTo NoFilesFound
FileCount = 0
FileName = Dir(FileSpec)
If FileName = "" Then GoTo NoFilesFound
' Loop until no more matching files are found
Do While FileName <> ""
FileCount = FileCount + 1
ReDim Preserve FileArray(1 To FileCount)
FileArray(FileCount) = FileName
FileName = Dir()
Loop
GetFileList = FileArray
Exit Function
NoFilesFound:
GetFileList = False
End Function
Sub YourMacro(Wb As Workbook)
Dim ws As Worksheet
Set ws = Wb.Worksheets(1)
ws.Range("A6").Value = "=((+A2*$CN2)+(A3*$CN3)+(A4*$CN4)+(A5*$CN5))/SUM($CN2:$CN5)"
ws.Range("A6").Copy ws.Range("B6:CM6")
ws.Range("CO6").Value = "=CO2"
End Sub
To save files in a different directory:
Dim SaveDirectory As String
SaveDirectory = "c:\Users\navin\Desktop\test\converted to excel"
Replace this line
NewWb.SaveAs YourDirectory & Left(ActiveFile, Len(ActiveFile) - 4) & ".xlsx"
with this
NewWb.SaveAs SaveDirectory & Left(ActiveFile, Len(ActiveFile) - 4) & ".xlsx"
This Excel VBA code creates hyperlinks to a list of items in Column A, to corresponding folder names from a FIXED location. For example:
Room101 is hyperlinked to C:\Files\Pictures\Room101
Room102 is hyperlinked to C:\Files\Pictures\Room102
Room103 is hyperlinked to C:\Files\Pictures\Room103
I have been trying to redesign the folder destination to be more dynamic, specifically the search folder should be the Excel file's current folder. Please see the code below on line 7:
Option Explicit
Dim lngRow
Public Sub Aufruf()
Dim lngTMP As Long
lngTMP = ActiveSheet.Cells(Cells(Rows.Count, "A").End(xlUp).Row, 1).Row
For lngRow = 1 To lngTMP
searchDir "M:\Pictures" 'fixed folder location
Next lngRow
End Sub
Private Sub searchDir(strDir)
Dim objSubDir As Object
Dim strName As String
Dim objFSO As Object
Dim objDir As Object
On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objDir = objFSO.getfolder(strDir)
For Each objSubDir In objDir.subfolders
strName = StrReverse(Split(StrReverse(objSubDir.Path), "\")(0))
If strName = Cells(lngRow, 1).Text Then
ActiveSheet.Hyperlinks.Add Anchor:=Cells(lngRow, 1), Address:= _
objSubDir.Path & "\", TextToDisplay:=Cells(lngRow, 1).Text
Exit Sub
End If
searchDir objSubDir
Next
Set objFSO = Nothing
Set objDir = Nothing
End Sub
You will notice that the file path is fixed to "M:\Pictures".
How do I search the folder the Excel document is saved in? I have attempted to use variations of:
path = ActiveWorkbook.Path
I am trying to do the following:
find folder based on the path given by a cell value
determine whether it's subfolders are empty
if the subfolders are all empty - put "subfolders empty" in a cell
if there are some files within any of the subfolders
put "contains files in a cell"
My code runs but it is skipping over the subfolders sub procedure.
Sub search_subfolders()
Application.ScreenUpdating = False
On Error Resume Next
With Workbooks("Folder_creator.xlsm").Sheets("Sheet1")
Dim Rng As Range
Dim Pth As String
Dim Model As String
Dim x As String
Set Rng = .Range("a2:a527")
Pth = .Range("b2").Value
For r = 2 To 527
Model = .Cells(r, 1).Text
ModelPth = Pth & Model & "\"
Set FSO = CreateObject("Scripting.FileSystemObject")
ShowSubFolders FSO.ModelPth
.Cells(r, 4).Value = x
Next r
End With
Application.ScreenUpdating = True
End Sub
Sub ShowSubFolders(ModelPth)
For Each Subfolder In ModelPath.SubFolders
If Subfolder.Size = 0 Then
x = "Subfolders empty"
Else
x = "Contains files"
End If
ShowSubFolders Subfolder
Next
End Sub
I think this is something to do with trying to pass variables to it without the correct syntax.
Ok, there are a number of problems with your code. Please see the code below for something that should work. I tried to explain changes with comments. Feel free to comment on this post if you need me to elaborate. Good luck, hope this helps.
Also, I wasn't sure if you wanted to check your ModelPth folder or subfolders in your ModelPth folder, so I made subroutines for both. I also took the liberty of implementing some small scale error handling.
'x needs to be declared here if it is to be accessed by multiple subroutines
Private x As String
Sub search_subfolders()
Application.ScreenUpdating = False
'Removed "On Error Resume next" .... this should only be used very sparingly
'Slightly better is to only use on a short section followed by "On Error Goto 0"
'or use "On Error Goto xyz" where "xyz" is a label
Dim sheet As Worksheet
'Perhaps you do want to refer to a workbook other than the one calling this macro
'but my guess is that this is intended to run within the workbook calling in
'in which case, it's much better to use "Activeworkbook" than to rely on a name that may change
'You may want to also reconsider your use of "Sheet1", you can use Sheets(1) which has it's own problems, or use "ActiveSheet",
'or just use "Range("B2")" which, is the same as ActiveWorkbook.ActiveSheet.Range("B2")
Set sheet = ActiveWorkbook.Sheets("Sheet1")
'If code is housed under a sheet module instead of in a standard module,
'your best option is to use "Set sheet = Me" and workbook shouldn't need to be specified.
'If you do ever want to specify calling workbook, you can use "ThisWorkbook"
Dim Rng As Range
Set Rng = sheet.Range("A2:A527")
Dim Pth As String
Pth = sheet.Range("b2").Value
Dim Model As String
'It's really best to avoid using "with" statements... just declare a variable and run with that
'In this case just make a sheet variable
For r = 2 To 527
Model = sheet.Cells(r, 1).Text
ModelPth = Pth & Model & "\"
'Are you sure ModelPth is in the correct syntax?
'That is, youmay want (Pth & "\" & Model & "\") instead.
CheckSubFolderContent ModelPth
sheet.Cells(r, 4).Value = x
CheckFolderContent ModelPth
sheet.Cells(r, 5).Value = x
Next r
End Sub
Sub CheckSubFolderContent(ModelPth)
'Checks for content in subfolders in a folder specified by path
x = "No Subfolders found"
'Error handling for Model = ""
If Right(ModelPth, 2) = "\\" Then
x = "N/A"
Exit Sub
End If
Dim FSO, Parent As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set Parent = FSO.GetFolder(ModelPth)
If Err > 0 Then
x = "Error! Parent folder does not exist."
Exit Sub
End If
For Each Subfolder In Parent.SubFolders
If Subfolder.Size = 0 Then
x = "Folder has subfolders without content"
Else
x = "Folder has subfolders with content"
End If
'Why this recursive line? "ShowSubFolders Subfolder"
'Recursive calls should be avoided and are rarely necesary.
Next
If Err > 0 Then x = "Error!"
On Error GoTo 0
End Sub
Sub CheckFolderContent(ModelPth)
'Checks for content in a folder specified by path
x = "No Subfolders found"
If Right(ModelPth, 2) = "\\" Then
x = "N/A"
Exit Sub
End If
Dim FSO, Folder As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set Folder = FSO.GetFolder(ModelPth)
If Err > 0 Then
x = "Error! Parent folder does not exist."
Exit Sub
End If
If Folder.Size = 0 Then
x = "Folder is empty"
Else
x = "Folder has content"
End If
If Err > 0 Then x = "Error!"
On Error GoTo 0
End Sub
Couple of things you are doing wrong.
1. You are trying to access sub-folders without making FSO(FileSystemObject) accessible in ShowSubFolders sub.
2. x is not global variable and yet you are trying to access it.
3. Less conditions in ShowSubFolders sub.
Here is the updated code.
Dim FSO As Object '<-- This one sets FSO global
Dim x As String '<-- This one sets x global
Sub search_subfolders()
Application.ScreenUpdating = False
On Error Resume Next
Workbooks("Folder_creator.xlsm").Sheets("Sheet1")
Dim Rng As Range
Dim Pth As String
Dim Model As String
Set Rng = .Range("a2:a527")
Pth = .Range("b2").Value
For r = 2 To 527
Model = .Cells(r, 1).Text
ModelPth = Pth & Model & "\"
Set FSO = CreateObject("Scripting.FileSystemObject")
ShowSubFolders FSO.GetFolder(ModelPth)
.Cells(r, 4).Value = x
x = ""
Next r
End With
Application.ScreenUpdating = True
End Sub
Sub ShowSubFolders(Folder)
Dim SubFolder
If Folder.SubFolders.Count > 0 Then
For Each SubFolder In Folder.SubFolders
ShowSubFolders SubFolder
If SubFolder.Size = 0 Then
x = "Subfolders empty"
Else
x = "Contains files"
End If
Next
Else
x = "Subfolders empty"
End If
End Sub