/ Forums / Advansys Formativ / Creating Solutions with Formativ / Programmatically accept an appointment

  • Creator
    Topic
  • #3892
    scaldwell
    Participant

      I’m cloning appointments and sending them to a new date but I’m having difficulty auto accepting them. Also, does anyone know how to set a custom date field to nothing once its got a date in it.

      Thanks

    • Author
      Replies
    • #6531
      Support 1a
      Participant

        My understanding is that custom fields do not contain null values in the true sense of the word. To add a custom field, you must first create a field definition, then add a field object to the appropriate object in the message store using the definition (i.e. address book entry, calendar entry etc). When you add the field to the object, you must provide a value for the field at the same time. In order to ‘remove’ the value you need to either provide a value to represent a null (i.e. with string custom fields you need to set the value to a space character in order to ‘clear’ its value). For example, you could set the date field to date representing a null value as far as your application is concerned (such as 1/1/1899). Howver, this could be an issue if you display the value somewhere in the GroupWise client. Your other option would be to remove the field object from the message that contained it. Of course, you would have to modify your applet to take this into account when trying to read the value of the custom date field.

        In terms of auto-excepting appointments, could you post an example of what you have tried so far.

        Advansys Support

        #6526
        scaldwell
        Participant

          Here’s a brief description of what this applet is suppose to do.

          We are using another applet to export our calendars from GW to .csv files, which are then uploaded to our website content management system and displayed to the public.

          Each Posted Appointment (event) can have several status categories, which are assigned through the use of a custom field. The categories are Active, Canceled, Postponed, and Rescheduled. Posted appointments or events that are rescheduled are cloned, in order to preserve all event information (mainly attachments) and the startdate and status is reset. The startdate is set to the new event date and the status is set to active or “”. This is modelled of one of your sample applets.

          When the new Posted Appointment is created through the clone method (which works) it is sent to the sender of it’s parent. It then must be accepted by the user. Posted Appointments don’t need to be accepted…do they? It would be cleaner if the Posted Appointment could be auto accepted by the applet. The new Posted Appointment doesn’t seem to be behaving like a true Posted Appointment.

          I’ve tried this method on the new message with no luck:

           objAppt.Accept("Accept") 

          Also, after the Posted Appointment is cloned it wont let me edit it again. In theory, the event can then be canceled…but whe I run the applet on this new cloned appointment and try to set the status again it says:

           Message.Object
          C:Program FilesAdvansysFormativAF_EDIT_NEW.vbf
          Update access is denied to current user. at line 104, column 17 

          I’ve included the entire applet for your viewing pleasure…don’t laugh!! It’s my first time.

          Thanks for any help you can provide.

          Scott
          scaldwell@ci.fayetteville.ar.us

           
          
          '-------------------------------------------------------------------------------
          ' Insert your comments here
          '-------------------------------------------------------------------------------
          
          'Dialog Variables
          Dim Dialog1
          Dim Dialog2
          Dim Dialog3
          Dim PriorityCtl
          Dim StatusCtl
          Dim DateCtl
          Dim TimeCtl
          Dim MemoCtl
          
          'Miscellaneous Variables
          Dim Msg
          Dim Cmd
          Dim iCount
          Dim Field1
          Dim Field2
          Dim Field3
          Dim Fields
          Dim FieldDefs
          Dim FieldObj1
          Dim FieldObj2
          Dim FieldObj3
          Dim sIndex1
          Dim sIndex2
          
          Const CUSTOM_FIELD1 = "STATUS"
          Const CUSTOM_FIELD2 = "RESCDATE"
          Const CUSTOM_FIELD3 = "RESCREASON"
          Const CAPTION = "AccessFayetteville Calendar Tools"
          
          '-------------------------------------------------------------------------------
          ' Main Function
          '-------------------------------------------------------------------------------
          
          Sub Main(Client, GWEvent)
          
            'Command Buttons
            cIntroDlg = 100
            cSelectEdit = 101
            cCheckReschedule = 102
            cReschedule = 103
            cExit = 999
          
            'Set the default status to 0
            sIndex1 = 1
            sIndex2 = 0
          
            'Set starting point
            Cmd = cIntroDlg
          
            Do While Cmd <> cExit
            
              If Cmd = cIntroDlg Then
                'Get the number of messages selected
                iCount = Client.ClientState.SelectedMessages.count
                If iCount > 1 Then
                  MsgBox("This applet only allows single calendar events to be edited")
                  Cmd = cExit
                Else
                  Set Msg = Client.ClientState.CommandMessage
                  AddFields
                  FieldValues
                  'Check message priority and pass to form
                  If Msg.Priority = 1 Then
                    sIndex1 = 0
                  Elseif Msg.Priority = 2 Then
                    sIndex1 = 1
                  Elseif Msg.Priority = 3 Then
                    sIndex1 = 2
                  End If
                  'Checks that some text is in the status field before checking for values
                  If IsObject(Field1) then
                    'Check custom status field for values and pass to form
                    If Field1.Value = "Canceled" Then
                      sIndex2 = 1
                    Elseif Field1.Value = "Postponed" Then
                      sIndex2 = 2
                    Elseif Field1.Value = "Rescheduled" Then
                      sIndex2 = 3
                    Else
                      sIndex2 = 0 'blank value for status signifies Active event
                    End If
                  End If
                  
                  'Create the Dialogs
                  Call SetupIntroDlg(sIndex1, sIndex2)
                  Select Case Dialog1.execute
                    Case Btn1 Cmd = cSelectEdit
                    Case Btn2 Cmd = cExit
                    Case Else Cmd = cExit
                  End Select     
                End If
              End If
                  
              If Cmd = cSelectEdit Then
                'Update the priority field if the new priority is different from the old priority
                If (PriorityCtl.ItemIndex) <> sIndex1 Then
                  Select Case PriorityCtl.ItemIndex
                    Case 0 Msg.Priority = fgwLow
                    Case 1 Msg.Priority = fgwNormal
                    Case 2 Msg.Priority = fgwHigh
                  End Select
                End If    
          
                'Update the status field if the new status is different from the old status
                If (StatusCtl.ItemIndex) = sIndex2 Then
                  If Field1 = "Rescheduled" Then
                    Cmd = cCheckReschedule
                  Else
                    Cmd = cExit
                  End If        
                Else
                  If Field1 = "" Then
                    Select Case StatusCtl.ItemIndex
                      Case 1 Call Fields.Add(CUSTOM_FIELD1, fgwString, "Canceled")
                      Case 2 Call Fields.Add(CUSTOM_FIELD1, fgwString, "Postponed")
                      Case 3 Call Fields.Add(CUSTOM_FIELD1, fgwString, "Rescheduled")
                    End Select
                    Cmd = cCheckReschedule        
                  ElseIf Field1 = "Canceled" Then
                    MsgBox("CANCELED items may not be changed")
                    Cmd = cIntroDlg
                  ElseIf Field1 = "Postponed" Then
                    Select Case StatusCtl.ItemIndex
                      Case 1 Call Fields.Add(CUSTOM_FIELD1, fgwString, "Canceled")
                      Case 3 Call Fields.Add(CUSTOM_FIELD1, fgwString, "Rescheduled")
                    End Select
                    If StatusCtl.ItemIndex = 1 or StatusCtl.ItemIndex = 3 Then
                      Cmd = cCheckReschedule
                    Else
                      MsgBox("POSTPONED items may only be CANCELED or RESCHEDULED")
                      Cmd = cIntroDlg
                    End If
                  ElseIf Field1 = "Rescheduled" Then
                    MsgBox("Only the explanation of a RESCHEDULED item may be changed")
                    Cmd = cCheckReschedule
                  End If
                End If
              End If
              
              'MsgBox(Field1)
              'MsgBox(StatusCtl.ItemIndex)
              
              If Cmd = cCheckReschedule Then
                If Field1 = "Rescheduled" Then
                  Call SetupExpDlg
                  Select Case Dialog3.execute
                    Case Btn1 Cmd = cReschedule
                    Case Btn2 Cmd = cReschedule
                    Case Else Cmd = cExit
                  End Select
                ElseIf StatusCtl.ItemIndex = 3 AND Field1 <> "Rescheduled" Then
                  Call SetupSuppDlg
                  Select Case Dialog2.execute
                    Case Btn1 Cmd = cReschedule
                    Case Btn2 Cmd = cReschedule
                    Case Else Cmd = cExit
                  End Select
                End If
              End If 
              
              If Cmd = cReschedule Then
                If (MemoCtl.Text = "") OR (MemoCtl.Text = " ") Then
                  MsgBox("Explanations are REQUIRED for all rescheduled events")
                  Cmd = cCheckReschedule
                Else 
                  'If original is reschedule then only update the explanation
                  If Field1 = "Rescheduled" Then
                    Call Fields.Add(CUSTOM_FIELD3, fgwString, MemoCtl.Text)
                    Cmd = cExit
                  'If the new status is reschedule then add new date/time and explanation
                  ElseIf (StatusCtl.ItemIndex = 3) Then
                    DT = (DateCtl.Date) + (TimeCtl.Time)
                      If (Msg.StartDate) = DT Then
                        MsgBox("The RESCHEDULED date and time must be different from the original")
                        Cmd = cCheckReschedule
                      Else
                        Call Fields.Add(CUSTOM_FIELD2, fgwDate, DT)
                        Call Fields.Add(CUSTOM_FIELD3, fgwString, MemoCtl.Text)
                        Call CreateNewEvent
                        Cmd = cExit
                      End If
                  End If
                End If
              End If
          
            Loop
          
          ' Refresh view
          Call GroupWise.Refresh
          
          'Clean up variables
          Set Fields = nothing
          Set Field1 = nothing
          'Set Field2 = nothing
          Set Field3 = nothing
          Set FieldObj1 = nothing
          Set FieldObj2 = nothing
          Set FieldObj3 = nothing
          Set Dialog1 = nothing
          Set Dialog2 = nothing
          Set Dialog3 = nothing
          Set PriorityCtl = nothing
          Set StatusCtl = nothing
          Set DateCtl = nothing
          Set MemoCtl = nothing
          Set Msg = nothing
          
          End Sub
          
          '-------------------------------------------------------------------------------
          ' Creates a new message when an event is rescheduled
          '-------------------------------------------------------------------------------
          function CreateNewEvent
          
            Dim objAppt
            Dim objNewAppt
            Dim objRecipient
            Dim NewAddress
            NewAddress = Msg.Sender
            ' Create a copy of the original Posted Appointment substituted the new date for the StartDate
            Set objAppt = Msg.Clone
            ' Set the recipient equal to the original sender which was ourself
            Set objRecipient = objAppt.Recipients.Add(NewAddress,,0)   
            With objAppt 
              '.OnCalendar = TRUE
              '.Priority = Msg.Priority
              '.FromText = "Auto Generated Event"  
              '.Place = Msg.Place
              .StartDate = (DateCtl.Date) + (TimeCtl.Time)
              '.EndDate = DT + 1      
              '.Subject = Msg.Subject
              '.BodyText.PlainText = Msg.BodyText
            End With
            
            objAppt.Accept("Accept")
            ' Get Fields of new message
            Set Fields = objAppt.Fields
            ' Set Status of new message to normal
            Call Fields.Add(CUSTOM_FIELD1, fgwString, " ")
            ' Send Message
            Set objNewAppt = objAppt.Send
            ' Clean up
            Set objRecipient = Nothing
            Set objAppt = Nothing
          
          End function
          '-------------------------------------------------------------------------------
          ' Adds the custom fields if they do not exist
          '-------------------------------------------------------------------------------
          function AddFields
             
            Set FieldDefs = GroupWise.Account.FieldDefinitions
            
            On Error Resume Next     
            Set FieldObj1 = FieldDefs.Item(CUSTOM_FIELD1, fgwString)
            Set FieldObj2 = FieldDefs.Item(CUSTOM_FIELD2, fgwDate)
            Set FieldObj3 = FieldDefs.Item(CUSTOM_FIELD3, fgwString)
            ' If the custom fields don't exist in the field definitions then add them.
            If FieldObj1 Is Nothing Then
              Call FieldDefs.Add(CUSTOM_FIELD1, fgwString) 
            Elseif FieldObj2 Is Nothing then
              Call FieldDefs.Add(CUSTOM_FIELD2, fgwDate)
            Elseif FieldObj3 Is Nothing then
              Call FieldDefs.Add(CUSTOM_FIELD3, fgwString)
            End If
          
            ' Refresh view
            Call GroupWise.Refresh
            
          End function
          
          '-------------------------------------------------------------------------------
          ' Get the values of the custom fields
          '-------------------------------------------------------------------------------
          function FieldValues
            
            ' Contains all field objects for the current message
            Set Fields = Msg.Fields
             
            On Error Resume Next
            ' Finds the specified field objects and there values    
            Set Field1 = Fields.Item(CUSTOM_FIELD1, fgwString)
            'Set Field2 = Fields.Item(CUSTOM_FIELD2, fgwDate)
            Set Field3 = Fields.Item(CUSTOM_FIELD3, fgwString)
            
          End function
          
          '-------------------------------------------------------------------------------
          ' Dialog to edit the status dialog of the event 
          '-------------------------------------------------------------------------------
          function SetupIntroDlg(sIndex1, sIndex2)
          
            Set Dialog1 = Utilities.NewControlBoxDialog
            With Dialog1
              .Height = 240
              .Caption = CAPTION    
              .Title = "Event Classification"
              .ShowWizardImage = FALSE
            End With
            
            Set PriorityCtl = Dialog1.AddRadioGroupControl
            With PriorityCtl
              .Caption = "Priority"
              .Items.Add("Low")
              .Items.Add("Normal")
              .Items.Add("High") 
              .ItemIndex = sIndex1
              .Height = 40  
              .Columns = 3
              .Hint = "Select an event priority"
            End With
            
            Set StatusCtl = Dialog1.AddRadioGroupControl
            With StatusCtl
              .Caption = "Status"
              .Items.Add("Active")
              .Items.Add("Canceled")
              .Items.Add("Postponed")
              .Items.Add("Rescheduled")  
              .ItemIndex = sIndex2
              .Height = 60  
              .Columns = 2
              .Hint = "Select an event status"
            End With
          
          End function
          
          '-------------------------------------------------------------------------------
          ' Dialog to edit reschedule information for an event 
          '-------------------------------------------------------------------------------
          Function SetupSuppDlg
          
            Set Dialog2 = Utilities.NewControlBoxDialog
            With Dialog2
              .Height = 460
              .Caption = CAPTION    
              .Title = "Reschedule Information"
              .ShowWizardImage = FALSE
            End With
          
            Set DateCtl = Dialog2.AddDateTimeControl
            with DateCtl
              .Caption = "Reschedule Date To:"
              .Kind = fdtkDate
              .Date = Msg.StartDate
              .MinDate = Date
              .CaptionWidth = iCaptWidth
              .CaptionAlign = ftaRightJustify
              .Hint = "Enter a new date for this event"
            end with
          
            Set TimeCtl = Dialog2.AddDateTimeControl
            with TimeCtl
              .Caption = "Reschedule Time To:"
              .Kind = fdtkTime
              .Time = Msg.StartDate
              .CaptionWidth = iCaptWidth
              .CaptionAlign = ftaRightJustify
              .Hint = "Enter a new time for this event"
            end with
            
            Set MemoCtl = Dialog2.AddMemoControl
            with MemoCtl
              .Caption = "I am rescheduling this event because:"
              .ScrollBars = 4
              .Text = field3
              .CaptionAlign = ftaRightJustify
              .WordWrap = TRUE
              .hint = "Enter an explanation for this reschedule"
            end with 
          
          end Function
          
          '-------------------------------------------------------------------------------
          ' Dialog to edit reschedule explanation 
          '-------------------------------------------------------------------------------
          Function SetupExpDlg
          
            Set Dialog3 = Utilities.NewControlBoxDialog
            With Dialog3
              .Height = 425
              .Caption = CAPTION    
              .Title = "Reschedule Information"
              .ShowWizardImage = FALSE
            End With
              
            Set MemoCtl = Dialog3.AddMemoControl
            with MemoCtl
              .Caption = "Edit Explanation:"
              .ScrollBars = 4
              .Text = field3
              .CaptionAlign = ftaRightJustify
              .WordWrap = TRUE
              .hint = "Enter an explanation for this reschedule"
            end with 
          
          end Function
          
          
          #6530
          Support 1a
          Participant

            Thank you for your detailed posting.

            Assuming you only wish to modify the properties of posted appointments, you don’t need to clone and send the original. Posted appointments are owned by the current account, which means you are free to modify most of the properties of the appointment directly, including custom field values.

            It seems you wish to change the start date and/or duration of the posted appointment. You should be able to update the startdate and duration of the message directly. For example:

            Set Msg = Client.ClientState.CommandMessage

            Msg.StartDate =
            Msg.Duration =

            There is no need to call the send method again, or call .Accept, as this is a posted appointment.

            Note that this approach will cause the original posted appointment to be moved to the new date/time in the calendar. If for some reason you wish to retain a copy of the original event, then you must use clone. I don’t think that you would need to use the accept method (as this only pertains to non-posted appointments). In either case, you can only call the .Accept method on appointments that have been sent. In your example you are calling .Accept() prior to send, which will result in a security error message being generated.

            In summary, if you simply wish to change the date/time of a personal/posted item, just change the appropriate properties of the object directly – there is no need to clone the message.

            I hope this helps.

            Advansys Support

            #6527
            scaldwell
            Participant

              Thanks for your help. It is important that the original Posted Appointment be kept in the calendar and a new one created throught the clone method and posted on the new date. That way individuals referencing the calendar will be able to see a trail of events. When they look at the calendar they need to be able to see that the event on May 8, 2003 was rescheduled and what the new event date is. They can then find the new event which was cloned and sent to a new date and classified as an active event.

              I’m running into problems editing the cloned Posted Appointment. When it is cloned it appears in both the calendar view and the mail view. I must then accept it to remove it from the mail view. This makes me think that it’s not acting like a true Posted Appointment. When I clone it I have to send it in order to get it from the draft message status to the calendar (don’t I?). I take the sender from the original Posted Appointment and make that person (me in this case) the recipient of the cloned Posted Appointment. The problem editing problem comes up when the cloned Posted Appointment needs to be reclassed to canceled, or whatever, Groupwise says I don’t have rights to edit it. Is this because I sent it to my self…I thought that was how a Posted Appointment worked. Is there any way around this?

              Thanks again

              Scott

              #6523
              Support 1a
              Participant

                Thanks for the additional information.

                We are looking into this issue, and will post a response here as soon as possible.

                Advansys Support

                #6524
                Support 2
                Moderator

                  We hope the following code may help. Let us know if it does not.

                  const IDS_SELECT_APPT_MSG       = "Select a posted personal appointment message to proceed."    
                  const IDS_SELECT_MSG            = "Select a message to proceed."
                  const IDS_MSG_CREATED           = "Message created."
                  const IDS_CAPTION               = "Formativ Business Solutions"  
                   
                  '-------------------------------------------------------------------------------
                  ' Main line processing
                  '-------------------------------------------------------------------------------
                  Sub Main(Client, GWEvent)
                    
                    dim iMsg
                    dim iNewMsg
                    dim iCloneMsg
                    
                    On Error Resume Next
                    Set iMsg = Client.ClientState.CommandMessage
                    
                    if isobject(iMsg) then    
                      ' Do we have an appointment message?
                      if (instr(1, iMsg.ClassName, "GW.MESSAGE.APPOINTMENT", vbTextCompare) <> 0) then
                        
                        ' Clone the message
                        set iCloneMsg = iMsg.Clone      
                        iCloneMsg.subject = "This is the clone message"
                        ' Adds an existing Message object to this collection. (This method is available only in GroupWise 6.0, SP1 and later versions) 
                        set iNewMsg = groupwise.account.Calendar.Messages.AddExistingMessage(iMsg.sender.displayname, iMsg.sender.emailaddress, "NGW", iMsg.CreationDate, fgwPersonal, 0, fgwNormal, 0, iCloneMsg, iMsg.ModifiedDate)      
                        call msgbox(IDS_MSG_CREATED, vbInformation, IDS_CAPTION)
                           
                      else
                        call msgbox(IDS_SELECT_APPT_MSG, vbInformation, IDS_CAPTION)  
                      end if    
                    else
                      call msgbox(IDS_SELECT_MSG, vbInformation, IDS_CAPTION)  
                    end if
                    
                    set iMsg = nothing
                    set iNewMsg = nothing
                    set iCloneMsg = nothing
                   
                  End Sub
                  
                  #6533
                  scaldwell
                  Participant

                    Your suggestion does exactly what I want. Thanks to all who participated in this discussion. I had yet to discover the AddExistingMessage method.

                    Your level of support is one of the best I’ve seen in a long time.

                    Thanks,

                    Scott

                    #6525
                    Support 1a
                    Participant

                      Thank you for the feedback. Please let us know if we can assist further.

                      Advansys Support

                      #6532
                      scaldwell
                      Participant

                        This is in reference to the Clone Appointment code that Support 2 provied.

                        If I’m proxied to another account and select an appointment the cloned appointment is created in my own account. I would like to cloned appointment to be created in the account of the original posted appointment. Sorry I didn’t mention that before. Thanks for your help.

                        Scott Caldwell

                        #6529
                        Support 1a
                        Participant

                          The technique suggested above, which uses Clone and AddExistingMessage, will only work within the currently logged in users account. It will not work when proxied to another account. This is because both methods/abojects are part of the GroupWise object API, which is an account-based API. The Account object referred to in the code is actually the account of the currently logged in user.

                          The only workaround would be to use the multilogin method. This method gives you a new account object representing another users account. You need to know the user name and password of the other user to use this method.

                          You can access another users account object by doing something like this:

                          set iAccount = GroupWise.Session.MultiLogin(UserID,,Password)
                          

                          UserID and Password are both strings.

                          I hope this helps.

                          Advansys Support

                          #6528
                          scaldwell
                          Participant

                            How does GroupWise itself handle this? When I proxy to an account it doesn’t require me to login. It only requires that the other account grant me proxy rights. Is this functionality that is unexposed in Formativ? I am using the technique you described to export calendar items from a proxied account.

                            Is there a way to have the Account object change when you use the built-int proxy process in GroupWise? I am new to this development environment so this question may be odd. I am just trying to make this as seamless as possible. It would be nice to just click the proxy button at the bottom of the main groupwise window….add calendar items, edit calendar items with thier new status, and export them to a csv without having to use the multilogin. The security exists for this to occur without using multilogin, so why is it not possible to do it. It may be that it’s not possible to do it easily. I’ll understand that.

                            Thanks for your help and advice.

                            Scott Caldwell

                            #6522
                            Support 1a
                            Participant

                              GroupWise doesn’t use its own API. When you proxy, GroupWise uses it’s own internal processes to provide the functionality you see. Formativ cannot expose this behaviour to third parties.

                              The GroupWise programming interface, broadly speaking, is divided into two main areas:

                              1) The Object API, which is used to access data that exists in the message store. The Object API is account-based, and is not associated with the GroupWise user interface in any way. For example, you don’t even need to see any GroupWise UI in order use the Object API. The Object API exposes the Clone and AddExistingMessage methods you have used. Formativ fully exposes this API.

                              2) The Token API. The Token API represents the commands that you generally execute from the client, such as created a new email message and seeing the new email message compose dialog appear. The Token API commands operate on the client in whatever state it finds it. For example, if you proxy to another account then call a token that deletes the current item (owned by the user who’s account you proxied to), as long as you have the appropriate security the item is deleted.

                              There is no simple way I know of to have the Account object automatically login to the account you have just proxied to. While the security exists to access other items when you proxy to another account, this security is applied at the GroupWise client level, not the API level.

                              It may be possible to acheive much of what you need to do using the token commands. Have a look at the GroupWise.Item… commands in the language guide. These commands essentially map back to native GroupWise tokens, and operate on whatever items are currently selected (regardless of whether you have proxied or not). Also, have a look at the ItemListCreate commands. However, to use any objects or methods under the Account object (such as clone), you need to be logged into the account you wish to access.

                              I hope this helps.

                              Advansys Support

                            Viewing 12 replies - 1 through 12 (of 12 total)
                            • You must be logged in to reply to this topic.