Excel workbook to outlook template - excel

Please see attached image below for reference.
I have an excel workbook that i need to input data into every day on the fly. After inputting data i then need to re input the data into an outlook template and send it to clients.
My outlook template contains a basic table as seen in the picture.
What i want to do is after inputting the data into excel, click the button and it will automatically open the outlook template and fill in the data from the excel workbook ready to be sent.
I've been copying and pasting the data in but its starting to get out of hand because several hundred of these emails need to be done each day.
Any suggestions would greatly be appreciated.

Here's something I use for simple emails - pretty generic but you can tweak as you wish.
Select a row in your data and run the macro. Adjust the HEADER_ROW and NUM_COLS constants to suit your layout.
Sub NotificationMail()
Const HEADER_ROW As Long = 1 '<< the row with column headers
Const NUM_COLS As Long = 7 '<< how many columns of data
Const olMailItem = 0
Const olFolderInbox = 6
Dim ol As Object, fldr, ns, msg
Dim html As String, c As Range, colReq As Long, hdr As Range
Dim rw As Range
On Error Resume Next
Set ol = GetObject(, "outlook.application")
On Error GoTo 0
If ol Is Nothing Then
On Error Resume Next
Set ol = CreateObject("outlook.application")
Set ns = ol.GetNamespace("MAPI")
Set fldr = ns.GetDefaultFolder(olFolderInbox)
fldr.display
On Error GoTo 0
End If
If ol Is Nothing Then
MsgBox "Couldn't start Outlook to compose mail!", vbExclamation
Exit Sub
End If
Set msg = ol.CreateItem(olMailItem)
Set rw = Selection.Cells(1).EntireRow
msg.Subject = "Here's your information"
html = "<style type='text/css'>"
html = html & "body, p {font:10pt calibri;padding:40px;}"
html = html & "table {border-collapse:collapse}"
html = html & "td {border:1px solid #000;padding:4px;}"
html = html & "</style>"
html = html & "<p>Your request has been updated:</p>"
html = html & "<table>"
For Each c In rw.Cells(1).Resize(1, NUM_COLS).Cells
If c.Column <> 4 Then '<<< EDIT to exclude ColD
Set hdr = rw.Parent.Cells(HEADER_ROW, c.Column) '<< get the header text for this cell
html = html & "<tr><td style='background-color:#DDD;width:200px;'>" & _
hdr.Value & _
"</td><td style='width:400px;'>" & Trim(c.Value) & "</td></tr>"
End If 'we want this cell
Next c
html = html & "</table>"
msg.htmlbody = html
msg.display
End Sub

