VBA: Code for creating subfolders and folders not working - vba

I got this code from an online source and cant figure out what I have to change, for it to work, the folders are not being created in the desired location and I am unaware of where they are be created if any where?
Within the excel I have 3 command buttons, one to save the file to a specified location, one to email it to a collegue and lastly the command button which I am having issue with. Ill include images below.
And is it possible to cause a chain reaction between the codes, that once one is completed then the other will begin, as I can get them to work as they are on there own atm.
enter image description here

Mkdir can only create a single directory. You are trying to make two by supplying "9999 William Cox ltd\BRAKEL".
Make "9999 William Cox ltd" first, then make its child directories.
Here is some code that will generate all of the sub directories via a loop:
Add these functions to your code module:
Private Function makeDir(parentDir As String, childDir As String) As String
'Checks if supplied directory name exists in current path, if not then create.
childDir = parentDir & _
IIf(Left(childDir, 1) = "\", "", "\") & _
childDir & _
IIf(Right(childDir, 1) = "\", "", "\")
On Error Resume Next
MkDir childDir
On Error GoTo 0
makeDir = childDir
End Function
Public Sub makePath(parentDir As String, childPath As String)
Dim i As Integer
Dim subDirs As Variant
Dim newdir As String
Dim fPath As String
fPath = parentDir
subDirs = Split(childPath, "\")
For i = 0 To UBound(subDirs)
newdir = subDirs(i)
fPath = makeDir(fPath, newdir)
Next i
End Sub
Then replace this:
MkDir ("T:\Estimating\William Cox Project Enquiries 2018\" & fPath)
If Err.Number <> 0 Then
Err.Clear
End If
With this:
makePath "T:\Estimating\William Cox Project Enquiries 2018\", fpath
You should also remove On Error Resume Next so that you can catch any other errors - Another of which might be in your path (per the screenshot) which has "T:\Estimating" twice at the beginning.

Related

Programmatically copy a folder (in a way that mimics a user copy/paste) and update a Progress Bar during the copy?

I would like to simulate a folder copy exactly how it would happen if a user copy/pasted it in Windows Explorer (keep all the file/directory attributes, copy all subfolders and files in the same structure, etc.), and be able to update a progress bar during the copy.
FileSystem.Copy is a wonderful function that would mimic a user copy/paste, but I am unable to update a progress bar during the copy using that function.
The only way I have found to be able to achieve this is to write a custom function, so the ProgressBar.Maximum can be set to the size of the Folder and the ProgressBar.Value is updated after each individual file copy.
This function is becoming a lot of code to achieve something that seems simple. I also cannot disregard the notion that since this is customized that I am doing something wrong that I just don't know to test for. For example, had the folder I was testing with not had empty subfolders and hidden folders, I never would have adjusted for those things.
So I have to wonder if I am overlooking something much simpler to achieve this same goal.
My code is as follows:
Private Sub CopyFolderWithProgress(folderToCopy As String, newFolder As String, progBar As ProgressBar)
'Validate folder to copy
If Directory.Exists(folderToCopy) Then
If folderToCopy.Substring(folderToCopy.Length - 1) <> "\" Then
folderToCopy &= "\"
End If
Else
MsgBox("Invalid directory given: " & folderToCopy)
End
End If
'Validate new folder
If Directory.Exists(newFolder) Then
If newFolder.Substring(newFolder.Length - 1) <> "\" Then
newFolder &= "\"
End If
Else
MsgBox("Invalid directory given: " & newFolder)
End
End If
'Create folderToCopy as a new subfolder of newFolder
newFolder &= New DirectoryInfo(folderToCopy).Name & "\"
Dim di As DirectoryInfo
di = Directory.CreateDirectory(newFolder)
di.Attributes = New DirectoryInfo(folderToCopy).Attributes
'Create all subfolders
For Each thisDir In Directory.GetDirectories(folderToCopy, "*", SearchOption.AllDirectories)
Dim thisDirRelative = thisDir.Remove(0, Len(folderToCopy))
di = Directory.CreateDirectory(newFolder & thisDirRelative)
di.Attributes = New DirectoryInfo(thisDir).Attributes
Next
'Determine size of all files for progress bar
Dim dirSize As Long
For Each curFile In Directory.GetFiles(folderToCopy, "*", SearchOption.AllDirectories)
dirSize += FileLen(curFile)
Next
'Set progress bar 100% to size of all files
progBar.Value = 0
progBar.Maximum = dirSize
'Copy all files into correct folder and update progress bar
For Each curFile In Directory.GetFiles(folderToCopy, "*", SearchOption.AllDirectories)
'Get name of file
Dim curFileName = Path.GetFileName(curFile)
'Determine if file is in a subfolder of fileTopCopy
Dim curFileDir = Path.GetDirectoryName(curFile) + "\"
Dim curFileSubfolders = curFile.Substring(0, curFile.IndexOf(curFileName)).Replace(folderToCopy, "")
'Copy file
If File.Exists(curFile) Then
File.Copy(curFile, newFolder & curFileSubfolders & curFileName)
Else
Console.Write("Issue copying a file that should exist in source folder: " & curFile)
End If
'Update Progress Bar
progBar.Value += FileLen(curFile)
Next
End Sub

VBA macro doesn't count/name files in a directory properly

I’ve made a simply macro to change names of files in a directory. At first it seemed correct, but then I’ve noticed something strange. For instance there is 48 files in a directory and initially the macro numbers files properly – “1”, “2”, “3” and so forth (in Immediate window the variable “i” changes from 1 to 49), but if I run the macro several times, sometimes the variable “i” changes from 1 to 148 and a first number of files starts from 100: “100”, “101”, “102” et cetera. Then I run the macro again and it counts files properly, then – again – an error mentioned above occurs … and so on. I don’t see any rule in it. Any help is greatly appreciated.
Sub nameChange()
Dim source As FileSystemObject
Dim fold As folder
Dim fObj As File
Dim path As String, newName As String, number As String, ext As String
Dim i As Long
On Error GoTo closeSub
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
path = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1)
End With
Set source = New FileSystemObject
Set fold = source.GetFolder(path)
i = 1
newName = InputBox("New name")
For Each fObj In fold.Files
ext = Mid(fObj.Name, (InStrRev(fObj.Name, ".")))
Name fObj As path & "\" & newName & i & ext
i = i + 1
Next fObj
closeSub:
Exit Sub
End Sub

VBA script to Unzip Files - It's Just Creating Empty Folders

I'm using the code by Ron (http://www.rondebruin.nl/win/s7/win002.htm) to, in theory, unzip a bunch of zip files in a folder. I believe what I have below is the code that takes each zip file in my 'Downloads' directory, creates a new folder with the name of the zip file without the ".zip", and then extracts the files into the new folder. I am not getting any errors (many times people get the runtime error 91) but the only thing that happens is that it creates a bunch of correctly named folders but they are all empty.
Sub UnZipMe()
Dim str_FILENAME As String, str_DIRECTORY As String, str_DESTINATION As String
'Your directory where zip file is kept
str_DIRECTORY = "C:\Users\Jennifer\Downloads\"
'Loop through all zip files in a given directory
str_FILENAME = Dir(str_DIRECTORY & "*.zip")
Do While Len(str_FILENAME) > 0
Call Unzip1(str_DIRECTORY & str_FILENAME)
Debug.Print str_FILENAME
str_FILENAME = Dir
Loop
End Sub
Sub Unzip1(str_FILENAME As String)
Dim oApp As Object
Dim Fname As Variant
Dim FnameTrunc As Variant
Dim FnameLength As Long
Fname = str_FILENAME
FnameLength = Len(Fname)
FnameTrunc = Left(Fname, FnameLength - 4) & "\"
If Fname = False Then
'Do nothing
Else
'Make the new folder in root folder
MkDir FnameTrunc
'Extract the files into the newly created folder
Set oApp = CreateObject("Shell.Application")
oApp.Namespace(FnameTrunc).CopyHere oApp.Namespace(Fname).items
End If
End Sub
The problem is you are not giving windows enough time to extract the zip file. Add DoEvents after the line as shown below.
TRIED AND TESTED
oApp.Namespace(FnameTrunc).CopyHere oApp.Namespace(Fname).items
DoEvents

Read item titles from SharePoint Document Library into Array using Excel VBA

I need to read all the item titles for all the documents in a SharePoint document library directly into an Array using Excel VBA. I can't seem to successfully use FileSystemObject and I do not want to map the document library to a drive letter as the macro will be distributed and widely used.
The SharePoint site has an https address
I have looked at this thread about referencing scrrun.dll but it does not work because I cannot change the trust settings on my local domain
This thread looked promising, but again it seems to use FileSystemObject which might be my hang up.
This thread on the SharePoint stackexchange site works well for reading in a list of files as a worksheet object, but I don't know how it could be adapted to be pushed directly into an array.
I tend to receive Error 76 "Bad Path", but I am easily able to execute on local (C:) files.
I have tried using a WebDAV address - like the answer I gave to this thread - but it too encounters a "Bad Path" error.
There must be a way to read in the contents of a SharePoint document library directly into an array that does not violate my local security policies and doesn't depend upon an excel worksheet.
Ok I am going to self answer. I'm not 100% thrilled with my solution, but it does suffice within my constraints. Here are the high level points:
Use VBA to create BAT files that have the "Net Use" command within them.
Reference the WebDAV address of the document library and find an available drive letter
I doubt that any of my users already have 26 mapped drives...).
Once the document library is mapped it can be iterated through using FileSystemObject commands and the item titles can be loaded into a two dimensional array.
The code will have to be modified to allow for 3 the listing of subfolders
The location of the file count in the ListMyFiles sub would have to be changed or another dimension would have to be added to the array.
Here is the code - I will try to credit all Stack solutions that were integrated into this answer:
Private Sub List_Files()
Const MY_FILENAME = "C:\BAT.BAT"
Const MY_FILENAME2 = "C:\DELETE.BAT"
Dim i As Integer
Dim FileNumber As Integer
Dim FileNumber2 As Integer
Dim retVal As Variant
Dim DriveLetter As String
Dim TitleArray()
FileNumber = FreeFile
'create batch file
For i = Asc("Z") To Asc("A") Step -1
DriveLetter = Chr(i)
If Not oFSO.DriveExists(DriveLetter) Then
Open MY_FILENAME For Output As #FileNumber
'Use CHR(34) to add escape quotes to the command prompt line
Print #FileNumber, "net use " & DriveLetter & ": " & Chr(34) & "\\sharepoint.site.com#SSL\DavWWWRoot\cybertron\HR\test\the_lab\Shared Documents" & Chr(34) & " > H:\Log.txt"
Close #FileNumber
Exit For
End If
Next i
'run batch file
retVal = Shell(MY_FILENAME, vbNormalFocus)
' NOTE THE BATCH FILE WILL RUN, BUT THE CODE WILL CONTINUE TO RUN.
'This area can be used to evaluate return values from the bat file
If retVal = 0 Then
MsgBox "An Error Occured"
Close #FileNumber
End
End If
'This calls a function that will return the array of item titles and other metadata
ListMyFiles DriveLetter & ":\", False, TitleArray()
'Create code here to work with the data contained in TitleArray()
'Now remove the network drive and delete the bat files
FileNumber2 = FreeFile
Open MY_FILENAME2 For Output As #FileNumber2
Print #FileNumber2, "net use " & DriveLetter & ": /delete > H:\Log2.txt"
Close #FileNumber2
retVal = Shell(MY_FILENAME2, vbNormalFocus)
'Delete batch file
Kill MY_FILENAME
Kill MY_FILENAME2
End Sub
Here is the function that will read through the directory and return the array of file information:
Sub ListMyFiles(mySourcePath As String, IncludeSubFolders As Boolean, TitleArray())
Dim MyObject As Object
Dim mySource As Object
Dim myFile As File
Dim mySubFolder As folder
Dim FileCount As Integer
Dim CurrentFile As Integer
'Dim TitleArray()
Dim PropertyCount As Integer
CurrentFile = 0
Set MyObject = New Scripting.FileSystemObject
Set mySource = MyObject.GetFolder(mySourcePath)
FileCount = mySource.Files.Count
ReDim TitleArray(0 To FileCount - 1, 4)
'On Error Resume Next
For Each myFile In mySource.Files
PropertyCount = 1
TitleArray(CurrentFile, PropertyCount) = myFile.Path
PropertyCount = PropertyCount + 1
TitleArray(CurrentFile, PropertyCount) = myFile.Name
PropertyCount = PropertyCount + 1
TitleArray(CurrentFile, PropertyCount) = myFile.Size
PropertyCount = PropertyCount + 1
TitleArray(CurrentFile, PropertyCount) = myFile.DateLastModified
CurrentFile = CurrentFile + 1
Next
'The current status of this code does not support subfolders.
'An additional dimension or a different counting method would have to be used
If IncludeSubFolders = True Then
For Each mySubFolder In mySource.SubFolders
Call ListMyFiles(mySubFolder.Path, True, TitleArray())
Next
End If
End Sub
Thank you to Chris Hayes for his answer to find empty network drives; thank you to Kenneth Hobson on ozgrid for his expanded answer on listing files in a directory. The rest of the code is ancient and I dredged it out of a folder I last touched in 2010.

Select values from a range to the right of a given cell and iteratively create a subfolder from them

Hope you are well.
I'm trying to create a mass folder creator using Excel and vba. It's my first time using VBA as I usually focus on web-based languages so forgive me for my lack of knowledge in advance. I have some code already it's just putting the finishing touches that I'm struggling with.
Currently, the user specifies a directory in a given cell and name of the parent file in another cell. Upon clicking a button, the macro creates the parent folder using the directory and name from the parent file cell. It then creates sub folders using the values of any cells the respondent has selected upon running the macro.
I am currently struggling with the next stage of the project which is creating sub-folders (I'll just call them Grandchildren) within the subfolders. This would be easy if all of the subfolders had the same Grandchildren however, this is not the case. What I would like to do is grab the 3 values to the right of each cell which defines the name of the subfolder and use them to create the Grandchildren however I'm currently getting the 'Invalid Qualifier' message with the code I am currently using (see below).
BasePath = Range("folder_path")
'Check if the project folder already exists and if so raise and error and exit
If Dir(BasePath, vbDirectory) <> "" Then
MsgBox BasePath & " already exists", , "Error"
Else
'Create the project folder
MkDir BasePath
MsgBox "Parent folder creation complete"
'Loop through the 1st tier subfolders and create them
For Each c In ActiveWindow.RangeSelection.Cells
'create new folder path
NewFolder = BasePath & "\" & c.Value
'create folder
If fs.folderexists(NewFolder) Then
'do nothing
Else
MkDir NewFolder
End If
Next c
'Create GrandChildren
For Each d In ActiveWindow.RangeSelection.Cells
'Offset the selection to the right
For Each e In d.Offset(0, 1).Resize(1, 3).Cells
Test = e.Value
GrandChild = BasePath & "\" & d.Value & "\" & Test
If fs.folderexists(GrandChild) Then
'do nothing
Else
MkDir GrandChild
End If
Next e
Next d
MsgBox "Sub-folder creation complete"
End If
End Sub
If you require any further information please let me know.
Cheers,
Jason
I think your problem is here
Test = d.Offset(0, 1).Select
Test is a String and you are selecting a cell. You should try this:
Test = d.Offset(0,1).Value
You may find this useful, it's a simple routine I use to make ALL the folders in an entire path fed into the function.
EXAMPLE:
C:\2011\Test\
C:\2012\Test
C:\2013\Test\DeepTest\
C:\2014\Test\DeeperTest\DeeperStill
Based on the list above, this macro will attempt to create 11 directories, ones that exist already...no problem.
Option Explicit
Sub MakeDirectories()
'Author: Jerry Beaucaire, 7/11/2010
'Summary: Create directories and subdirectories based
' on the text strings listed in column A
' Parses parent directories too, no need to list separately
' 10/19/2010 - International compliant
Dim Paths As Range
Dim Path As Range
Dim MyArr As Variant
Dim pNum As Long
Dim pBuf As String
Dim Delim As String
Set Paths = Range("A:A").SpecialCells(xlConstants)
Delim = Application.PathSeparator
On Error Resume Next
For Each Path In Paths
MyArr = Split(Path, Delim)
pBuf = MyArr(LBound(MyArr)) & Delim
For pNum = LBound(MyArr) + 1 To UBound(MyArr)
pBuf = pBuf & MyArr(pNum) & Delim
MkDir pBuf
Next pNum
pBuf = ""
Next Path
Set Paths = Nothing
End Sub
There is a UDF version too and a sample file for testing found here. FYI.