How to get function value in main sub VBA - vba

I would like to get the value (The regex result) of the function below inside my main sub in orde to add it to the title of my file, how can I do this ?
Public Sub Process_SAU(Item As Outlook.MailItem)
Dim object_attachment As Outlook.Attachment
Dim saveFolder As String
Dim Code as String
Code = ExtractText
' Folder location when I want to save my file
saveFolder = "C:\Users\gdeange1\Desktop\suggestion updates\UpdateBusinessInformation\Processed_By_Bulks"
For Each object_attachment In Item.Attachments
' Criteria to save .doc files only
If InStr(object_attachment.DisplayName, ".json") Then
object_attachment.SaveAsFile saveFolder & "\" & Format(Now(), "dd-mm-yyyy") & "_" & Code & "_" & object_attachment.DisplayName
End If
Next
End Sub
Function ExtractText(Str As String) ' As String
Dim regEx As New RegExp
Dim NumMatches As MatchCollection
Dim M As Match
regEx.Pattern = "((.*))[A-Z]{0}(Danièle Loubert|Véronique Mantha|Julie-Emmanuelle Carle|Nicolas Bertrand|Martine Jean)"
Set NumMatches = regEx.Execute(Str)
If NumMatches.Count = 0 Then
ExtractText = "Blabla"
Else
Set M = NumMatches(0)
ExtractText = M.SubMatches(0)
End If
Code = ExtractText
End Function
The code I tried above did not work.
Thank's for your help!

You might have copied the function ExtractText(Str As String) , but this function expects a string value to be passed while using this function, which you are missing. If you pass a string type value while using the function in your main code, it should work.

You pass Item to Public Sub Process_SAU(Item As MailItem).
Similarly, you have to pass Str to Function ExtractText(Str As String) As String.
Option Explicit
Private Sub test_Process_SAU()
Dim currItem As Object
' with a selected item
Set currItem = ActiveExplorer.Selection(1)
' or
' with an open item
'Set currItem = ActiveInspector.currentItem
If currItem.Class = olMail Then
Process_SAU currItem
End If
End Sub
Public Sub Process_SAU(Item As MailItem)
Dim Code As String
' Pass the applicable string to the function
Code = ExtractText(Item.body)
Debug.Print " Code: " & Code
Dim object_attachment As outlook.Attachment
Dim saveFolder As String
saveFolder = "C:\Users\gdeange1\Desktop\suggestion updates\UpdateBusinessInformation\Processed_By_Bulks"
For Each object_attachment In Item.Attachments
If InStr(object_attachment.DisplayName, ".json") Then
object_attachment.SaveAsFile saveFolder & "\" & Format(Now(), "dd-mm-yyyy") & "_" & Code & "_" & object_attachment.DisplayName
End If
Next
End Sub
Function ExtractText(Str As String) As String
Dim regEx As New regExp
Dim NumMatches As MatchCollection
Dim M As Match
regEx.Pattern = "((.*))[A-Z]{0}(Danièle Loubert|Véronique Mantha|Julie-Emmanuelle Carle|Nicolas Bertrand|Martine Jean)"
Set NumMatches = regEx.Execute(Str)
If NumMatches.count = 0 Then
ExtractText = "Blabla"
Else
Set M = NumMatches(0)
ExtractText = M.Value
End If
End Function

Related

How to rename attachments with sender's name in outlook

