Jump to content
Revelation343

Mailing from Excel/variable storing

Recommended Posts

Revelation343

Purpose of script: To send emails in Outlook based on data in an excel spreadsheet. From: fields are entered for purposes of sending on behalf of (delegate), copies A2 cell from excel for To: field, Subject field is a static value and entered, returns to excel spreadsheet to read A1 and copy the first name and insert into the body of a template at an insertion point. The From, and the body of the email change based on region, so currently I have 6 different scripts that do essentially the same thing with some minor changes and want to consolidate into one script to save time.

Question:
To expedite the process of this and cut down on the amount of scripts, 6 in total I use daily, is it possible for me to somehow add the region to column C in excel, have autoit read column C values per row, and then decide which function, within a master script, to execute and loop this until there is no value in column C field?

Example spreadsheet:

Rob | rob@annuity.com |Midwest
Annie | annie@agency.com | Midwest
Kyle | kyle@agency.com | MidAtlantic
Rick | rick@megasales.com | MidAtlantic
Blank | Blank | Blank |

Example execution:
Run Birthday.au3, execute loop part through hotkey
Reads row 1, C1, value is Midwest, calls Midwest(), script runs as Midwest Birthday.au3 does currently
Reads row 2, C2, value is Midwest, calls Midwest(), script runs as Midwest Birthday.au3 does currently
Reads row 3, C3, value is MidAtlantic, calls MidAtlantic(), script runs as MidAtlantic Birthday.au3 currently
Reads row 4, C4, value is MidAtlantic, calls MidAtlantic(), script runs as MidAtlantic Birthday.au3 currently
Reads row 5, C5, value is null or blank, ends script through Exit

 

Everything I have coded in my time in AutoIt has been based mostly on mouse based movements and I don't have variable programming knowledge so I feel like I'm close to understanding how to do this, but the reading/storing variables part is beyond my current skill set. Help is appreciated. :)

Mail Merges don't work as delegated in Outlook 07, for those that might be questioning why I just don't do that.
 

MidAtlantic Birthday.au3

Midwest Birthday.au3

Edited by Revelation343

Share this post


Link to post
Share on other sites
water

I suggest to use the Excel UDF that comes with AutoIt plus the OutlookEX UDF which you can download from my signature.
First use _Excel_RangeRead to read the whole worksheet into an array, then loop through the array and call _OL_Wrapper_SendMail to create the mail and send it.

If needed I can provide an example script.

 

 

Edited by water
  • Like 1

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
water
#include <Excel.au3>
#include "OutlookEX.au3"

Global $oExcel = _Excel_Open()
Global $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\Test_Mail.xlsx", True) ; Open Excel workbook read-only
Global $aData = _Excel_RangeRead($oWorkbook)
_Excel_BookClose($oWorkbook, False)
_Excel_Close($oExcel, False)

$oOL = _OL_Open()

; Retrieve defined signatures
Global $aSignatures = _OL_MailSignatureGet()
; Deactivate signature for new emails
_OL_MailSignatureSet("", Default)

; Create, Modify and send mails
For $i = 0 To UBound($aData, 1) - 1
    $oItem = _OL_ItemCreate($oOL, $olMailItem, "", @ScriptDir & "\" & $aData[$i][2] & ".msg", "Subject=Test")
    ConsoleWrite("IC: " & @error & "-" & @extended & @CRLF)
    $aBody = _OL_ItemGet($oOL, $oItem, Default, "HTMLBody")
    ConsoleWrite("IG: " & @error & "-" & @extended & @CRLF)
    $sBody = StringReplace($aBody[1][1], "%Firstname%", $aData[$i][0])
    _OL_ItemModify($oOL, $oItem, Default, "HTMLBody=" & $sBody)
    ConsoleWrite("IM: " & @error & "-" & @extended & @CRLF)
    _OL_ItemRecipientAdd($oOL, $oItem, Default, $olTo, $aData[$i][1])
    ConsoleWrite("RA: " & @error & "-" & @extended & @CRLF)
    $oItem.Display()
Next

; Set signature for new emails to previous value
For $i = 1 To $aSignatures[0][0]
    If $aSignatures[$i][1] = True Then
        _OL_MailSignatureSet($aSignatures[$i][0], Default)
        ExitLoop
    EndIf
Next

_OL_Close($oOL)

First (quick & dirty) example. Reads all records from Test_mail.xlsx with the structure as defined by you.
Depending on the value in column C (MidWest, MidAtlantic) an email is created based on template MidWest.msg or MidAtlantic.msg.
Placeholder "%Firstname%" is replaced with the recipients name.
Then the mail is being displayed (parameter SentOnBehalf has not been set yet).

What you need to do:

  • Place above script in a directory
  • Create MidWest.Msg and MidAtlantic.msg in the same directory
  • Create Test_mail.xlsx in the same directory

Example MidAtlantic.msg:

Quote

Dear %FirstName%,

Happy Birthday from your friends at x y.

Signature MidAtlantic

 

Edited by water
  • Like 1

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
Revelation343

Ok this makes sense. Is there a way to input the From field based on column C? Or I could just make it to where the From email is in Column D if need be if that would be easier.

Edit: Nevermind, I think I got it to work here, I just added the values for the From address to the D column. :) Take a look at it and let me know if there's anything obvious I'm missing but based on my testing it looks like this is exactly the functionality I need and I have a much better understanding of how this works now.

