I was trying to write a code to check for a specific file if it is existing in a folder and subfolder in any subfolder \DESKTOP in c:\users*.* (= all users directories). And if the file is existing in any folder the script will delete the file.
Option Explicit
Dim Shell, FSO, DesktopPath
Dim objShortcutFile, objDesktopFolder, objDesktopSubFolder, Folder, strSysDrive
Set Shell = CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
strSysDrive = Shell.ExpandEnvironmentStrings("%SystemDrive%")
Set Folder = FSO.GetFolder(strSysDrive & "\Users")
msgbox Folder & "\sample1.lnk"
For Each objDesktopFolder in Folder.SubFolders
If FSO.FileExists(Folder & "\sample1.lnk") Then
FSO.DeleteFile Folder & "\sample1.lnk"
msgbox "success"
Else
msgbox "not existing"
End If
Next
Folder is the C:\Users folder object; objDesktopFolder is the folder object for each folder directly in C:\Users, e.g. C:\Users\user1 - not further levels of subfolders e.g. C:\Users\user1\Desktop (so it's a misleading name as it is not the desktop folder).
If you only want to look directly on the desktop, then just change this line (and any other line that uses that path):
If FSO.FileExists(Folder & "\sample1.lnk") Then
to:
If FSO.FileExists(FSO.BuildPath(objDesktopFolder.Path, "Desktop\sample1.lnk")) Then
If you also want to look through each folder that may exist on the desktop, then you'll have to perform the same sort of logic, e.g.
Option Explicit
Dim Shell, FSO, DesktopPath
Dim objShortcutFile, objDesktopFolder, objDesktopSubFolder, Folder, strSysDrive
Dim filepath, userfolder, desktop, subfolder, filename
Set Shell = CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
strSysDrive = Shell.ExpandEnvironmentStrings("%SystemDrive%")
Set Folder = FSO.GetFolder(strSysDrive & "\Users")
msgbox Folder & "\sample1.lnk"
filename = "sample1.lnk"
For Each userfolder in Folder.SubFolders
desktop = FSO.BuildPath(userfolder.Path, "Desktop")
filepath = FSO.BuildPath(desktop, filename)
If FSO.FolderExists(desktop) Then
' Delete file on desktop
If FSO.FileExists(filepath) Then
FSO.DeleteFile filepath, True
MsgBox "Success: deleted " & filepath
Else
MsgBox filepath & " doesn't exist"
End If
' Check folders on desktop
For Each subfolder In FSO.GetFolder(desktop).SubFolders
filepath = FSO.BuildPath(subfolder.Path, filename)
If FSO.FileExists(filepath) Then
FSO.DeleteFile filepath, True
MsgBox "Success: deleted " & filepath
End If
Next
End If
Next
That will only look for the file in folders directly on the desktop (as well as the file on the desktop, of course). If you want to look through further levels of subfolders then it's really best to create a separate sub that uses recursion to go through all levels of subfolders.
Related
Does a folder need to be unzipped in order for a macro to access its files? I am trying to move files from a zipped file to their respective folder and would like to know if the folder needs to be unzipped for a File System Object to copy it. Thanks
Sub MoveFiles()
Dim FSO As Object
Dim SourceFileName As String, DestinFileName As String
Set FSO = CreateObject("Scripting.Filesystemobject")
SourceFileName = Sheets("NIS File Allocation").Cells(2, 2).Value
DestinFileName = Sheets("NIS File Allocation").Cells(2, 7).Value
MsgBox FSO.FileExists(SourceFileName)
Call FSO.CopyFile(SourceFileName, DestinFileName, False)
MsgBox (SourceFileName + " Copied to " + DestinFileName)
End Sub
When running this code, SourceFileName must be in an unzipped folder in order to copy it to the destination file. Otherwise a "Path Not Found" Error will result. Tested with .FileExists
I have an excel file that when opened needs to download and open the latest version of an add in that is stored in Sharepoint. I have this code that downloads the add in, saves it in a specific location (strSavePath) and tries to open it.
Function funLoadRomeFiles(strURL As String, strSavePath As String)
Dim objConnection As Object
Dim objStream As Object
Set objConnection = CreateObject("MSXML2.ServerXMLHTTP.6.0")
On Error GoTo ExitConnect
objConnection.Open "GET", strURL, False
objConnection.send
strURL = objConnection.responseBody
If objConnection.Status = 200 Then
Set objStream = CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = 1
objStream.Write objConnection.responseBody
objStream.SaveToFile strSavePath, 2
objStream.Close
End If
ExitConnect:
On Error GoTo 0
Shell "C:\WINDOWS\explorer.exe """ & strSavePath & "", vbHide
End Function
However I get an error on the second to last row. The error is: Excel cannot open the file "Filename" because the file format or file extension is not valid [...]". The file downloaded is corrupted and cannot be opened manually either. When I download it and open it manually , it works.
The file size is 30.9 kb, but executing the code will download it as a 51 kb file. I've tried downloading other files using this code, and they have also become corrupted and 51 kb no matter the actual file size. Is there any way to change the code so the file will not be corrupted or any other ways of doing this?
Update: The file downloaded seems to be a html file even though its name still ends with .xlam
Also, I,ve tried using a link that ends with "filename.xlam" and one that ends with "filename.xlam?csf=1&e=b5f7991021ab45c1833229210f3ce810", both gives the same result, and when you copy the links into chrome both immediately downloads the correct file
I had a once a similar Problem.
The Problem by me was, that sharepoint did not allow a certain kind of file Type. So i had to do a workaround. So what you can try is to Zip your *.xlam File and Put that on the Sharepoint. Then you download it with the Code you already have. And then you just unzipped with the Following Code.
Sub Unzip1()
Dim FSO As Object
Dim oApp As Object
Dim Fname As Variant
Dim FileNameFolder As Variant
Dim DefPath As String
Dim strDate As String
Fname = strSavePath' I assume that this is the Path to the File you Downloaded
If Fname = False Then
'Do nothing
Else
'Root folder for the new folder.
DefPath = Application.DefaultFilePath 'Or Change it to the Path you want to unzip the Files
If Right(DefPath, 1) <> "\" Then
DefPath = DefPath & "\"
End If
'Create the folder name
strDate = Format(Now, " dd-mm-yy h-mm-ss")
FileNameFolder = DefPath & "MyUnzipFolder " & strDate & "\"
'Make the normal folder in DefPath
MkDir FileNameFolder
'Extract the files into the newly created folder
Set oApp = CreateObject("Shell.Application")
oApp.Namespace(FileNameFolder).CopyHere oApp.Namespace(Fname).items
'If you want to extract only one file you can use this:
'oApp.Namespace(FileNameFolder).CopyHere _
'oApp.Namespace(Fname).items.Item("test.txt")
MsgBox "You find the files here: " & FileNameFolder
On Error Resume Next
Set FSO = CreateObject("scripting.filesystemobject")
FSO.deletefolder Environ("Temp") & "\Temporary Directory*", True
End If
End Sub
And after that you just executed the Extension.
I Hope this can help you.
I could not find a way to download to add-ins, tried multiple different way and concluded that there was som authorization error or something else caused by the version of SharePoint I was using. The solution I found that suited my needs was to open the add-ins directly from SharePoint using this code:
On Error Resume Next
ActiveWorkbook.FollowHyperlink Address:="strUrl"
On Error GoTo 0
I'm trying to upload a local xlsm file to SharePoint online using VBA. The file would auto upload to SharePoint after the user saves the file.
The concept is after the user saves the xlsm file, it would create a new folder with the copied file and upload the copied file in the folder to SharePoint. After upload, the folder would be deleted.
However, I'm unable to save the file to the folder due to
Runtime error 1004
I check the possible reasons, the file name/path do exist, the folder was successfully created.
The file is not being used by another program, only excel runs the file.
The folder is newly created, it an empty folder, does not contain a file with the same name.
I did check all the paths and they are all correct.
This is my code
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
Dim UploadToSharepoint As Boolean
Dim SharePointLib As String
Dim myPath As String
Dim folderPath As String
Dim objNet As Object
Dim FS As Object
Dim copyPath As String
Dim copyFilePath As String
folderPath = Application.ActiveWorkbook.path
myPath = Application.ActiveWorkbook.FullName
SharePointLib = "https://company.com/folder/subfoler"
copyPath = folderPath + "\copyPath"
MsgBox "This is the folderPath = " & folderPath & vbNewLine & "This is the filepath = " & myPath & vbNewLine & "The copyPath is = " & copyPath
If Not FolderExists(copyPath) Then
FolderCreate (copyPath)
End If
SharePointLib = SharePointLib & FileNameWithExt(myPath)
ThisWorkbook.SaveCopyAs (copyPath)
Exit Sub
loadFailed:
UploadToSharepoint = False
End Sub
Your copyPath is only a folder, but the argument of SaveCopyAs should be a full path with file name.
Try this:
ThisWorkbook.SaveCopyAs copyPath & "\filename.xlsx"
I'm using Microsoft Scripting Runtime (FSO) to parse folders and produce a list of all of its contents, the folders are on a network and resultant paths end up longer than 260. The minimum code I have is as below:-
Private Sub ProcessFolder(ByVal StrFolder As String)
Dim Fl As File
Dim Fldr As Folder
Dim RootFldr As Folder
Set RootFldr = FS.GetFolder(StrFolder)
For Each Fl In RootFldr.Files
Debug.Print Fl.Path
Next
For Each Fldr In RootFldr.SubFolders
DoEvents
ProcessFolder Fldr.Path
Next
Set RootFldr = nothing
End sub
At a certain level StrFolder length became 259, the Set RootFldr ... folder line worked but For Each Fl In RootFldr.Files gave the error of 76: Path not found, presumably because the content causes the path to breach the 260 limit.
There were files in the folder when looking in Windows Explorer. I am using Excel as the host for this code as I'm outputting the result to workbooks.
Just to be super clear on my question and its background, I need to use FSO (happy to be shown alternatives if they exist) to access files deeper than 260 characters deep in their network path. I need it as FSO as the tool I have is taking the folder paths and the file paths, name, size created, and modified.
The technique to convert MAXFILE encumbered DOS path names to native OS path names is well established and documented. Summarizing:
Prefix a path that uses a drive letter with \\?\, like \\?\C:\foo\bar\baz.txt
Prefix a path that uses a file share with '\\?\UNC\, like \\?\UNC\server\share\baz.txt.
Works well with FileSystemObject too, at least when I tested your code on Windows 10. That might not necessarily be the case in older Windows versions or with the network redirector on your server. Tested by using the FAR file manager to create subdirectories with long names and verified with:
Dim path = "\\?\C:\temp\LongNameTest"
ProcessFolder path
Produced:
\\?\c:\temp\LongNameTest\VeryLongFolderName0123456789012345678901234567890123456789012345678901234567890123456789\VeryLongFolderName0123456789012345678901234567890123456789012345678901234567890123456789\VeryLongFolderName0123456789012345678901234567890123456789012345678901234567890123456789\VeryLongFolderName0123456789012345678901234567890123456789012345678901234567890123456789\VeryLongFolderName0123456789012345678901234567890123456789012345678901234567890123456789\Chrysanthemum.jpg
Which is 488 characters long. Things to keep in mind:
Native path names must be full paths, they cannot be relative paths. In other words, they must always start with a drive letter or share name and start from the root of the drive/share.
You get the native path name back, don't forget to strip the prefix off again if you display it.
Not tested but should fail, there is still a limitation on the the length of the filename itself (without the directory names), can't be longer than 259 chars. Shouldn't be a problem at all since the user can't create them either.
This took a little creative coding but the use of ShortPath was the answer.
This tool was to create a list of every folder and file in a root folder, the files also showing their size, and created/modified dates. The issue was when the resultant path of a file or folder was over 260, then the error Error 76: Path Not Found was thrown and the code would not capture the content of that area.
Using Microsoft Scripting Runtime (FSO) ShortPath would get around this issue but the path went from human readable to coded:-
Full path
\\ServerName00000\Root_Root_contentmanagement\DPT\STANDARDS_GUIDELINES\VENDOR_CERTIFICATION_FILES\PDFX_CERTIFICATION_ALL\2006_2007\DPT\CompantName0\Approved\Quark\India under Colonial Rule_structure sample\058231738X\Douglas M. Peers_01_058231738X\SUPPORT\ADDITIONAL INFORMATION\IUC-XTG & XML file
Short Path
\\lo3uppesaapp001\pesa_cmcoe_contentmanagement\CTS\S4SJ05~5\V275SE~8\PDM5D9~G\2N52EQ~5\HPE\GS9C6L~U\Approved\Quark\IQPSJ5~F\0CWHH1~G\DOFNHA~8\SUPPORT\A6NO7S~K\IUC-XTG & XML file
(Note I've altered the full path to protect IP and company info but the size is the same)
You can see while I could pass short path to someone and they could put it into Windows Explorer to get there, they would know know where it went by simply looking, to get around this a used a global variable that kept the folder path as a full string and followed what the short path was doing. this string is then what I output to the user. The below code is cut down but shows how I achieved it.
The short answer is ShortPath in FSO will get past the issue but the path will not be pretty.
Dim FS As New FileSystemObject
Dim LngRow As Long
Dim StrFolderPath As String
Dim WkBk As Excel.Workbook
Dim WkSht As Excel.Worksheet
Public Sub Run_Master()
Set WkBk = Application.Workbooks.Add
WkBk.SaveAs ThisWorkbook.Path & "\Data.xlsx"
Set WkSht = WkBk.Worksheets(1)
WkSht.Range("A1") = "Path"
WkSht.Range("B1") = "File Name"
WkSht.Range("C1") = "Size (KB)"
WkSht.Range("D1") = "Created"
WkSht.Range("E1") = "Modified"
LngRow = 2
Run "\\ServerName00000\AREA_DEPT0_TASK000"
Set WkSht = Nothing
WkBk.Close 1
Set WkBk = Nothing
MsgBox "Done!"
End Sub
Private Sub Run(ByVal StrVolumeToCheck As String)
Dim Fldr As Folder
Dim Fldr2 As Folder
Set Fldr = FS.GetFolder(StrVolumeToCheck)
'This is the variable that follows the full path name
StrFolderPath = Fldr.Path
WkSht.Range("A" & LngRow) = StrFolderPath
LngRow = LngRow +1
For Each Fldr2 In Fldr.SubFolders
If (Left(Fldr2.Name, 1) <> ".") And (UCase(Trim(Fldr2.Name)) <> "LOST+FOUND") Then
ProcessFolder Fldr2.Path
End If
Next
Set Fldr = Nothing
End Sub
Private Sub ProcessFolder(ByVal StrFolder As String)
'This is the one that will will be called recursively to list all files and folders
Dim Fls As Files
Dim Fl As File
Dim Fldrs As Folders
Dim Fldr As Folder
Dim RootFldr As Folder
Set RootFldr = FS.GetFolder(StrFolder)
If (RootFldr.Name <> "lost+found") And (Left(RootFldr.Name, 1) <> ".") Then
'Add to my full folder path
StrFolderPath = StrFolderPath & "\" & RootFldr.Name
WkSht.Range("A" & LngRow) = StrFolderPath
WkSht.Range("D1") = RootFldr.DateCreated
WkSht.Range("E1") = RootFldr.DateLastModified
Lngrow = LngRow + 1
'This uses the short path to get the files in FSO
Set Fls = FS.GetFolder(RootFldr.ShortPath).Files
For Each Fl In Fls
'This output our string variable of the path (i.e. not the short path)
WkSht.Range("A" & LngRow) = StrFolderPath
WkSht.Range("B" & LngRow) = Fl.Name
WkSht.Range("C" & LngRow) = Fl.Size /1024 '(bytes to kilobytes)
WkSht.Range("D" & LngRow) = Fl.DateCreated
WkSht.Range("E" & LngRow) = Fl.DateLastModified
LngRow = LngRow + 1
Next
Set Fls = Nothing
'This uses the short path to get the sub-folders in FSO
Set Fldrs = FS.GetFolder(RootFldr.ShortPath).SubFolders
For Each Fldr In Fldrs
'Recurse this Proc
ProcessFolder Fldr.Path
DoEvents
Next
Set Fldrs = Nothing
'Now we have processed this folder, trim the folder name off of the string
StrFolderPath = Left(StrFolderPath, Len(StrFolderPath) - Len(RootFldr.Name)+1)
End If
Set RootFldr = Nothing
End Sub
As mentioned this is a cut version of the code that is working for me to exemplify the the method used to get past this limit. Actually seems quite rudimentary once I'd done it.
I got around this once using the subst command of the command shell. It allows you to assign a drive letter to a local path (kind of like a network share).
I have created a VBA macro that pulls files from folder/subfolders based on a number of parameters. This includes finding zip folders that meet those parameters and copying them to a new directory so that each file can be searched through also. The problem that I'm having is that many of the files in those zips are duplicates, and as the project is to be automated, I cannot sit there and push the don't copy button every time it pops up. Is there a way to search through zip files and ignore the duplicate files? What I have for this part of my code is:
Sub Unzip(fileName As String, mainSubfolder As String)
Dim sourceDir As String, fileString As String
Dim FileNameFolder As Variant
Dim oApp As Object
sourceDir = "\\Filesrv02\depts\AR\EDIfiles\Remits"
fileString = mainSubfolder + fileName
If Right(sourceDir, 1) <> "\" Then
sourceDir = sourceDir & "\"
End If
FileNameFolder = sourceDir & "Unzipped"
If Dir(FileNameFolder, vbDirectory) = vbNullString Then
MkDir FileNameFolder
End If
Set oApp = CreateObject("Shell.Application")
oApp.Namespace(FileNameFolder).CopyHere oApp.Namespace(fileString).Items
End Sub
The last two lines are where I copy files from the zip folder into a new folder called "Unzipped". However, I'm not sure how to get at each individual file in the zip folder to say if it already exists, ignore it. Any suggestions would be greatly appreciated!
Maybe this helps:
(taken from: https://stackoverflow.com/a/14987890/3883521)
With oApp.NameSpace(ZipFile & "\")
If OverwriteFile Then
For Each fil In .Items
If FSO.FileExists(DefPath & fil.Name) Then
Kill DefPath & fil.Name
End If
Next
End If
oApp.NameSpace(CVar(DefPath)).CopyHere .Items
End With