编码为电子邮件的日历项目按创建日期排序 - 需要按预约日期排序

时间:2012-01-26 17:27:10

标签: outlook-vba

下面的代码很乐意使用本周的任命填充电子邮件,但它会按预约创建日期而不是实际约会日期列出电子邮件中的日历项目。有没有办法按预约日期列出项目? 我谦虚地感谢任何帮助或建议。 (我把这些代码粘贴在一起,因为我粘贴在网上找到的东西。我对Excel和Access VBA比对Outlook更熟悉。再次感谢。)John

Public Sub ListAppointments()
    On Error GoTo On_Error

    Dim Session As Outlook.NameSpace
    Dim Report As String
    Dim AppointmentsFolder As Outlook.Folder
    Dim currentItem As Object
    Dim currentAppointment As AppointmentItem
    Set Session = Application.Session

    Set AppointmentsFolder = Session.GetDefaultFolder(olFolderCalendar)

    For Each currentItem In AppointmentsFolder.Items
        If (currentItem.Class = olAppointment) Then
            Set currentAppointment = currentItem
            'get the week's appointments
        If currentAppointment.Start >= Now() And currentAppointment.Start <= Now() + 7 Then
                    If currentAppointment.AllDayEvent = False Then 'exclude all day events

               Call AddToReportIfNotBlank(Report, "Subject", currentAppointment.Subject)
               Call AddToReportIfNotBlank(Report, "Start", currentAppointment.Start)
               Call AddToReportIfNotBlank(Report, "End", currentAppointment.End)
               Call AddToReportIfNotBlank(Report, "Location", currentAppointment.Location)
               Report = Report & "-----------------------------------------------------"
               Report = Report & vbCrLf & vbCrLf

                    End If
                End If
        End If

    Next

    Call CreateReportAsEmail("List of Appointments", Report)

Exiting:
        Exit Sub
On_Error:
    MsgBox "error=" & Err.Number & " " & Err.Description
    Resume Exiting

End Sub

Private Function AddToReportIfNotBlank(Report As String, FieldName As String, FieldValue)
    AddToReportIfNotBlank = ""
    If (IsNull(FieldValue) Or FieldValue <> "") Then
        AddToReportIfNotBlank = FieldName & " : " & FieldValue & vbCrLf
        Report = Report & AddToReportIfNotBlank
    End If

End Function

'publish items to Outlook email
Public Sub CreateReportAsEmail(Title As String, Report As String)
    On Error GoTo On_Error

    Dim objNS As Outlook.NameSpace
    Dim objItem  As MailItem
    Dim objFolder As MAPIFolder

    Set objNS = Application.GetNamespace("MAPI") 'Application.Session
    Set objItem = Application.CreateItem(olMailItem)
    Set objFolder = objNS.GetDefaultFolder(olFolderInbox)

    With objItem
        .Subject = "This weeks appointments"
        .Body = Report
        .Display
    End With

Exiting:
        'Set Session = Nothing
        Exit Sub
On_Error:
    'MsgBox "error=" & Err.Number & " " & Err.Description
    Resume Exiting

End Sub

1 个答案:

答案 0 :(得分:0)

