Referencing an email address from a different sheet - vba

I am having some trouble referencing an email address from a different sheet so I can send an email when a certain name is selected and "open" is chosen from a drop down box it will automatically send an email to that person. I have so far:
Sub Macro1()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("M").Cells.SpecialCells(xlCellTypeConstants)
If cell.Value Like "?*#xyz.com" And _
LCase(Cells(cell.Row, "N").Value) = "open" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = cell.Value
.Subject = "Open Issue"
.Body = "Dear " & Cells(cell.Row, "J").Value _
& vbNewLine & _
"Issue raised: " & Cells(cell.Row, "C").Value _
& vbNewLine & _
"Regards"
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
This works if I input an email address in to column M manually but I am trying to have it so that when a name is selected from a drop down box in J it matches up the email to the name and sends it when "open" is selected from column N.
I have created a table with names and emails in another sheet which M uses VLookup to reference using =VLOOKUP(J3,Team!B5:E8,4,FALSE). I have tried adding HYPERLINK in front of VLOOKUP but it still doesn't create a link.
I also tried creating the email address from the names using split and concatenate but to no avail.

Your problem is that you use SpecialCells(xlCellTypeConstants). Once you made column M a formula your code will now ignore all the cells that have formulas in column M.
You can adjust the xlCellTypeConstants to xlCellTypeFormulas or just get rid of SpecialCells altogether to include both.

Related

why does my VBA code that works in module not work as expected when assigned to a worksheet and a button

I have a workbook that is essentially an automated test, marking and feedback tool for end of topic tests for students. On the '701Test' sheetThey input their teaching group via a drop down list and the select their from subsequent list. They answer the multiple choice questions and press a button when finished. The button takes them to a 'results' page which gives their marks for each question, give feedback for incorrect answers and gives a total score. They then hit the finish button which generates a PDF copy of the mark sheet in their my documents folder and then emails a copy to themselves and the Schools email account. At this point I also wanted to post the final score to the students record on a central registry using a loop through the student list to find the name and offset to post the Score value from the 'Results' page and finally return to the test page. This last bit I wrote the code for in a module and it executes perfectly, but when added to the main code and run from the button the loop part fails to execute but the return to the test page does work, but no error is recorded for the loop failure.
Here is the 'Results' page code in full the 'With Central reg' bit at the bottom is the problem, any help is greatly appreciated.
Private Sub CommandButton1_Click()
Dim IsCreated As Boolean
Dim PdfFile As String, Title As String
Dim OutlApp As Object
Dim cell As Range
Dim Students As Range
Title = Range("D1").Value
sname = Range("B2").Value
PdfFile = CreateObject("WScript.Shell").SpecialFolders("MyDocuments") & "\" & sname & Title & ".pdf"
With ActiveSheet
.ExportAsFixedFormat Type:=xlTypePDF, Filename:=PdfFile, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
End With
On Error Resume Next
Set OutlApp = GetObject(, "Outlook.Application")
If Err Then
Set OutlApp = CreateObject("Outlook.Application")
IsCreated = True
End If
OutlApp.Visible = True
On Error GoTo 0
With OutlApp.CreateItem(0)
.Subject = Title
.to = Range("B2").Value ' <-- Put email of the recipient here"
.CC = "" ' <-- Put email of 'copy to' recipient here
.Body = "Hi," & vbLf & vbLf _
& "Yr 7 701 EOT test attached in PDF format." & vbLf & vbLf _
& "Regards," & vbLf _
& "KDS ICT Dept" & vbLf & vbLf
.Attachments.Add PdfFile
Application.Visible = True
.Display
End With
If IsCreated Then OutlApp.Quit
Set OutlApp = Nothing
With CentralReg
For Each cell In Range("A2:A250")
If cell = Range("Results!B2").Value Then
cell.Offset(0, 4).Activate
ActiveCell.Value = Range("Results!B27").Value
End If
Next
End With
End Sub
I believe you are trying to refer to CentralReg which is a worksheet, which means you should qualify it as such.
Also, you should not dim variables that are similar to defined objects/properties in VBE. Try MyCell instead of cell (good practice, not required).
I am assuming you want to see if the value on sheet CentralReg in Column A is equal to sheet Result B2. If this condition is met, your MyCell will take on the value equal sheet Result B27
Dim MyCell As Range
Dim Result, NewValue as Variant
Result = ThisWorkbook.Sheets("Result").Range("B2")
NewValue = ThisWorkbook.Sheets("Result").Range("B27")
With ThisWorkbook.Sheets("CentralReg")
For Each MyCell In .Range("A2:A250")
If MyCell = Result Then MyCell.Offset(, 4) = NewValue
Next MyCell
End With
That with statement is useless as nothing actually uses it within the construct.
Delete with CentralReg and End with and it will work.
alternatively if CentralReg IS something like a sheet then you need to precede your code with a . so this: Range("A2:A250") becomes this: .Range("A2:A250") and so on, the . tells the code that it is related to whatever your with construct surrounds

