AppleScript for sending emails from a list in Excel - excel

I don’t know AppleScript at all so thanks in advance for any help offered on this question.
I’m on my Macbook Pro laptop with the latest version of OSX installed. I have an Excel spreadsheet (I could use numbers if that makes it easier) with two columns.
FirstName Email
------------ -----------------
Ken blah#blah.com
Mike blahblah#blahblah.com
This is my customer list and I want to send them an email. Unfortunately I don’t have this list in an autoresponder so I have to send the emails one by one.
I know that I could whip up a PHP script to send the emails, however there are issues with email deliverability when doing it this way.
I want to write an AppleScript that processes my spreadsheet one row at a time and sends a message.
The message would be something like this:
Subject: How’s it going?
Hi Ken
It’s been a while since I sold you that defective widget from China.
If you need more defective elctronics I’m here for you. Just give me
a call at xxx-xxx-xxxx.
Sincerely
Ken
The AppleScript would read the name and email address from one row of the spreadsheet and send this email, filling in name and email address, using the standard apple mail program.
After sending the message I want the script to wait 60 seconds. Then send another email.
This needs to happen until a blank row is encountered.
My first question… Is this possible? If possible how do I do it?
Also is there a better way to do what I’m trying to do?
Thanks

There's probably a better way to do this, but couldn't you just copy the addresses as TSV or CSV?
set addresses to "Ken;blah#blah.com
Mike;blahblah#blahblah.com"
set text item delimiters to ";"
repeat with l in paragraphs of addresses
tell application "Mail"
tell (make new outgoing message)
set subject to "subject"
set content to "Hi " & text item 1 of l & linefeed & linefeed & "..."
make new to recipient at end of to recipients with properties {name:text item 1 of l, address:text item 2 of l}
send
delay (random number) * 100
end tell
end tell
end repeat

