【问题标题】:Do While Loop to Send Multiple Emails by Row执行 While 循环以按行发送多封电子邮件
【发布时间】:2018-06-14 22:52:28
【问题描述】:

我正在寻求一些 VBA 代码的帮助。

我有一个包含多列和多行的 Excel 表。每行代表一个不同的报告,我必须创建并通过电子邮件发送给特定的收件人。每个报告都是特定于工作日的。我要做的是以下。自动为给定工作日的每一行创建一封电子邮件。我在下面粘贴的代码可以完美地创建一封电子邮件,但我想避免每行都有一个宏按钮。

我希望代码在给定工作日内循环播放每一行。例如,如果第 1 个工作日有 10 份报告,则单击宏会生成 10 封不同的唯一电子邮件。

我尝试创建一个 do while 循环,但我在使用该方法时遇到了一些问题,我不完全确定如何处理主题和正文,它们是连接的文本单元格,每行都是唯一的。

Sub makeReports(dueDate As Date)

Dim reportsRange As Range
Dim xlCell As Range

Dim objOutlook As Outlook.Application
Dim strTo As String
Dim strCc As String
Dim strSubject As String
Dim strBody As String

'Determine reports range (from uppermost cell to last nonempty cell in column)
Set reportsRange = Range("B5", Range("B" & Cells.Rows.Count).End(xlUp))


Set objOutlook = CreateObject("Outlook.Application")

For Each xlCell In reportsRange
    If xlCell.Value = dueDate Then
        strTo = xlCell.Offset(0, 5).Value
        strCc = xlCell.Offset(0, 6).Value
        strSubject = xlCell.Offset(0, 10).Value
        strBody = xlCell.Offset(0, 11).Value

        Call createMail(objOutlook, strTo, strCc, strSubject, strBody)
    End If

Next xlCell

Set objOutlook = Nothing

End Sub


 Sub createMail(objOutlook As Outlook.Application, strTo As String, strCc As String, strSubject   As String, strBody As String)

Dim objMail As Outlook.MailItem

Set objMail = objOutlook.CreateItem(0)


With objMail
    .To = strTo
    .cc = strCc
    .Subject = strSubject
    .Body = strBody
    .display
    ' If you want to send:
    '.Send
End With

Set objMail = Nothing

End Sub


Sub test()
  Call makeReports(1)
End Sub

Private Sub CommandButton1_Click()
  Call makeReports(Date)
End Sub

第三次编辑:

我附上了工作日功能的屏幕截图,以确定正确的交付日期

截图

【问题讨论】:

  • 您是否考虑过查找最后一行并使用For 循环遍历您的行?
  • 充分利用自动化。如果您可以用您已经提供的一些额外细节来修改您的问题:逐步对每一行的决策过程进行逻辑分解。如,工作日列在哪里?是数字还是文本工作日?是什么决定了在构建主题和正文时使用哪些列?之类的东西。让它变得非常简单,并将其分解成单独的语句,如下所示: 1. 我查看一行,如果 B 列中的值 =“星期一”,那么 2. 我查看 C 列。如果是这样,那么 3. 我合并正文的 F 和 G 列,然后...
  • 您还需要告诉我们如何识别要处理的行数。我假设您首先选择一天(这是一列?),然后找到该列的底部,并且只处理每行包含一个值的单元格。日子是 1-31 还是周一到周五?
  • 大家好。我可以帮忙澄清一下。工作日可以是表示工作日的任何内容。我在想我们可以在第一天使用 1,在第二天使用 2,依此类推。随着我们添加和删除报告,未来行数可能会发生变化,因此如果代码会在工作日列上执行某种类型的计数以查看我们有多少工作日 1 报告,这将很有帮助。让我知道我是否可以进一步澄清。我确实在上面发布了我的更新代码供您参考。我建立了一个 for 循环,我想我已经接近了。
  • 我现在收到运行时错误 91,因为未设置对象变量或 With 块变量。这出现在生成第一封电子邮件之后,我想当代码循环到下一个 i 时。有什么建议吗?

标签: vba loops excel


【解决方案1】:

假设您在给定工作日的报告存储在 A 列中,下面的代码应该可以帮助您开始:

Sub SendReports(columnLetter As String)

    Dim reportsRange As Range
    Dim xlCell As Range

    'Determine reports range (from uppermost cell to last nonempty cell in column)
    Set reportsRange = Range(columnLetter & "1", Range(columnLetter & Cells.Rows.Count).End(xlUp))

    For Each xlCell In reportsRange
        Call CreateMail(xlCell.value)
    Next xlCell