here is some code i have for reference
it shows how to create tables and how to address cells
has lot of extra stuff
just step through it
Sub aTestEmail()
Dim outMail As Outlook.mailItem
Set outMail = Application.CreateItem(olMailItem)
outMail.BodyFormat = olFormatHTML
outMail.Display (False) ' modeless
Dim wd As Document
' Set wd = Application.ActiveInspector.WordEditor
Set wd = outMail.GetInspector.WordEditor
' wd.Range.InsertBreak 3 ' section (continuous)
' wd.Range.InsertBreak 3 ' section (continuous)
For i = 0 To 9
wd.Range.InsertParagraphAfter
Next
debug_aTestEmail wd
Stop
Dim rng As Range
Set rng = wd.Range(2, 8)
rng.Select
Debug.Print rng.Text
rng.Collapse (1) ' 0 - left, 1 - right
rng.Select
wd.Content.Select
' Debug.Print wd.Content.Text
' wd.Range(wd.Characters(104).End, wd.Characters(150).End).Select
' wd.Range(wd.Words(5).Start, wd.Words(10).Start).Select
' wd.Range(wd.Words(5).Start, wd.Words(10).End).Select
wd.Range(wd.Words(5).End, wd.Words(10).End).Select
' wd.Range.Select
' wd.Sentences(1).Select
' wd.Sentences(1).Words(1).Select
' wd.Sentences(1).Words(5).Select
' wd.Sentences(1).Words(10).Select
' wd.Sentences(5).Characters(10).Select
' wd.Sentences(5).Characters(10).Select
' wd.Words(10).Select
' wd.Words(11).Select
' wd.Range.Words(10).Select
' wd.Range.Words(11).Select
' debug_aTestEmail wd
' wd.Characters(4).Select
wd.Tables.Add Range:=wd.Characters(8), NumRows:=5, NumColumns:=3, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:=wdAutoFitFixed
wd.Tables.Add Range:=wd.Characters(3), NumRows:=5, NumColumns:=2, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:=wdAutoFitFixed
wd.Tables(1).Range.Words(1).Select
wd.Tables(1).Range.Words(2).Select
wd.Tables(1).Columns(1).Cells(1).Select
wd.Tables(1).Columns(1).Cells(2).Select
wd.Tables(1).Columns(1).Cells(3).Select
wd.Tables(1).Columns(1).Cells(4).Select
wd.Tables(1).Columns(1).Cells(5).Select
Debug.Print wd.Sentences(1).Words.Count
Debug.Print wd.Words.Count
Dim tabl As Tables
Set tabl = wd.Tables
tabl(1).Style = "Grid Table 4 - Accent 3" ' get this name from "table design" tab (hover over whichever style you like and a tool tip will give you the name)
' tabl(1).ApplyStyleHeadingRows = True
' tabl(1).ApplyStyleLastRow = False
' tabl(1).ApplyStyleFirstColumn = True
' tabl(1).ApplyStyleLastColumn = False
' tabl(1).ApplyStyleRowBands = True
' tabl(1).ApplyStyleColumnBands = False
tabl(1).Range.InsertParagraph
tabl(1).Cell(1, 1).Range.InsertParagraph
tabl(1).Cell(2, 1).Range.InsertParagraph
tabl(1).Cell(3, 1).Range.InsertParagraph
tabl(1).Cell(1, 1).Range.InsertBefore "cell1"
tabl(1).Cell(2, 1).Range.InsertBefore "cell2"
tabl(1).Cell(3, 1).Range.InsertBefore "cell3"
tabl(1).Cell(4, 1).Range.InsertBefore "cell4"
tabl(1).Cell(5, 1).Range.InsertBefore "cell5"
tabl(2).Cell(1, 1).Range.InsertBefore "cell6"
tabl(2).Cell(2, 1).Range.InsertBefore "cell7"
tabl(2).Cell(3, 1).Range.InsertBefore "cell8"
tabl(2).Cell(4, 1).Range.InsertBefore "cell9"
tabl(2).Cell(5, 1).Range.InsertBefore "cell10"
' wd.Range.InsertBreak 3 ' section (continuous)
' wd.Range.InsertBreak 3 ' section (continuous)
debug_aTestEmail wd
' wd.Sections(2).Range.InsertBefore ("before" & vbCrLf & vbCrLf)
' wd.Sections(2).Range.InsertAfter ("after" & vbCrLf & vbCrLf)
' debug_aTestEmail wd
' wd.Sections(1).Range.Words(wd.Sections(1).Range.Words.Count).InsertBefore ("after1.1" & vbCrLf & vbCrLf)
' wd.Sections(1).Range.Words(wd.Sections(1).Range.Words.Count).InsertBefore ("after1.2" & vbCrLf & vbCrLf)
' wd.Sections(1).Range.Words(wd.Sections(1).Range.Words.Count).InsertBefore ("after1.3" & vbCrLf & vbCrLf)
' wd.Sections(1).Range.Words(wd.Sections(1).Range.Words.Count).InsertBefore ("after1.4" & vbCrLf & vbCrLf)
' For i = 1 To wd.Sections(1).Range.Words.Count
' Debug.Print wd.Sections(1).Range.Words(i).Characters.Count & " ";
' Debug.Print wd.Sections(1).Range.Words(i) & " "
' Next
' debug_aTestEmail wd
' wd.Sections(2).Range.InsertAfter ("after2.1" & vbCrLf & vbCrLf)
' wd.Sections(2).Range.InsertAfter ("after2.2" & vbCrLf & vbCrLf)
' wd.Sections(2).Range.InsertAfter ("after2.3" & vbCrLf & vbCrLf)
' wd.Sections(2).Range.InsertAfter ("after2.4" & vbCrLf & vbCrLf)
Set wd = Nothing
Set outMail = Nothing
End Sub
Sub debug_aTestEmail(wd As Document)
Debug.Print "------------------------------------------------"
Debug.Print " wd.Sections.Count : " & wd.Sections.Count
Debug.Print " wd.Paragraphs.Count : " & wd.Paragraphs.Count
Debug.Print " wd.Sentences.Count : " & wd.Sentences.Count
Debug.Print " wd.Words.Count : " & wd.Words.Count
Debug.Print " wd.Characters.Count : " & wd.Characters.Count
Debug.Print " wd.Range.End : " & wd.Range.End
Debug.Print "wd.StoryRanges.Count : " & wd.StoryRanges.Count
Debug.Print "------------------------------------------------"
Debug.Print wd.Tables.Count
End Sub