Try:
set {firstName, eAddress} to getData()
repeat with i from 1 to count firstName
tell application "Mail"
activate
set mymail to make new outgoing message at the beginning of outgoing messages with properties {subject:"How’s it going?"}
tell mymail
make new to recipient at beginning of to recipients with properties {address:item i of eAddress}
set content to "Hi " & item i of firstName & "
It’s been a while since I sold you that defective widget from China.
If you need more defective elctronics I’m here for you. Just give me
a call at xxx-xxx-xxxx.
Sincerely
Ken"
end tell
--show message window (otherwise it's hidden)
set visible of mymail to true
--bring Mail to front
activate
send mymail
end tell
end repeat
on getData()
set colA to {}
set colB to {}
tell application "Microsoft Excel"
activate
tell active sheet
set lastRow to first row index of (get end (last cell of column 1) direction toward the top)
repeat with i from 3 to lastRow
set end of colA to (value of range ("A" & i))
set end of colB to (value of range ("B" & i))
end repeat
end tell
end tell
return {colA, colB}
end getData

Related

Having issue trying to retrieve data from Website to Excel

I want to retrieve a number from the stock website TipRanks, specifically how much upside the stock has according to analyst. It is a simple number to grab and place in a cell range. First off, I am not familiar with coding in VBA at all. I found some video that explains how to retrieve data from a website and used that code. I edited the code where it was needed. Here is my sample code:
Sub StockRetrieve()
Dim bot As New WebDriver
bot.Start "chrome"
For i = 3 To 16
link = Sheets(1).Range("A" & i).Value
bot.ExecuteScript "window.open(arguments[0])", link
bot.SwitchToNextWindow
upside = bot.FindElementByXPath("//*[#id='tr-stock-page-
content']/div[1]/div[4]/div[2]/div[2]/div[3]/div/div/div[1]/div[1]/div").Text
Sheets(1).Range("G" & i).Value = upside
Next i
MsgBox "good"
Basically the code is suppose to read through a list of URLs on my spreadsheet and open those urls up in new tabs. It then finds the upside percentage put them in column G rows 3 to 16.
The error message that i just got was: The source was not found, but some or all event logs could not be searched. Innaccessible logs: security
Any help is appreciated

Excel VBA - Change tab colours based on user

I'm setting up a spreadsheet for multiple users on my team for testing purposes.
The idea is that a spreadsheet gets passed around and any feedback whether it be a pass or fail is noted on the spreadsheet.
I've currently added validation on certain cells which are red until something is filled in by, let's call them the primary tester.
I've added further validation via VBA to check that all red cells have something entered, otherwise the tab colour will turn red.
My problem is that the spreadsheet then gets accessed by the secondary tester then I want the tab to stay red until they have passed or failed the work (again based on cell validation).
So I think I've found a solution whereby the
In a module I've got:
Public Function UserName()
UserName = Environ$("UserName")
End Function
Range("M5").Value = Environ("username")
In another worksheet I've got:
Set myRange3 = ActiveSheet.Range("P21")
If UserName <> Range("M5").Value Then
If UserName = Range("E15").Value Then
If Application.WorksheetFunction.CountA(myRange3) = 0 Then
ActiveWorkbook.ActiveSheet.Tab.Color = vbRed
Else
ActiveWorkbook.ActiveSheet.Tab.Color = xlColorIndexNone
End If
End If
End If
'M5 = Primary tester
'E15 = Secondary tester
I expect the primary tester to have filled in all their requirements, making the tab turn from Red to neutral.
I would then expect the secondary tester to open up the spreadsheet and notice that a tab has been flagged as Red, meaning they need to add their validation of pass/fail for the tab to go neutral.

VBA/Excel - Group by value in table and send e-mail

I have a large list where I have different companies and organisations. My current VBA codes iterates through each table row, and send out an e-mail for each line.
However, what I need to achieve is that there might be companies which have the same parent organisation - in this case, I don't want to send out an e-mail for each company, but would rather send out one e-mail to the organisation, including all the associated companies.
I have tried to illustrate it in below table.
So for record #1, I would just send out an e-mail as always. However for [2-3], I would like to send out one e-mail, which includes company name 2 and 3.
Same goes for record [4-6], which should also send out one e-mail, but include company name #4, #5 and #6.
Example:
Hi Organisation B
Please check below companies in your organisation:
Company 2
Company 3
My current code:
Below is my current code, which iterates through all table rows and send out mails:
'Count table rows
Set tbl = oWorksheet.ListObjects("DataTable")
TableRows = tbl.ListRows.Count
TableRows = TableRows + 1 'Skips the header
iRow = 2 'Skip the header
Do While iRow <= TableRows
Set oNotesMail = oMailDB.CreateDocument
oNotesMail.Form = "Memo"
oNotesMail.SendTo = oWorksheet.Cells(iRow, 5).Value
oNotesMail.Subject = "Company check"
oNotesMail.Body = "Hi " & oWorksheet.Cells(iRow, 2) & "Please check"
oNotesMail.SaveMessageOnSend = True
oNotesMail.PostedDate = Now()
oNotesMail.Send 0, oWorksheet.Cells(iRow, 5).Value
Set oNotesMail = Nothing
Loop
So above code send out an email (in Lotus Notes) for each line.
How can I achieve my example above?
Please note
The table will always be sorted by 'Organisation' - hopefully this will help when the code is iterating through the rows.

VBA Like Function

Basically my code works in such a way that an Incoming email subject from Outlook is compared to a list column in Excel - supposedly those existing email. If the Incoming email is matched with any records then it Shows the value in Excel. However, I noticed that, if the data in Excel contains the hashtag (#) value, even if the incoming email is not the same as the one in Excel- the code marks it as matched.
If emlSubj Like "*" & strSubj & "*" Then
Debug.Print strSubj
Is there something wrong with the code or is it the limitation of the LIKE function?
Use the InStr function instead. It returns an integer specifying the start position of the first occurrence of one string within another.
If InStr(emlSubj , strSubj) > 0 Then
Debug.Print strSubj
End If

Add a space after colored text

I'm Using Microsoft Excel 2013.
I have a lot of data that I need to separate in Excel that is in a single cell. The "Text to Columns" feature works great except for one snag.
In a single cell, I have First Name, Last Name & Email address. The last name and email addresses do not have a space between them, but the color of the names are different than the email.
Example (all caps represent colored names RGB (1, 91, 167), lowercase is the email which is just standard black text):
JOHN DOEjohndoe#acmerockets.com
So I need to put a space after DOE so that it reads:
JOHN DOE johndoe#acmerockets.com
I have about 20k rows to go through so any tips would be appreciated. I just need to get a space or something in between that last name and email so I can use the "Text to Columns" feature and split those up.
Not a complete answer, but I would do it way:
Step 1 to get rid of the formatting:
Copy all text that you have to the notepad
Then copy-paste text from Notepad to excel as text
I think this should remove all the formatting issues
Step 2 is to use VBA to grab emails. I assume that you have all your emails as lowercase. Therefore something like this should do the trick (link link2):
([a-z0-9\-_+]*#([a-z0-9\-_+].)?[a-z0-9\-_+].[a-z0-9]{2,6})
Step 3 is to exclude emails that you extracted from Step2 from your main text. Something like this via simple Excel function:
=TRIM(SUBSTITUTE(FULLTEXT,EMAIL,""))
Since you removed all the formatting in Step1, you can apply it back when you done
You can knock this out pretty quickly taking advantage of a how Font returns the Color for a set of characters that do not have the same color: it returns Null! Knowing this, you can iterate through the characters 2 at a time and find the first spot where it throws Null. You now know that the color shift is there and can spit out the pieces using Mid.
Code makes use of this behavior and IsNull to iterate through a fixed Range. Define the Range however you want to get the cells. By default it spits them out in the neighboring two columns with Offset.
Sub FindChangeInColor()
Dim rng_cell As Range
Dim i As Integer
For Each rng_cell In Range("B2:B4")
For i = 1 To Len(rng_cell.Text) - 1
If IsNull(rng_cell.Characters(i, 2).Font.Color) Then
rng_cell.Offset(0, 1) = Mid(rng_cell, 1, i)
rng_cell.Offset(0, 2) = Mid(rng_cell, i + 1)
End If
Next
Next
End Sub
Picture of ranges and results
The nice thing about this approach is that the actual colors involved don't matter. You also don't have to manually search for a switch, although that would have been the next step.
Also your neighboring cells will be blank if no color change was found, so it's decently robust against bad inputs.
Edit adds ability to change original string if you want that instead:
Sub FindChangeInColorAndAddChar()
Dim rng_cell As Range
Dim i As Integer
For Each rng_cell In Range("B2:B4")
For i = 1 To Len(rng_cell.Text) - 1
If IsNull(rng_cell.Characters(i, 2).Font.Color) Then
rng_cell = Mid(rng_cell, 1, i) & "|" & Mid(rng_cell, i + 1)
End If
Next
Next
End Sub
Picture of results again use same input as above.

Resources