AutoRunning Upon Open Issue

First off, I'm not very savvy when it comes to programming in VBA. I've done a lot of programming in the past in Java, C++, C#, and a few others so I'm not completely new to programming in general.
My current issue is that I have an inventory list that I want a notification to be emailed from once a certain quantity has reached a certain value. The email notification is setup and working fine except when the worksheet is closed then reopened, the notification will be sent again if the value has not gone above what was previously set. For example, if the quantity is at or below 1, a notification will be emailed. If that quantity is not changed to 2+ before the worksheet is saved and closed, the next time the sheet is opened, the notification will be sent again.
I want to limit this so that only when the quantity is changed for the first time then the notification is sent.
Code below:
Public Function EmailNotification(model As String, color As String, cell1 As Range)
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
If cell1.Value <= 1 Then
'For Each cell In Columns("R").Cells.SpecialCells(xlCellTypeConstants)
'If cell.Value Like "?*#?*.?*" And _
'LCase(Cells(cell.Row, "S").Value) = "yes" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "username#domain.com"
.Subject = "Excel Notification: Toner Renewal"
.Body = "Dear Team," & _
vbNewLine & vbNewLine & _
"Please prep an order for " & color & " toner for a Dell " & model & vbNewLine & vbNewLine & _
"Quantity Remaining: " & cell1 & vbNewLine & vbNewLine & _
"Notification Sent: " & Now() & " from " & ActiveWorkbook.FullName
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
'End If
'Next cell
End If
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Function
cell1 is the quantity that gets checked in the function.
I'm not sure if there is a way to halt this AutoRun at the startup then allow it to run again whenever one of the quantities is changed.
Thanks in advance for your help!
I'd take a cell in your workbook (say cell2) and store a boolean to say if the email has already been sent once or not.
Your function would look something like this:
Public Function EmailNotification(model As String, color As String, cell1 As Range, cell2 As Range)
Dim notifSent As Boolean: notifSent = cell2.Value '<-- get the value of cell2
If cell1.Value <= 1 And Not notifSent 'if quantity below threshold and no notification yet sent
'you send the email for the first time...
cell2.Value = True 'and you set this information in your cell
ElseIf cell1.Value > 1 And notifSent 'if quantity above threshold and notification has been sent before
cell2.Value = False 'reset notification to false
End If

VBA Excel creating Outlook email subject and body blank

I've got an Excel spreadsheet built by someone else that sends an email to a group via a scheduled task, or at least used to. It recently stopped working. I don't have the time to rebuild his whole Rube Goldberg / Wile E. Coyote system at the moment, so I'm trying to fix it.
In one of the excel documents, this code exists
Set rng = Nothing
On Error Resume Next
Set rng = Sheets("Weight").Range("A2")
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected" & _
vbNewLine & "please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "eric.lizotte#.com"
.CC = ""
.BCC = ""
.Subject = Sheets("Weight").Range("A1")
.HTMLBody = Convert.ToString(rng)
.Send
End With
whenever I see so many "on error resume next" in something I grit my teeth.
What's happening is that it "works" but the email it sends is blank. In debug I can see that the subject content and body content both exist and have values. I rewrote it to be
OutMail.To = "eric.lizotte#.com"
OutMail.CC = ""
OutMail.BCC = ""
OutMail.Subject = Sheets("Weight").Range("A1")
OutMail.HTMLBody = Convert.ToString(rng)
OutMail.Send
and threw a debug point on the send, and checked the properties of outmail, and the subject and htmlbody have values. I can't figure out why after the send they are blank.
Given you are automating another application you probably should not rely on the default property of the range - just specify the property you want e.g. Value:
OutMail.Subject = Sheets("Weight").Range("A1").Value
OutMail.HTMLBody = rng.Value
You might also try the Text property for the HTMLBody:
OutMail.HTMLBody = rng.Text
You can then be confident that you are assigning a String to the mail properties which is what it expects.

"Run-time error '13': Type Mismatch." when there is no email address

