I have several files that need to be distributed into respective folders. How can I check to see if a folder exists with a dynamic name using an excel VBA macro?
I split a single workbook into several by the various worksheets within it. I believe it would be easiest if the macro used the name of each sheet in the original workbook to check for the existence of that folder. That way it's dynamic and I don't have to worry about coding it to search for each folder, as the data source continues to grow and need additional worksheets. I already have a code for searching for the folder, I just need to understand how to write it so that its dynamic.
Dim Path As String
Dim Folder As String
Dim Answer As VbMsgBoxResult
Dim NewPath As String
NewPath = ActvieWorkbook.Sheets.Name
Path = "C:\Test" & NewPath
Folder = Dir(Path, vbDirectory)
For Each sheetz0r In ActiveWorkbook.Sheets
If Folder = vbNullString Then
Answer = MsgBox("Path does not exist. Would you like to create it?", vbYesNo, "Create Path?")
Select Case Answer
Case vbYes
VBA.FileSystem.MkDir (Path)
Case Else
Exit Sub
End Select
End If
Next
In the code I have written, I just need the "NewPath =" line adjusted so that it will search for the sheet names.
Move the Path and Folder assignments inside the loop body, and replace & NewPath with & sheetz0r.Name - not sure what ActiveSheet.Sheets.Name is supposed to be, the Sheets collection class doesn't have a Name member.
I'd restructure things a bit, remove the redundant variables, and move declarations closer to their usage. I think what you mean to do is something like this?
Dim sheet As Worksheet
For Each sheet In ActiveWorkbook.Worksheets
Dim Path As String
Path = Dir("C:\Test" & sheet.Name, vbDirectory)
If Path = vbNullString Then
If MsgBox("Path does not exist. Would you like to create it?", vbYesNo, "Create Path?") = vbYes Then
VBA.FileSystem.MkDir Path
Else
Exit For
End If
End If
Next
That said, verifying whether a folder exists, and creating a new one, is much simpler/cleaner using a FileSystemObject from the Scripting library - I would also abstract away the prompting part into its own function:
With New Scripting.FileSystemObject
Dim sheet As Worksheet
For Each sheet In ActiveWorkbook.Worksheets
Dim Path As String
Path = "C:\Test\" & sheet.Name
If Not .FolderExists(Path) Then
If ConfirmCreateFolder(Path) Then
.CreateFolder Path
Else
Exit For
End If
End If
Next
End With
Private Function ConfirmCreateFolder(ByVal Path As String) As Boolean
Dim prompt As String
prompt = "Folder '" & Path & "' does not exist. Would you like to create it?"
ConfirmCreateFolder = (MsgBox(prompt, vbYesNo, "Create Folder?") = vbYes)
End Function
Try this
Sub CheckFolder()
Dim Path As String
Dim Folder As String
Dim Answer As VbMsgBoxResult
Dim NewPath As String
Dim scripObj As New Scripting.FileSystemObject
Path = "C:\Test\"
For Each sheetz0r In ActiveWorkbook.Sheets
If Not scripObj.FolderExists(Path & sheetz0r.Name) Then
Answer = MsgBox("Path does not exist. Would you like to create it?", vbYesNo, "Create Path?")
Select Case Answer
Case vbYes
scripObj.CreateFolder (Path & sheetz0r.Name)
Case Else
Exit Sub
End Select
End If
Next
End Sub
Related
i am trying to access variables across several modules, sheets and workbooks.
i'm not even able to share them across modules in same workbook...
i wonder what's missing. In this case, i want to open a file and then share its name across modules in order to manipulate it through other functions.
When running this procedure "Sub get_workbook_and_sheets_names_S", it asks to run a macro (I chose Sub myMain), but then I only got the macro output.
Sub myMain()
Dim i As Integer
Static v_sheet_name_S As Variant
Static v_workbook_name_S As Variant
'Call f_FSOGetFileName_S
With Application.Workbooks(f_FSOGetFileName_S)
v_workbook_name_S = .Name
Debug.Print "this is WORKBOOK : " & v_workbook_name_S
For i = 1 To .Sheets.Count
v_sheet_name_S = .Sheets(i).Name
Debug.Print "this is workbook SHEET : " & v_sheet_name_S
Next
End With
'Call f_FSOGetFileName_T
End Sub
Function f_FSOGetFileName_S() 'OPEN SOURCE FILE
Dim v_strFile_S As String
Dim v_FileName_S As String
Dim v_FSO_S As New FileSystemObject
Dim v_FileNameWOExt_S As Variant
Set v_FSO_S = CreateObject("Scripting.FileSystemObject")
'get file full path
v_strFile_S = Application.GetOpenFilename(filefilter:="Excel files,*.x*", Title:="select SOURCE file")
Workbooks.Open Filename:=v_strFile_S
'Get File Name
v_FileName_S = v_FSO_S.GetFileName(v_strFile_S)
'Get File Name no Extension
v_FileNameWOExt_S = Left(v_FileName_S, InStr(v_FileName_S, ".") - 1)
f_FSOGetFileName_S = v_FileName_S 'FUNCTION RESULT
End Function
Sub get_workbook_and_sheets_names_S(v_workbook_name_S, v_sheet_name_S)
Debug.Print "Source workbook name : " & v_workbook_name_S
Debug.Print "Source sheet name : " & v_sheet_name_S
End Sub
In order to create a Global variable, please proceed in the next way:
Create a Public variable on top of a standard module (in the declarations area):
Public v_workbook_name_S As String
This variable can be accessed/used from all modules of the workbook where it has been declared. You should simple use:
Debug.print v_workbook_name_S
Of course, the variable must previously receive a value...
In order to be accessible from other workbooks, you should also create a function (**not Private) in the workbook where the global variable has been declared. In a standard module, too:
Sub setGobVarStr()
v_workbook_name_S = "myString"
End Sub
The global variable value can be accessed colling the above function, using:
Sub testReadGlobalVar()
Dim wbName As String, myName As String
wbName = "Teste Forum StackOverflow Last.xlsm"
myName = Application.Run("'" & wbName & "'!getWbName")
Debug.Print myName
End Sub
Of course, the global variable should previously received a value. If not, the code will return a VBNullString, anyhow...
Note:
You must not declare the same variable inside the colling Sub/Function! In such a case, the code will not raise any error, but it will rewrite the global variable and return a VBnullString, too...
I am writing a VBA code to pull the file at the source folder and move to my folder to analyze it in order not to corrupt the original file. But, i am facing difficulties to write a code that replace the older file if detect the name is the same.
Private Sub CommandButton1_Click()
Dim FSO
Dim sFile As String
Dim sSFolder As String
Dim sDFolder As String
Dim datasource As Workbook
Dim target As Worksheet
Dim strName As String
Dim lastrow As Long
Dim userinput As String
userinput = InputBox(Prompt:="Please key in the file name and format", Title:=" File name", Default:=".xlsm") 'This is Your File Name which you want to Copy
sSFolder = "J:\Inter Dept\MP8 Packaging\2.0 MP8.1\B2-Machine Data Tracking\B2-Machine Data Tracking 2019\" 'Change to match the source folder path
sDFolder = "C:\Users\limmigmy\Desktop\Rejection Report\Rejection\Packing Analysis\Production Files\" 'Change to match the destination folder path
Set FSO = CreateObject("Scripting.FileSystemObject") 'Create Object
If Not FSO.FileExists(sSFolder & userinput) Then 'Checking If File Is Located in the Source Folder
MsgBox "Specified File Not Found", vbInformation, "Not Found"
ElseIf Not FSO.FileExists(sDFolder & userinput) Then 'Copying If the Same File is Not Located in the Destination Folder
FSO.CopyFile (sSFolder & sFile), sDFolder, True
MsgBox "Specified File Copied Successfully", vbInformation, "Done!"
**Else
MsgBox "Specified File Already Exists In The Destination Folder",** vbExclamation, "File Already Exists"
End If
I think i know what you mean, its just the "But, i am facing difficulties to write a code that replace the older file if detect the name is the same." is abit confusing.
Check out this see if it helps, by all means you can chop and change it.
It goes about it in a slightly different way but it works as expected.
Sub CopyFileIfOlder()
'declare your variables
Dim strFilePathOne As String, FileDateOne As Date, FileOneLoc As String
Dim strFilePathTwo As String, FileDateTwo As Date, FileTwoLoc As String
'set your file paths to the two different files
strFilePathOne = "C:\VBNET Test Area\StackOverFlow\File1.txt"
strFilePathTwo = "C:\VBNET Test Area\File1.txt"
'declare and set your objects
Dim oFSO As Object
Set oFSO = CreateObject("Scripting.FileSystemObject")
Dim oFile1 As Object
Set oFile1 = oFSO.GetFile(strFilePathOne)
Dim oFile2 As Object
Set oFile2 = oFSO.GetFile(strFilePathTwo)
'grabs your files modified dates : grabs your files dir location not inc filename
FileDateOne = oFile1.DateLastModified: FileOneLoc = oFile1.Path
FileDateTwo = oFile2.DateLastModified: FileTwoLoc = oFile2.Path
'sets an error handler incase anything goes wrong copying
On Error GoTo FileDeleteAndCopyError
'tests to see if file1 is older
If FileDateOne < FileDateTwo Then
'file one is older
Kill strFilePathOne 'deletes file1
FileCopy strFilePathTwo, FileOneLoc 'copies the newer version into older files place
Else
'file two is newer
Debug.Print "FILE ONE IS NEWER THAN FILE TWO SO I WONT DO ANYTHING" 'PRINTS A MESSAGE SAYING NO COPY HAS BEEN DONE
End If
'RETURNS ERROR HANDLER TO NORMAL
On Error GoTo 0
'EXITS SUB BECAUSE IF NOT THE ERROR HANDLER WILL FIRE
Exit Sub
'ERROR HANDLER INCASE FILE COPY GOES WRONG
FileDeleteAndCopyError:
MsgBox "There has been an error!", vbCritical
End Sub
I have a activex button trying to get it to check folder for a specific set of .txt files. I would like to compare all files names against a list of files names to see what is not listed inside the folder. Also within this check for files module is a publicvariable call to list the folder path (that the user picked with folderpicker) but haven't got it to work. This same publicvariable should be in the next line down in the Msgbox listing the folder path that was selected. I can place a list of files anywhere in the workbook. Currently, I have working a check file module that returns a message whether or not file exist.
I was just able to get my public variable to work. This is not what i do so learning by reading and learning how to asks questions. By moving lines /words around I have been able to get a few things working. Although, I sure it is not the most efficient way.
'Working but only checks one file at a time. and hard coded
Sub CheckFolderForFiles()
'
' CheckFolderForFiles Macro
'
'Check if file exist
If Dir$("C:\txtdata\cf_preferences.txt") = "" Then
MsgBox "C:\txtdata\cf_preferences.txt - File not found"
Exit Sub
End If
____________________________________
' Not working - Just testing public variable call for Dir$ and figure out MsgBox areas.
Sub CheckFolderForFiles()
'
' CheckFolderForFiles Macro
'
'Check if file exist
If Dir$(Module33.fle + "\alerts.txt") = "" Then
MsgBox & fle & "alerts.txt - File not found"
Exit Sub
End If
'
'
End Sub
__________________________________
'Folder Picker FileDialog user select folder.
'After some guidence by one our your users I was able to get this module work.
'Now have a public variable I wish to use throughtout the workbook to
'call the path.
Public fle As String
Sub FolderPicker()
Dim diaFolder As FileDialog
Set diaFolder = Application.FileDialog(msoFileDialogFolderPicker)
diaFolder.AllowMultiSelect = False
diaFolder.Show
fle = diaFolder.SelectedItems(1)
Range("M11") = fle
Set diaFolder = Nothing
End Sub
-------------------------------
Sub CheckFolderForFiles()
'
' CheckFolderForFiles Macro
'
'Check if file exist
'
'
If Dir$(Module33.fle + "\alerts.txt") = "" Then
MsgBox Module33.fle + "\alerts.txt - File not found"
End If
'
If Dir$(Module33.fle + "\cf_messages.txt") = "" Then
MsgBox Module33.fle + "\cf_messages.txt - File not found"
End If
End Sub
----------------------------
I'm trying to learn this to help with my wife's work project. so please be patient with my descriptions and lack of terminology. But if someone could guide me to a script that compares files within a folder that came from the publicvariable and tell me all files missing from the list. (15 files in all) this would help a bunch. Also, anyone know how or if you can clear a publicvariable of it's stored data? googling is saying just put an ( End ) in the module. not working.
Thank You in Advance. I do appreciate the guidance.
Try this. I use ArrayList to filter out nonexisting files. If you want to print out a list of non existing files, just print out the remaining element of the arraylist FileList, you could google the syntax.
Sub TestFileExist()
Dim fd As FileDialog
Dim mFiles As Variant, Item As Variant
Dim FileList As Object, mRange As Range, strFile As String
Dim FilesInFolder() As String
Dim i As Long
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
With fd
.Title = "Select a folder"
.AllowMultiSelect = False
End With
If fd.Show = -1 Then
Set FileList = CreateObject("System.Collections.ArrayList")
Set mRange = Range("A1:A5") 'Range contains files' names
ReDim FilesInFolder(0) As String
strFile = Dir(fd.SelectedItems(1) & "\*.txt")
Do While Len(strFile) > 0
FilesInFolder(UBound(FilesInFolder)) = strFile
strFile = Dir
ReDim Preserve FilesInFolder(UBound(FilesInFolder) + 1) As String
Loop
For Each Item In mRange
If Not FileList.contains(Item.Value) Then
FileList.Add Item.Value
End If
Next Item
For i = 0 To UBound(FilesInFolder) - 1
If FileList.contains(FilesInFolder(i)) Then
FileList.Remove FilesInFolder(i)
End If
Next i
MsgBox FileList.Count 'Nbr of files not found
End If
End Sub
How to import a Sheet from an external Workbook AND use the Filename (WITHOUT the .datatype at the end) as the new Worksheet name?
The part with WITHOUT the .datatype at the end I meant because I could split the filename from the file path with UBound, but when I try to do that with the filename and the filetype at the end, it doesn't work and gives me an error. Perhaps i dont understand ubound
well enough.
I found this Sub somewhere here on the forum.
But I don't want to import any sheet except the sheet which has the same name as the file itself. So I am not even sure if you need to specify the sheet name.
So I have this Excel file with VBA macros. And the Sheet is called Blank (Since I can't have an excel file without a sheet inside it) and
I have a Userform button where I browse for the file first, and the sheet there should be imported to my Excel File and delete the Blank sheet and import the new EXTERNAL sheet.
Also, it should import ANY Sheet from the file path. Because the names will always be different.
And also, how do I import the data as csv?
I am googling but I don't see what exactly causes it to be imported as csv at other peoples solutions.
Sub ImportSheet()
Dim sImportFile As String, sFile As String
Dim sThisBk As Workbook, wbBk As Workbook
Dim vfilename As Variant
Dim wsSht As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set sThisBk = ActiveWorkbook
sImportFile = Application.GetOpenFilename( _
FileFilter:="Comma Separated Value, *.csv", Title:="Open Workbook")
If sImportFile = "False" Then
MsgBox "No File Selected!"
Exit Sub
Else
vfilename = Split(sImportFile, "\")
sFile = vfilename(UBound(vfilename))
Application.Workbooks.Open Filename:=sImportFile
Set wbBk = Workbooks(sFile)
With wbBk
If SheetExists("GaebTesten.g42_2") Then
Set wsSht = .Sheets("GaebTesten.g42_2")
wsSht.Copy Before:=sThisBk.Sheets("Start")
Else
MsgBox "There is no sheet with name :US in:" & vbCr & .Name
End If
wbBk.Close SaveChanges:=False
End With
End If
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Private Function SheetExists(sWSName As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Worksheets(sWSName)
If Not ws Is Nothing Then SheetExists = True
End Function
this is my second post here on stack overflow, and my first question was very dumb, and when I asked my first question, it was my 2nd hour with vba.
I think I am at about 30 hours now and I've learned a lot.
Question: I am doing this Excel Macro in VBA with userform too now. But mostly I google how to do what and I try to implement it WHILE understanding it, I don't just copy and paste code. Often I just do line by line and test it out.
BUT... how do you guys remember all that?
If I had to program the same thing again right now, I won't know how to, because I know how a syntax works, but I wouldn't know which syntax and stuff to actually use to achieve the desired effect...
Does it come from repeating the same things = experience?
Or how do you acquire the abilities to code without googling almost every single thing? When watching youtubers live streaming how they code something, they never look it up on the internet....
Let me present you a different way than pure string manipulation:
Set a new reference to Microsoft Scripting Runtime. This will enable the Scripting namespace. With it you can do things like the following:
sImportFile = "C:\StackFolder\PrintMyName.xlsx"
With New Scripting.FileSystemObject
Debug.Print .GetBaseName(sImportFile)
' Outputs "PrintMyName"
Debug.Print .GetExtensionName(sImportFile)
' Outputs "xlsx"
Debug.Print .GetFileName(sImportFile)
' Outputs "PrintMyName.xlsx"
Debug.Print .GetDriveName(sImportFile)
' Outputs "C:"
Debug.Print .GetParentFolderName(sImportFile)
' Outputs "C:\StackFolder"
End With
You can build a little helper function to give you the part of the file name you need:
Public Function GetFilenameWithoutExtension(ByVal filename as String) as String
With New Scripting.FileSystemObject
GetFilenameWithoutExtension = .GetBaseName(filename)
End With
End Function
and call it: sFile = GetFilenameWithoutExtension(sImportFile)
Regarding the interesting use of UBound in your subroutine, you could even get the filename (without extension) that way - assuming it doesn't contain additional dots:
vfilename = Split(sImportFile, "\")
sFile = vfilename(UBound(vfilename))
SplitName = Split(sFile, ".")
FilenameWithoutExtension = SplitName(UBound(SplitName)-1)
Extension = SplitName(UBound(SplitName))
These are, however, purely academical thoughts and I wouldn't recommend doing it this way.
Here are two ways to extract the workbook name without the file extension. Here I am removing the extension .xlsx. If the extension is constant, you can just hard code it. If not, you can use wildcards also
MsgBox Left(wbBk.Name, Len(ThisWorkbook.Name) - 5)
MsgBox Replace(wbBk.Name, ".xlsx", "")
You can refer to the sheet with the same name as the workbook by using something like
Sheets(Left(wbBk.Name, Len(ThisWorkbook.Name) - 5).Copy
Sheets(Replace(wbBk.Name, ".xlsx", "").Copy
You can use InstrRev. It is efficient as starts from the end of the string which is where the extension is located.
Left$(wbBk.Name, InStrRev((wbBk.Name, ".") - 1)
My code asks the user to input a file name. We'll say we have 5 text files in directory "C:\Users\aUser\Desktop\myFolder". These text files are named A, B, C, D, and E.
If the text file exists, then I would like to write over the contents with a script I've already made. If the text file does not exist, I would like to make one with the file name they inputted, and populate it [with the script I've already written].
Thanks for your help.
The way you explain it, it seems that the easiest workflow would be:
1) Delete the file if exists
Sub test()
Dim FSO As FileSystemObject
Dim sPath As String
sPath = "U:\Test.txt"
Set FSO = New FileSystemObject
If FSO.FileExists(sPath) Then
FSO.DeleteFile (sPath)
End If
End Sub
Copy the script (I assume also a txt file) into the path:
FileCopy "U:\Script", sPath
If you have the script in a string variable:
Set txtFile = FSO.CreateTextFile(sPath, True)
txtFile.WriteLine(sText)
FSO.Close
End Sub
If the script is contained in an array, you can loop through the array and produce multiple writelines.
Don't forget to reference the Microsoft Scripting Runtime library.
Something like this
locates the folder for the logged on user regardless of OS
checks that the user input file is contained in a master list (held by StrFiles)
then either creates a new file if it doesn't exist, or
provides a logic branch for you to add your overrwrite script
Sub
code
GetFiles()
Dim wsShell As Object
Dim objFSO As Object
Dim objFil As Object
Dim strFolder As String
Dim StrFile As String
Dim StrFiles()
StrFiles = Array("A.txt", "B.txt", "C.txt")
Set wsShell = CreateObject("wscript.shell")
strFolder = wsShell.specialFolders("Desktop") & "\myFolder"
StrFile = Application.InputBox("Please enter A.txt, B.txt", "File Selection", , , , , 2)
If IsError(Application.Match(StrFile, StrFiles, 0)) Then
MsgBox StrFile & " is invalid", vbCritical
Exit Sub
End If
If Len(Dir(strFolder & "\" & StrFile)) = 0 Then
'make file
Set objFSO = CreateObject("scripting.filesystemobject")
Set objFil = objFSO.createtextfile(strFolder & "\" & StrFile, 2)
objFil.Close
Else
'write over file
'add your code here
End If
End Sub