I am trying to make an outlook vba to download attachments from selected emails in outlook and rename them to include unique words to identify each sender. So far, I have managed to do so except for the last part.
For example,
if I receive an email from asdf#asdf.com(unique identifier: Company A) with an attachment(order.xlsx), then download the attachment and rename it to 'Company A - order.xlsx'.
It would be a great help if someone could solve this issue.
Thank you in advance!
Public Sub save_attchments()
Dim coll As VBA.Collection
Dim obj As Object
Dim Att As Outlook.attachment
Dim Sel As Outlook.Selection
Dim Path$
Dim i&
Dim itm As Outlook.MailItem
Path = "\\~~\~~\" & Format(Date, "yymmdd") & "\"
On Error Resume Next
MkDir Path
On Error GoTo 0
Set coll = New VBA.Collection
If TypeOf Application.ActiveWindow Is Outlook.Inspector Then
coll.Add Application.ActiveInspector.CurrentItem
Else
Set Sel = Application.ActiveExplorer.Selection
For i = 1 To Sel.Count
coll.Add Sel(i)
Next
End If
For Each obj In coll
For Each Att In obj.Attachments
Att.SaveAsFile Path & " - " & Att.FileName
Next
Next
Shell "Explorer.exe /n, /e, " & Path, vbNormalFocus
End Sub
Here is the code I use to save attachments from selected e-mails. I have updated it to allow a prefix addition to the file save names which you should be able to adapt to your needs. A suffix is more involved so currently omitted.
Public Sub SaveAttachmentsSelectedEmails()
Dim olItem As Outlook.MailItem
Dim olSelection As Outlook.Selection: Set olSelection = ActiveExplorer.Selection
Dim FilePath As String: FilePath = Environ("USERPROFILE") & "\Documents\Documents\Attachments"
If Dir(FilePath, vbDirectory) = "" Then
Debug.Print "Save folder does not exist"
Exit Sub
End If
For Each olItem In olSelection
SaveAttachments olItem, FilePath, RemoveAttachments:=False
Next olItem
End Sub
Private Function SaveAttachments(ByVal Item As Object, FilePath As String, _
Optional Prefix As String = "", _
Optional FileExtensions As String = "*", _
Optional Delimiter As String = ",", _
Optional RemoveAttachments As Boolean = False, _
Optional OverwriteFiles As Boolean = False) As Boolean
On Error GoTo ExitFunction
Dim i As Long, j As Long, FileName As String, Flag As Boolean
Dim Extensions() As String: Extensions = Split(FileExtensions, Delimiter)
If Right(FilePath, 1) <> "\" Then FilePath = FilePath & "\"
For j = LBound(Extensions) To UBound(Extensions)
With Item.Attachments
If .Count > 0 Then
For i = .Count To 1 Step -1
FileName = FilePath & Prefix & .Item(i).FileName
Flag = IIf(LCase(Right(FileName, Len(Extensions(j)))) = LCase(Extensions(j)), True, False)
Flag = IIf(FileExtensions = "*" Or Flag = True, True, False)
If Flag = True Then
If Dir(FileName) = "" Or OverwriteFiles = True Then
.Item(i).SaveAsFile FileName
Else
Debug.Print FileName & " already exists"
Flag = False
End If
End If
If RemoveAttachments = True And Dir(FileName) <> "" And Flag = True Then .Item(i).Delete
Next i
End If
End With
Next j
SaveAttachments = True
ExitFunction:
End Function

Save PDF attachments only using If UCase + SaveAsFile + SenderEmailAddress

