I am writing an Excel macro to send emails from data in a spreadsheet. The data are in a table with each column providing different variables to create the email (to:, cc:, subject, attachments, etc).
I’ve got the macro to do what I want on one line of the table. My question is:
How do I scale the VBA code to work for each line of my table? I would like a hyperlink in each row to run the macro using the data in that row. Below is a small snippet of my code as an example:
Sub SendMail() Dim xContractNumber As String xContractNumber = Worksheets("Program Info").Range("L10").Value End Sub
In the above example, I would like a hyperlink that runs the macro using the data in row 10 of the ‘Program Info’ sheet… And another button or link that would run the macro using data in row 11, and so on.
This answer attempts to combine many of the good answers and comments everyone has already given. The code below contains the functionality for both buttons and hyperlinks in a condensed way.
This code could go in one separate module:
Sub SendMailByButton() SendMailForRow ActiveSheet.Buttons(Application.Caller).TopLeftCell.Row End Sub Sub SendMailForRow(ByVal r As Long) If r < 1 Then Exit Sub 'Failsafe in case the row number is invalid Dim xContractNumber As String, xValueInColumnM As String, xValueInColumnN As String xContractNumber = ActiveSheet.Cells(r, 12).Value 'Col 12 is col "L" xValueInColumnM = ActiveSheet.Cells(r, 13).Value xValueInColumnN = ActiveSheet.Cells(r, 14).Value '...etc. '...Rest of code to send the actual email End Sub
If buttons are used,
SendMailByButton must be attached to every button’s click event, and the above code would be enough.
If manually-added hyperlinks are used, the above code would need to be complemented with the following code in the sheet module for every sheet that uses the hyperlinks (in your case, you may only need to add this code in one sheet’s module) …
'This event is fired when the hyperlink is clicked Private Sub Worksheet_FollowHyperlink(ByVal target As Hyperlink) On Error Resume Next SendMailForRow target.Range.Row End Sub
Each manual hyperlink would have to link to the same cell it is sitting on (i.e. to a “Place in This Document” with the cell reference set to its current cell).
The problem remains that you will need to manually create a button or hyperlink for every row in your table, which can be a hassle, especially if there are many rows or if the number of rows can grow in future.
A way to circumvent this problem is to have an extra button at the top of the table that allows the user to automatically create the buttons and/or hyperlinks for each row of data (removing excess buttons or hyperlinks if the table shrinks in size). This may require that you post a separate question.
Another way to circumvent this problem is to forego buttons altogether and, instead, use Excel formulas with the native HYPERLINK function (replacing the “regular” links). In that case, the FollowHyperlink event handler above would no longer be needed, but you would need to add the following function (which can go in the same module where
SendMailForRow would reside) …
Function SendMailByHLink() SendMailForRow ActiveCell.Row Set SendMailByHLink = ActiveCell End Function
You would then have to create an Excel formula such as the following in each row (in the column where you want the hyperlink) …
=HYPERLINK("#SendMailByHLink()", "Send email")
Entering this formula will auto-generate a hyperlink in the cell, and it will tell Excel to execute function
SendMailByHLink when the hyperlink is clicked. The function after the “#” is supposed to return the link’s target, which is why
ActiveCell to ensure that the focus remains on that cell (if you prefer, you could return another cell such as
ActiveCell.Offset(, -2) so that the user is taken to the cell 2 columns back in the same row after the link is clicked). Before returning
ActiveCell to Excel,
SendMailByHLink will execute the email-sending code.
The nice thing about using a HYPERLINK formula is that you can easily copy/paste the formula up and down the all the rows in the table. Therefore, if your table increases in size, all the user has to do is to copy/paste the HYPERLINK formula into the new rows. The user can also delete excess HYPERLINK formulas if the table shrinks. It may even be possible to have Excel automatically copy the formula if the data is sitting on an official Excel table by using a calculated column.
Sorry for all the extra explanation. If you focus on the code blocks, you will see that the solution is simpler than it looks.