#include <Excel.au3>
#include "OutlookEX.au3"

Global $oExcel = _Excel_Open()
Global $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\" & "Birthday.xlsx", True) ; Open Excel workbook read-only
Global $aData = _Excel_RangeRead($oWorkbook)
_Excel_BookClose($oWorkbook, False)
_Excel_Close($oExcel, False)

$oOL = _OL_Open()

; Retrieve defined signatures
Global $aSignatures = _OL_MailSignatureGet()
; Deactivate signature for new emails
_OL_MailSignatureSet("", Default)

; Create, Modify and send mails
For $i = 0 To UBound($aData, 1) - 1
    $oItem = _OL_ItemCreate($oOL, $olMailItem, "", @ScriptDir & "\" & $aData[$i][2] & ".msg", "Subject=Test", "SentOnBehalfOfName="& $aData[$i][3])
    ConsoleWrite("IC: " & @error & "-" & @extended & @CRLF)
    $aBody = _OL_ItemGet($oOL, $oItem, Default, "HTMLBody")
    ConsoleWrite("IG: " & @error & "-" & @extended & @CRLF)
    $sBody = StringReplace($aBody[1][1], "%Firstname%", $aData[$i][0])
    _OL_ItemModify($oOL, $oItem, Default, "HTMLBody=" & $sBody)
    ConsoleWrite("IM: " & @error & "-" & @extended & @CRLF)
    _OL_ItemRecipientAdd($oOL, $oItem, Default, $olTo, $aData[$i][1])
    ConsoleWrite("RA: " & @error & "-" & @extended & @CRLF)
    $oItem.Display()
Next

; Set signature for new emails to previous value
For $i = 1 To $aSignatures[0][0]
    If $aSignatures[$i][1] = True Then
        _OL_MailSignatureSet($aSignatures[$i][0], Default)
        ExitLoop
    EndIf
Next

 

Edited by Revelation343

Share this post


Link to post
Share on other sites
water

Looks quite good :)
Before using the script in production you could remove the ConsoleWrite statements. I inserted them for debugging reasons.

  • Like 1

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
Revelation343

Okay. Is there a maximum of new messages outlook has? So far I'm just running in batches of about 24. I don't know if it would be dependent on RAM or if Outlook has a hard cap. I feel like I've encountered a cap before when I was doing an deliverable report.

Share this post


Link to post
Share on other sites
water

Outlook is just the frontend to a mail server like Exchange. I've never heard of a limit for Outlook. Maybe the mail server has a limit to prevent mail floods.

Next idea would be to set the date in the Excel file. This would allow to restart the script without re-sending all mails by checking the date.
Right now the created mails get displayed. If you want to send them automatically then better error checking would be needed.

What do you plan as a next step?

  • Like 1

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
Revelation343

I like the ability to review before sending. Though in my first 3 batches of 24, there were no errors. I mean, this function is to basically pat some people on the back and isn't a high influence sort of issue. I've been out of the office for a few days so I have 249 more to send, but on the daily, this functionality should be more than sufficient. I am interested in the concept of being able to check the date incase I do have a large list like this in the future though.

 

Edit: I was able to just keep hitting send and produce all 249 at once so the hard cap that I ran into before must have only been a figment of my overworked imagination. :) 