I have two VBA macros that are slightly different and I want to combine the best of both.
Both save attachments within a selection of emails, however:
Macro A saves every attachment within the selection as a PDF. Some are JPEG signatures or disclaimers etc. that I don't want. The plus side is that it uses eml.SenderEmailAddress which is super as I want the name of the saved attachment to include 'someone#something.com'
Macro B saves every attachment within the selection as a PDF but uses the If UCase function to filter out PDF files only. For instance if an email contains a .txt and .pdf file, only the PDF file is considered. I don't have to clean out fake pdfs.
I cannot figure out how to incorporate SenderEmailAddress into this macro.
How do I merge the features in bold above?
Macro A)
Sub SaveAttachmentsFromSelectedItemsPDF()
Dim currentItem As Object
Dim currentAttachment As Attachment
Dim saveToFolder As String
Dim savedFileCountPDF As Long
saveToFolder = "the_path_private_its_a_work_one_lol"
savedFileCountPDF = 0
For Each currentItem In Application.ActiveExplorer.Selection
For Each currentAttachment In currentItem.Attachments
If UCase(Right(currentAttachment.DisplayName, 4)) = ".PDF" Then
currentAttachment.SaveAsFile saveToFolder & "\" & _
Left(currentAttachment.DisplayName, Len(currentAttachment.DisplayName) - 4) & "_" & Format(Now, "yyyy-mm-dd_hh-mm-ss") & ".pdf"
savedFileCountPDF = savedFileCountPDF + 1
End If
Next currentAttachment
Next currentItem
MsgBox "Number of PDF files saved: " & savedFileCountPDF, vbInformation
End Sub
Macro B)
Sub attsave_yann()
Dim win As Outlook.Explorer
Dim sel As Outlook.Selection
Dim att As Outlook.Attachments
Dim eml As MailItem
Dim i As Integer
Dim fn As String
Dim objAtt As Outlook.Attachment
Dim myRandom As Double
Randomize 'Initialize the Rnd function
myRandom = Rnd 'Generate a random number between 0-1
' Count = Count + 1
Set win = Application.ActiveExplorer
Set sel = win.Selection
For Each eml In sel
Set att = eml.Attachments
If UCase(Right(att.DisplayName, 4)) = ".PDF" Then
For i = 1 To att.Count
fn = "the_path_private_its_a_work_one_lol" & eml.SenderEmailAddress & "_" & Rnd & "_.pdf"
att(i).SaveAsFile fn
Next i
End If
Next
End Sub
B is almost there:
Sub attsave_yann()
Dim eml As MailItem
Dim fn As String
Dim objAtt As Outlook.Attachment
Randomize 'Initialize the Rnd function
For Each eml In Application.ActiveExplorer.Selection
For Each objAtt In eml.Attachments
'need to test objAtt.DisplayName
If UCase(objAtt.DisplayName) Like "*.PDF" Then
fn = "the_path_private_its_a_work_one_lol" & _
DomainOnly(eml.SenderEmailAddress) & "_" & Rnd & "_.pdf"
objAtt.SaveAsFile fn
End If
Next objAtt
Next
End Sub
'return only the part after the `#`
Function DomainOnly(sAddr as string)
Dim arr
arr = Split(sAddr, "#")
if UBound(arr) = 0 then
DomainOnly = sAddr
Else
DomainOnly = arr(1)
End If
End Function

Call function within another sub in VBA for Outlook

I have a VBA script for Outlook. I am writing to download the attachments and sort them into their own folders. I am trying to call a function to calculate the name of the folder that it should go into based on the domain name but when I introduced the function, the rule is not running. I was able to download the files into a single folder when function was not there.
I have tried examples on changing function and also tried it as a Sub but unable to get them to work.
Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
Dim EmailAddress As String
Dim FullDomainName As String
Dim DomainName As String
Dim CalculatedFolderName As String
EmailAddress = itm.SenderEmailAddress
DomainName = ""
CalculatedFolderName = ""
If (InStr(EmailAddress, "#") > 0) Then
FullDomainName = Right(EmailAddress, Len(EmailAddress) - InStr(EmailAddress, "#"))
DomainName = Left(FullDomainName, InStr(FullDomainName, ".") - 1)
End If
MsgBox DomainName
CalculatedFolderName = FolderName(DomainName)
saveFolder = "c:\attachment\test\"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile saveFolder & "\" & DomainName & " " & objAtt.DisplayName
Set objAtt = Nothing
Next
End Sub
Function FolderName(DomainName As String) As String
MsgBox DomainName
FolderName = ""
If (DomainName = "abc") Then FolderName = "A"
ElseIf (DomainName = "xyz") Then FolderName = "B"
Else
FolderName = DomainName
End If
Exit Function
End Function
I was expecting a folder name to return when the function is called.
The fix was done by moving the next statement to the next line.
If (DomainName = "abc") Then
FolderName = "A"
ElseIf (DomainName = "xyz") Then
FolderName = "B"

Saving E-Mails with Meeting Invitation From Outlook