I am having trouble solving an error that occurs when sending an email through excel. At the moment it is set so that when a drop down list is titled "Open" in column "N" it send an email to a specific person who's email address appears in column "M" (I select the name for emailing in "J" and it creates the address in "M"). I think the problem could be that it checks every row that I have "Open" in "N" and so when there is no email address it throws up the "Run-time error '13': Type Mismatch." I currently have the following code:
In Sheet 1 (Issue Sheet):
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("N3")) Is Nothing Then
Select Case Range("N3")
Case "Open": Macro1
End Select
End If
End Sub
and my Module being:
Option Explicit
Sub Macro1()
Dim OutApp As Object
Dim OutMail As Object
Dim cell As Range
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
For Each cell In Columns("M").Cells
If cell.Value Like "?*#xyz.com" And _
LCase(Cells(cell.Row, 14).Value) = "open" Then
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = cell.Value
.Subject = "Open Issue"
.Body = "Dear " & Cells(cell.Row, "J").Value _
& vbNewLine & _
"Issue raised: " & Cells(cell.Row, "C").Value _
& vbNewLine & _
"Regards"
'You can add files also like this
'.Attachments.Add ("C:\test.txt")
.Display 'Or use Display
End With
On Error GoTo 0
Set OutMail = Nothing
End If
Next cell
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
Essentially what I want it to do is be able to send an email only to the address, in the row that the "Open" drop down is selected from i.e "Open" chosen in column "N" and then will send email only to the address in "M" of that row. I need this to be expandable too so I can go down several rows and only send email from that one.
I am addressing only the error in the title, I haven't looked at the rest of the code or whether it does what you want. Your problem is in this line
LCase(Cells(cell.Row, "N").Value) = "open" Then
Cells() is expecting a row number and a column number but you are using a string ("N") as the column number, thats a type mismatch, if you want column "N" then use the number 14 like this
LCase(Cells(cell.Row, 14).Value) = "open" Then

VBA Excel - If cell in one column contains email address and cell in another column is "SOLD" , send email

Just started experimenting with VBA today. Creating Excel sheet to track SOLD, PENDING, LOST that will allow salesmen to click a button to send a group email to one category at a time. After much searching I found some code that works well to send group email by checking a column to make sure a proper address is there. I found some other code that I thought would check the "Job Status" column so that only the "SOLD" or whatever would be chosen for email. I am a clueless beginner and need help. Here is the code that was working until I added the - If Sh.Cells(Target.Row, 7) = "PENDING" Then - part. Any help would be greatly appreciated. Thanks!
Private Sub CommandButton1_Click()
Dim cell As Range
Dim strto As String
For Each cell In ThisWorkbook.Sheets("Sales 2013").Range("E3:E500")
If cell.Value Like "?*#?*.?*" Then
If Sh.Cells(Target.Row, 7) = "PENDING" Then
strto = strto & cell.Value & ";"
End If
End If
Next cell
If Len(strto) > 0 Then strto = Left(strto, Len(strto) - 1)
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
OutApp.Session.Logon
On Error GoTo cleanup
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "Anchor Sales"
.Bcc = strto
.Subject = "Enter subject here"
.Body = "" ' EMPTY FOR NOW
'USE THIS FOR ENTERING NAMES OF RECIPIENTS IN BODY TEXT "here"
'"Dear" & Cells(cell.Row, "A").Value _
& vbNewLine & vbNewLine & _
"Enter body text " & _
"here"
'You can add files also like this
'.Attachments.Add ("C:\test.txt")
'.Send 'Or use Display
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
Private Sub CommandButton2_Click()
End Sub
Please help!
of course I would prefer to send one mail per Person (if the recipients shall not know each other), but let's stay with your Problem.
you only need minor changes:
Private Sub CommandButton1_Click()
Dim cell As Range
Dim strto As String
For Each cell In ThisWorkbook.Sheets("Sales 2013").Range("E3:E500")
If cell.Value = "PENDING" Then strto = strto & cell.offset(0, 1).value & ";"
I am not sure if you Need the part "If cell.Value Like "?#?.?*" " or if that is from copy-paste from the code you found... If you Need it, the last line would have to be replaced by
If cell.Value Like "?*#?*.?*" and cell.Value = "PENDING" Then strto = strto & cell.offset(0, 1).value & ";"
'in Offset(0,1) I assume the mailadress is in the cell next to the cell tested for "pending"
Next cell
If Len(strto) > 0 Then strto = Left(strto, Len(strto) - 1)
the rest as you have it.
the Problem was caused by
If Sh.Cells(Target.Row, 7) = "PENDING" Then
as you have no definition for "sh" - but you also don't need it.
I hope this helps