Edited by Revelation343

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • nooneclose
      By nooneclose
      Good morning everyone, I thought I had already solved this issue but it turns out I did not. 
      My code finds unread emails with this specific subject line of "request" but when I change the subject to SKIPPED + "request" = ("SKIPPED request") the program still finds the email and tries to process it. I only want to process emails with the exact match subject of "request".
      Here is my code that "finds" the unread emails with the subject of "request" or so I thought. 
      Func ListUnreadEmails() ;******************************************************************************* ; Lists all unread E-mails from the folder Outlook-UDF-Test ;******************************************************************************* ; Stores all the unRead emails into an array Global $aItems = _OL_ItemFind($oOutlook, "*\Outlook-UDF-Test", $olMail, _ "[UnRead]=True", "Subject", "request", "EntryID,Subject", "", 1) ; Displays the array of unRead emails If IsArray($aItems) Then ;_ArrayDisplay($aItems, "OutlookEX UDF: _OL_ItemFind - Unread mails") Else MsgBox(48, "OutlookEX UDF: _OL_ItemFind Example Script", _ "Could not find an unread mail. @error = " & @error & ", @extended: " & @extended) EndIf ; Gets the number of unread emails Global $numberOfUnRead = UBound($aItems, $UBOUND_ROWS) - 1 ;MsgBox("", "Number of Unread emails", $numberOfUnRead) EndFunc It acts as if any part of the subject containing the word "request" and the email is unread that it will try to process it. (I think)
    • nooneclose
      By nooneclose
      Good afternoon, I am in need of some help. I am sure this is a stupid question requiring only one or two lines of code. However, I would greatly appreciate the help I cannot figure this out. I also tried searching for the answer on the internet but no one except me apparently seems to be having a hard time figuring this out and or is asking about it. 
      I simply want to change the "status" of an email from unread to read once I have processed it. My code is over 500 lines and I would like not to clutter this post with it. Assume I have all my includes and connections properly defined and stuff. 
      Here is the bit of code where I am trying to change the email that was used from unread to read:
      Func ChangeEmailStatus() ;******************************************************************************* ; changes the status of an email from unread to Read ;******************************************************************************* Local $iRows = UBound($aItems, $UBOUND_ROWS) MsgBox("", "Number of Unread emails (Before Change)", $iRows) _OL_ItemModify($oOutlook,$aItems[$i][0], Default, "Read=True") MsgBox("", "Array Display 1", $aItems[1][0]) MsgBox("", "Array Display 2", $aItems[2][0]) Local $iRows = UBound($aItems, $UBOUND_ROWS) MsgBox("", "Number of Unread emails (After Change)", $iRows) EndFunc  
    • Jackized
      By Jackized
      Is there a way to loop back to the beginning and keep the already entered data in the GUI Input boxes? I can GUIDelete and start a new GUI but all the typed data has to be redone. Here is a sample.

       
      #Include <GuiConstants.au3> Dim $msg,$okbutton,$cancelbutton,$objOU,$intAccValue,$strGroup1,$strGroup2 Dim $strFirstName,$strLastName,$strUserName,$strUserName2,$strPassword,$strDescription,$strContainer Dim $Combo,$Duration Do $Form1 = GuiCreate("", 300, 300)          GUISetBkColor(0xA6CAF0)         GuiCtrlCreateLabel("First Name:", 50, 10)         $strFirstName = GuiCtrlCreateInput("", 50, 25, 200, 20)         GUICtrlSetState ( $okbutton, $GUI_FOCUS )         GuiSetState()     $okbutton = GUICtrlCreateButton ("OK",75,240,50,20)     $cancelbutton = GUICtrlCreateButton ("Cancel",175,240,50,20) While 1     $msg = GUIGetMsg()     Select     Case $msg = $GUI_EVENT_CLOSE Or $msg = $cancelbutton             Exit     Case $msg = $okbutton             $strFirstName = GUICtrlRead($strFirstName)             ExitLoop     EndSelect Wend $len = StringLen($strFirstName)     If $len > "20" then         MsgBox(0, "ERROR Name to long", $strFirstName & " can't be over 20 characters." & @CRLF & "Total: " & $len)         ;Exit         GUIDelete($Form1)     EndIf Until $len < "20" MsgBox(0, "Done", "")  
×