I have the following VBA code macro to save all selected e-mails in .msg format to any folder but it doesn't save emails with meeting invitations. How do I also save mails with meeting invitations? Do I have to include any special objects? Below is the code that I am using to save the e-mails in .msg format:
Option Explicit
Public Sub SaveMessageAsMsg()
Dim xShell As Object
Dim xFolder As Object
Dim strStartingFolder As String
Dim xFolderItem As Object
Dim xMail As MailItem
Dim xObjItem As Object
Dim xPath As String
Dim xFileName As String
Dim xName As String
Dim xDtDate As Date
Set xShell = CreateObject("Shell.Application")
On Error Resume Next
' Bypass error when xFolder is nothing on Cancel
Set xFolder = xShell.BrowseForFolder(0, "Select a folder:", 0, strStartingFolder)
' Remove error bypass as soon as the purpose is served
On Error GoTo 0
If Not TypeName(xFolder) = "Nothing" Then
Set xFolderItem = xFolder.Self
xFileName = xFolderItem.Path
' missing path separator
If Right(xFileName, 1) <> "\" Then xFileName = xFileName & "\"
Else
xFileName = ""
Exit Sub
End If
For Each xObjItem In ActiveExplorer.Selection
If xObjItem.Class = olMail Then
Set xMail = xObjItem
xName = Left(CleanFileName(xMail.Subject), 100)
Debug.Print xName
xDtDate = xMail.ReceivedTime
xName = Format(xDtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & "-" & xName & ".msg"
xPath = xFileName & xName
xMail.SaveAs xPath, olMSG
End If
Next
End Sub
Public Function CleanFileName(strFileName As String) As String
Dim Invalids
Dim e
Dim strTemp As String
Invalids = Array("?", "*", ":", "|", "<", ">", "[", "]", """", "/", "\")
strTemp = strFileName
For Each e In Invalids
strTemp = Replace(strTemp, e, " ")
'strTemp = Replace(strTemp, e, "")
Next
CleanFileName = strTemp
End Function
In the code posted above only mail items are handled:
If xObjItem.Class = olMail Then
There are various object types in Outlook, see OlObjectClass enumeration for more information.
Basically, you need to handle also meeting items:
Dim xMail As Object
If xObjItem.Class = olMail Or xObjItem.Class = olMeetingRequest Then

Fixing Next Without For Error

This code is meant to save attachments from selected items in Outlook 2010 to a folder in My Documents. I ran into a problem using the previous iteration that
Dim itm As Outlook.MailItem
My best guess as to why it failed to save attachments is there were some calendar invites mixed in, some of which had attachments. I modified the code to try and address this and have been getting Next Without For errors.
Public Sub saveAttachtoDisk()
Dim objOL As Outlook.Application
Dim objItems As Outlook.Items
Dim objFolder As Outlook.MAPIFolder
Dim obj As Object
Dim currentExplorer As Explorer
Dim Selection As Selection
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
Dim fso As Object
Dim oldName
Dim file As String
Dim DateFormat As String
Dim newName As String
Dim enviro As String
enviro = CStr(Environ("USERPROFILE"))
saveFolder = enviro & "\Documents\Attachments\"
Set objOL = Outlook.Application
Set objFolder = objOL.ActiveExplorer.CurrentFolder
Set objItems = objFolder.Items
Set fso = CreateObject("Scripting.FileSystemObject")
For Each obj In objItems
With obj
For Each objAtt In itm.Attachments
file = saveFolder & objAtt.DisplayName
objAtt.SaveAsFile file
'Get the file name
Set oldName = fso.GetFile(file)
x = 1
Saved = False
DateFormat = Format(oldName.DateLastModified, "yyyy-mm-dd ")
newName = DateFormat & objAtt.DisplayName
'See if file name exists
If FileExist(saveFolder & newName) = False Then
oldName.Name = newName
GoTo NextAttach
End If
'Need a new filename
Count = InStrRev(newName, ".")
FnName = Left(newName, Count - 1)
fileext = Right(newName, Len(newName) - Count + 1)
Do While Saved = False
If FileExist(saveFolder & FnName & x & fileext) = False Then
oldName.Name = FnName & x & fileext
Saved = True
Else
x = x + 1
End If
Loop
NextAttach:
Set objAtt = Nothing
Next
Next
Set fso = Nothing
MsgBox "Done saving attachments"
End With
End Sub
Function FileExist(FilePath As String) As Boolean
Dim TestStr As String
Debug.Print FilePath
On Error Resume Next
TestStr = Dir(FilePath)
On Error GoTo 0
'Determine if File exists
If TestStr = "" Then
FileExist = False
Else
FileExist = True
End If
End Function
The logic is:
For Each obj In objItems
With obj
For Each objAtt In itm.Attachments
This must be "closed" in the reverse manner:
Next objAtt
End With
Next obj
Check this sequence in your code and adjust accordingly.
Note: although VB doesn't require (anymore) that a Next mentions its loop variable, it is good practice and helps you to better understand your For loops.