Related

VBA: Emailing a different range image to each of the recipients

I'm trying to automate an emailing process with outlook.
So far my code enables to:
Send different attachments to different recipients
Send the same range of the excel sheet (ex: A1:B3) as an image in the email body to all the recipients
Personalized message
What I would like is to send different ranges to different recipients (like the attachments) for example:
Email 1: Range A1 B3
Email 2: Range A4:B7
Email 3: Range A8:B11
etc...
Is it possible to make it on loop or sth?
Sub Send_Files()
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim cell As Range
Dim FileCell As Range
Dim rng As Range
Dim MakeJPG As String
Dim PictureRange As Range
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set sh = Sheets("Sheet1")
Set OutApp = CreateObject("Outlook.Application")
For Each cell In sh.Columns("B").Cells.SpecialCells(xlCellTypeConstants)
'Enter the path/file names in the C:Z column in each row
Set rng = sh.Cells(cell.Row, 1).Range("C1:Z1")
MakeJPG = CopyRangeToJPG("Sheet1", "F31: J37")
If MakeJPG = "" Then
MsgBox "Something go wrong, we can't create the mail"
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Exit Sub
End If
On Error Resume Next
If cell.Value Like "?*#?*.?*" And _
Application.WorksheetFunction.CountA(rng) > 0 Then
Set OutMail = OutApp.CreateItem(0)
With OutMail
.Display
.To = cell.Value
.Subject = Range("B11") & Range("H13") & " - " & cell.Offset(0, 2)
.Attachments.Add MakeJPG, 1, 0
.HTMLBody = "Bonjour " & cell.Offset(0, -1).Value & "," & "<br/>" & "<br/>" & Range("B15") & " " & Range("C15") & " " & Range("D15") & "<p>" & Range("B16") & "<p>" & "<\p>" & "</p><img src=""cid:NamePicture.jpg"" width=550 height=150></html>" & "<p>" & "<\p>" & Range("B17") & .HTMLBody
For Each FileCell In rng.SpecialCells(xlCellTypeConstants)
If Trim(FileCell) <> "" Then
If Dir(FileCell.Value) <> "" Then
.Attachments.Add FileCell.Value
End If
End If
Next FileCell
End With
Set OutMail = Nothing
End If
Next cell
Set OutApp = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Function CopyRangeToJPG(NameWorksheet As String, RangeAddress As String) As String
Dim PictureRange As Range
With ActiveWorkbook
On Error Resume Next
.Worksheets(NameWorksheet).Activate
Set PictureRange = .Worksheets(NameWorksheet).Range(RangeAddress)
If PictureRange Is Nothing Then
MsgBox "Sorry this is not a correct range"
On Error GoTo 0
Exit Function
End If
PictureRange.CopyPicture
With .Worksheets(NameWorksheet).ChartObjects.Add(PictureRange.Left, PictureRange.Top, PictureRange.Width, PictureRange.Height)
.Activate
.Chart.Paste
.Chart.Export Environ$("temp") & Application.PathSeparator & "NamePicture.jpg", "JPG"
End With
.Worksheets(NameWorksheet).ChartObjects(.Worksheets(NameWorksheet).ChartObjects.Count).Delete
End With
CopyRangeToJPG = Environ$("temp") & Application.PathSeparator & "NamePicture.jpg"
Set PictureRange = Nothing
End Function
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
Set the initial image range and then offset it after each email sent .
Set rngImage = sh.Range("F27:J28")
Set rngImage = rngImage.Offset(rngImage.Rows.Count)
With the constant TEST = True this code should run without sending emails. If correct set TEST = False.
Option Explicit
Sub Send_Files()
Dim OutApp As Object, OutMail As Object
Dim ws As Worksheet, cell As Range, cellA, rngA As Range
Dim jpgFilename As String, filename As String, html As String
Dim rngImage As Range, sImage As String, n As Long
Const TEST = True ' set to False to use Outlook
Const IMG_NAME = "Image_"
Const IMG_RANGE = "F27:J28" ' first email
If Not TEST Then
Set OutApp = CreateObject("Outlook.Application")
End If
Set ws = Sheets("Sheet1")
Set rngImage = ws.Range(IMG_RANGE) ' first image
' scan column B for valid email addresses
For Each cell In ws.Columns("B").Cells.SpecialCells(xlCellTypeConstants)
'Enter the path/file names in the C:Z column in each row
Set rngA = cell.Offset(,1).Resize(, 24) ' C:Z attachments
If Application.WorksheetFunction.CountA(rngA) = 0 Then
' no attachments - do nothing
ElseIf cell.Value Like "?*#?*.?*" Then
sImage = IMG_NAME & rngImage.Row & ".jpg" ' unique image name for each email
jpgFilename = CopyRangeToJPG(rngImage, sImage)
' email body
html = "Bonjour " & cell.Offset(0, -1).Value & "," & "<br/><br/>" _
& ws.Range("B15") & " " & ws.Range("C15") & " " & ws.Range("D15") & _
"<p>" & ws.Range("B16") & "</p><br/>" & _
"<img src=""cid:" & sImage & """ width=550 height=150>" & _
"<br/>" & ws.Range("B17")
If TEST Then
MsgBox "Image: " & jpgFilename & vbLf & html, vbInformation, "To: " & cell.Value
'Debug.Print html
Else
Set OutMail = OutApp.CreateItem(0)
With OutMail
.Display
.To = cell.Value
.Subject = Range("B11") & Range("H13") & " - " & cell.Offset(0, 2)
.Attachments.Add jpgFilename, 1, 0
.HTMLBody = html & .HTMLBody
' add attachments
For Each cellA In rngA.SpecialCells(xlCellTypeConstants)
filename = Trim(cellA.Value)
If filename <> "" Then
If Dir(filename) <> "" Then ' check file exists
.Attachments.Add filename
Else
MsgBox "Could not attach : " & filename, vbExclamation, cell.Value
End If
End If
Next
End With
Set OutMail = Nothing
End If
' next image
Set rngImage = rngImage.Offset(rngImage.Rows.Count)
n = n + 1
End If
Next
Set OutApp = Nothing
MsgBox n & " emails sent", vbInformation
End Sub
Function CopyRangeToJPG(rngImage As Range, filename As String) As String
Dim ws As Worksheet, folder As String
Set ws = rngImage.Parent ' sheet
' check range
If rngImage Is Nothing Then
MsgBox "Sorry this is not a correct range"
CopyRangeToJPG = ""
Exit Function
End If
' create image file
folder = Environ$("temp") & Application.PathSeparator
rngImage.CopyPicture
With ws.ChartObjects.Add(rngImage.Left, rngImage.Top, rngImage.Width, rngImage.Height)
.Activate
.Chart.Paste
.Chart.Export folder & filename, "JPG"
End With
ws.ChartObjects(ws.ChartObjects.Count).Delete
' return status
CopyRangeToJPG = folder & filename
End Function

Is there a way to export associated comments and replies (comment children) from Microsoft Word to Excel?

I already have this existing code which works great for exporting comments and responses, but it doesn't link them in anyway. Is there a way to modify the code so that when comments are exported comments and replies/responses are linked/identified so you can trace which comments are in response to what? TYIA
Sub ExportComments()
' Note: A reference to the Microsoft Excel # Object Library is required, set via Tools|References in the Word VBE.
Dim StrCmt As String, StrTmp As String, i As Long, j As Long, xlApp As Object, xlWkBk As Object
StrCmt = "Page,Line,Author,Date & Time,Comment,Reference Text"
StrCmt = Replace(StrCmt, ",", vbTab)
With ActiveDocument
' Process the Comments
For i = 1 To .Comments.Count
With .Comments(i)
StrCmt = StrCmt & vbCr & .Reference.Information(wdActiveEndAdjustedPageNumber) & vbTab
StrCmt = StrCmt & .Reference.Information(wdFirstCharacterLineNumber) & vbTab & .Author & vbTab
StrCmt = StrCmt & .Date & vbTab & Replace(Replace(.Range.Text, vbTab, "<TAB>"), vbCr, "<P>")
StrCmt = StrCmt & vbTab & Replace(Replace(.Reference.Text, vbTab, "<TAB>"), vbCr, "<P>")
End With
Next
End With
' Test whether Excel is already running.
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
'Start Excel if it isn't running
If xlApp Is Nothing Then
Set xlApp = CreateObject("Excel.Application")
If xlApp Is Nothing Then
MsgBox "Can't start Excel.", vbExclamation
Exit Sub
End If
End If
On Error GoTo 0
With xlApp
Set xlWkBk = .Workbooks.Add
' Update the workbook.
With xlWkBk.Worksheets(1)
For i = 0 To UBound(Split(StrCmt, vbCr))
StrTmp = Split(StrCmt, vbCr)(i)
For j = 0 To UBound(Split(StrTmp, vbTab))
.Cells(i + 1, j + 1).Value = Split(StrTmp, vbTab)(j)
Next
Next
.Columns("A:D").AutoFit
End With
' Tell the user we're done.
MsgBox "Workbook updates finished.", vbOKOnly
' Switch to the Excel workbook
.Visible = True
End With
' Release object memory
Set xlWkBk = Nothing: Set xlApp = Nothing
End Sub
Replace .Reference.Text with .Scope.Text

Get Emails Not Replied from Shared mailbox VBA

I am trying to Extract Emails from Shared mailbox which i am not Owner i have access to send on behalf
but Unable to save search and If any one can assist to Get Email in last 24hours Which are not Replied from Shared Mailbox
Below is Code Which I was Able to do it
Sub CreateSearchFolder_AllNotRepliedEmails()
Dim OutlookApp As Outlook.Application
Dim strScope As String
Dim OutlookNamespace As NameSpace
Dim strRepliedProperty As String
Dim strFilter As String
Dim objSearch As Outlook.Search
Dim objOwner As Outlook.Recipient
Dim Folder As MAPIFolder
Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")
Set objOwner = OutlookNamespace.CreateRecipient("Sdk#dau.ae")
objOwner.Resolve
Set objOwner = OutlookNamespace.CreateRecipient("Sdk#dau.ae")
objOwner.Resolve
'If objOwner.Resolved Then
'Set Folder = OutlookNamespace.GetSharedDefaultFolder(objOwner, olFolderInbox)
'End If
strScope = "'" & Application.Session.GetSharedDefaultFolder(objOwner, olFolderInbox).FolderPath & "'"
'Search filter
strRepliedProperty = "http://schemas.microsoft.com/mapi/proptag/0x10810003"
strFilter = Chr(34) & strRepliedProperty & Chr(34) & " <> 102" & "AND" & Chr(34) & strRepliedProperty & Chr(34) & " <> 103"
Set objSearch = Outlook.Application.AdvancedSearch(Scope:=strScope, Filter:=strFilter, SearchSubFolders:=True)
'Save the search folder
objSearch.Save ("Sd email not Replied")// Tried This But Not working
MsgBox "Search folder is created successfully!", vbInformation + vbOKOnly, "Search Folder"
End Sub
Kindly advise for Solution
There is no reason to use (asynchronous) AdvancedSearch (unless you want the list saved as a search folder); use (synchronous) Items.Restrict:
filter = "#SQL=""http://schemas.microsoft.com/mapi/proptag/0x10810003"" IS NULL"
set folder = Application.Session.GetSharedDefaultFolder(objOwner, olFolderInbox)
set notRepliedOrForwardedItems = folder.Items.Restrict(filter)
This demonstrates processing search results without a search folder.
After a Eureka moment.
Option Explicit
' Code in ThisOutlookSession
Public blnSearchComp As Boolean
Private Sub Application_AdvancedSearchComplete(ByVal objSearch As Search)
' https://learn.microsoft.com/en-us/office/vba/api/outlook.application.advancedsearch
' Code should be in a class module such as ThisOutlookSession
Debug.Print "The AdvancedSearchComplete Event fired"
If objSearch.Tag = "AdvancedSearch_WithSubfolders_AllNotRepliedEmails_WithoutSavingSearchFolder_220701" Then
'm_SearchComplete = True` ' Use Option Explicit.
blnSearchComp = True
End If
End Sub
Private Sub AdvancedSearch_WithSubfolders_AllNotRepliedEmails_WithoutSavingSearchFolder_220701()
' Code in ThisOutlookSession
Dim strScope As String
Dim strRepliedProperty As String
Dim strFilter As String
Dim objSearch As Search
Dim objOwner As Recipient
Dim rsts As results
Dim objFolder As Folder
' For testing
Set objFolder = Session.GetDefaultFolder(olFolderInbox)
'Set objOwner = Session.CreateRecipient("Sdk#dau.ae")
'objOwner.Resolve
'If objOwner.Resolved Then
' Set objFolder = Session.GetSharedDefaultFolder(objOwner, olFolderInbox)
'End If
strScope = "'" & objFolder.folderPath & "'"
Debug.Print "strScope : " & strScope
'Search filter
strRepliedProperty = "http://schemas.microsoft.com/mapi/proptag/0x10810003"
strFilter = Chr(34) & strRepliedProperty & Chr(34) & " <> 102" & _
"AND" & Chr(34) & strRepliedProperty & Chr(34) & " <> 103"
Debug.Print "strFilter : " & strFilter
' Fewer results than above.
'strFilter = """http://schemas.microsoft.com/mapi/proptag/0x10810003"" IS NULL"
'Debug.Print "strFilter : " & strFilter
' If subfolders not required then Restrict on single folder would be simpler.
'
' If subfolder search required "SearchSubFolders:=True" then
Set objSearch = AdvancedSearch(Scope:=strScope, filter:=strFilter, SearchSubFolders:=True, _
Tag:="AdvancedSearch_WithSubfolders_AllNotRepliedEmails_WithoutSavingSearchFolder_220701")
' 2022-07-01 Eureka!
blnSearchComp = False
' Otherwise remains True.
' Search would work once until Outlook restarted.
While blnSearchComp = False
DoEvents
'Code should be in a class module such as ThisOutlookSession
Debug.Print "Wait a few seconds. Ctrl + Break if needed."
Wend
Debug.Print "objSearch.results.count: " & objSearch.results.count
Set rsts = objSearch.results
' When no saved searchfolder, ensure the search is complete before processing the results.
'
' ---> The Application.AdvancedSearchComplete event signals when search is complete. <---
'
' https://learn.microsoft.com/en-us/office/vba/api/outlook.application.advancedsearchcomplete
' Errors in the sample code:
' Typo blnSearchComp = True - use Option Explicit
' Syntax error Set sch = Application.AdvancedSearch(strS, strF, , "Test") - Missing comma
' Before each search: blnSearchComp = False - Else permanently True after first run
'
' ********************************************
' *** Process search result without saving ***
' ********************************************
If rsts.count > 0 Then
Debug.Print "rsts.count: " & rsts.count
rsts.Sort "[ReceivedTime]", True
With rsts(1)
Debug.Print "First item in results: " & .ReceivedTime & " " & .subject
' .Display ' If required
End With
With rsts(rsts.count)
Debug.Print " Last item in results: " & .ReceivedTime & " " & .subject
' .Display ' If required
End With
Else
Debug.Print "No items found."
End If
Debug.Print "Done."
End Sub
Leaving this in case there are even more pitfalls in AdvancedSearch.
Option Explicit
Private Sub AdvancedSearch_WithSubfolders_AllNotRepliedEmails_WithoutSavingSearchFolder()
' Code in Outlook
Dim strScope As String
Dim strRepliedProperty As String
Dim strFilter As String
Dim objSearch As Search
Dim objOwner As Recipient
Dim rsts As results
Dim objFolder As Folder
' For testing
Set objFolder = Session.GetDefaultFolder(olFolderInbox)
'Set objOwner = Session.CreateRecipient("Sdk#dau.ae")
'objOwner.Resolve
'If objOwner.Resolved Then
' Set objFolder = Session.GetSharedDefaultFolder(objOwner, olFolderInbox)
'End If
strScope = "'" & objFolder.folderPath & "'"
Debug.Print "strScope : " & strScope
'Search filter
strRepliedProperty = "http://schemas.microsoft.com/mapi/proptag/0x10810003"
strFilter = Chr(34) & strRepliedProperty & Chr(34) & " <> 102" & "AND" _
& Chr(34) & strRepliedProperty & Chr(34) & " <> 103"
Debug.Print "strFilter : " & strFilter
' Deleted question indicates other options
' https://stackoverflow.com/questions/19381504/determine-whether-mail-has-been-replied-to
' 102 "Reply to Sender"
' 103 "Reply to All"
' 104 "Forward"
' 108 "Reply to Forward"
' Fewer results than above. NULL may be correct.
'strFilter = """http://schemas.microsoft.com/mapi/proptag/0x10810003"" IS NULL"
'Debug.Print "strFilter : " & strFilter
' If subfolders not required then Restrict on single folder would be simpler.
'
' If subfolder search required "SearchSubFolders:=True" then
Set objSearch = AdvancedSearch(Scope:=strScope, filter:=strFilter, SearchSubFolders:=True)
Set rsts = objSearch.results
' When no saved searchfolder, ensure the search is complete before processing the results.
'
' ---> The Application.AdvancedSearchComplete event signals when search is complete. <---
'
' https://learn.microsoft.com/en-us/office/vba/api/outlook.application.advancedsearchcomplete
' https://stackoverflow.com/questions/31909315/advanced-search-complete-event-not-firing-in-vba
'
' I have to use a workaround for AdvancedSearchComplete.
' I delay to allow the search to complete.
' Resist using this workaround in production code.
'Debug.Print "rsts.count: " & rsts.count
If rsts.count = 0 Then
Dim waitTime As Long
Dim delay As Date
moreDelay:
Debug.Print " Delay invoked."
waitTime = 1 ' in seconds - adjust as needed
Debug.Print vbCr & "Wait start: " & Now
delay = DateAdd("s", waitTime, Now)
Debug.Print "Wait until: " & delay
Do Until Now > delay
DoEvents
Loop
'Debug.Print "rsts.Count: " & rsts.count
If rsts.count = 0 Then
Debug.Print "No mail found or delay too short."
If MsgBox("No mail found or delay too short. Allow more time?", vbYesNo) = vbYes Then
GoTo moreDelay
Else
Debug.Print "No items found. / Search failure acknowledged."
End If
Else
Debug.Print " Delay successful."
GoTo processItems
End If
Else
Debug.Print "Delay not required."
GoTo processItems
End If
Debug.Print "Done."
Exit Sub
processItems:
' ---> After search is confirmed complete with AdvancedSearchComplete <---
' ********************************************
' *** Process search result without saving ***
' ********************************************
If rsts.count > 0 Then
Debug.Print "rsts.count: " & rsts.count
rsts.Sort "[ReceivedTime]", True
With rsts(1)
Debug.Print "First item in results: " & .ReceivedTime & " " & .subject
' .Display ' If required
End With
With rsts(rsts.count)
Debug.Print " Last item in results: " & .ReceivedTime & " " & .subject
' .Display ' If required
End With
End If
Debug.Print "Done."
End Sub