我没有查看您现有的代码,尽管我确实发现了:

  1. 如果您创建了我的约会列表并省略了我的全天会议,我会非常不高兴。
  2. AddToReportIfNotBlank不是函数,因为它不返回值。
  3. 使用我的解决方案,您不会在发现Report时添加约会。相反,它们被添加到结构数组中。一旦找到所有相关约会,就会创建一个结构数组的索引数组,并按约会日期排序。然后,从索引序列中的结构数组构建报告。我希望这是有道理的。代码中的更多细节。

    我的解决方案需要一个结构。类型定义必须放在任何子例程或函数之前。

    Type typAppointment
      Start As Date
      AllDay As Boolean
      End As Date
      Subject As String
      Location As String
    End Type
    

    除了你的以外我还需要这些变量:

      Dim AppointmentDtl() As typAppointment
      Dim InxADCrnt As Long
      Dim InxADCrntMax As Long
      Dim InxAppointmentSorted() As Long
      Dim InxSrtCrnt1 As Long
      Dim InxSrtCrnt2 As Long
      Dim Stg as String
    

    此代码准备要使用的结构数组。放在寻找约会的循环之前:

      ReDim AppointmentDtl(1 To 100)
      ' * I avoid having too many ReDim Preserves because they
      '   involve creating a copy of the original array.
      ' * 100 appointments should be enough but the array will
      '   be resized if necessary.
      InxADCrntMax = 0      ' The current last used entry in AppointmentDtl
    

    删除你的代码:

            Call AddToReportIfNotBlank(Report, "Subject", currentAppointment.Subject)
            Call AddToReportIfNotBlank(Report, "Start", currentAppointment.Start)
            Call AddToReportIfNotBlank(Report, "End", currentAppointment.End)
            Call AddToReportIfNotBlank(Report, "Location", currentAppointment.Location)
            Report = Report & "-----------------------------------------------------"
            Report = Report & vbCrLf & vbCrLf
    

    并替换为以下内容,以存储结构中所选约会的详细信息。此代码处理全天会议以及部分日会议:

            InxADCrntMax = InxADCrntMax + 1
            If InxADCrntMax > UBound(AppointmentDtl) Then
              ' Have filled array.  Add another 100 entries
              ReDim Preserve AppointmentDtl(1 To 100 + UBound(AppointmentDtl))
            End If
            AppointmentDtl(InxADCrntMax).Start = .Start
            If .AllDayEvent Then
              AppointmentDtl(InxADCrntMax).AllDay = True
            Else
              AppointmentDtl(InxADCrntMax).AllDay = False
              AppointmentDtl(InxADCrntMax).End = .End
            End If
            AppointmentDtl(InxADCrntMax).Subject = .Subject
            AppointmentDtl(InxADCrntMax).Location = .Location
          End If
    

    高于Call CreateReportAsEmail("List of Appointments", Report)插入:

      ' Initialise index array as 1, 2, 3, 4, ...
      ReDim InxAppointmentSorted(1 To InxADCrntMax)
      For InxSrtCrnt1 = 1 To InxADCrntMax
        InxAppointmentSorted(InxSrtCrnt1) = InxSrtCrnt1
      Next
    
      ' Sort index array by AppointmentDtl(xxx).Start.
      ' This is not an efficient sort but it should be sufficient for your purposes.
      ' If not, I have a Shell Sort written in VBA although a Quick Sort
      ' is considered the best.
      InxADCrnt = 1
      Do While InxADCrnt < InxADCrntMax
        InxSrtCrnt1 = InxAppointmentSorted(InxADCrnt)
        InxSrtCrnt2 = InxAppointmentSorted(InxADCrnt + 1)
        If AppointmentDtl(InxSrtCrnt1).Start > AppointmentDtl(InxSrtCrnt2).Start Then
          InxAppointmentSorted(InxADCrnt) = InxSrtCrnt2
          InxAppointmentSorted(InxADCrnt + 1) = InxSrtCrnt1
          If InxADCrnt > 1 Then
            InxADCrnt = InxADCrnt - 1
          Else
            InxADCrnt = InxADCrnt + 1
          End If
        Else
          InxADCrnt = InxADCrnt + 1
        End If
      Loop
    
      ' InxAppointmentSorted() is now: 5, 20, 2, ... where appointment 5 is
      ' the earliest, appointment 20 the next and so on
    
      ' Process appointments in Start order
      For InxSrtCrnt1 = 1 To InxADCrntMax
        InxADCrnt = InxAppointmentSorted(InxSrtCrnt1)
        With AppointmentDtl(InxADCrnt)
          ' I have tested all other code on my calendar.  This code is untested.
          ' I have included all day meetings but you could easily restore the
          ' original approach.
          Call AddToReportIfNotBlank(Report, "Subject", .Subject)
          If .AllDay Then
            Stg = "All day " & Format(.Start, "dddd d mmm")
          Else
            ' Date formatted as "Friday 27 Jan". Use "dddd mmmm, d" if you
            ' prefer "Friday January, 27".  That is: "d" gives day of month
            ' with leading zero omitted. "dddd" gives full day of week. "mmm"
            ' gives three letter month.  "mmmm" gives full month.  "yy", if
            ' required, give two day year. "yyyy" gives four day year. Include
            ' spaces and punctuation as desired. 
            Stg = Format(.Start, "dddd d mmm") & _
                  Format(.Start, " hh:mm") & " to " & _
                  Format(.End, "hh:mm")
          End If
          Call AddToReportIfNotBlank(Report, "When", Stg)
          Call AddToReportIfNotBlank(Report, "Location", .Location)
          Report = Report & "-----------------------------------------------------"
          Report = Report & vbCrLf & vbCrLf
        End With
      Next
    

    我希望我已经包含了足够的评论,所以这一切都有道理。回来问题是必要的。