End Sub

测试它:

Sub test()
 Call SendReports("A")
End Sub

只需更改 CreateMail 使其接受 rngBody 作为参数。

编辑:

以下代码适用于我的电脑。确保您设置了对 Outlook 对象库的引用(在 VBA 编辑器中,选择工具>引用并勾选 Microsoft Outlook ##.# 对象库(其中 ##.# 是您安装的版本))并删除所有空的报告行A列。

  Sub makeReports(businessDay As Integer)

    Dim reportsRange As Range
    Dim xlCell As Range

    Dim objOutlook As Outlook.Application
    Dim strTo As String
    Dim strCc As String
    Dim strSubject As String
    Dim strBody As String

    'Determine reports range (from uppermost cell to last nonempty cell in column)
    Set reportsRange = Range("A5", Range("A" & Cells.Rows.Count).End(xlUp))


    Set objOutlook = CreateObject("Outlook.Application")

    For Each xlCell In reportsRange
        If xlCell.Value = businessDay Then
            strTo = xlCell.Offset(0, 4).Value
            strCc = xlCell.Offset(0, 5).Value
            strSubject = xlCell.Offset(0, 8).Value
            strBody = xlCell.Offset(0, 7).Value

            Call createMail(objOutlook, strTo, strCc, strSubject, strBody)
        End If

    Next xlCell

    Set objOutlook = Nothing

End Sub


Sub createMail(objOutlook As Outlook.Application, strTo As String, strCc As String, strSubject As String, strBody As String)

    Dim objMail As Outlook.MailItem

    Set objMail = objOutlook.CreateItem(0)


    With objMail
        .To = strTo
        .cc = strCc
        .Subject = strSubject
        .Body = strBody
        .display
        ' If you want to send:
        '.Send
    End With

    Set objMail = Nothing

End Sub


Sub test()
 Call makeReports(1)
End Sub

现在您只需要一些逻辑来计算当前工作日。

编辑2:

这是代码的修改版本,接受到期日期作为参数并考虑到您插入的附加列:

  Sub makeReports(dueDate As Date)

    Dim reportsRange As Range
    Dim xlCell As Range

    Dim objOutlook As Outlook.Application
    Dim strTo As String
    Dim strCc As String
    Dim strSubject As String
    Dim strBody As String

    'Determine reports range (from uppermost cell to last nonempty cell in column)
    Set reportsRange = Range("B5", Range("B" & Cells.Rows.Count).End(xlUp))


    Set objOutlook = CreateObject("Outlook.Application")

    For Each xlCell In reportsRange
        If xlCell.Value = dueDate Then
            strTo = xlCell.Offset(0, 4).Value
            strCc = xlCell.Offset(0, 5).Value
            strSubject = xlCell.Offset(0, 8).Value
            strBody = xlCell.Offset(0, 7).Value

            Call createMail(objOutlook, strTo, strCc, strSubject, strBody)
        End If

    Next xlCell

    Set objOutlook = Nothing

End Sub

在您的工作表上添加一个命令按钮并输入以下代码:

Private Sub CommandButton1_Click()
  Call makeReports(Date)
End Sub

这应该为今天到期的每份报告打开一封邮件。

【讨论】:

  • 感谢您的回复,silentsurfer。我非常感谢您的建议。我不确定我是否理解如何将这个新子例程合并到我当前的代码中。显然,我是 VBA 新手。我会稍微处理一下,有任何问题都会回来。
  • @TWDeac,我很乐意提供帮助。代码的哪一部分给您带来了麻烦? SendReports 循环遍历由 columnLetter 指定的列中的所有行,从第一个 (A1) 开始到包含数据的最后一行,并调用 CreateMail,将当前单元格值作为 rngBody 参数传递。如果这不是您所需要的,那么在您的工作表上发布您的数据布局方式的屏幕截图可能会有所帮助。
  • Silentsurfer,这是我的数据截图。会有更多的数据,但这会给你一个想法。 link
  • 哇。这真太了不起了。我非常感谢您的帮助!我将处理当前工作日的逻辑,并用我的解决方案回复您。再次感谢。
  • @TWDeac,很高兴你喜欢它。提示:你可能想看看 Weekday() 函数。
猜你喜欢
  • 2020-02-24
  • 2015-05-17
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
相关资源
最近更新 更多