Отправка нескольких электронных писем с использованием данных из ячеек Excel с использованием VBA - PullRequest
0 голосов
/ 16 сентября 2018

У меня есть таблица клиентов с указанием их имени, адреса электронной почты, контакта и администратора.Я хочу иметь возможность отправлять отдельное электронное письмо каждому клиенту, используя данные из строк, перечисленных в нем.

У меня есть несколько VBA, которые я написал (части получены от других людей), ноон пытается добавить все адреса электронной почты в поле to, а каждое другое поле извлекает все данные вместо соответствующей строки.

Я довольно новичок в этом материале VBA и очень признателен за помощь.

Как мне составить черновик отдельных писем для каждого клиента с информацией только из строки, в которой указан клиент.

Пример данных:

В столбце B указаны имена клиентов из строки 3вниз

В столбце C указаны адреса электронной почты из строки 3 вниз

В столбце E указано имя контакта из строки 3 вниз

В столбце G указано имя администратора из строки 3 вниз

Вот VBA:

    Option Explicit

Sub AlexsEmailSender()
    Dim OutApp As Object
    Dim OutMail As Object
    Dim lngLastRow  As Long
    Dim rngMyCell   As Range
    Dim objEmailTo  As Object
    Dim strEmailTo  As String
    Dim objCCTo     As Object
    Dim strCCTo     As String
    Dim objContact As Object
    Dim strContact As String
    Dim objAdmin As Object
    Dim strAdmin As String
    Dim strbody     As String
    Dim objClient As Object
    Dim strClient As String
    Dim strToday As Date
    strToday = Date
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

     'Make sure emails are unique
    Set objEmailTo = CreateObject("Scripting.Dictionary")

    lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "C").End(xlUp).Row

    For Each rngMyCell In Worksheets("Sheet1").Range("C3:C" & lngLastRow)
        If Len(rngMyCell) > 0 Then
            If objEmailTo.Exists(CStr(rngMyCell)) = False Then
                objEmailTo.Add CStr(rngMyCell), rngMyCell
            End If
        End If
    Next rngMyCell

    strEmailTo = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objEmailTo.Items)), ";")

     'Make sure cc emails are unique
    Set objCCTo = CreateObject("Scripting.Dictionary")

    lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "D").End(xlUp).Row

    For Each rngMyCell In Worksheets("Sheet1").Range("D3:D" & lngLastRow)
        If Len(rngMyCell) > 0 Then
            If objCCTo.Exists(CStr(rngMyCell)) = False Then
                objCCTo.Add CStr(rngMyCell), rngMyCell
            End If
        End If
    Next rngMyCell

    strCCTo = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objCCTo.Items)), ";")

    'Make sure contacts are unique
    Set objContact = CreateObject("Scripting.Dictionary")

    lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "E").End(xlUp).Row

    For Each rngMyCell In Worksheets("Sheet1").Range("E3:E" & lngLastRow)
        If Len(rngMyCell) > 0 Then
            If objContact.Exists(CStr(rngMyCell)) = False Then
                objContact.Add CStr(rngMyCell), rngMyCell
            End If
        End If
    Next rngMyCell

    strContact = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objContact.Items)), ";")

    'Make sure admins are unique
    Set objAdmin = CreateObject("Scripting.Dictionary")

    lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "G").End(xlUp).Row

    For Each rngMyCell In Worksheets("Sheet1").Range("G3:G" & lngLastRow)
        If Len(rngMyCell) > 0 Then
            If objAdmin.Exists(CStr(rngMyCell)) = False Then
                objAdmin.Add CStr(rngMyCell), rngMyCell
            End If
        End If
    Next rngMyCell

    strAdmin = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objAdmin.Items)), ";")

    'Make sure clients are unique
    Set objClient = CreateObject("Scripting.Dictionary")

    lngLastRow = Worksheets("Sheet1").Cells(Rows.Count, "B").End(xlUp).Row

    For Each rngMyCell In Worksheets("Sheet1").Range("B3:B" & lngLastRow)
        If Len(rngMyCell) > 0 Then
            If objClient.Exists(CStr(rngMyCell)) = False Then
                objClient.Add CStr(rngMyCell), rngMyCell
            End If
        End If
    Next rngMyCell

    strClient = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(objClient.Items)), ";")

    Application.ScreenUpdating = True
    strbody = "Dear " & strContact & "," & vbNewLine & vbNewLine & _
    "Say Hello World!" & vbNewLine & vbNewLine & _
    "Kind Regards," & vbNewLine & _
    "Mr A Nother"

    Set OutApp = CreateObject("Outlook.Application")
    Set OutMail = OutApp.CreateItem(0)

    On Error Resume Next
            With OutMail
                    .To = strEmailTo
                    .CC = strCCTo
                    .BCC = ""
                    .Subject = strToday & " - Agreement"
                    .Body = strbody
                    '.Attachments.Add
                    .Display
             End With
    On Error GoTo 0
    Set OutMail = Nothing
    Set OutApp = Nothing

    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

End Sub

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

Ответить на ваш вопрос:

Я думаю, что причина того, что вы видите только одно электронное письмо, заключается в том, что вы создали только один объект OutMail. Если вы хотите выполнить цикл, вам нужно установить объект = ничего, прежде чем вы сможете создать новый:

Set OutMail = Nothing

Выглядит так, как будто вы создаете один словарь, в котором все электронные письма объединены в поле электронного письма, собраны имена и т. Д. Вам нужен способ перебирать каждое электронное письмо, которое вы хотите отправить. Вы можете создать массив словарей, создать коллекцию объектов или просмотреть диапазон, в котором хранятся данные. Зацикливание диапазона звучит так, как будто это будет наименее сложно в этом случае.