Deleting appointments from shared Outlook calendar

I want to clear a shared calendar.
I have a delete method that works in my Outlook calendar however it doesn't clear the shared calendar.
Private Sub DeleteAllAppointments()
Dim olkApp As Object, _
olkSession As Object, _
olkCalendar As Object, _
olkItem As Object, _
intIndex As Integer
Set olkApp = CreateObject("Outlook.Application")
Set olkSession = olkApp.Session
olkSession.Logon
Set olkCalendar = olkSession.GetDefaultFolder(olFolderCalendar)
For intIndex = olkCalendar.Items.Count To 1 Step -1
Set olkItem = olkCalendar.Items.Item(intIndex)
olkItem.Delete
Next
Set olkItem = Nothing
Set olkCalendar = Nothing
olkSession.Logoff
Set olkSession = Nothing
Set olkApp = Nothing
End Sub
This is where the method fails
Set olkCalendar = olkSession.GetDefaultFolder(olFolderCalendar)
Is this is a folder path issue?
This is how I did it.
Sub Delete_SharedCal_History()
DeleteCal_Appts "Office Calendar", "1/9/2001", "0:00:01", "12/31/2013", "23:59:59"
End Sub
Sub DeleteCal_Appts(sCalendarName As String, ap_dateStart As String, ap_startTime As String, ap_dateEnd As String, ap_endTime As String)
' Specified Shared Calendar - Delete all events in specified Date Range
' Author: Frank Zakikian
Dim objAppointment As AppointmentItem
Dim objAppointments As Items
Dim objNameSpace As NameSpace
Dim objRecip As Recipient
Dim nInc As Integer
Dim sFilter As Variant
Dim dtStartTime As Date, dtEndTime As Date
dtStartTime = CDate(ap_dateStart & " " & ap_timeStart)
dtEndTime = CDate(ap_dateEnd & " " & ap_timeEnd)
Set objNameSpace = Application.GetNamespace("MAPI")
'next line would be for use of personal calendar object..
'Set objAppointments = objNameSpace.GetDefaultFolder(olFolderCalendar)
Set objRecip = objNameSpace.CreateRecipient(sCalendarName)
objRecip.Resolve
'Debug.Print objRec.AddressEntry
Set objAppointments = objNameSpace.GetSharedDefaultFolder(objNameSpace.CreateRecipient("Akron Chambers Calendar"), olFolderCalendar).Items
sFilter = "[Start] > '" & Format(dtStartTime, "ddddd h:nn AMPM") & _
"' And [Start] < '" & Format(dtEndTime, "ddddd h:nn AMPM") & "'"
objAppointments.Sort "[Start]", False
Debug.Print "Total Items at begin: " & objAppointments.Count 'dev. fyi
Set objAppointment = objAppointments.Find(sFilter)
While TypeName(objAppointment) <> "Nothing"
'If MsgBox(objAppointment.Subject & vbCrLf & "Delete " & objRec.AddressEntry & " item now? ", vbYesNo, "Delete Calendar Item") = vbYes Then
objAppointment.Delete
nInc = nInc + 1
'End If
Set objAppointment = objAppointments.FindNext
Wend
MsgBox "Deleted " & nInc & " calendar items.", vbInformation, "Delete done"
Debug.Print "Total Items at finish: " & objAppointments.Count 'dev. fyi
Set objAppointment = Nothing
Set objAppointments = Nothing
End Sub
olkSession.GetDefaultFolder(olFolderCalendar) would retrieve your default Calendar folder. You need to either use olkSession.GetSharedDefaultFolder(someRecipient, olFolderCalendar) (where someRecipient is returned by olkSession.CreateRecipient) or open the appropriate store from the Namespace.Stores collection (assuming the delegate mailbox is already there) and call Store.GetDefaultFolder.

