I created a function in Excel to save a specified attachment (Excel file) from a specified email to a file location.
My organisation has moved all of our files to Sharepoint. I tried to update my function using the SharePoint path, but it fails to save the attachment.
Function OpenEMailAttachment(Path As String, FileName As String, FindSubj As String, FindAttachName As String, SubFolder As Object)
Dim oOlAp As Object, oOlns As Object, oOlInb As Object
Dim oOlItm As Object, oOlAtch As Object
Dim wb As Workbook
Dim sSubj As String
'~~> Outlook Variables for email
' Other options for email properties are:
' eSender = oOlItm.SenderEmailAddress
' dtRecvd = oOlItm.ReceivedTime
' dtSent = oOlItm.CreationTime
' sMsg = oOlItm.Body
'~~> Get Outlook instance
Set oOlAp = GetObject(, "Outlook.application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'~~> Store the relevant info in the variables
For Each oOlItm In oOlInb.Items
sSubj = oOlItm.Subject
Debug.Print sSubj & "-->" & FindSubj
If sSubj Like FindSubj Then
Debug.Print "Opening attachment"
If oOlItm.Attachments.Count <> 0 Then
For Each oOlAtch In oOlItm.Attachments
'~~> Download the attachment
If oOlAtch.FileName Like FindAttachName Then
Debug.Print Path & FileName
oOlAtch.SaveAsFile Path & FileName
Debug.Print Path & oOlAtch.FileName
oOlItm.UnRead = False
DoEvents
oOlItm.Save
On Error Resume Next
oOlItm.Move SubFolder
On Error GoTo 0
End If
Next
End If
End If
Next
'~~> FilePath is the file that we earlier downloaded
Set wb = Workbooks.Open(Path & FileName)
OpenEMailAttachment = FileName
End Function
The path I specified is like https://MyOrg.sharepoint.com/teams/FolderName/
and the FileName like File%20Name.xlsx
Try this.
Sub copyFilesTo_Sharepoint()
Dim srcFolder As String
Dim dstFolder As String
' source path
srcFolder = "WriteYourSourcePathHere"
' destination path
dstFolder = "\\MyOrg.sharepoint.com\teams\FolderName"
' copies all Excel files starting with 'myfiles' with extension 'xslx'
Call fs_cpyFilesToFolder(srcFolder, dstFolder, "myfile*.xlsx")
End Sub
Sub fs_cpyFilesToFolder(srcPath As String, dstPath As String, Optional FileExt As String = "*.xlsx")
Dim fso As Object: Set fso = CreateObject("scripting.filesystemobject")
' checks if source path has a '\'
If Right(srcPath, 1) <> "\" Then
srcPath = srcPath & "\"
End If
' checks if source path exists
If fso.FolderExists(srcPath) = False Then
MsgBox srcPath & " doesn't exist"
Exit Sub
End If
' checks if destination path exists
If fso.FolderExists(dstPath) = False Then
MsgBox dstPath & " doesn't exist"
Exit Sub
End If
' copies files to sharepoint
fso.CopyFile Source:=srcPath & FileExt, Destination:=dstPath
End Sub
Related
I want to fetch data from an email attachment in excel to a new excel and save the file in c drive in with a specific name. Below is the code which works fine. I want to add one more code which can copy data into new excel instead of renaming the same excel that comes as attachment in email.
Sub Test()
SaveEmailAttachmentsToFolder "Test", "xls", "C:\Users\fdmello\Desktop\Daily Reports\FL"
End Sub
Sub SaveEmailAttachmentsToFolder(OutlookFolderInInbox As String, _
ExtString As String, DestFolder As String)
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim SubFolder As MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim FileName As String
Dim TempFileName As String
Dim MyDocPath As String
Dim I As Integer
Dim wsh As Object
Dim fs As Object
Dim FileNameString As String
On Error GoTo ThisMacro_err
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set SubFolder = Inbox.Folders(OutlookFolderInInbox)
I = 0
' Check subfolder for messages and exit of none found
If SubFolder.Items.Count = 0 Then
MsgBox "There are no messages in this folder : " & OutlookFolderInInbox, _
vbInformation, "Nothing Found"
Set SubFolder = Nothing
Set Inbox = Nothing
Set ns = Nothing
Exit Sub
End If
If Right(DestFolder, 1) <> "\" Then
DestFolder = DestFolder & "\"
End If
For Each Item In SubFolder.Items
For Each Atmt In Item.Attachments
If LCase(Right(Atmt.FileName, Len(ExtString))) = LCase(ExtString) Then
FileNameString = "Data FL_MU_"
TempFileName = DestFolder & "Stagefile.xls"
FileName = DestFolder & FileNameString & Format(Item.ReceivedTime - 1, "ddmm") & ".xlsx"
Atmt.SaveAsFile FileName
I = I + 1
End If
Next Atmt
Next Item
Show this message when Finished
If I > 0 Then
MsgBox "You can find the files here : " _
& DestFolder, vbInformation, "Finished!"
Else
MsgBox "No attached files in your mail.", vbInformation, "Finished!"
End If
End Sub
Iam developing a vba marco-script for a customer which downloads zip file from github, and unpack the zip folder to a folder.
The script will create a folder ´pb´ if it doesnt exist already - and if the folder already exist it will delete the folder and create a new.
It works properly on my own pc, but the customer is getting this error as shown on screenshot.
The path on client's computer is following:
C:\Users\Nicol\xxx\xxx - Carina og Nicolas - Carina og Nicolas\Analyseværktøjer\Rådgivningsværktøj
And the client is using mircosoft teams drive, but it didnt work neither on his own desktop folder. So i dont know what cause it.
I cant figure out how to solve this.
[
Here is full source code of the marco.
Option Explicit
Function versionIsOutdated(strDir As String, strPath As String)
Dim FSO As New FileSystemObject
Dim FileToRead As Variant
Dim TextString As String
Dim path As String
path = strPath & strDir
If FSO.FolderExists(path) Then
' exist, lookup versionNumber
Dim FileUrl As String
Dim objXmlHttpReq As Object
Dim objStream As Object
Dim strResult
FileUrl = "https://raw.githubusercontent.com/Securelife-A-S/pb_integration/main/version.txt"
Set objXmlHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0")
objXmlHttpReq.Open "GET", FileUrl, False
objXmlHttpReq.send
strResult = objXmlHttpReq.responseText
Set FSO = CreateObject("Scripting.FileSystemObject")
Set FileToRead = FSO.OpenTextFile(path & "\pb_integration-main\version.txt", ForReading) 'add here the path of your text file
TextString = FileToRead.ReadAll
FileToRead.Close
Debug.Print (TextString)
Debug.Print (strResult)
Dim compResult As Integer
If StrComp(TextString, strResult) = 0 Then
Debug.Print ("Version is up to date")
versionIsOutdated = False
Else
versionIsOutdated = True
Debug.Print ("Version is outdated")
End If
Else
versionIsOutdated = True
Debug.Print ("Folder is not downloaded yet")
End If
End Function
Function MkDir(strDir As String, strPath As String)
Dim FSO As New FileSystemObject
Dim path As String
path = strPath & strDir
If FSO.FolderExists(path) Then
' exist, so delete the folder
FSO.DeleteFolder path, True
Debug.Print "Deleting folder"
End If
If Not FSO.FolderExists(path) Then
' doesn't exist, so create the folder
FSO.CreateFolder path
Debug.Print "Creating folder"
End If
End Function
Function downloadAndUnzip()
Dim FileUrl As String
Dim objXmlHttpReq As Object
Dim objStream As Object
Dim strResult
FileUrl = "https://raw.githubusercontent.com/Securelife-A-S/pb_integration/main/version.txt"
Set objXmlHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0")
objXmlHttpReq.Open "GET", FileUrl, False
objXmlHttpReq.send
strResult = objXmlHttpReq.responseText
Debug.Print (strResult)
FileUrl = "https://github.com/Securelife-A-S/pb_integration/archive/refs/heads/main.zip"
Set objXmlHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0")
objXmlHttpReq.Open "GET", FileUrl, False
objXmlHttpReq.send
If objXmlHttpReq.Status = 200 Then
Set objStream = CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = 1
objStream.Write objXmlHttpReq.responseBody
objStream.SaveToFile ThisWorkbook.path & "\" & "pb.zip", 2
objStream.Close
End If
Debug.Print ("Download done")
Dim ShellApp As Object
'Copy the files & folders from the zip into a folder
Set ShellApp = CreateObject("Shell.Application")
ShellApp.Namespace(ThisWorkbook.path & "\pb").CopyHere ShellApp.Namespace(ThisWorkbook.path & "\pb.zip").Items
Debug.Print ("Unpack done")
End Function
Function DeleteVBComponent()
Dim CompName As String
CompName = "Main"
'Disabling the alert message
Application.DisplayAlerts = False
'Ignore errors
On Error Resume Next
'Delete the component
Dim vbCom As Object
Set vbCom = Application.VBE.ActiveVBProject.VBComponents
vbCom.Remove VBComponent:= _
vbCom.Item(CompName)
On Error GoTo 0
'Enabling the alert message
Application.DisplayAlerts = True
End Function
Function addBasFile()
Dim path As String
Dim objModule As Object
path = ThisWorkbook.path & "\pb\pb_integration-main\Main.bas"
Set objModule = Application.VBE.ActiveVBProject.VBComponents.Import(path)
objModule.Name = "Main"
Debug.Print path
End Function
Sub Workbook_Open()
Dim asd As Boolean
asd = versionIsOutdated("pb", ThisWorkbook.path & "\")
If asd = True Then
MsgBox "Der er kommet ny version - Downloading påbegyndt"
Call MkDir("pb", ThisWorkbook.path & "\")
Call downloadAndUnzip
Call DeleteVBComponent
Call addBasFile
Application.Run ("Main.init")
End If
End Sub
I need to do the following:
Allow the user to select any number of files, in any format, and copy them to a new folder.
Create the destination folder if it doesn't exist. In this case, the folder name should be given by the content of the C2 & C3 cells (Range("C2").Value & Range("C3").Text & "\").
Private Sub CommandButton4_Click()
Dim strDirname As String
Dim strDefpath As String
Dim strPathname As String
Dim strFilename As String
Dim FSO
Dim sFile As FileDialog
Dim sSFolder As String
Dim sDFolder As String
strDirname = Range("C2").Value & Range("C3").Text
MkDir strDefpath & "\" & strDirname
strPathname = strDefpath & "\" & strDirname & "\" & strFilename
Set sFile = Application.FileDialog(msoFileDialogOpen)
sDFolder = strDirname & "\"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set FSO = New FileSystemObject
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
If Not .Show Then Exit Sub
Set xFolder = FSO.GetFolder(.SelectedItems(1))
For Each xFile In xFolder.Files
On Error Resume Next
xRow = Application.Match(xFile.Name, Range("A:A"), 0)
On Error GoTo 0
Next
End With
End Sub
I know the error is here...
Set xFolder = FSO.GetFolder(.SelectedItems(1))
...because I'm asking it to get a file, not a folder.
It is not very clear to me what you are trying to do but, if you intend to select a folder, you have to use it
Application.FileDialog (msoFileDialogFolderPicker)
instead of
Application.FileDialog (msoFileDialogFilePicker)
Your posted code shows so little resemblance to what you Q asks for, I've disregarded it.
This code follows the description. You may need to alter certain details to fully match your needs
Sub Demo()
Dim FilePicker As FileDialog
Dim DefaultPath As String
Dim DestinationFolderName As String
Dim SelectedFile As Variant
Dim DestinationFolder As Folder
Dim FSO As FileSystemObject
DefaultPath = "C:\Data" ' <~~ update to suit, or get it from somewhere else
' Validate Default Path
If Right$(DefaultPath, 1) <> Application.PathSeparator Then
DefaultPath = DefaultPath & Application.PathSeparator
End If
If Not FSO.FolderExists(DefaultPath) Then Exit Sub
' Get Destination Folder, add trailing \ if required
DestinationFolderName = Range("C2").Value & Range("C3").Value
If Right$(DestinationFolderName, 1) <> Application.PathSeparator Then
DestinationFolderName = DestinationFolderName & Application.PathSeparator
End If
Set FSO = New FileSystemObject
' Get reference to Destination folder, create it if required
If FSO.FolderExists(DefaultPath & DestinationFolderName) Then
Set DestinationFolder = FSO.GetFolder(DefaultPath & DestinationFolderName)
Else
Set DestinationFolder = FSO.CreateFolder(DefaultPath & DestinationFolderName)
End If
' File Selection Dialog
Set FilePicker = Application.FileDialog(msoFileDialogFilePicker)
With FilePicker
.AllowMultiSelect = True ' allow user to select multiple files
.InitialFileName = DefaultPath ' set initial folder for dialog
If .Show = False Then Exit Sub ' check if user cancels
For Each SelectedFile In .SelectedItems ' loop over selected files
If SelectedFile Like DefaultPath & "*" Then 'Optional: disallow browsing higher than default folder
FSO.CopyFile SelectedFile, DefaultPath & DestinationFolderName, True ' Copy file, overwrite is it exists
End If
Next
End With
End Sub
I want to copy specific file type(*.SLDDRW) from source to destination,in destination path we have lots of folders and sub-folders .in below code i am trying to walk on any sub folders but unfortunately it didn't work and didn't walk all sub-folders S.O can help me?
Sub copy_specific_files_in_folder()
Dim FSO As Object
Dim sourcePath As String
Dim destinationPath As String
Dim fileExtn As String
sourcePath = "C:\Users\6\"
destinationPath = "C:\Users\"
fileExtn = "*.SLDDRW"
If Right (sourcePath, 1) <> "\" Then
sourcePath = sourcePath & "\"
End If
Set FSO = CreateObject ("scripting.filesystemobject")
If FSO.FolderExists(sourcepath) = False Then
MsgBox sourcePath & " does not exist"
Exit Sub
End If
FSO.CopyFile Source:=sourcePath & fileExtn, Destination :=destinationPath
copy_files_from_subfolders
MsgBox "Your files have been copied from the sub-folders of " & sourcePath
End sub
sub copy_files_from_subfolders()
Dim FSO AS Object , fld As Object
Dim fsoFile As Object
Dim fsoFol As Object
sourcePath = "C:\Users\6\"
targetPath = "C:\Users\"
If Right (sourcePath , 1) <> "\" then sourcePath = sourcePath & "\"
Set FSO = createObject("Scripting.FileSystemObject")
Set fld = FSO.getFolder(sourcePath)
If FSO.FolderExists(fld) Then
For Each fsoFol In FSO.GetFolder(sourcePath).SubFolders
For Each fsoFile In fsoFol.Files
If Right (fsoFile, 6) = "sldprt" Then
fsoFile.Copy targetPath
End If
Next
Next
End If
Here's a function that will recursively search a folder and all subfolders for a specific extension and then copy found files to a specified destination:
Sub SearchFoldersAndCopy(ByVal arg_sFolderPath As String, _
ByVal arg_sDestinationFolder As String, _
ByVal arg_sExtension As String)
Dim oFSO As Object
Dim oFolder As Object
Dim oSubFolder As Object
Dim sTest As String
'Test if FolderPath exists
sTest = Dir(arg_sFolderPath, vbDirectory)
If Len(sTest) = 0 Then
MsgBox "Specified folder [" & arg_sFolderPath & "] doesn't exist. Please check spelling or create the directory."
Exit Sub
End If
'Test if Destination exists
sTest = Dir(arg_sDestinationFolder, vbDirectory)
If Len(sTest) = 0 Then
MsgBox "Specified destination [" & arg_sDestinationFolder & "] doesn't exist. Please check spelling or create the directory."
Exit Sub
End If
'FolderPath and Destination both exist, proceed with search and copy
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder(arg_sFolderPath)
'Test if any files with the Extension exist in directory and copy if one or more found
sTest = Dir(oFolder.Path & Application.PathSeparator & "*." & arg_sExtension)
If Len(sTest) > 0 Then oFSO.copyfile oFolder.Path & Application.PathSeparator & "*." & arg_sExtension, arg_sDestinationFolder
'Recursively search subfolders
For Each oSubFolder In oFolder.SubFolders
SearchFoldersAndCopy oSubFolder.Path, arg_sDestinationFolder, arg_sExtension
Next oSubFolder
End Sub
Here's an example of how to call it:
Sub tgr()
Dim sStartFolder As String
Dim sDestination As String
Dim sExtension As String
sStartFolder = "C:\Test"
sDestination = "C:\Output\" '<-- The ending \ may be required on some systems
sExtension = "SLDDRW"
SearchFoldersAndCopy sStartFolder, sDestination, sExtension
End Sub
Historically I was using Excel and lotus notes to do this, company is transitioning thru to Outlook 2016 as it's standard email client.
We get daily reports to a mailbox from our Fridge units at multiple branches. each branch is a separate email but some of the attachments are named the same.
I used a script that copied the attachments from LN and it had a private function that in the processing of copying the attachments it would rename them if they had the same name.
I found a script here at stack overflow that I modified to save the attachments from Outlook into a Network folder. That works fine.
Here is the script
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
' Get the path to your My Documents folder
'strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
strFolderpath = "J:\Clayton\Logistics\Plantwatch\REPORTS\ZDumpSites\"
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
' Set the Attachment folder.
strFolderpath = strFolderpath '& "\Attachments\"
' Check each selected item for attachments. If attachments exist,
' save them to the strFolderPath folder and strip them from the item.
For Each objMsg In objSelection
' This code only strips attachments from mail items.
' If objMsg.class=olMail Then
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
strDeletedFiles = ""
If lngCount > 0 Then
' We need to use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.Item(i).FileName
' Combine with the path to the Temp folder.
strFile = strFolderpath & strFile
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strFile
' Delete the attachment.
'objAttachments.Item(i).Delete
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
'Use the MsgBox command to troubleshoot. Remove it from the final code.
'MsgBox strDeletedFiles
Next i
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = vbCrLf & "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
End If
objMsg.Save
End If
Next
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
I am trying to add this Function to this Script:
Private Function UniqueFileName(ByVal Fn As String) As String ' Rename same Name files.
Dim Fun As String ' Function return value
Dim Sp() As String ' Split file name
Dim Ext As Long ' file extension character count
Dim i As Integer ' file name index
Sp = Split(Fn, ".")
If UBound(Sp) Then Ext = Len(Sp(UBound(Sp))) + 1
Fun = stPath & Fn
Do While Len(Dir(Fun))
i = i + 1
Fun = stPath & Left(Fn, Len(Fn) - Ext) & _
"(" & CStr(i) & ")" & Right(Fn, Ext)
If i > 100 Then Exit Do
Loop
UniqueFileName = Fun
End Function
But search as I can I cannot see where this would fit or be added to the script.
How can I add this function to the excellent Script above to rename same named attachments?
I suspect I am missing something simple!
Change:
strFile = strFolderpath & strFile
to:
strFile = MakeUnique(strFolderpath & strFile)
Function:
Function MakeUnique(fPath As String) As String
Dim rv As String, fso, fName, fldr, ext, n
Set fso = CreateObject("scripting.filesystemobject")
rv = fPath
ext = "." & fso.getextensionname(fPath)
n = 2
Do While fso.fileexists(rv)
rv = Left(fPath, Len(fPath) - Len(ext)) & "(" & n & ")" & ext
n = n + 1
Loop
MakeUnique = rv
End Function
Try it like this
add the following to your variables
Dim nFileName As String
Dim Ext As String
then call the Function
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.Item(i).FileName
' ==============================================================
' ' // added
Ext = Right(strFile, _
Len(strFile) - InStrRev(strFile, Chr(46)))
nFileName = FileNameUnique(strFolderpath, strFile, Ext)
'================================================================
' Combine with the path to the Temp folder.
strFile = strFolderpath & strFile
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strFolderpath & nFileName ' < added
Here are you have two functions
'// Check if the file exists
Private Function FileExists(FullName As String) As Boolean
Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(FullName) Then
FileExists = True
Else
FileExists = False
End If
Exit Function
End Function
'// If the same file name exist then add (1)
Private Function FileNameUnique(sPath As String, _
FileName As String, _
Ext As String) As String
Dim lngF As Long
Dim lngName As Long
lngF = 1
lngName = Len(FileName) - (Len(Ext) + 1)
FileName = Left(FileName, lngName)
Do While FileExists(sPath & FileName & Chr(46) & Ext) = True
FileName = Left(FileName, lngName) & " (" & lngF & ")"
lngF = lngF + 1
Loop
FileNameUnique = FileName & Chr(46) & Ext
Exit Function
End Function
Good Luck - :-)