Псевдокод / ​​код выглядит следующим образом:

'instantiate the outlook object. Use:
Set OutApp = CreateObject("Outlook.Application")

'Create your array of dictionaries or return a range with the data
'Let's call it listOfEmails

For each email in listOfEmails:

    'instantiate the mail object. Use:
    Set OutMail = OutApp.CreateItem(0)

    'The block that creates the email:
    With OutMail
        .To = strEmailTo
        .CC = strCCTo
        .BCC = ""
        .Subject = strToday & " - Agreement"
        .Body = strbody
        '.Attachments.Add
        .Display
     End With

    'destroy the object when you are done with that particular email
    Set OutMail = Nothing

Next email


Set OutApp = Nothing

Некоторые общие советы:

Разбиение вашего кода на более мелкие части может облегчить исправление и чтение. Это также делает его более пригодным для повторного использования как для этого проекта, так и для будущих проектов. Я включил этот отзыв, потому что он также облегчает вопросы здесь.

Например:

Функция для проверки, открыт ли Outlook:

Function isOutlookOpen() As Boolean
'returns true or false if Outlook is open

    Dim OutApp As Object

    On Error Resume Next
    Set OutApp = CreateObject("Outlook.Application")

    If OutApp Is Nothing Then
        isOutlookOpen = False
    Else: isOutlookOpen = True
    End If
    On Error GoTo 0

End Function

Подпрограмма для отправки электронного письма, по которому можно позвонить из другого подпрограммы:

Sub sendEmail(ByVal recTO As String, ByVal subjectContent As String, ByVal bodyContent As String)

    Dim OutApp As Object
    Dim OutMail As Object

    Set OutApp = CreateObject("Outlook.Application")
    Set OutMail = OutApp.CreateItem(0)

    With OutMail
        .To = recTO
        '.CC = ""
        '.BCC = ""
        .subject = subjectContent
        .body = bodyContent '.HTMLBody
        .display
    End With

    Set OutMail = Nothing
    Set OutApp = Nothing

End Sub

Функция для возврата диапазона данных:

Function dataRange() As Range
'Returns the range where the data is kept

    Dim ws As Worksheet
    Dim dataRng As Range
    Dim lastRow As Integer
    Dim rng As Range

    Set ws = Workbooks("outlookEmail.xlsm").Sheets("dataSheetName")
    lastRow = Cells(Rows.Count, 2).End(xlUp).Row

    'still select where the data should go if the data range is empty
    If lastRow = 2 Then
    lastRow = lastRow + 1
    End If

    Set dataRange = Range("B3", "G" & lastRow)

End Function

Подпрограмма, чтобы собрать все вместе:

Sub main()
'This sub does more than one thing, but I'm asuming it's extremely custom ans still relatively short

    Dim data As Range
    Dim subj As String
    Dim recEmail As String
    Dim body As String
    Dim Row As Range

    'check if data exists. Exit the sub if there's nothing
    Set data = dataRange
    If dataRange.Cells(1, 1).Value = "" Then
    MsgBox "Data is empty"
    Exit Sub
    End If

    'Loop through the data and send the email.
    For Each Row In data.Rows
        'Row is still a range object, so you can access the ranges inside of it like you normally would

        recEmail = Row.Cells(1, 2).Value

        If recEmail <> "" Then 'if the email is not blank, send the email
            subj = Format(Date, "mm.dd.yy") & " - Agreement"
            body = "Dear " & Row.Cells(1, 4).Value & "," & vbNewLine & vbNewLine & _
                "Say Hello World!" & vbNewLine & vbNewLine & _
                "Kind Regards," & vbNewLine & _
                "Mr A Nother"

            Call sendEmail(recEmail, subj, body)
        End If
    Next Row

End Sub

Очень важно:

Спасибо Рону де Брюину за то, что он научил меня отправлять электронные письма из Outlook, используя код в Excel VBA

0 голосов
/ 17 сентября 2018

Вы хотите использовать Excel VBA для доставки почты Outlook?Если это так, Вы можете использовать следующий метод, чтобы получить адрес электронной почты в диапазоне.

Вы не можете быть таким хлопотным.У вас есть более простой код для реализации.

        Sub Send_Email()
        Dim rng As Range
        For Each rng In Range("C1:C4")
                   Call mymacro(rng)
        Next rng
    End Sub
 Private Sub mymacro(rng As Range)
        Dim OutApp As Object
        Dim OutMail As Object
        Dim MailBody As String
        Set OutApp = CreateObject("Outlook.Application")
        Set OutMail = OutApp.CreateItem(0)
        MailBody = "hello"
        On Error Resume Next
        With OutMail
            .To = rng.Value
            .CC = ""
            .BCC = ""
            .Subject = Sheet1.Cells(rng.Row, 1).Value
            .Body = Sheet1.Cells(rng.Row, 2).Value
            .Display
            '.Send
        End With
        On Error GoTo 0
        Set xOutMail = Nothing
        Set xOutApp = Nothing
    End Sub

Я использую метод mymacro для создания и отправки сообщения.

Я перебираю адреса электронной почты ("C1: C4"). И вызываю метод mymacro для отправки электронного письма.по этому адресу.

0 голосов
/ 16 сентября 2018

Прежде всего, добавьте

Опция Явный

над всем кодом.Затем исправьте ошибки.Тогда: https://stackoverflow.com/help/mcve

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...