I want to copy data from one excel workbook in to another one(Both have same format) using VBA in MAC OS

Please find the VBA code below:
Sub Select_File_Or_Files_Mac()
Dim MyPath As String
Dim MyScript As String
Dim MyFiles As String
Dim MySplit() As String
Dim a As String
Dim mybook As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim LastCell2 As Range
Dim cell As Variant
Dim Column As Integer
Dim rowno As Integer
On Error GoTo ErrHandler:
MyPath = MacScript("return (path to documents folder) as String")
'Or use MyPath = "Macintosh HD:Users:Ron:Desktop:TestFolder:"
' In the following statement, change true to false in the line "multiple
' selections allowed true" if you do not want to be able to select more
' than one file. Additionally, if you want to filter for multiple files, change
' {""com.microsoft.Excel.xls""} to
' {""com.microsoft.excel.xls"",""public.comma-separated-values-text""}
' if you want to filter on xls and csv files, for example.
MyScript = _
"set applescript's text item delimiters to "","" " & vbNewLine & _
"set theFiles to (choose file of type " & _
" {""org.openxmlformats.spreadsheetml.sheet.macroenabled""} " & _
"with prompt ""Please select a file or files"" default location alias """ & _
MyPath & """ multiple selections allowed true) as string" & vbNewLine & _
"set applescript's text item delimiters to """" " & vbNewLine & _
"return theFiles"
MyFiles = MacScript(MyScript)
MsgBox MyFiles
'On Error GoTo 0
MySplit = Split(MyFiles, ":")
MsgBox MySplit
'For N = LBound(MySplit) To UBound(MySplit)
a = MySplit(UBound(MySplit()))
MsgBox a
' Get the fi le name only and test to see if it is open.
'Fname = Right(MySplit(N), Len(MySplit(N)) - InStrRev(MySplit(N), Application.PathSeparator, , 1))
'If bIsBookOpen(Fname) = False Then
'MsgBox MySplit
'Set mybook = Nothing
'On Error Resume Next
Set mybook = Workbooks.Open(a)
Set ws1 = ThisWorkbook.Worksheets("User_Financial_Input")
Set ws2 = mybook.Worksheets("User_Financial_Input")
ws2.Activate
With ws2
Set LastCell2 = ws2.Range("InputCells_User_Financial_Input")
MsgBox LastCell2
End With
ws2.Select
ws1.Activate
For Each cell In LastCell2
Column = cell.Column
rowno = cell.Row
ws1.Cells(rowno, Column) = cell.value
Next
ErrHandler:
If Err.Number = 9 Then
Answer = MsgBox(Err.Description & Err.Number, vbCritical, "Error")
ElseIf Err.Number = 1004 Then
Answer = MsgBox(Err.Description & Err.Number, vbCritical, "Error")
ElseIf Err.Number = 0 Then
Else
Answer = MsgBox(Err.Description & Err.Number, vbCritical, "Error")
End If
End Sub
There is some problem in the line Set mybook = Workbooks.Open(a). I am getting "Type 13" mismatch error.

Resources