Creating JIRA task from Email in MS Outlook

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












Every day I get 5 to 30 Appointment emails with almost the same content from which I need to create the Tasks in Atlassian Jira. I wrote a macro to automate this process. I've never written anything in vba before and would be grateful for correcting my code. This macro works.



There is a function Base64Encode that I copied from this documentation



I also long searched for a way to create an json object from Appointment email, in the end I decided to create it myself. It looks scary but works.



Public Sub AcceptMeeting(ActiveFolder, Inbox As String)
'Parameter: Postfach / Ordner im Postfach

Dim myNamespace As Outlook.NameSpace
Dim myFolder As Outlook.Folder

Dim Subfolder As Outlook.Folder
Dim Folder As Outlook.Folder
Dim Change As Outlook.Folder

Dim Item As Object
Dim myAppt As Outlook.AppointmentItem
Dim myMtg As Outlook.MeetingItem

'Counter to return how many Events was accepted
Dim counter As Integer
counter = 0

Dim Forward As Outlook.MeetingItem
Dim Accept As Boolean

Set myNamespace = Application.GetNamespace("MAPI")

Set myFolder = myNamespace.Folders(ActiveFolder)
Set Folders = myFolder.Folders

Set Subfolder = Folders.Item(Inbox)

For Each Item In Subfolder.Items
DoEvents

Accept = False

If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then

If ActiveFolder = "Application Management Linux1, I351" Then
Accept = True
End If

'Label for JIRA task
Dim jiraLabel As String

If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then
If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
Item.Categories = "Change Produktion" 'Kategorie setzen PROD
jiraLabel = """Produktion"""
ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
Item.Categories = "Change Integration" 'Kategorie setzen INT
jiraLabel = """Integration"""
ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
Item.Categories = "Change Integration" 'Kategorie setzen INT
jiraLabel = """Testing"""
Else
Item.Categories = "Change Info" 'Kategorie setzen Info
jiraLabel = """Info"""
End If

'Accept Appointment
Set myAppt = Item.GetAssociatedAppointment(True)
Set myMtg = myAppt.Respond(olResponseAccepted, True)

Item.UnRead = False

If ActiveFolder = "Application Management Linux1, I351" Then

'Parse Email to JSON and send
Dim Msg As Outlook.MeetingItem
Set Msg = Item
Set recips = Msg.Recipients
Dim recip As Outlook.Recipient

Dim customBody As String
customBody = Replace(Msg.Body, """", "'")
customBody = Replace(customBody, vbCr & vbLf, "n")
customBody = Replace(customBody, vbCr, "n")
customBody = Replace(customBody, vbLf, "n")
Dim customSubject As String
customSubject = Replace(Msg.Subject, """", "'")
customSubject = Replace(customSubject, vbCr & vbLf, "n")
customSubject = Replace(customSubject, vbCr, "n")
customSubject = Replace(customSubject, vbLf, "n")


Dim regEx As New RegExp
regEx.Pattern = "^w+sw+,sI351$"

For Each recip In recips
If regEx.Test(recip.AddressEntry) And recip.AddressEntry <> "Application Management Linux1, I351" Then


'Values to create JSON
Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
flds = """fields"""
prt = """project"""
id = """id"""
asgn = """assignee"""
smry = """summary"""
descrp = """description"""
issu = """issuetype"""
label = """labels"""
issuName = """Test"""
startAt = """customfield_10021"""
endDate = """customfield_12760"""
name = """name"""
lfbrkt = ""
rtbrkt = ""
cma = ","
dbdots = ":"
sqLfBrkt = "["
sqRtBrkt = "]"

'Custom Date Formatting
Dim appStartDate, appStartTime, appEndDate, appEndTime As Date
appStartDate = myAppt.Start
appStartTime = myAppt.Start
appEndDate = myAppt.End
appEndTime = myAppt.End

'JIRA Rest requears specific format, so we have to format out date and time
Dim startDateString, endDateString As String
startDateString = Format(appStartDate, "yyyy-mm-yy") + "T" + Format(appStartTime, "hh:mm") + ":00.000+0200"
endDateString = Format(appEndDate, "yyyy-mm-dd") + "T" + Format(appEndTime, "hh:mm") + ":00.000+0200"

'Creating JSON - It looks scary but works
JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
vbCrLf + vbTab + rtbrkt + cma + _
vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
vbCrLf + vbTab + rtbrkt + cma + _
vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
vbCrLf + vbTab + rtbrkt + cma + _
vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
vbCrLf + rtbrkt + _
vbCrLf + rtbrkt

'JIRA user
user = "username"
Password = "password"

'Sending request to JIRA
Dim URL As String
URL = "https://jira.app.com/rest/api/2/issue/"
Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
xhr.Open "POST", URL, False
xhr.setRequestHeader "Content-Type", "application/json"
xhr.setRequestHeader "User-Agent", "Outlook"
xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(user + ":" + Password)
xhr.Send JSON

End If
Next
Set Change = myFolder.Folders("*** SPAM")
Item.Move Change
End If
counter = counter + 1
End If
End If
Next

MsgBox Inbox & ": " & counter & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

End Sub






share|improve this question



























    up vote
    4
    down vote

    favorite












    Every day I get 5 to 30 Appointment emails with almost the same content from which I need to create the Tasks in Atlassian Jira. I wrote a macro to automate this process. I've never written anything in vba before and would be grateful for correcting my code. This macro works.



    There is a function Base64Encode that I copied from this documentation



    I also long searched for a way to create an json object from Appointment email, in the end I decided to create it myself. It looks scary but works.



    Public Sub AcceptMeeting(ActiveFolder, Inbox As String)
    'Parameter: Postfach / Ordner im Postfach

    Dim myNamespace As Outlook.NameSpace
    Dim myFolder As Outlook.Folder

    Dim Subfolder As Outlook.Folder
    Dim Folder As Outlook.Folder
    Dim Change As Outlook.Folder

    Dim Item As Object
    Dim myAppt As Outlook.AppointmentItem
    Dim myMtg As Outlook.MeetingItem

    'Counter to return how many Events was accepted
    Dim counter As Integer
    counter = 0

    Dim Forward As Outlook.MeetingItem
    Dim Accept As Boolean

    Set myNamespace = Application.GetNamespace("MAPI")

    Set myFolder = myNamespace.Folders(ActiveFolder)
    Set Folders = myFolder.Folders

    Set Subfolder = Folders.Item(Inbox)

    For Each Item In Subfolder.Items
    DoEvents

    Accept = False

    If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then

    If ActiveFolder = "Application Management Linux1, I351" Then
    Accept = True
    End If

    'Label for JIRA task
    Dim jiraLabel As String

    If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then
    If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
    Item.Categories = "Change Produktion" 'Kategorie setzen PROD
    jiraLabel = """Produktion"""
    ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
    Item.Categories = "Change Integration" 'Kategorie setzen INT
    jiraLabel = """Integration"""
    ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
    Item.Categories = "Change Integration" 'Kategorie setzen INT
    jiraLabel = """Testing"""
    Else
    Item.Categories = "Change Info" 'Kategorie setzen Info
    jiraLabel = """Info"""
    End If

    'Accept Appointment
    Set myAppt = Item.GetAssociatedAppointment(True)
    Set myMtg = myAppt.Respond(olResponseAccepted, True)

    Item.UnRead = False

    If ActiveFolder = "Application Management Linux1, I351" Then

    'Parse Email to JSON and send
    Dim Msg As Outlook.MeetingItem
    Set Msg = Item
    Set recips = Msg.Recipients
    Dim recip As Outlook.Recipient

    Dim customBody As String
    customBody = Replace(Msg.Body, """", "'")
    customBody = Replace(customBody, vbCr & vbLf, "n")
    customBody = Replace(customBody, vbCr, "n")
    customBody = Replace(customBody, vbLf, "n")
    Dim customSubject As String
    customSubject = Replace(Msg.Subject, """", "'")
    customSubject = Replace(customSubject, vbCr & vbLf, "n")
    customSubject = Replace(customSubject, vbCr, "n")
    customSubject = Replace(customSubject, vbLf, "n")


    Dim regEx As New RegExp
    regEx.Pattern = "^w+sw+,sI351$"

    For Each recip In recips
    If regEx.Test(recip.AddressEntry) And recip.AddressEntry <> "Application Management Linux1, I351" Then


    'Values to create JSON
    Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
    dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
    flds = """fields"""
    prt = """project"""
    id = """id"""
    asgn = """assignee"""
    smry = """summary"""
    descrp = """description"""
    issu = """issuetype"""
    label = """labels"""
    issuName = """Test"""
    startAt = """customfield_10021"""
    endDate = """customfield_12760"""
    name = """name"""
    lfbrkt = ""
    rtbrkt = ""
    cma = ","
    dbdots = ":"
    sqLfBrkt = "["
    sqRtBrkt = "]"

    'Custom Date Formatting
    Dim appStartDate, appStartTime, appEndDate, appEndTime As Date
    appStartDate = myAppt.Start
    appStartTime = myAppt.Start
    appEndDate = myAppt.End
    appEndTime = myAppt.End

    'JIRA Rest requears specific format, so we have to format out date and time
    Dim startDateString, endDateString As String
    startDateString = Format(appStartDate, "yyyy-mm-yy") + "T" + Format(appStartTime, "hh:mm") + ":00.000+0200"
    endDateString = Format(appEndDate, "yyyy-mm-dd") + "T" + Format(appEndTime, "hh:mm") + ":00.000+0200"

    'Creating JSON - It looks scary but works
    JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
    vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
    vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
    vbCrLf + vbTab + rtbrkt + cma + _
    vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
    vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
    vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
    vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
    vbCrLf + vbTab + rtbrkt + cma + _
    vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
    vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
    vbCrLf + vbTab + rtbrkt + cma + _
    vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
    vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
    vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
    vbCrLf + rtbrkt + _
    vbCrLf + rtbrkt

    'JIRA user
    user = "username"
    Password = "password"

    'Sending request to JIRA
    Dim URL As String
    URL = "https://jira.app.com/rest/api/2/issue/"
    Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
    xhr.Open "POST", URL, False
    xhr.setRequestHeader "Content-Type", "application/json"
    xhr.setRequestHeader "User-Agent", "Outlook"
    xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(user + ":" + Password)
    xhr.Send JSON

    End If
    Next
    Set Change = myFolder.Folders("*** SPAM")
    Item.Move Change
    End If
    counter = counter + 1
    End If
    End If
    Next

    MsgBox Inbox & ": " & counter & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

    End Sub






    share|improve this question























      up vote
      4
      down vote

      favorite









      up vote
      4
      down vote

      favorite











      Every day I get 5 to 30 Appointment emails with almost the same content from which I need to create the Tasks in Atlassian Jira. I wrote a macro to automate this process. I've never written anything in vba before and would be grateful for correcting my code. This macro works.



      There is a function Base64Encode that I copied from this documentation



      I also long searched for a way to create an json object from Appointment email, in the end I decided to create it myself. It looks scary but works.



      Public Sub AcceptMeeting(ActiveFolder, Inbox As String)
      'Parameter: Postfach / Ordner im Postfach

      Dim myNamespace As Outlook.NameSpace
      Dim myFolder As Outlook.Folder

      Dim Subfolder As Outlook.Folder
      Dim Folder As Outlook.Folder
      Dim Change As Outlook.Folder

      Dim Item As Object
      Dim myAppt As Outlook.AppointmentItem
      Dim myMtg As Outlook.MeetingItem

      'Counter to return how many Events was accepted
      Dim counter As Integer
      counter = 0

      Dim Forward As Outlook.MeetingItem
      Dim Accept As Boolean

      Set myNamespace = Application.GetNamespace("MAPI")

      Set myFolder = myNamespace.Folders(ActiveFolder)
      Set Folders = myFolder.Folders

      Set Subfolder = Folders.Item(Inbox)

      For Each Item In Subfolder.Items
      DoEvents

      Accept = False

      If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then

      If ActiveFolder = "Application Management Linux1, I351" Then
      Accept = True
      End If

      'Label for JIRA task
      Dim jiraLabel As String

      If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then
      If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
      Item.Categories = "Change Produktion" 'Kategorie setzen PROD
      jiraLabel = """Produktion"""
      ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
      Item.Categories = "Change Integration" 'Kategorie setzen INT
      jiraLabel = """Integration"""
      ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
      Item.Categories = "Change Integration" 'Kategorie setzen INT
      jiraLabel = """Testing"""
      Else
      Item.Categories = "Change Info" 'Kategorie setzen Info
      jiraLabel = """Info"""
      End If

      'Accept Appointment
      Set myAppt = Item.GetAssociatedAppointment(True)
      Set myMtg = myAppt.Respond(olResponseAccepted, True)

      Item.UnRead = False

      If ActiveFolder = "Application Management Linux1, I351" Then

      'Parse Email to JSON and send
      Dim Msg As Outlook.MeetingItem
      Set Msg = Item
      Set recips = Msg.Recipients
      Dim recip As Outlook.Recipient

      Dim customBody As String
      customBody = Replace(Msg.Body, """", "'")
      customBody = Replace(customBody, vbCr & vbLf, "n")
      customBody = Replace(customBody, vbCr, "n")
      customBody = Replace(customBody, vbLf, "n")
      Dim customSubject As String
      customSubject = Replace(Msg.Subject, """", "'")
      customSubject = Replace(customSubject, vbCr & vbLf, "n")
      customSubject = Replace(customSubject, vbCr, "n")
      customSubject = Replace(customSubject, vbLf, "n")


      Dim regEx As New RegExp
      regEx.Pattern = "^w+sw+,sI351$"

      For Each recip In recips
      If regEx.Test(recip.AddressEntry) And recip.AddressEntry <> "Application Management Linux1, I351" Then


      'Values to create JSON
      Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
      dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
      flds = """fields"""
      prt = """project"""
      id = """id"""
      asgn = """assignee"""
      smry = """summary"""
      descrp = """description"""
      issu = """issuetype"""
      label = """labels"""
      issuName = """Test"""
      startAt = """customfield_10021"""
      endDate = """customfield_12760"""
      name = """name"""
      lfbrkt = ""
      rtbrkt = ""
      cma = ","
      dbdots = ":"
      sqLfBrkt = "["
      sqRtBrkt = "]"

      'Custom Date Formatting
      Dim appStartDate, appStartTime, appEndDate, appEndTime As Date
      appStartDate = myAppt.Start
      appStartTime = myAppt.Start
      appEndDate = myAppt.End
      appEndTime = myAppt.End

      'JIRA Rest requears specific format, so we have to format out date and time
      Dim startDateString, endDateString As String
      startDateString = Format(appStartDate, "yyyy-mm-yy") + "T" + Format(appStartTime, "hh:mm") + ":00.000+0200"
      endDateString = Format(appEndDate, "yyyy-mm-dd") + "T" + Format(appEndTime, "hh:mm") + ":00.000+0200"

      'Creating JSON - It looks scary but works
      JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
      vbCrLf + vbTab + rtbrkt + cma + _
      vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
      vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
      vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
      vbCrLf + vbTab + rtbrkt + cma + _
      vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
      vbCrLf + vbTab + rtbrkt + cma + _
      vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
      vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
      vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
      vbCrLf + rtbrkt + _
      vbCrLf + rtbrkt

      'JIRA user
      user = "username"
      Password = "password"

      'Sending request to JIRA
      Dim URL As String
      URL = "https://jira.app.com/rest/api/2/issue/"
      Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
      xhr.Open "POST", URL, False
      xhr.setRequestHeader "Content-Type", "application/json"
      xhr.setRequestHeader "User-Agent", "Outlook"
      xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(user + ":" + Password)
      xhr.Send JSON

      End If
      Next
      Set Change = myFolder.Folders("*** SPAM")
      Item.Move Change
      End If
      counter = counter + 1
      End If
      End If
      Next

      MsgBox Inbox & ": " & counter & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

      End Sub






      share|improve this question













      Every day I get 5 to 30 Appointment emails with almost the same content from which I need to create the Tasks in Atlassian Jira. I wrote a macro to automate this process. I've never written anything in vba before and would be grateful for correcting my code. This macro works.



      There is a function Base64Encode that I copied from this documentation



      I also long searched for a way to create an json object from Appointment email, in the end I decided to create it myself. It looks scary but works.



      Public Sub AcceptMeeting(ActiveFolder, Inbox As String)
      'Parameter: Postfach / Ordner im Postfach

      Dim myNamespace As Outlook.NameSpace
      Dim myFolder As Outlook.Folder

      Dim Subfolder As Outlook.Folder
      Dim Folder As Outlook.Folder
      Dim Change As Outlook.Folder

      Dim Item As Object
      Dim myAppt As Outlook.AppointmentItem
      Dim myMtg As Outlook.MeetingItem

      'Counter to return how many Events was accepted
      Dim counter As Integer
      counter = 0

      Dim Forward As Outlook.MeetingItem
      Dim Accept As Boolean

      Set myNamespace = Application.GetNamespace("MAPI")

      Set myFolder = myNamespace.Folders(ActiveFolder)
      Set Folders = myFolder.Folders

      Set Subfolder = Folders.Item(Inbox)

      For Each Item In Subfolder.Items
      DoEvents

      Accept = False

      If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then

      If ActiveFolder = "Application Management Linux1, I351" Then
      Accept = True
      End If

      'Label for JIRA task
      Dim jiraLabel As String

      If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then
      If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
      Item.Categories = "Change Produktion" 'Kategorie setzen PROD
      jiraLabel = """Produktion"""
      ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
      Item.Categories = "Change Integration" 'Kategorie setzen INT
      jiraLabel = """Integration"""
      ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
      Item.Categories = "Change Integration" 'Kategorie setzen INT
      jiraLabel = """Testing"""
      Else
      Item.Categories = "Change Info" 'Kategorie setzen Info
      jiraLabel = """Info"""
      End If

      'Accept Appointment
      Set myAppt = Item.GetAssociatedAppointment(True)
      Set myMtg = myAppt.Respond(olResponseAccepted, True)

      Item.UnRead = False

      If ActiveFolder = "Application Management Linux1, I351" Then

      'Parse Email to JSON and send
      Dim Msg As Outlook.MeetingItem
      Set Msg = Item
      Set recips = Msg.Recipients
      Dim recip As Outlook.Recipient

      Dim customBody As String
      customBody = Replace(Msg.Body, """", "'")
      customBody = Replace(customBody, vbCr & vbLf, "n")
      customBody = Replace(customBody, vbCr, "n")
      customBody = Replace(customBody, vbLf, "n")
      Dim customSubject As String
      customSubject = Replace(Msg.Subject, """", "'")
      customSubject = Replace(customSubject, vbCr & vbLf, "n")
      customSubject = Replace(customSubject, vbCr, "n")
      customSubject = Replace(customSubject, vbLf, "n")


      Dim regEx As New RegExp
      regEx.Pattern = "^w+sw+,sI351$"

      For Each recip In recips
      If regEx.Test(recip.AddressEntry) And recip.AddressEntry <> "Application Management Linux1, I351" Then


      'Values to create JSON
      Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
      dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
      flds = """fields"""
      prt = """project"""
      id = """id"""
      asgn = """assignee"""
      smry = """summary"""
      descrp = """description"""
      issu = """issuetype"""
      label = """labels"""
      issuName = """Test"""
      startAt = """customfield_10021"""
      endDate = """customfield_12760"""
      name = """name"""
      lfbrkt = ""
      rtbrkt = ""
      cma = ","
      dbdots = ":"
      sqLfBrkt = "["
      sqRtBrkt = "]"

      'Custom Date Formatting
      Dim appStartDate, appStartTime, appEndDate, appEndTime As Date
      appStartDate = myAppt.Start
      appStartTime = myAppt.Start
      appEndDate = myAppt.End
      appEndTime = myAppt.End

      'JIRA Rest requears specific format, so we have to format out date and time
      Dim startDateString, endDateString As String
      startDateString = Format(appStartDate, "yyyy-mm-yy") + "T" + Format(appStartTime, "hh:mm") + ":00.000+0200"
      endDateString = Format(appEndDate, "yyyy-mm-dd") + "T" + Format(appEndTime, "hh:mm") + ":00.000+0200"

      'Creating JSON - It looks scary but works
      JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
      vbCrLf + vbTab + rtbrkt + cma + _
      vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
      vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
      vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
      vbCrLf + vbTab + rtbrkt + cma + _
      vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
      vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
      vbCrLf + vbTab + rtbrkt + cma + _
      vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
      vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
      vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
      vbCrLf + rtbrkt + _
      vbCrLf + rtbrkt

      'JIRA user
      user = "username"
      Password = "password"

      'Sending request to JIRA
      Dim URL As String
      URL = "https://jira.app.com/rest/api/2/issue/"
      Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
      xhr.Open "POST", URL, False
      xhr.setRequestHeader "Content-Type", "application/json"
      xhr.setRequestHeader "User-Agent", "Outlook"
      xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(user + ":" + Password)
      xhr.Send JSON

      End If
      Next
      Set Change = myFolder.Folders("*** SPAM")
      Item.Move Change
      End If
      counter = counter + 1
      End If
      End If
      Next

      MsgBox Inbox & ": " & counter & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

      End Sub








      share|improve this question












      share|improve this question




      share|improve this question








      edited May 22 at 14:41









      200_success

      123k14143399




      123k14143399









      asked May 22 at 13:11









      khashashin

      385




      385




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          4
          down vote



          accepted










          "Why Are We Scared?"



          The number one reason that we are scared of something is that we don't fully understand it. The key to understanding a complex problem is to break it down into small easy to understand units. The key to writing good code is to write small easy to understand and test (debug) subroutines.



          Variable Declaration



          I personally always use Option Explicit and declare the Type for each variable. This will give you the most information and the best feedback from the compiler.



          I try and declare my variables in groups by type: Strings, Numeric, Objects, Outlook Objects, Excel Object at the top of the subroutine after any constants. Basically, whatever seems right for the code. I do it this way because I want my declarations to have a low profile and be separated from the logic of the subroutine. Ideally, I would like to be able to read the entire logic of a subroutine without having to scroll the code pane.



          Repeated Logic



          I am specifically referring to the use of Accept. As Raystafarian noted the name sucks, at least I think that was what he said. More importantly, the logic behind it is repeated several times.




          Accept = False
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          If ActiveFolder = "Application Management Linux1, I351" Then
          Accept = True
          End If



          Since Accept is not used outside of the If Item.MessageClass... block I would simplify it like this:




          Accept = ActiveFolder = "Application Management Linux1, I351"




          Accept is then used on line 43:




          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then




          But then on line 64 the same logic is used but without the Accept variable:




          If ActiveFolder = "Application Management Linux1, I351" Then



          But want the code from lines 43:60 is only relevant if it passes the Accept condition. So why don't lines 43:60 follow line 64???



          Why not just get rid of the Accept variable like this:




          If Item.MessageClass = "IPM.Schedule.Meeting.Request" And ActiveFolder = "Application Management Linux1, I351" Then



          Not only will this simplify the code it will remove a nesting level making it easier to read.




          Now this wouldn't be a Narcissistic Answer if I don't show my way of doing things. So here we go!!




          Writing JSON and SQL Statements



          There are plenty of good tools that help of write, format, and test our JSON and SQL statements. But what do we do? While until recently, I would spend a lot time writing code like & CHR(34) & UGH & CHR(34) & "This Sucks" & or """ & UGH & """This Sucks"""". Why not just not just write the JSON or SQL with the right tools copy their results to the CLipboard and process it from there.



          Note: I use the @ sign to signify named parameters. I will later either use Replace(Text,"@Name",Name) or replace @ with " & " and then after the variable finish the concatenation with & ".



          This is the first time I use JSONEditor and it only took about 10-12 minute to write ProcessClipboard().



          Sub ProcessClipboard()
          Dim lines() As String, Text As String
          Dim x As Long
          With CreateObject("New:1C3B4210-F441-11CE-B9EA-00AA006B1A69")
          .GetFromClipboard
          Text = .GetText
          End With

          Text = Replace(Text, Chr(34), String(2, 34))

          lines = Split(Text, Chr(10))

          For x = 0 To UBound(lines)
          Debug.Print "JSON(" & x & ") =", Chr(34); lines(x); Chr(34)
          Next
          End Sub


          JSON Editor Image



          JSON Editor Code



          Immediate Window Output



          The Immediate Window raw output



          getJSON Immediate Window Test



          This is a perfect example of why we you should use smaller functions and subroutines. Look how easy it is to test.



          Refactored Code



          Refactored Code Subroutines



          Option Explicit

          Public Sub AcceptMeeting(ActiveFolder As String, Inbox As String)
          Const SPAM_FOLDER As String = "*** SPAM"
          Dim jiraLabel As String
          Dim Item As Object, items As Collection, recip As Outlook.Recipient
          Dim AppointmentItem As Outlook.AppointmentItem
          Dim JSON As String

          If ActiveFolder = "Application Management Linux1, I351" Then

          Set items = getIPMMeetingRequests(ActiveFolder, Inbox)

          For Each Item In items
          DoEvents

          'Label for JIRA task
          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True Then
          If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
          Item.Categories = "Change Produktion" 'Kategorie setzen PROD
          jiraLabel = "Produktion"
          ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Integration"
          ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Testing"
          Else
          Item.Categories = "Change Info" 'Kategorie setzen Info
          jiraLabel = "Info"
          End If

          'Accept Appointment
          Set AppointmentItem = Item.GetAssociatedAppointment(True)

          Item.UnRead = False

          'CustomReplace Msg.Body Msg.Subject
          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON(CustomReplace(Item.Subject), CustomReplace(Item.Body), _
          "Test", recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, AppointmentItem.End, "")

          createJIRATask "username", "password", JSON
          End If
          Next

          Item.Move Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders(SPAM_FOLDER)

          End If
          Next

          End If
          MsgBox Inbox & ": " & items.Count & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

          End Sub

          Private Sub createJIRATask(User As String, Password As String, JSON As String)
          'Sending request to JIRA
          Dim xhr As Object
          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(User + ":" + Password)
          xhr.Send JSON
          End Sub

          Private Function CustomReplace(Text As String) As String
          Text = Replace(Text, """", "'")
          Text = Replace(Text, vbCr & vbLf, "n")
          Text = Replace(Text, vbCr, "n")
          Text = Replace(Text, vbLf, "n")
          CustomReplace = Text
          End Function

          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection
          Dim myFolder As Outlook.Folder, Folders As Outlook.Folders, Item As Object, Subfolder As Outlook.Folder
          Dim col As New Collection
          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders

          Set Subfolder = Folders.Item(Inbox)
          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next
          Set getIPMMeetingRequests = col
          End Function

          Private Function getJSON(customSubject As String, customBody As String, issuName As String, recipAlias As String, appStartDateTime As Date, appEndDateTime As Date, jiraLabel As String) As String
          Dim JSON(19) As String, JSONText As String
          JSON(0) = ""
          JSON(1) = " ""fields"": "
          JSON(2) = " ""project"": "
          JSON(3) = " ""id"": 30611"
          JSON(4) = " ,"
          JSON(5) = " ""summary"": ""@customSubject"","
          JSON(6) = " ""description"": ""@customBody"","
          JSON(7) = " ""issuetype"": "
          JSON(8) = " ""name"": ""@issuName"""
          JSON(9) = " ,"
          JSON(10) = " ""assignee"": "
          JSON(11) = " ""name"": ""@recipAlias"""
          JSON(12) = " ,"
          JSON(13) = " ""customfield_10021"": ""@appStartDateTime"","
          JSON(14) = " ""customfield_12760"": ""@appEndDateTime"","
          JSON(15) = " ""labels"": ["
          JSON(16) = " ""@jiraLabel"""
          JSON(17) = " ]"
          JSON(18) = " "
          JSON(19) = ""

          JSONText = Join(JSON, vbNewLine)
          JSONText = Replace(JSONText, "@customSubject", customSubject)
          JSONText = Replace(JSONText, "@customBody", customBody)
          JSONText = Replace(JSONText, "@issuName", issuName)
          JSONText = Replace(JSONText, "@recipAlias", recipAlias)
          JSONText = Replace(JSONText, "@appStartDateTime", Format(appStartDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@appEndDateTime", Format(appEndDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@jiraLabel", jiraLabel)

          getJSON = JSONText
          End Function

          Private Function isValidAddressEntry(AddressEntry As String) As Boolean
          Dim regEx As New RegExp
          regEx.Pattern = "^w+sw+,sI351$"
          isValidAddressEntry = regEx.Test(AddressEntry) And AddressEntry <> "Application Management Linux1, I351"
          End Function

          Private Function Base64Encode(Text As String) As String
          '.... Not Provided
          End Function


          As always my code comes with a "3 Time Your Money Back Guarantee" minus $19.95 shipping and handling.






          share|improve this answer























          • it was really narcissistic but everything was famously explained thank you very much :))) .
            – khashashin
            May 23 at 10:21










          • It almost works exept jiraLabel Variable. This value is empty as "". But schould be "Production", "Integration", "Testing" or "info" how can I fix it?
            – khashashin
            May 23 at 10:36










          • I found it, just have to give it in getJSON call not as empty "" but as jiraLabel
            – khashashin
            May 23 at 10:41










          • And you have wrong link to JSON online Editor ;)
            – khashashin
            May 23 at 10:45










          • @khashashin I fixed the link, thanks. I don't know how CR messed it up :). Happy Coding
            – user109261
            May 23 at 14:29

















          up vote
          1
          down vote













          Variables



          First, the variables folders, recips, xhr aren't defined.



          When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch.



          Always turn on Option Explicit. You can have it automatically by going to Tools -> Options in the VBE and checking the Require Variable Declaration option. This way if you have any variables not defined, the compiler will let you know.




          Also when you declare variables on the same line, you need to specify each variable's type -




          Dim appStartDate, appStartTime, appEndDate, appEndTime As Date



          This is what it's doing -



          Dim appStartDate as Variant
          Dim appStartTime as Variant
          Dim appEndDate as Variant
          Dim appEndTime as Date


          Same thing happens here




          Dim startDateString, endDateString As String



          And here




          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String




          With that out of the way, your variable naming leaves a bit to be desired. Right now, looking at the code it is kind of difficult to know exactly what each variable is doing.




          Dim myFolder As Outlook.Folder
          Set myFolder = myNamespace.Folders(ActiveFolder)

          Dim Folders
          Set Folders = myFolder.Folders

          Dim Subfolder As Outlook.Folder
          Set Subfolder = Folders.Item(Inbox)

          Dim Folder As Outlook.Folder 'I don't see this used



          I'll make the assumption that the missing declaration of Folders was just supposed to be the variable Folder.



          So MyFolder is the ActiveFolder. And Folders are the Folders in the ActiveFolder. And a SubFolder is some items?



          So for all that jazz it basically comes down to the loop -



          For Each Item In Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders.Items(Inbox).Items


          I think giving the namespace a variable is a good idea, but all those other folders can probably be combined into a single variable, which you iterate the item through, especially since all of that at the top is never referenced again.



          The Change folder could just be spamFolder and set to the spam folder in the beginning, I don't see it reassigned anywhere.



          I think myAppt and myMtg are okay, but why not just write the entire name out? The characters are free.




          Dim Forward As Outlook.MeetingItem



          This isn't used either, as far as I can see.




          Dim Accept As Boolean



          Usually with a boolean you want it to read like a boolean, like isTrue or isAccepted or shouldAccept - something like that makes it more clear.




          Structure



          It seems to be that the logic in this macro is broken up into a few things -



          1. Find meeting requests

          2. Categorize the request

          3. Parse the request

          4. Build the JSON

          5. Send the JSON

          Because that's the business logic, break it out into different procedures or functions to indicate what each part does. This makes it easier to follow, makes it simpler to review and allows you to refactor.



          Sub FindMeetingRequests(ByVal targetFolder as Folder)
          Sub ProcessMeetingRequests(ByVal item as Object)
          Function BuildJSON(ByVal body as String) as String
          Sub SubmitJSON(ByVal JSON as String)


          This would be especially helpful when writing the JSON as your comment indicates - it looks scary. Break it out into its own function and then work on that function to make it seem less scary, or more manageable.



          And since sending the HTTP request really doesn't have anything to do with the actual meeting request items, pull that out to its own procedure as well. Compartmentalize.




          Constants




          'Values to create JSON
          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
          flds = """fields"""
          prt = """project"""
          id = """id"""
          asgn = """assignee"""
          smry = """summary"""
          descrp = """description"""
          issu = """issuetype"""
          label = """labels"""
          issuName = """Test"""
          startAt = """customfield_10021"""
          endDate = """customfield_12760"""
          name = """name"""
          lfbrkt = ""
          rtbrkt = ""
          cma = ","
          dbdots = ":"
          sqLfBrkt = "["
          sqRtBrkt = "]"
          Creating JSON - It looks scary but works
          JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
          vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
          vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
          vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
          vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
          vbCrLf + rtbrkt + _
          vbCrLf + rtbrkt



          I applaud your efforts on creating those variables the way you did. It seems to me, however, that the majority of the JSON is a constant - I see the use of the dates, the subject, the body, etc. Maybe break those strings up into constant variables, like



          Const JSON_BEFORE_SUBJECT as String = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """"


          In a way you end up with something a lot less scary



          JSON = JSON_BEFORE_SUBJECT & customSubject & JSON_BEFORE_BODY & customBody & JSON_BEFORE_ISSUE & issuName ....





          share|improve this answer





















          • As I said it was my fisrt code in vba, thanks to your explanation i have lerned something new for me. Thank you very much!!!
            – khashashin
            May 23 at 10:48

















          up vote
          0
          down vote













          My advice is very similar to what Narcissistic Answers posted, so I don't have a ton to add. Using multiple small/single-purpose functions is almost always better than using one long/complex sub, which their answer demonstrated very well.



          One thing to keep in mind when you're making "helper" functions is whether you may want to reuse them in another project. Take a look at this function from Narcissistic Answers' implementation:



          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection

          Dim myFolder As Outlook.Folder
          Dim Folders As Outlook.Folders
          Dim Item As Object
          Dim Subfolder As Outlook.Folder
          Dim col As New Collection

          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders
          Set Subfolder = Folders.Item(Inbox)

          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next

          Set getIPMMeetingRequests = col

          End Function


          The function is incredibly specific to this particular problem. It can only loop through a folder ("FolderName") that has a subfolder ("Inbox"), and it can only look for "IPM.Schedule.Meeting.Request" items.



          With a few tweaks, however, you can make the function general enough to reuse in a variety of situations:



          Function getItems(folder As Outlook.Folder, itemType As String) As Collection

          Dim item As Object
          Dim results As New Collection
          For Each item In folder.Items
          If item.MessageClass = itemType Then
          results.Add Item
          End If
          Next
          Set getItems = results

          End Function


          And if you're really thinking ahead, you can make the function incredibly flexible. You could specify more than one item type, use partial/wildcard matches when checking the item types, or even loop through more than one folder at once:



          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function


          The other thing I'll mention is to watch out for instances where a function is unnecessarily called in every iteration of a loop. In Narcissistic Answers' post, the function that formats the Subject/Body portions of the JSON string is called once for every recipient:



          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON( _
          CustomReplace(Item.Subject), _
          CustomReplace(Item.Body), _
          "Test", _
          recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, _
          AppointmentItem.End, _
          "")

          createJIRATask "username", "password", JSON
          End If
          Next


          However, these strings are determined by the Item, not the recipient, so they should be formatted before entering the inner loop. That way you just have to format them once.



          In this particular case, it's not a huge deal. But it's good practice to watch out for unnecessary function calls.



          EDIT: Adding the full version of how I'd recommend approaching the problem.



          Sub AcceptMeeting(ActiveFolder As String, Inbox As String)

          If Not ActiveFolder = "Application Management Linux1, I351" Then
          Exit Sub
          End If

          'Set up objects used in each pass of outer loop
          Dim myFolder As Outlook.Folder
          Dim regEx As New RegExp
          Set myFolder = Application.GetNamespace("MAPI").Folders(ActiveFolder)
          regEx.Pattern = "^w+sw+,sI351$"

          'Get collection of meeting items and loop through
          Dim i As Long
          Dim message As Object
          Dim messages As Collection
          Set messages = getItems(myFolder.Folders.Item(Inbox), "IPM.Schedule.Meeting.Request")
          For Each message In messages
          'Determine if message fits criteria
          If InStr(LCase(message.Subject), "change") > 0 And message.UnRead Then
          'Accept appointment
          Dim appt As Outlook.AppointmentItem
          Set appt = message.GetAssociatedAppointment(True)
          appt.Respond olResponseAccepted, True
          message.UnRead = False

          'Format JSON components for message by removing illegal characters and surrounding elements with quotes
          'Since they stay the same for each pass of inner loop...
          '...doing it here saves execution time
          Dim jiraLabel As String
          Dim customBody As String
          Dim customSubject As String
          Dim startDate As String
          Dim endDate As String
          jiraLabel = parseSubject(message)
          customBody = formatForJSON(message.Body)
          customSubject = formatForJSON(message.Subject)
          startDate = formatDate(appt.Start)
          endDate = formatDate(appt.End)

          'Send response for each matching recipient
          Dim recipient As Outlook.Recipient
          For Each recipient In message.Recipients
          If addressMatches(recipient.AddressEntry, regEx) Then
          Dim JSON As String
          JSON = createJSON( _
          exchangeID:="""" & recipient.AddressEntry.GetExchangeUser().Alias & """", _
          label:=jiraLabel, _
          subject:=customSubject, _
          body:=customBody, _
          startDate:=startDate, _
          endDate:=endDate)

          Call sendJIRA(JSON, "username", "password")
          End If
          Next
          message.Move myfolder.Folders("*** SPAM")
          i = i + 1
          End If
          Next

          MsgBox Inbox & ": " & i & " Meetings accepted", vbOKOnly, ActiveFolder

          End Sub
          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function
          Function parseSubject(obj As Object) As String

          Dim subjectText As String
          Dim itemLabel As String
          subjectText = LCase(obj.Subject)

          If InStr(subjectText), "produktion") > 0 Then
          obj.Categories = "Change Produktion"
          itemLabel = "Produktion"
          ElseIf InStr(subjectText), "integration") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Integration"
          ElseIf InStr(subjectText, "test") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Testing"
          Else
          obj.Categories = "Change Info"
          itemLabel = "Info"
          End If

          parseSubject = """" & itemLabel & """"

          End Function
          Function formatForJSON(str As String) As String

          Dim resultStr As String
          resultStr = Replace(str, """", "'")
          resultStr = Replace(resultStr, vbCr & vbLf, "n")
          resultStr = Replace(resultStr, vbCr, "n")
          resultStr = Replace(resultStr, vbLf, "n")
          formatForJSON = """" & resultStr & """"

          End Function
          Function createJSON(exchangeID As String, label As String, subject As String, _
          body As String, startDate As String, endDate As String) As String

          Dim JSON As String
          JSON = JSON & """fields: " & vbCrLf
          JSON = JSON & " ""project"": " & vbCrLf
          JSON = JSON & " ""id"": 30611" & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""summary"": " & subject & "," & vbCrLf
          JSON = JSON & " ""description"": " & body & "," & vbCrLf
          JSON = JSON & " ""issuetype"": " & vbCrLf
          JSON = JSON & " ""name"": " & exchangeID & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""customfield_10021"": " & startDate & "," & vbCrLf
          JSON = JSON & " ""customfield_12760"": " & endDate & "," & vbCrLf
          JSON = JSON & " ""labels"": [" & label & "]" & vbCrLf
          JSON = JSON & "" & vbCrLf & ""

          createJSON = JSON

          End Function
          Function formatDate(dt As Date) As String

          formatDate = """" & Format(dt, "yyyy-mm-dd") & "T" & _
          Format(dt, "hh:mm") & ":00.000+0200" & """"

          End Function
          Sub sendJIRA(JSON As String, username As String, pw As String)

          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(username & ":" & pw)
          xhr.Send JSON

          End Sub
          Function addressMatches(address As String, regEx As RegExp) As Boolean

          If address = "Application Management Linux1, I351" Then
          addressMatches = False
          Else
          addressMatches = regEx.Test(address)
          End If

          End Function





          share|improve this answer























          • You are commentary on code reuse is "Spot On" . It seems to me that a JIRA is setup per recipient and that the JSON changes for each recipient. As evidenced by recip.AddressEntry.GetExchangeUser().Alias which is passed to my getJSON function as the recipAlias parameter and used in JSON string of the OP's post (JSON = .... """" + recip.AddressEntry.GetExchangeUser().Alias + """" ). +1
            – user109261
            May 23 at 19:46










          • The only part that changes is the recipAlias parameter, the Subject/Body portions stay the same. I'll edit the post to show what I mean.
            – Daniel McCracken
            May 23 at 21:03










          • Your Full Version is solid. The intermediate variables do make the code read and test better. I'm still not a big fan of the JSON string concatenation but you handled it well.
            – user109261
            May 24 at 2:49










          • Fair enough! I don't usually work with JSON but when it comes to SQL strings I have a couple of approaches I normally use. Typically I just import a .sql file from our network drive + do string replacement (though I surround my parameters <like this> rather than using @). If I can't be sure I'll have local network access, I have a macro that can take a text file and convert it to a SQL query string suitable for copy/pasting directly into a VBA module. In this case, my answer was already pretty long, and the JSON string was pretty short, so I didn't bother with a more complex solution.
            – Daniel McCracken
            May 24 at 4:08











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194943%2fcreating-jira-task-from-email-in-ms-outlook%23new-answer', 'question_page');

          );

          Post as a guest






























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          4
          down vote



          accepted










          "Why Are We Scared?"



          The number one reason that we are scared of something is that we don't fully understand it. The key to understanding a complex problem is to break it down into small easy to understand units. The key to writing good code is to write small easy to understand and test (debug) subroutines.



          Variable Declaration



          I personally always use Option Explicit and declare the Type for each variable. This will give you the most information and the best feedback from the compiler.



          I try and declare my variables in groups by type: Strings, Numeric, Objects, Outlook Objects, Excel Object at the top of the subroutine after any constants. Basically, whatever seems right for the code. I do it this way because I want my declarations to have a low profile and be separated from the logic of the subroutine. Ideally, I would like to be able to read the entire logic of a subroutine without having to scroll the code pane.



          Repeated Logic



          I am specifically referring to the use of Accept. As Raystafarian noted the name sucks, at least I think that was what he said. More importantly, the logic behind it is repeated several times.




          Accept = False
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          If ActiveFolder = "Application Management Linux1, I351" Then
          Accept = True
          End If



          Since Accept is not used outside of the If Item.MessageClass... block I would simplify it like this:




          Accept = ActiveFolder = "Application Management Linux1, I351"




          Accept is then used on line 43:




          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then




          But then on line 64 the same logic is used but without the Accept variable:




          If ActiveFolder = "Application Management Linux1, I351" Then



          But want the code from lines 43:60 is only relevant if it passes the Accept condition. So why don't lines 43:60 follow line 64???



          Why not just get rid of the Accept variable like this:




          If Item.MessageClass = "IPM.Schedule.Meeting.Request" And ActiveFolder = "Application Management Linux1, I351" Then



          Not only will this simplify the code it will remove a nesting level making it easier to read.




          Now this wouldn't be a Narcissistic Answer if I don't show my way of doing things. So here we go!!




          Writing JSON and SQL Statements



          There are plenty of good tools that help of write, format, and test our JSON and SQL statements. But what do we do? While until recently, I would spend a lot time writing code like & CHR(34) & UGH & CHR(34) & "This Sucks" & or """ & UGH & """This Sucks"""". Why not just not just write the JSON or SQL with the right tools copy their results to the CLipboard and process it from there.



          Note: I use the @ sign to signify named parameters. I will later either use Replace(Text,"@Name",Name) or replace @ with " & " and then after the variable finish the concatenation with & ".



          This is the first time I use JSONEditor and it only took about 10-12 minute to write ProcessClipboard().



          Sub ProcessClipboard()
          Dim lines() As String, Text As String
          Dim x As Long
          With CreateObject("New:1C3B4210-F441-11CE-B9EA-00AA006B1A69")
          .GetFromClipboard
          Text = .GetText
          End With

          Text = Replace(Text, Chr(34), String(2, 34))

          lines = Split(Text, Chr(10))

          For x = 0 To UBound(lines)
          Debug.Print "JSON(" & x & ") =", Chr(34); lines(x); Chr(34)
          Next
          End Sub


          JSON Editor Image



          JSON Editor Code



          Immediate Window Output



          The Immediate Window raw output



          getJSON Immediate Window Test



          This is a perfect example of why we you should use smaller functions and subroutines. Look how easy it is to test.



          Refactored Code



          Refactored Code Subroutines



          Option Explicit

          Public Sub AcceptMeeting(ActiveFolder As String, Inbox As String)
          Const SPAM_FOLDER As String = "*** SPAM"
          Dim jiraLabel As String
          Dim Item As Object, items As Collection, recip As Outlook.Recipient
          Dim AppointmentItem As Outlook.AppointmentItem
          Dim JSON As String

          If ActiveFolder = "Application Management Linux1, I351" Then

          Set items = getIPMMeetingRequests(ActiveFolder, Inbox)

          For Each Item In items
          DoEvents

          'Label for JIRA task
          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True Then
          If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
          Item.Categories = "Change Produktion" 'Kategorie setzen PROD
          jiraLabel = "Produktion"
          ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Integration"
          ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Testing"
          Else
          Item.Categories = "Change Info" 'Kategorie setzen Info
          jiraLabel = "Info"
          End If

          'Accept Appointment
          Set AppointmentItem = Item.GetAssociatedAppointment(True)

          Item.UnRead = False

          'CustomReplace Msg.Body Msg.Subject
          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON(CustomReplace(Item.Subject), CustomReplace(Item.Body), _
          "Test", recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, AppointmentItem.End, "")

          createJIRATask "username", "password", JSON
          End If
          Next

          Item.Move Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders(SPAM_FOLDER)

          End If
          Next

          End If
          MsgBox Inbox & ": " & items.Count & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

          End Sub

          Private Sub createJIRATask(User As String, Password As String, JSON As String)
          'Sending request to JIRA
          Dim xhr As Object
          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(User + ":" + Password)
          xhr.Send JSON
          End Sub

          Private Function CustomReplace(Text As String) As String
          Text = Replace(Text, """", "'")
          Text = Replace(Text, vbCr & vbLf, "n")
          Text = Replace(Text, vbCr, "n")
          Text = Replace(Text, vbLf, "n")
          CustomReplace = Text
          End Function

          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection
          Dim myFolder As Outlook.Folder, Folders As Outlook.Folders, Item As Object, Subfolder As Outlook.Folder
          Dim col As New Collection
          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders

          Set Subfolder = Folders.Item(Inbox)
          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next
          Set getIPMMeetingRequests = col
          End Function

          Private Function getJSON(customSubject As String, customBody As String, issuName As String, recipAlias As String, appStartDateTime As Date, appEndDateTime As Date, jiraLabel As String) As String
          Dim JSON(19) As String, JSONText As String
          JSON(0) = ""
          JSON(1) = " ""fields"": "
          JSON(2) = " ""project"": "
          JSON(3) = " ""id"": 30611"
          JSON(4) = " ,"
          JSON(5) = " ""summary"": ""@customSubject"","
          JSON(6) = " ""description"": ""@customBody"","
          JSON(7) = " ""issuetype"": "
          JSON(8) = " ""name"": ""@issuName"""
          JSON(9) = " ,"
          JSON(10) = " ""assignee"": "
          JSON(11) = " ""name"": ""@recipAlias"""
          JSON(12) = " ,"
          JSON(13) = " ""customfield_10021"": ""@appStartDateTime"","
          JSON(14) = " ""customfield_12760"": ""@appEndDateTime"","
          JSON(15) = " ""labels"": ["
          JSON(16) = " ""@jiraLabel"""
          JSON(17) = " ]"
          JSON(18) = " "
          JSON(19) = ""

          JSONText = Join(JSON, vbNewLine)
          JSONText = Replace(JSONText, "@customSubject", customSubject)
          JSONText = Replace(JSONText, "@customBody", customBody)
          JSONText = Replace(JSONText, "@issuName", issuName)
          JSONText = Replace(JSONText, "@recipAlias", recipAlias)
          JSONText = Replace(JSONText, "@appStartDateTime", Format(appStartDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@appEndDateTime", Format(appEndDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@jiraLabel", jiraLabel)

          getJSON = JSONText
          End Function

          Private Function isValidAddressEntry(AddressEntry As String) As Boolean
          Dim regEx As New RegExp
          regEx.Pattern = "^w+sw+,sI351$"
          isValidAddressEntry = regEx.Test(AddressEntry) And AddressEntry <> "Application Management Linux1, I351"
          End Function

          Private Function Base64Encode(Text As String) As String
          '.... Not Provided
          End Function


          As always my code comes with a "3 Time Your Money Back Guarantee" minus $19.95 shipping and handling.






          share|improve this answer























          • it was really narcissistic but everything was famously explained thank you very much :))) .
            – khashashin
            May 23 at 10:21










          • It almost works exept jiraLabel Variable. This value is empty as "". But schould be "Production", "Integration", "Testing" or "info" how can I fix it?
            – khashashin
            May 23 at 10:36










          • I found it, just have to give it in getJSON call not as empty "" but as jiraLabel
            – khashashin
            May 23 at 10:41










          • And you have wrong link to JSON online Editor ;)
            – khashashin
            May 23 at 10:45










          • @khashashin I fixed the link, thanks. I don't know how CR messed it up :). Happy Coding
            – user109261
            May 23 at 14:29














          up vote
          4
          down vote



          accepted










          "Why Are We Scared?"



          The number one reason that we are scared of something is that we don't fully understand it. The key to understanding a complex problem is to break it down into small easy to understand units. The key to writing good code is to write small easy to understand and test (debug) subroutines.



          Variable Declaration



          I personally always use Option Explicit and declare the Type for each variable. This will give you the most information and the best feedback from the compiler.



          I try and declare my variables in groups by type: Strings, Numeric, Objects, Outlook Objects, Excel Object at the top of the subroutine after any constants. Basically, whatever seems right for the code. I do it this way because I want my declarations to have a low profile and be separated from the logic of the subroutine. Ideally, I would like to be able to read the entire logic of a subroutine without having to scroll the code pane.



          Repeated Logic



          I am specifically referring to the use of Accept. As Raystafarian noted the name sucks, at least I think that was what he said. More importantly, the logic behind it is repeated several times.




          Accept = False
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          If ActiveFolder = "Application Management Linux1, I351" Then
          Accept = True
          End If



          Since Accept is not used outside of the If Item.MessageClass... block I would simplify it like this:




          Accept = ActiveFolder = "Application Management Linux1, I351"




          Accept is then used on line 43:




          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then




          But then on line 64 the same logic is used but without the Accept variable:




          If ActiveFolder = "Application Management Linux1, I351" Then



          But want the code from lines 43:60 is only relevant if it passes the Accept condition. So why don't lines 43:60 follow line 64???



          Why not just get rid of the Accept variable like this:




          If Item.MessageClass = "IPM.Schedule.Meeting.Request" And ActiveFolder = "Application Management Linux1, I351" Then



          Not only will this simplify the code it will remove a nesting level making it easier to read.




          Now this wouldn't be a Narcissistic Answer if I don't show my way of doing things. So here we go!!




          Writing JSON and SQL Statements



          There are plenty of good tools that help of write, format, and test our JSON and SQL statements. But what do we do? While until recently, I would spend a lot time writing code like & CHR(34) & UGH & CHR(34) & "This Sucks" & or """ & UGH & """This Sucks"""". Why not just not just write the JSON or SQL with the right tools copy their results to the CLipboard and process it from there.



          Note: I use the @ sign to signify named parameters. I will later either use Replace(Text,"@Name",Name) or replace @ with " & " and then after the variable finish the concatenation with & ".



          This is the first time I use JSONEditor and it only took about 10-12 minute to write ProcessClipboard().



          Sub ProcessClipboard()
          Dim lines() As String, Text As String
          Dim x As Long
          With CreateObject("New:1C3B4210-F441-11CE-B9EA-00AA006B1A69")
          .GetFromClipboard
          Text = .GetText
          End With

          Text = Replace(Text, Chr(34), String(2, 34))

          lines = Split(Text, Chr(10))

          For x = 0 To UBound(lines)
          Debug.Print "JSON(" & x & ") =", Chr(34); lines(x); Chr(34)
          Next
          End Sub


          JSON Editor Image



          JSON Editor Code



          Immediate Window Output



          The Immediate Window raw output



          getJSON Immediate Window Test



          This is a perfect example of why we you should use smaller functions and subroutines. Look how easy it is to test.



          Refactored Code



          Refactored Code Subroutines



          Option Explicit

          Public Sub AcceptMeeting(ActiveFolder As String, Inbox As String)
          Const SPAM_FOLDER As String = "*** SPAM"
          Dim jiraLabel As String
          Dim Item As Object, items As Collection, recip As Outlook.Recipient
          Dim AppointmentItem As Outlook.AppointmentItem
          Dim JSON As String

          If ActiveFolder = "Application Management Linux1, I351" Then

          Set items = getIPMMeetingRequests(ActiveFolder, Inbox)

          For Each Item In items
          DoEvents

          'Label for JIRA task
          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True Then
          If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
          Item.Categories = "Change Produktion" 'Kategorie setzen PROD
          jiraLabel = "Produktion"
          ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Integration"
          ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Testing"
          Else
          Item.Categories = "Change Info" 'Kategorie setzen Info
          jiraLabel = "Info"
          End If

          'Accept Appointment
          Set AppointmentItem = Item.GetAssociatedAppointment(True)

          Item.UnRead = False

          'CustomReplace Msg.Body Msg.Subject
          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON(CustomReplace(Item.Subject), CustomReplace(Item.Body), _
          "Test", recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, AppointmentItem.End, "")

          createJIRATask "username", "password", JSON
          End If
          Next

          Item.Move Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders(SPAM_FOLDER)

          End If
          Next

          End If
          MsgBox Inbox & ": " & items.Count & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

          End Sub

          Private Sub createJIRATask(User As String, Password As String, JSON As String)
          'Sending request to JIRA
          Dim xhr As Object
          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(User + ":" + Password)
          xhr.Send JSON
          End Sub

          Private Function CustomReplace(Text As String) As String
          Text = Replace(Text, """", "'")
          Text = Replace(Text, vbCr & vbLf, "n")
          Text = Replace(Text, vbCr, "n")
          Text = Replace(Text, vbLf, "n")
          CustomReplace = Text
          End Function

          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection
          Dim myFolder As Outlook.Folder, Folders As Outlook.Folders, Item As Object, Subfolder As Outlook.Folder
          Dim col As New Collection
          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders

          Set Subfolder = Folders.Item(Inbox)
          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next
          Set getIPMMeetingRequests = col
          End Function

          Private Function getJSON(customSubject As String, customBody As String, issuName As String, recipAlias As String, appStartDateTime As Date, appEndDateTime As Date, jiraLabel As String) As String
          Dim JSON(19) As String, JSONText As String
          JSON(0) = ""
          JSON(1) = " ""fields"": "
          JSON(2) = " ""project"": "
          JSON(3) = " ""id"": 30611"
          JSON(4) = " ,"
          JSON(5) = " ""summary"": ""@customSubject"","
          JSON(6) = " ""description"": ""@customBody"","
          JSON(7) = " ""issuetype"": "
          JSON(8) = " ""name"": ""@issuName"""
          JSON(9) = " ,"
          JSON(10) = " ""assignee"": "
          JSON(11) = " ""name"": ""@recipAlias"""
          JSON(12) = " ,"
          JSON(13) = " ""customfield_10021"": ""@appStartDateTime"","
          JSON(14) = " ""customfield_12760"": ""@appEndDateTime"","
          JSON(15) = " ""labels"": ["
          JSON(16) = " ""@jiraLabel"""
          JSON(17) = " ]"
          JSON(18) = " "
          JSON(19) = ""

          JSONText = Join(JSON, vbNewLine)
          JSONText = Replace(JSONText, "@customSubject", customSubject)
          JSONText = Replace(JSONText, "@customBody", customBody)
          JSONText = Replace(JSONText, "@issuName", issuName)
          JSONText = Replace(JSONText, "@recipAlias", recipAlias)
          JSONText = Replace(JSONText, "@appStartDateTime", Format(appStartDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@appEndDateTime", Format(appEndDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@jiraLabel", jiraLabel)

          getJSON = JSONText
          End Function

          Private Function isValidAddressEntry(AddressEntry As String) As Boolean
          Dim regEx As New RegExp
          regEx.Pattern = "^w+sw+,sI351$"
          isValidAddressEntry = regEx.Test(AddressEntry) And AddressEntry <> "Application Management Linux1, I351"
          End Function

          Private Function Base64Encode(Text As String) As String
          '.... Not Provided
          End Function


          As always my code comes with a "3 Time Your Money Back Guarantee" minus $19.95 shipping and handling.






          share|improve this answer























          • it was really narcissistic but everything was famously explained thank you very much :))) .
            – khashashin
            May 23 at 10:21










          • It almost works exept jiraLabel Variable. This value is empty as "". But schould be "Production", "Integration", "Testing" or "info" how can I fix it?
            – khashashin
            May 23 at 10:36










          • I found it, just have to give it in getJSON call not as empty "" but as jiraLabel
            – khashashin
            May 23 at 10:41










          • And you have wrong link to JSON online Editor ;)
            – khashashin
            May 23 at 10:45










          • @khashashin I fixed the link, thanks. I don't know how CR messed it up :). Happy Coding
            – user109261
            May 23 at 14:29












          up vote
          4
          down vote



          accepted







          up vote
          4
          down vote



          accepted






          "Why Are We Scared?"



          The number one reason that we are scared of something is that we don't fully understand it. The key to understanding a complex problem is to break it down into small easy to understand units. The key to writing good code is to write small easy to understand and test (debug) subroutines.



          Variable Declaration



          I personally always use Option Explicit and declare the Type for each variable. This will give you the most information and the best feedback from the compiler.



          I try and declare my variables in groups by type: Strings, Numeric, Objects, Outlook Objects, Excel Object at the top of the subroutine after any constants. Basically, whatever seems right for the code. I do it this way because I want my declarations to have a low profile and be separated from the logic of the subroutine. Ideally, I would like to be able to read the entire logic of a subroutine without having to scroll the code pane.



          Repeated Logic



          I am specifically referring to the use of Accept. As Raystafarian noted the name sucks, at least I think that was what he said. More importantly, the logic behind it is repeated several times.




          Accept = False
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          If ActiveFolder = "Application Management Linux1, I351" Then
          Accept = True
          End If



          Since Accept is not used outside of the If Item.MessageClass... block I would simplify it like this:




          Accept = ActiveFolder = "Application Management Linux1, I351"




          Accept is then used on line 43:




          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then




          But then on line 64 the same logic is used but without the Accept variable:




          If ActiveFolder = "Application Management Linux1, I351" Then



          But want the code from lines 43:60 is only relevant if it passes the Accept condition. So why don't lines 43:60 follow line 64???



          Why not just get rid of the Accept variable like this:




          If Item.MessageClass = "IPM.Schedule.Meeting.Request" And ActiveFolder = "Application Management Linux1, I351" Then



          Not only will this simplify the code it will remove a nesting level making it easier to read.




          Now this wouldn't be a Narcissistic Answer if I don't show my way of doing things. So here we go!!




          Writing JSON and SQL Statements



          There are plenty of good tools that help of write, format, and test our JSON and SQL statements. But what do we do? While until recently, I would spend a lot time writing code like & CHR(34) & UGH & CHR(34) & "This Sucks" & or """ & UGH & """This Sucks"""". Why not just not just write the JSON or SQL with the right tools copy their results to the CLipboard and process it from there.



          Note: I use the @ sign to signify named parameters. I will later either use Replace(Text,"@Name",Name) or replace @ with " & " and then after the variable finish the concatenation with & ".



          This is the first time I use JSONEditor and it only took about 10-12 minute to write ProcessClipboard().



          Sub ProcessClipboard()
          Dim lines() As String, Text As String
          Dim x As Long
          With CreateObject("New:1C3B4210-F441-11CE-B9EA-00AA006B1A69")
          .GetFromClipboard
          Text = .GetText
          End With

          Text = Replace(Text, Chr(34), String(2, 34))

          lines = Split(Text, Chr(10))

          For x = 0 To UBound(lines)
          Debug.Print "JSON(" & x & ") =", Chr(34); lines(x); Chr(34)
          Next
          End Sub


          JSON Editor Image



          JSON Editor Code



          Immediate Window Output



          The Immediate Window raw output



          getJSON Immediate Window Test



          This is a perfect example of why we you should use smaller functions and subroutines. Look how easy it is to test.



          Refactored Code



          Refactored Code Subroutines



          Option Explicit

          Public Sub AcceptMeeting(ActiveFolder As String, Inbox As String)
          Const SPAM_FOLDER As String = "*** SPAM"
          Dim jiraLabel As String
          Dim Item As Object, items As Collection, recip As Outlook.Recipient
          Dim AppointmentItem As Outlook.AppointmentItem
          Dim JSON As String

          If ActiveFolder = "Application Management Linux1, I351" Then

          Set items = getIPMMeetingRequests(ActiveFolder, Inbox)

          For Each Item In items
          DoEvents

          'Label for JIRA task
          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True Then
          If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
          Item.Categories = "Change Produktion" 'Kategorie setzen PROD
          jiraLabel = "Produktion"
          ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Integration"
          ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Testing"
          Else
          Item.Categories = "Change Info" 'Kategorie setzen Info
          jiraLabel = "Info"
          End If

          'Accept Appointment
          Set AppointmentItem = Item.GetAssociatedAppointment(True)

          Item.UnRead = False

          'CustomReplace Msg.Body Msg.Subject
          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON(CustomReplace(Item.Subject), CustomReplace(Item.Body), _
          "Test", recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, AppointmentItem.End, "")

          createJIRATask "username", "password", JSON
          End If
          Next

          Item.Move Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders(SPAM_FOLDER)

          End If
          Next

          End If
          MsgBox Inbox & ": " & items.Count & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

          End Sub

          Private Sub createJIRATask(User As String, Password As String, JSON As String)
          'Sending request to JIRA
          Dim xhr As Object
          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(User + ":" + Password)
          xhr.Send JSON
          End Sub

          Private Function CustomReplace(Text As String) As String
          Text = Replace(Text, """", "'")
          Text = Replace(Text, vbCr & vbLf, "n")
          Text = Replace(Text, vbCr, "n")
          Text = Replace(Text, vbLf, "n")
          CustomReplace = Text
          End Function

          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection
          Dim myFolder As Outlook.Folder, Folders As Outlook.Folders, Item As Object, Subfolder As Outlook.Folder
          Dim col As New Collection
          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders

          Set Subfolder = Folders.Item(Inbox)
          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next
          Set getIPMMeetingRequests = col
          End Function

          Private Function getJSON(customSubject As String, customBody As String, issuName As String, recipAlias As String, appStartDateTime As Date, appEndDateTime As Date, jiraLabel As String) As String
          Dim JSON(19) As String, JSONText As String
          JSON(0) = ""
          JSON(1) = " ""fields"": "
          JSON(2) = " ""project"": "
          JSON(3) = " ""id"": 30611"
          JSON(4) = " ,"
          JSON(5) = " ""summary"": ""@customSubject"","
          JSON(6) = " ""description"": ""@customBody"","
          JSON(7) = " ""issuetype"": "
          JSON(8) = " ""name"": ""@issuName"""
          JSON(9) = " ,"
          JSON(10) = " ""assignee"": "
          JSON(11) = " ""name"": ""@recipAlias"""
          JSON(12) = " ,"
          JSON(13) = " ""customfield_10021"": ""@appStartDateTime"","
          JSON(14) = " ""customfield_12760"": ""@appEndDateTime"","
          JSON(15) = " ""labels"": ["
          JSON(16) = " ""@jiraLabel"""
          JSON(17) = " ]"
          JSON(18) = " "
          JSON(19) = ""

          JSONText = Join(JSON, vbNewLine)
          JSONText = Replace(JSONText, "@customSubject", customSubject)
          JSONText = Replace(JSONText, "@customBody", customBody)
          JSONText = Replace(JSONText, "@issuName", issuName)
          JSONText = Replace(JSONText, "@recipAlias", recipAlias)
          JSONText = Replace(JSONText, "@appStartDateTime", Format(appStartDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@appEndDateTime", Format(appEndDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@jiraLabel", jiraLabel)

          getJSON = JSONText
          End Function

          Private Function isValidAddressEntry(AddressEntry As String) As Boolean
          Dim regEx As New RegExp
          regEx.Pattern = "^w+sw+,sI351$"
          isValidAddressEntry = regEx.Test(AddressEntry) And AddressEntry <> "Application Management Linux1, I351"
          End Function

          Private Function Base64Encode(Text As String) As String
          '.... Not Provided
          End Function


          As always my code comes with a "3 Time Your Money Back Guarantee" minus $19.95 shipping and handling.






          share|improve this answer















          "Why Are We Scared?"



          The number one reason that we are scared of something is that we don't fully understand it. The key to understanding a complex problem is to break it down into small easy to understand units. The key to writing good code is to write small easy to understand and test (debug) subroutines.



          Variable Declaration



          I personally always use Option Explicit and declare the Type for each variable. This will give you the most information and the best feedback from the compiler.



          I try and declare my variables in groups by type: Strings, Numeric, Objects, Outlook Objects, Excel Object at the top of the subroutine after any constants. Basically, whatever seems right for the code. I do it this way because I want my declarations to have a low profile and be separated from the logic of the subroutine. Ideally, I would like to be able to read the entire logic of a subroutine without having to scroll the code pane.



          Repeated Logic



          I am specifically referring to the use of Accept. As Raystafarian noted the name sucks, at least I think that was what he said. More importantly, the logic behind it is repeated several times.




          Accept = False
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          If ActiveFolder = "Application Management Linux1, I351" Then
          Accept = True
          End If



          Since Accept is not used outside of the If Item.MessageClass... block I would simplify it like this:




          Accept = ActiveFolder = "Application Management Linux1, I351"




          Accept is then used on line 43:




          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True And Accept = True Then




          But then on line 64 the same logic is used but without the Accept variable:




          If ActiveFolder = "Application Management Linux1, I351" Then



          But want the code from lines 43:60 is only relevant if it passes the Accept condition. So why don't lines 43:60 follow line 64???



          Why not just get rid of the Accept variable like this:




          If Item.MessageClass = "IPM.Schedule.Meeting.Request" And ActiveFolder = "Application Management Linux1, I351" Then



          Not only will this simplify the code it will remove a nesting level making it easier to read.




          Now this wouldn't be a Narcissistic Answer if I don't show my way of doing things. So here we go!!




          Writing JSON and SQL Statements



          There are plenty of good tools that help of write, format, and test our JSON and SQL statements. But what do we do? While until recently, I would spend a lot time writing code like & CHR(34) & UGH & CHR(34) & "This Sucks" & or """ & UGH & """This Sucks"""". Why not just not just write the JSON or SQL with the right tools copy their results to the CLipboard and process it from there.



          Note: I use the @ sign to signify named parameters. I will later either use Replace(Text,"@Name",Name) or replace @ with " & " and then after the variable finish the concatenation with & ".



          This is the first time I use JSONEditor and it only took about 10-12 minute to write ProcessClipboard().



          Sub ProcessClipboard()
          Dim lines() As String, Text As String
          Dim x As Long
          With CreateObject("New:1C3B4210-F441-11CE-B9EA-00AA006B1A69")
          .GetFromClipboard
          Text = .GetText
          End With

          Text = Replace(Text, Chr(34), String(2, 34))

          lines = Split(Text, Chr(10))

          For x = 0 To UBound(lines)
          Debug.Print "JSON(" & x & ") =", Chr(34); lines(x); Chr(34)
          Next
          End Sub


          JSON Editor Image



          JSON Editor Code



          Immediate Window Output



          The Immediate Window raw output



          getJSON Immediate Window Test



          This is a perfect example of why we you should use smaller functions and subroutines. Look how easy it is to test.



          Refactored Code



          Refactored Code Subroutines



          Option Explicit

          Public Sub AcceptMeeting(ActiveFolder As String, Inbox As String)
          Const SPAM_FOLDER As String = "*** SPAM"
          Dim jiraLabel As String
          Dim Item As Object, items As Collection, recip As Outlook.Recipient
          Dim AppointmentItem As Outlook.AppointmentItem
          Dim JSON As String

          If ActiveFolder = "Application Management Linux1, I351" Then

          Set items = getIPMMeetingRequests(ActiveFolder, Inbox)

          For Each Item In items
          DoEvents

          'Label for JIRA task
          If InStr(1, LCase(Item.Subject), "change") > 0 And Item.UnRead = True Then
          If InStr(1, LCase(Item.Subject), "produktion") > 0 Then
          Item.Categories = "Change Produktion" 'Kategorie setzen PROD
          jiraLabel = "Produktion"
          ElseIf InStr(1, LCase(Item.Subject), "integration") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Integration"
          ElseIf InStr(1, LCase(Item.Subject), "test") > 0 Then
          Item.Categories = "Change Integration" 'Kategorie setzen INT
          jiraLabel = "Testing"
          Else
          Item.Categories = "Change Info" 'Kategorie setzen Info
          jiraLabel = "Info"
          End If

          'Accept Appointment
          Set AppointmentItem = Item.GetAssociatedAppointment(True)

          Item.UnRead = False

          'CustomReplace Msg.Body Msg.Subject
          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON(CustomReplace(Item.Subject), CustomReplace(Item.Body), _
          "Test", recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, AppointmentItem.End, "")

          createJIRATask "username", "password", JSON
          End If
          Next

          Item.Move Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders(SPAM_FOLDER)

          End If
          Next

          End If
          MsgBox Inbox & ": " & items.Count & " Meetings accepted", vbOKOnly, ActiveFolder 'Infofeld

          End Sub

          Private Sub createJIRATask(User As String, Password As String, JSON As String)
          'Sending request to JIRA
          Dim xhr As Object
          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(User + ":" + Password)
          xhr.Send JSON
          End Sub

          Private Function CustomReplace(Text As String) As String
          Text = Replace(Text, """", "'")
          Text = Replace(Text, vbCr & vbLf, "n")
          Text = Replace(Text, vbCr, "n")
          Text = Replace(Text, vbLf, "n")
          CustomReplace = Text
          End Function

          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection
          Dim myFolder As Outlook.Folder, Folders As Outlook.Folders, Item As Object, Subfolder As Outlook.Folder
          Dim col As New Collection
          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders

          Set Subfolder = Folders.Item(Inbox)
          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next
          Set getIPMMeetingRequests = col
          End Function

          Private Function getJSON(customSubject As String, customBody As String, issuName As String, recipAlias As String, appStartDateTime As Date, appEndDateTime As Date, jiraLabel As String) As String
          Dim JSON(19) As String, JSONText As String
          JSON(0) = ""
          JSON(1) = " ""fields"": "
          JSON(2) = " ""project"": "
          JSON(3) = " ""id"": 30611"
          JSON(4) = " ,"
          JSON(5) = " ""summary"": ""@customSubject"","
          JSON(6) = " ""description"": ""@customBody"","
          JSON(7) = " ""issuetype"": "
          JSON(8) = " ""name"": ""@issuName"""
          JSON(9) = " ,"
          JSON(10) = " ""assignee"": "
          JSON(11) = " ""name"": ""@recipAlias"""
          JSON(12) = " ,"
          JSON(13) = " ""customfield_10021"": ""@appStartDateTime"","
          JSON(14) = " ""customfield_12760"": ""@appEndDateTime"","
          JSON(15) = " ""labels"": ["
          JSON(16) = " ""@jiraLabel"""
          JSON(17) = " ]"
          JSON(18) = " "
          JSON(19) = ""

          JSONText = Join(JSON, vbNewLine)
          JSONText = Replace(JSONText, "@customSubject", customSubject)
          JSONText = Replace(JSONText, "@customBody", customBody)
          JSONText = Replace(JSONText, "@issuName", issuName)
          JSONText = Replace(JSONText, "@recipAlias", recipAlias)
          JSONText = Replace(JSONText, "@appStartDateTime", Format(appStartDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@appEndDateTime", Format(appEndDateTime, "yyyy-mm-ddThh:mm:00.000+0200"))
          JSONText = Replace(JSONText, "@jiraLabel", jiraLabel)

          getJSON = JSONText
          End Function

          Private Function isValidAddressEntry(AddressEntry As String) As Boolean
          Dim regEx As New RegExp
          regEx.Pattern = "^w+sw+,sI351$"
          isValidAddressEntry = regEx.Test(AddressEntry) And AddressEntry <> "Application Management Linux1, I351"
          End Function

          Private Function Base64Encode(Text As String) As String
          '.... Not Provided
          End Function


          As always my code comes with a "3 Time Your Money Back Guarantee" minus $19.95 shipping and handling.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited May 23 at 14:27


























          answered May 23 at 7:06







          user109261


















          • it was really narcissistic but everything was famously explained thank you very much :))) .
            – khashashin
            May 23 at 10:21










          • It almost works exept jiraLabel Variable. This value is empty as "". But schould be "Production", "Integration", "Testing" or "info" how can I fix it?
            – khashashin
            May 23 at 10:36










          • I found it, just have to give it in getJSON call not as empty "" but as jiraLabel
            – khashashin
            May 23 at 10:41










          • And you have wrong link to JSON online Editor ;)
            – khashashin
            May 23 at 10:45










          • @khashashin I fixed the link, thanks. I don't know how CR messed it up :). Happy Coding
            – user109261
            May 23 at 14:29
















          • it was really narcissistic but everything was famously explained thank you very much :))) .
            – khashashin
            May 23 at 10:21










          • It almost works exept jiraLabel Variable. This value is empty as "". But schould be "Production", "Integration", "Testing" or "info" how can I fix it?
            – khashashin
            May 23 at 10:36










          • I found it, just have to give it in getJSON call not as empty "" but as jiraLabel
            – khashashin
            May 23 at 10:41










          • And you have wrong link to JSON online Editor ;)
            – khashashin
            May 23 at 10:45










          • @khashashin I fixed the link, thanks. I don't know how CR messed it up :). Happy Coding
            – user109261
            May 23 at 14:29















          it was really narcissistic but everything was famously explained thank you very much :))) .
          – khashashin
          May 23 at 10:21




          it was really narcissistic but everything was famously explained thank you very much :))) .
          – khashashin
          May 23 at 10:21












          It almost works exept jiraLabel Variable. This value is empty as "". But schould be "Production", "Integration", "Testing" or "info" how can I fix it?
          – khashashin
          May 23 at 10:36




          It almost works exept jiraLabel Variable. This value is empty as "". But schould be "Production", "Integration", "Testing" or "info" how can I fix it?
          – khashashin
          May 23 at 10:36












          I found it, just have to give it in getJSON call not as empty "" but as jiraLabel
          – khashashin
          May 23 at 10:41




          I found it, just have to give it in getJSON call not as empty "" but as jiraLabel
          – khashashin
          May 23 at 10:41












          And you have wrong link to JSON online Editor ;)
          – khashashin
          May 23 at 10:45




          And you have wrong link to JSON online Editor ;)
          – khashashin
          May 23 at 10:45












          @khashashin I fixed the link, thanks. I don't know how CR messed it up :). Happy Coding
          – user109261
          May 23 at 14:29




          @khashashin I fixed the link, thanks. I don't know how CR messed it up :). Happy Coding
          – user109261
          May 23 at 14:29












          up vote
          1
          down vote













          Variables



          First, the variables folders, recips, xhr aren't defined.



          When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch.



          Always turn on Option Explicit. You can have it automatically by going to Tools -> Options in the VBE and checking the Require Variable Declaration option. This way if you have any variables not defined, the compiler will let you know.




          Also when you declare variables on the same line, you need to specify each variable's type -




          Dim appStartDate, appStartTime, appEndDate, appEndTime As Date



          This is what it's doing -



          Dim appStartDate as Variant
          Dim appStartTime as Variant
          Dim appEndDate as Variant
          Dim appEndTime as Date


          Same thing happens here




          Dim startDateString, endDateString As String



          And here




          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String




          With that out of the way, your variable naming leaves a bit to be desired. Right now, looking at the code it is kind of difficult to know exactly what each variable is doing.




          Dim myFolder As Outlook.Folder
          Set myFolder = myNamespace.Folders(ActiveFolder)

          Dim Folders
          Set Folders = myFolder.Folders

          Dim Subfolder As Outlook.Folder
          Set Subfolder = Folders.Item(Inbox)

          Dim Folder As Outlook.Folder 'I don't see this used



          I'll make the assumption that the missing declaration of Folders was just supposed to be the variable Folder.



          So MyFolder is the ActiveFolder. And Folders are the Folders in the ActiveFolder. And a SubFolder is some items?



          So for all that jazz it basically comes down to the loop -



          For Each Item In Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders.Items(Inbox).Items


          I think giving the namespace a variable is a good idea, but all those other folders can probably be combined into a single variable, which you iterate the item through, especially since all of that at the top is never referenced again.



          The Change folder could just be spamFolder and set to the spam folder in the beginning, I don't see it reassigned anywhere.



          I think myAppt and myMtg are okay, but why not just write the entire name out? The characters are free.




          Dim Forward As Outlook.MeetingItem



          This isn't used either, as far as I can see.




          Dim Accept As Boolean



          Usually with a boolean you want it to read like a boolean, like isTrue or isAccepted or shouldAccept - something like that makes it more clear.




          Structure



          It seems to be that the logic in this macro is broken up into a few things -



          1. Find meeting requests

          2. Categorize the request

          3. Parse the request

          4. Build the JSON

          5. Send the JSON

          Because that's the business logic, break it out into different procedures or functions to indicate what each part does. This makes it easier to follow, makes it simpler to review and allows you to refactor.



          Sub FindMeetingRequests(ByVal targetFolder as Folder)
          Sub ProcessMeetingRequests(ByVal item as Object)
          Function BuildJSON(ByVal body as String) as String
          Sub SubmitJSON(ByVal JSON as String)


          This would be especially helpful when writing the JSON as your comment indicates - it looks scary. Break it out into its own function and then work on that function to make it seem less scary, or more manageable.



          And since sending the HTTP request really doesn't have anything to do with the actual meeting request items, pull that out to its own procedure as well. Compartmentalize.




          Constants




          'Values to create JSON
          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
          flds = """fields"""
          prt = """project"""
          id = """id"""
          asgn = """assignee"""
          smry = """summary"""
          descrp = """description"""
          issu = """issuetype"""
          label = """labels"""
          issuName = """Test"""
          startAt = """customfield_10021"""
          endDate = """customfield_12760"""
          name = """name"""
          lfbrkt = ""
          rtbrkt = ""
          cma = ","
          dbdots = ":"
          sqLfBrkt = "["
          sqRtBrkt = "]"
          Creating JSON - It looks scary but works
          JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
          vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
          vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
          vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
          vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
          vbCrLf + rtbrkt + _
          vbCrLf + rtbrkt



          I applaud your efforts on creating those variables the way you did. It seems to me, however, that the majority of the JSON is a constant - I see the use of the dates, the subject, the body, etc. Maybe break those strings up into constant variables, like



          Const JSON_BEFORE_SUBJECT as String = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """"


          In a way you end up with something a lot less scary



          JSON = JSON_BEFORE_SUBJECT & customSubject & JSON_BEFORE_BODY & customBody & JSON_BEFORE_ISSUE & issuName ....





          share|improve this answer





















          • As I said it was my fisrt code in vba, thanks to your explanation i have lerned something new for me. Thank you very much!!!
            – khashashin
            May 23 at 10:48














          up vote
          1
          down vote













          Variables



          First, the variables folders, recips, xhr aren't defined.



          When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch.



          Always turn on Option Explicit. You can have it automatically by going to Tools -> Options in the VBE and checking the Require Variable Declaration option. This way if you have any variables not defined, the compiler will let you know.




          Also when you declare variables on the same line, you need to specify each variable's type -




          Dim appStartDate, appStartTime, appEndDate, appEndTime As Date



          This is what it's doing -



          Dim appStartDate as Variant
          Dim appStartTime as Variant
          Dim appEndDate as Variant
          Dim appEndTime as Date


          Same thing happens here




          Dim startDateString, endDateString As String



          And here




          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String




          With that out of the way, your variable naming leaves a bit to be desired. Right now, looking at the code it is kind of difficult to know exactly what each variable is doing.




          Dim myFolder As Outlook.Folder
          Set myFolder = myNamespace.Folders(ActiveFolder)

          Dim Folders
          Set Folders = myFolder.Folders

          Dim Subfolder As Outlook.Folder
          Set Subfolder = Folders.Item(Inbox)

          Dim Folder As Outlook.Folder 'I don't see this used



          I'll make the assumption that the missing declaration of Folders was just supposed to be the variable Folder.



          So MyFolder is the ActiveFolder. And Folders are the Folders in the ActiveFolder. And a SubFolder is some items?



          So for all that jazz it basically comes down to the loop -



          For Each Item In Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders.Items(Inbox).Items


          I think giving the namespace a variable is a good idea, but all those other folders can probably be combined into a single variable, which you iterate the item through, especially since all of that at the top is never referenced again.



          The Change folder could just be spamFolder and set to the spam folder in the beginning, I don't see it reassigned anywhere.



          I think myAppt and myMtg are okay, but why not just write the entire name out? The characters are free.




          Dim Forward As Outlook.MeetingItem



          This isn't used either, as far as I can see.




          Dim Accept As Boolean



          Usually with a boolean you want it to read like a boolean, like isTrue or isAccepted or shouldAccept - something like that makes it more clear.




          Structure



          It seems to be that the logic in this macro is broken up into a few things -



          1. Find meeting requests

          2. Categorize the request

          3. Parse the request

          4. Build the JSON

          5. Send the JSON

          Because that's the business logic, break it out into different procedures or functions to indicate what each part does. This makes it easier to follow, makes it simpler to review and allows you to refactor.



          Sub FindMeetingRequests(ByVal targetFolder as Folder)
          Sub ProcessMeetingRequests(ByVal item as Object)
          Function BuildJSON(ByVal body as String) as String
          Sub SubmitJSON(ByVal JSON as String)


          This would be especially helpful when writing the JSON as your comment indicates - it looks scary. Break it out into its own function and then work on that function to make it seem less scary, or more manageable.



          And since sending the HTTP request really doesn't have anything to do with the actual meeting request items, pull that out to its own procedure as well. Compartmentalize.




          Constants




          'Values to create JSON
          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
          flds = """fields"""
          prt = """project"""
          id = """id"""
          asgn = """assignee"""
          smry = """summary"""
          descrp = """description"""
          issu = """issuetype"""
          label = """labels"""
          issuName = """Test"""
          startAt = """customfield_10021"""
          endDate = """customfield_12760"""
          name = """name"""
          lfbrkt = ""
          rtbrkt = ""
          cma = ","
          dbdots = ":"
          sqLfBrkt = "["
          sqRtBrkt = "]"
          Creating JSON - It looks scary but works
          JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
          vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
          vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
          vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
          vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
          vbCrLf + rtbrkt + _
          vbCrLf + rtbrkt



          I applaud your efforts on creating those variables the way you did. It seems to me, however, that the majority of the JSON is a constant - I see the use of the dates, the subject, the body, etc. Maybe break those strings up into constant variables, like



          Const JSON_BEFORE_SUBJECT as String = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """"


          In a way you end up with something a lot less scary



          JSON = JSON_BEFORE_SUBJECT & customSubject & JSON_BEFORE_BODY & customBody & JSON_BEFORE_ISSUE & issuName ....





          share|improve this answer





















          • As I said it was my fisrt code in vba, thanks to your explanation i have lerned something new for me. Thank you very much!!!
            – khashashin
            May 23 at 10:48












          up vote
          1
          down vote










          up vote
          1
          down vote









          Variables



          First, the variables folders, recips, xhr aren't defined.



          When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch.



          Always turn on Option Explicit. You can have it automatically by going to Tools -> Options in the VBE and checking the Require Variable Declaration option. This way if you have any variables not defined, the compiler will let you know.




          Also when you declare variables on the same line, you need to specify each variable's type -




          Dim appStartDate, appStartTime, appEndDate, appEndTime As Date



          This is what it's doing -



          Dim appStartDate as Variant
          Dim appStartTime as Variant
          Dim appEndDate as Variant
          Dim appEndTime as Date


          Same thing happens here




          Dim startDateString, endDateString As String



          And here




          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String




          With that out of the way, your variable naming leaves a bit to be desired. Right now, looking at the code it is kind of difficult to know exactly what each variable is doing.




          Dim myFolder As Outlook.Folder
          Set myFolder = myNamespace.Folders(ActiveFolder)

          Dim Folders
          Set Folders = myFolder.Folders

          Dim Subfolder As Outlook.Folder
          Set Subfolder = Folders.Item(Inbox)

          Dim Folder As Outlook.Folder 'I don't see this used



          I'll make the assumption that the missing declaration of Folders was just supposed to be the variable Folder.



          So MyFolder is the ActiveFolder. And Folders are the Folders in the ActiveFolder. And a SubFolder is some items?



          So for all that jazz it basically comes down to the loop -



          For Each Item In Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders.Items(Inbox).Items


          I think giving the namespace a variable is a good idea, but all those other folders can probably be combined into a single variable, which you iterate the item through, especially since all of that at the top is never referenced again.



          The Change folder could just be spamFolder and set to the spam folder in the beginning, I don't see it reassigned anywhere.



          I think myAppt and myMtg are okay, but why not just write the entire name out? The characters are free.




          Dim Forward As Outlook.MeetingItem



          This isn't used either, as far as I can see.




          Dim Accept As Boolean



          Usually with a boolean you want it to read like a boolean, like isTrue or isAccepted or shouldAccept - something like that makes it more clear.




          Structure



          It seems to be that the logic in this macro is broken up into a few things -



          1. Find meeting requests

          2. Categorize the request

          3. Parse the request

          4. Build the JSON

          5. Send the JSON

          Because that's the business logic, break it out into different procedures or functions to indicate what each part does. This makes it easier to follow, makes it simpler to review and allows you to refactor.



          Sub FindMeetingRequests(ByVal targetFolder as Folder)
          Sub ProcessMeetingRequests(ByVal item as Object)
          Function BuildJSON(ByVal body as String) as String
          Sub SubmitJSON(ByVal JSON as String)


          This would be especially helpful when writing the JSON as your comment indicates - it looks scary. Break it out into its own function and then work on that function to make it seem less scary, or more manageable.



          And since sending the HTTP request really doesn't have anything to do with the actual meeting request items, pull that out to its own procedure as well. Compartmentalize.




          Constants




          'Values to create JSON
          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
          flds = """fields"""
          prt = """project"""
          id = """id"""
          asgn = """assignee"""
          smry = """summary"""
          descrp = """description"""
          issu = """issuetype"""
          label = """labels"""
          issuName = """Test"""
          startAt = """customfield_10021"""
          endDate = """customfield_12760"""
          name = """name"""
          lfbrkt = ""
          rtbrkt = ""
          cma = ","
          dbdots = ":"
          sqLfBrkt = "["
          sqRtBrkt = "]"
          Creating JSON - It looks scary but works
          JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
          vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
          vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
          vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
          vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
          vbCrLf + rtbrkt + _
          vbCrLf + rtbrkt



          I applaud your efforts on creating those variables the way you did. It seems to me, however, that the majority of the JSON is a constant - I see the use of the dates, the subject, the body, etc. Maybe break those strings up into constant variables, like



          Const JSON_BEFORE_SUBJECT as String = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """"


          In a way you end up with something a lot less scary



          JSON = JSON_BEFORE_SUBJECT & customSubject & JSON_BEFORE_BODY & customBody & JSON_BEFORE_ISSUE & issuName ....





          share|improve this answer













          Variables



          First, the variables folders, recips, xhr aren't defined.



          When you don't define your variable, VBA will declare it as a Variant type that can hold any type of data. While this may be more flexible, it adds processing time to your macro as VBA decides or tests for the type. Additionally, since a Variant can be any type of data, you may miss out on valuable troubleshooting information on Type Mismatch.



          Always turn on Option Explicit. You can have it automatically by going to Tools -> Options in the VBE and checking the Require Variable Declaration option. This way if you have any variables not defined, the compiler will let you know.




          Also when you declare variables on the same line, you need to specify each variable's type -




          Dim appStartDate, appStartTime, appEndDate, appEndTime As Date



          This is what it's doing -



          Dim appStartDate as Variant
          Dim appStartTime as Variant
          Dim appEndDate as Variant
          Dim appEndTime as Date


          Same thing happens here




          Dim startDateString, endDateString As String



          And here




          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String




          With that out of the way, your variable naming leaves a bit to be desired. Right now, looking at the code it is kind of difficult to know exactly what each variable is doing.




          Dim myFolder As Outlook.Folder
          Set myFolder = myNamespace.Folders(ActiveFolder)

          Dim Folders
          Set Folders = myFolder.Folders

          Dim Subfolder As Outlook.Folder
          Set Subfolder = Folders.Item(Inbox)

          Dim Folder As Outlook.Folder 'I don't see this used



          I'll make the assumption that the missing declaration of Folders was just supposed to be the variable Folder.



          So MyFolder is the ActiveFolder. And Folders are the Folders in the ActiveFolder. And a SubFolder is some items?



          So for all that jazz it basically comes down to the loop -



          For Each Item In Application.GetNamespace("MAPI").Folders(ActiveFolder).Folders.Items(Inbox).Items


          I think giving the namespace a variable is a good idea, but all those other folders can probably be combined into a single variable, which you iterate the item through, especially since all of that at the top is never referenced again.



          The Change folder could just be spamFolder and set to the spam folder in the beginning, I don't see it reassigned anywhere.



          I think myAppt and myMtg are okay, but why not just write the entire name out? The characters are free.




          Dim Forward As Outlook.MeetingItem



          This isn't used either, as far as I can see.




          Dim Accept As Boolean



          Usually with a boolean you want it to read like a boolean, like isTrue or isAccepted or shouldAccept - something like that makes it more clear.




          Structure



          It seems to be that the logic in this macro is broken up into a few things -



          1. Find meeting requests

          2. Categorize the request

          3. Parse the request

          4. Build the JSON

          5. Send the JSON

          Because that's the business logic, break it out into different procedures or functions to indicate what each part does. This makes it easier to follow, makes it simpler to review and allows you to refactor.



          Sub FindMeetingRequests(ByVal targetFolder as Folder)
          Sub ProcessMeetingRequests(ByVal item as Object)
          Function BuildJSON(ByVal body as String) as String
          Sub SubmitJSON(ByVal JSON as String)


          This would be especially helpful when writing the JSON as your comment indicates - it looks scary. Break it out into its own function and then work on that function to make it seem less scary, or more manageable.



          And since sending the HTTP request really doesn't have anything to do with the actual meeting request items, pull that out to its own procedure as well. Compartmentalize.




          Constants




          'Values to create JSON
          Dim flds, prt, id, asgn, smry, descrp, issu, name, lfbrkt, rtbrkt, cma, _
          dbdots, JSON, issuName, label, startAt, endDate, sqLfBrkt, sqRtBrkt As String
          flds = """fields"""
          prt = """project"""
          id = """id"""
          asgn = """assignee"""
          smry = """summary"""
          descrp = """description"""
          issu = """issuetype"""
          label = """labels"""
          issuName = """Test"""
          startAt = """customfield_10021"""
          endDate = """customfield_12760"""
          name = """name"""
          lfbrkt = ""
          rtbrkt = ""
          cma = ","
          dbdots = ":"
          sqLfBrkt = "["
          sqRtBrkt = "]"
          Creating JSON - It looks scary but works
          JSON = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """" + customSubject + """" + cma + _
          vbCrLf + vbTab + descrp + dbdots + " " + """" + customBody + """" + cma + _
          vbCrLf + vbTab + issu + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + issuName + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + asgn + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + name + dbdots + " " + """" + recip.AddressEntry.GetExchangeUser().Alias + """" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + startAt + dbdots + " " + """" + startDateString + """" + cma + _
          vbCrLf + vbTab + endDate + dbdots + " " + """" + endDateString + """" + cma + _
          vbCrLf + vbTab + label + dbdots + " " + sqLfBrkt + jiraLabel + sqRtBrkt + _
          vbCrLf + rtbrkt + _
          vbCrLf + rtbrkt



          I applaud your efforts on creating those variables the way you did. It seems to me, however, that the majority of the JSON is a constant - I see the use of the dates, the subject, the body, etc. Maybe break those strings up into constant variables, like



          Const JSON_BEFORE_SUBJECT as String = lfbrkt + flds + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + prt + dbdots + " " + lfbrkt + _
          vbCrLf + vbTab + vbTab + id + dbdots + " " + "30611" + _
          vbCrLf + vbTab + rtbrkt + cma + _
          vbCrLf + vbTab + smry + dbdots + " " + """"


          In a way you end up with something a lot less scary



          JSON = JSON_BEFORE_SUBJECT & customSubject & JSON_BEFORE_BODY & customBody & JSON_BEFORE_ISSUE & issuName ....






          share|improve this answer













          share|improve this answer



          share|improve this answer











          answered May 23 at 4:00









          Raystafarian

          5,4331046




          5,4331046











          • As I said it was my fisrt code in vba, thanks to your explanation i have lerned something new for me. Thank you very much!!!
            – khashashin
            May 23 at 10:48
















          • As I said it was my fisrt code in vba, thanks to your explanation i have lerned something new for me. Thank you very much!!!
            – khashashin
            May 23 at 10:48















          As I said it was my fisrt code in vba, thanks to your explanation i have lerned something new for me. Thank you very much!!!
          – khashashin
          May 23 at 10:48




          As I said it was my fisrt code in vba, thanks to your explanation i have lerned something new for me. Thank you very much!!!
          – khashashin
          May 23 at 10:48










          up vote
          0
          down vote













          My advice is very similar to what Narcissistic Answers posted, so I don't have a ton to add. Using multiple small/single-purpose functions is almost always better than using one long/complex sub, which their answer demonstrated very well.



          One thing to keep in mind when you're making "helper" functions is whether you may want to reuse them in another project. Take a look at this function from Narcissistic Answers' implementation:



          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection

          Dim myFolder As Outlook.Folder
          Dim Folders As Outlook.Folders
          Dim Item As Object
          Dim Subfolder As Outlook.Folder
          Dim col As New Collection

          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders
          Set Subfolder = Folders.Item(Inbox)

          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next

          Set getIPMMeetingRequests = col

          End Function


          The function is incredibly specific to this particular problem. It can only loop through a folder ("FolderName") that has a subfolder ("Inbox"), and it can only look for "IPM.Schedule.Meeting.Request" items.



          With a few tweaks, however, you can make the function general enough to reuse in a variety of situations:



          Function getItems(folder As Outlook.Folder, itemType As String) As Collection

          Dim item As Object
          Dim results As New Collection
          For Each item In folder.Items
          If item.MessageClass = itemType Then
          results.Add Item
          End If
          Next
          Set getItems = results

          End Function


          And if you're really thinking ahead, you can make the function incredibly flexible. You could specify more than one item type, use partial/wildcard matches when checking the item types, or even loop through more than one folder at once:



          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function


          The other thing I'll mention is to watch out for instances where a function is unnecessarily called in every iteration of a loop. In Narcissistic Answers' post, the function that formats the Subject/Body portions of the JSON string is called once for every recipient:



          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON( _
          CustomReplace(Item.Subject), _
          CustomReplace(Item.Body), _
          "Test", _
          recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, _
          AppointmentItem.End, _
          "")

          createJIRATask "username", "password", JSON
          End If
          Next


          However, these strings are determined by the Item, not the recipient, so they should be formatted before entering the inner loop. That way you just have to format them once.



          In this particular case, it's not a huge deal. But it's good practice to watch out for unnecessary function calls.



          EDIT: Adding the full version of how I'd recommend approaching the problem.



          Sub AcceptMeeting(ActiveFolder As String, Inbox As String)

          If Not ActiveFolder = "Application Management Linux1, I351" Then
          Exit Sub
          End If

          'Set up objects used in each pass of outer loop
          Dim myFolder As Outlook.Folder
          Dim regEx As New RegExp
          Set myFolder = Application.GetNamespace("MAPI").Folders(ActiveFolder)
          regEx.Pattern = "^w+sw+,sI351$"

          'Get collection of meeting items and loop through
          Dim i As Long
          Dim message As Object
          Dim messages As Collection
          Set messages = getItems(myFolder.Folders.Item(Inbox), "IPM.Schedule.Meeting.Request")
          For Each message In messages
          'Determine if message fits criteria
          If InStr(LCase(message.Subject), "change") > 0 And message.UnRead Then
          'Accept appointment
          Dim appt As Outlook.AppointmentItem
          Set appt = message.GetAssociatedAppointment(True)
          appt.Respond olResponseAccepted, True
          message.UnRead = False

          'Format JSON components for message by removing illegal characters and surrounding elements with quotes
          'Since they stay the same for each pass of inner loop...
          '...doing it here saves execution time
          Dim jiraLabel As String
          Dim customBody As String
          Dim customSubject As String
          Dim startDate As String
          Dim endDate As String
          jiraLabel = parseSubject(message)
          customBody = formatForJSON(message.Body)
          customSubject = formatForJSON(message.Subject)
          startDate = formatDate(appt.Start)
          endDate = formatDate(appt.End)

          'Send response for each matching recipient
          Dim recipient As Outlook.Recipient
          For Each recipient In message.Recipients
          If addressMatches(recipient.AddressEntry, regEx) Then
          Dim JSON As String
          JSON = createJSON( _
          exchangeID:="""" & recipient.AddressEntry.GetExchangeUser().Alias & """", _
          label:=jiraLabel, _
          subject:=customSubject, _
          body:=customBody, _
          startDate:=startDate, _
          endDate:=endDate)

          Call sendJIRA(JSON, "username", "password")
          End If
          Next
          message.Move myfolder.Folders("*** SPAM")
          i = i + 1
          End If
          Next

          MsgBox Inbox & ": " & i & " Meetings accepted", vbOKOnly, ActiveFolder

          End Sub
          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function
          Function parseSubject(obj As Object) As String

          Dim subjectText As String
          Dim itemLabel As String
          subjectText = LCase(obj.Subject)

          If InStr(subjectText), "produktion") > 0 Then
          obj.Categories = "Change Produktion"
          itemLabel = "Produktion"
          ElseIf InStr(subjectText), "integration") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Integration"
          ElseIf InStr(subjectText, "test") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Testing"
          Else
          obj.Categories = "Change Info"
          itemLabel = "Info"
          End If

          parseSubject = """" & itemLabel & """"

          End Function
          Function formatForJSON(str As String) As String

          Dim resultStr As String
          resultStr = Replace(str, """", "'")
          resultStr = Replace(resultStr, vbCr & vbLf, "n")
          resultStr = Replace(resultStr, vbCr, "n")
          resultStr = Replace(resultStr, vbLf, "n")
          formatForJSON = """" & resultStr & """"

          End Function
          Function createJSON(exchangeID As String, label As String, subject As String, _
          body As String, startDate As String, endDate As String) As String

          Dim JSON As String
          JSON = JSON & """fields: " & vbCrLf
          JSON = JSON & " ""project"": " & vbCrLf
          JSON = JSON & " ""id"": 30611" & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""summary"": " & subject & "," & vbCrLf
          JSON = JSON & " ""description"": " & body & "," & vbCrLf
          JSON = JSON & " ""issuetype"": " & vbCrLf
          JSON = JSON & " ""name"": " & exchangeID & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""customfield_10021"": " & startDate & "," & vbCrLf
          JSON = JSON & " ""customfield_12760"": " & endDate & "," & vbCrLf
          JSON = JSON & " ""labels"": [" & label & "]" & vbCrLf
          JSON = JSON & "" & vbCrLf & ""

          createJSON = JSON

          End Function
          Function formatDate(dt As Date) As String

          formatDate = """" & Format(dt, "yyyy-mm-dd") & "T" & _
          Format(dt, "hh:mm") & ":00.000+0200" & """"

          End Function
          Sub sendJIRA(JSON As String, username As String, pw As String)

          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(username & ":" & pw)
          xhr.Send JSON

          End Sub
          Function addressMatches(address As String, regEx As RegExp) As Boolean

          If address = "Application Management Linux1, I351" Then
          addressMatches = False
          Else
          addressMatches = regEx.Test(address)
          End If

          End Function





          share|improve this answer























          • You are commentary on code reuse is "Spot On" . It seems to me that a JIRA is setup per recipient and that the JSON changes for each recipient. As evidenced by recip.AddressEntry.GetExchangeUser().Alias which is passed to my getJSON function as the recipAlias parameter and used in JSON string of the OP's post (JSON = .... """" + recip.AddressEntry.GetExchangeUser().Alias + """" ). +1
            – user109261
            May 23 at 19:46










          • The only part that changes is the recipAlias parameter, the Subject/Body portions stay the same. I'll edit the post to show what I mean.
            – Daniel McCracken
            May 23 at 21:03










          • Your Full Version is solid. The intermediate variables do make the code read and test better. I'm still not a big fan of the JSON string concatenation but you handled it well.
            – user109261
            May 24 at 2:49










          • Fair enough! I don't usually work with JSON but when it comes to SQL strings I have a couple of approaches I normally use. Typically I just import a .sql file from our network drive + do string replacement (though I surround my parameters <like this> rather than using @). If I can't be sure I'll have local network access, I have a macro that can take a text file and convert it to a SQL query string suitable for copy/pasting directly into a VBA module. In this case, my answer was already pretty long, and the JSON string was pretty short, so I didn't bother with a more complex solution.
            – Daniel McCracken
            May 24 at 4:08















          up vote
          0
          down vote













          My advice is very similar to what Narcissistic Answers posted, so I don't have a ton to add. Using multiple small/single-purpose functions is almost always better than using one long/complex sub, which their answer demonstrated very well.



          One thing to keep in mind when you're making "helper" functions is whether you may want to reuse them in another project. Take a look at this function from Narcissistic Answers' implementation:



          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection

          Dim myFolder As Outlook.Folder
          Dim Folders As Outlook.Folders
          Dim Item As Object
          Dim Subfolder As Outlook.Folder
          Dim col As New Collection

          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders
          Set Subfolder = Folders.Item(Inbox)

          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next

          Set getIPMMeetingRequests = col

          End Function


          The function is incredibly specific to this particular problem. It can only loop through a folder ("FolderName") that has a subfolder ("Inbox"), and it can only look for "IPM.Schedule.Meeting.Request" items.



          With a few tweaks, however, you can make the function general enough to reuse in a variety of situations:



          Function getItems(folder As Outlook.Folder, itemType As String) As Collection

          Dim item As Object
          Dim results As New Collection
          For Each item In folder.Items
          If item.MessageClass = itemType Then
          results.Add Item
          End If
          Next
          Set getItems = results

          End Function


          And if you're really thinking ahead, you can make the function incredibly flexible. You could specify more than one item type, use partial/wildcard matches when checking the item types, or even loop through more than one folder at once:



          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function


          The other thing I'll mention is to watch out for instances where a function is unnecessarily called in every iteration of a loop. In Narcissistic Answers' post, the function that formats the Subject/Body portions of the JSON string is called once for every recipient:



          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON( _
          CustomReplace(Item.Subject), _
          CustomReplace(Item.Body), _
          "Test", _
          recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, _
          AppointmentItem.End, _
          "")

          createJIRATask "username", "password", JSON
          End If
          Next


          However, these strings are determined by the Item, not the recipient, so they should be formatted before entering the inner loop. That way you just have to format them once.



          In this particular case, it's not a huge deal. But it's good practice to watch out for unnecessary function calls.



          EDIT: Adding the full version of how I'd recommend approaching the problem.



          Sub AcceptMeeting(ActiveFolder As String, Inbox As String)

          If Not ActiveFolder = "Application Management Linux1, I351" Then
          Exit Sub
          End If

          'Set up objects used in each pass of outer loop
          Dim myFolder As Outlook.Folder
          Dim regEx As New RegExp
          Set myFolder = Application.GetNamespace("MAPI").Folders(ActiveFolder)
          regEx.Pattern = "^w+sw+,sI351$"

          'Get collection of meeting items and loop through
          Dim i As Long
          Dim message As Object
          Dim messages As Collection
          Set messages = getItems(myFolder.Folders.Item(Inbox), "IPM.Schedule.Meeting.Request")
          For Each message In messages
          'Determine if message fits criteria
          If InStr(LCase(message.Subject), "change") > 0 And message.UnRead Then
          'Accept appointment
          Dim appt As Outlook.AppointmentItem
          Set appt = message.GetAssociatedAppointment(True)
          appt.Respond olResponseAccepted, True
          message.UnRead = False

          'Format JSON components for message by removing illegal characters and surrounding elements with quotes
          'Since they stay the same for each pass of inner loop...
          '...doing it here saves execution time
          Dim jiraLabel As String
          Dim customBody As String
          Dim customSubject As String
          Dim startDate As String
          Dim endDate As String
          jiraLabel = parseSubject(message)
          customBody = formatForJSON(message.Body)
          customSubject = formatForJSON(message.Subject)
          startDate = formatDate(appt.Start)
          endDate = formatDate(appt.End)

          'Send response for each matching recipient
          Dim recipient As Outlook.Recipient
          For Each recipient In message.Recipients
          If addressMatches(recipient.AddressEntry, regEx) Then
          Dim JSON As String
          JSON = createJSON( _
          exchangeID:="""" & recipient.AddressEntry.GetExchangeUser().Alias & """", _
          label:=jiraLabel, _
          subject:=customSubject, _
          body:=customBody, _
          startDate:=startDate, _
          endDate:=endDate)

          Call sendJIRA(JSON, "username", "password")
          End If
          Next
          message.Move myfolder.Folders("*** SPAM")
          i = i + 1
          End If
          Next

          MsgBox Inbox & ": " & i & " Meetings accepted", vbOKOnly, ActiveFolder

          End Sub
          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function
          Function parseSubject(obj As Object) As String

          Dim subjectText As String
          Dim itemLabel As String
          subjectText = LCase(obj.Subject)

          If InStr(subjectText), "produktion") > 0 Then
          obj.Categories = "Change Produktion"
          itemLabel = "Produktion"
          ElseIf InStr(subjectText), "integration") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Integration"
          ElseIf InStr(subjectText, "test") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Testing"
          Else
          obj.Categories = "Change Info"
          itemLabel = "Info"
          End If

          parseSubject = """" & itemLabel & """"

          End Function
          Function formatForJSON(str As String) As String

          Dim resultStr As String
          resultStr = Replace(str, """", "'")
          resultStr = Replace(resultStr, vbCr & vbLf, "n")
          resultStr = Replace(resultStr, vbCr, "n")
          resultStr = Replace(resultStr, vbLf, "n")
          formatForJSON = """" & resultStr & """"

          End Function
          Function createJSON(exchangeID As String, label As String, subject As String, _
          body As String, startDate As String, endDate As String) As String

          Dim JSON As String
          JSON = JSON & """fields: " & vbCrLf
          JSON = JSON & " ""project"": " & vbCrLf
          JSON = JSON & " ""id"": 30611" & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""summary"": " & subject & "," & vbCrLf
          JSON = JSON & " ""description"": " & body & "," & vbCrLf
          JSON = JSON & " ""issuetype"": " & vbCrLf
          JSON = JSON & " ""name"": " & exchangeID & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""customfield_10021"": " & startDate & "," & vbCrLf
          JSON = JSON & " ""customfield_12760"": " & endDate & "," & vbCrLf
          JSON = JSON & " ""labels"": [" & label & "]" & vbCrLf
          JSON = JSON & "" & vbCrLf & ""

          createJSON = JSON

          End Function
          Function formatDate(dt As Date) As String

          formatDate = """" & Format(dt, "yyyy-mm-dd") & "T" & _
          Format(dt, "hh:mm") & ":00.000+0200" & """"

          End Function
          Sub sendJIRA(JSON As String, username As String, pw As String)

          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(username & ":" & pw)
          xhr.Send JSON

          End Sub
          Function addressMatches(address As String, regEx As RegExp) As Boolean

          If address = "Application Management Linux1, I351" Then
          addressMatches = False
          Else
          addressMatches = regEx.Test(address)
          End If

          End Function





          share|improve this answer























          • You are commentary on code reuse is "Spot On" . It seems to me that a JIRA is setup per recipient and that the JSON changes for each recipient. As evidenced by recip.AddressEntry.GetExchangeUser().Alias which is passed to my getJSON function as the recipAlias parameter and used in JSON string of the OP's post (JSON = .... """" + recip.AddressEntry.GetExchangeUser().Alias + """" ). +1
            – user109261
            May 23 at 19:46










          • The only part that changes is the recipAlias parameter, the Subject/Body portions stay the same. I'll edit the post to show what I mean.
            – Daniel McCracken
            May 23 at 21:03










          • Your Full Version is solid. The intermediate variables do make the code read and test better. I'm still not a big fan of the JSON string concatenation but you handled it well.
            – user109261
            May 24 at 2:49










          • Fair enough! I don't usually work with JSON but when it comes to SQL strings I have a couple of approaches I normally use. Typically I just import a .sql file from our network drive + do string replacement (though I surround my parameters <like this> rather than using @). If I can't be sure I'll have local network access, I have a macro that can take a text file and convert it to a SQL query string suitable for copy/pasting directly into a VBA module. In this case, my answer was already pretty long, and the JSON string was pretty short, so I didn't bother with a more complex solution.
            – Daniel McCracken
            May 24 at 4:08













          up vote
          0
          down vote










          up vote
          0
          down vote









          My advice is very similar to what Narcissistic Answers posted, so I don't have a ton to add. Using multiple small/single-purpose functions is almost always better than using one long/complex sub, which their answer demonstrated very well.



          One thing to keep in mind when you're making "helper" functions is whether you may want to reuse them in another project. Take a look at this function from Narcissistic Answers' implementation:



          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection

          Dim myFolder As Outlook.Folder
          Dim Folders As Outlook.Folders
          Dim Item As Object
          Dim Subfolder As Outlook.Folder
          Dim col As New Collection

          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders
          Set Subfolder = Folders.Item(Inbox)

          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next

          Set getIPMMeetingRequests = col

          End Function


          The function is incredibly specific to this particular problem. It can only loop through a folder ("FolderName") that has a subfolder ("Inbox"), and it can only look for "IPM.Schedule.Meeting.Request" items.



          With a few tweaks, however, you can make the function general enough to reuse in a variety of situations:



          Function getItems(folder As Outlook.Folder, itemType As String) As Collection

          Dim item As Object
          Dim results As New Collection
          For Each item In folder.Items
          If item.MessageClass = itemType Then
          results.Add Item
          End If
          Next
          Set getItems = results

          End Function


          And if you're really thinking ahead, you can make the function incredibly flexible. You could specify more than one item type, use partial/wildcard matches when checking the item types, or even loop through more than one folder at once:



          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function


          The other thing I'll mention is to watch out for instances where a function is unnecessarily called in every iteration of a loop. In Narcissistic Answers' post, the function that formats the Subject/Body portions of the JSON string is called once for every recipient:



          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON( _
          CustomReplace(Item.Subject), _
          CustomReplace(Item.Body), _
          "Test", _
          recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, _
          AppointmentItem.End, _
          "")

          createJIRATask "username", "password", JSON
          End If
          Next


          However, these strings are determined by the Item, not the recipient, so they should be formatted before entering the inner loop. That way you just have to format them once.



          In this particular case, it's not a huge deal. But it's good practice to watch out for unnecessary function calls.



          EDIT: Adding the full version of how I'd recommend approaching the problem.



          Sub AcceptMeeting(ActiveFolder As String, Inbox As String)

          If Not ActiveFolder = "Application Management Linux1, I351" Then
          Exit Sub
          End If

          'Set up objects used in each pass of outer loop
          Dim myFolder As Outlook.Folder
          Dim regEx As New RegExp
          Set myFolder = Application.GetNamespace("MAPI").Folders(ActiveFolder)
          regEx.Pattern = "^w+sw+,sI351$"

          'Get collection of meeting items and loop through
          Dim i As Long
          Dim message As Object
          Dim messages As Collection
          Set messages = getItems(myFolder.Folders.Item(Inbox), "IPM.Schedule.Meeting.Request")
          For Each message In messages
          'Determine if message fits criteria
          If InStr(LCase(message.Subject), "change") > 0 And message.UnRead Then
          'Accept appointment
          Dim appt As Outlook.AppointmentItem
          Set appt = message.GetAssociatedAppointment(True)
          appt.Respond olResponseAccepted, True
          message.UnRead = False

          'Format JSON components for message by removing illegal characters and surrounding elements with quotes
          'Since they stay the same for each pass of inner loop...
          '...doing it here saves execution time
          Dim jiraLabel As String
          Dim customBody As String
          Dim customSubject As String
          Dim startDate As String
          Dim endDate As String
          jiraLabel = parseSubject(message)
          customBody = formatForJSON(message.Body)
          customSubject = formatForJSON(message.Subject)
          startDate = formatDate(appt.Start)
          endDate = formatDate(appt.End)

          'Send response for each matching recipient
          Dim recipient As Outlook.Recipient
          For Each recipient In message.Recipients
          If addressMatches(recipient.AddressEntry, regEx) Then
          Dim JSON As String
          JSON = createJSON( _
          exchangeID:="""" & recipient.AddressEntry.GetExchangeUser().Alias & """", _
          label:=jiraLabel, _
          subject:=customSubject, _
          body:=customBody, _
          startDate:=startDate, _
          endDate:=endDate)

          Call sendJIRA(JSON, "username", "password")
          End If
          Next
          message.Move myfolder.Folders("*** SPAM")
          i = i + 1
          End If
          Next

          MsgBox Inbox & ": " & i & " Meetings accepted", vbOKOnly, ActiveFolder

          End Sub
          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function
          Function parseSubject(obj As Object) As String

          Dim subjectText As String
          Dim itemLabel As String
          subjectText = LCase(obj.Subject)

          If InStr(subjectText), "produktion") > 0 Then
          obj.Categories = "Change Produktion"
          itemLabel = "Produktion"
          ElseIf InStr(subjectText), "integration") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Integration"
          ElseIf InStr(subjectText, "test") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Testing"
          Else
          obj.Categories = "Change Info"
          itemLabel = "Info"
          End If

          parseSubject = """" & itemLabel & """"

          End Function
          Function formatForJSON(str As String) As String

          Dim resultStr As String
          resultStr = Replace(str, """", "'")
          resultStr = Replace(resultStr, vbCr & vbLf, "n")
          resultStr = Replace(resultStr, vbCr, "n")
          resultStr = Replace(resultStr, vbLf, "n")
          formatForJSON = """" & resultStr & """"

          End Function
          Function createJSON(exchangeID As String, label As String, subject As String, _
          body As String, startDate As String, endDate As String) As String

          Dim JSON As String
          JSON = JSON & """fields: " & vbCrLf
          JSON = JSON & " ""project"": " & vbCrLf
          JSON = JSON & " ""id"": 30611" & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""summary"": " & subject & "," & vbCrLf
          JSON = JSON & " ""description"": " & body & "," & vbCrLf
          JSON = JSON & " ""issuetype"": " & vbCrLf
          JSON = JSON & " ""name"": " & exchangeID & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""customfield_10021"": " & startDate & "," & vbCrLf
          JSON = JSON & " ""customfield_12760"": " & endDate & "," & vbCrLf
          JSON = JSON & " ""labels"": [" & label & "]" & vbCrLf
          JSON = JSON & "" & vbCrLf & ""

          createJSON = JSON

          End Function
          Function formatDate(dt As Date) As String

          formatDate = """" & Format(dt, "yyyy-mm-dd") & "T" & _
          Format(dt, "hh:mm") & ":00.000+0200" & """"

          End Function
          Sub sendJIRA(JSON As String, username As String, pw As String)

          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(username & ":" & pw)
          xhr.Send JSON

          End Sub
          Function addressMatches(address As String, regEx As RegExp) As Boolean

          If address = "Application Management Linux1, I351" Then
          addressMatches = False
          Else
          addressMatches = regEx.Test(address)
          End If

          End Function





          share|improve this answer















          My advice is very similar to what Narcissistic Answers posted, so I don't have a ton to add. Using multiple small/single-purpose functions is almost always better than using one long/complex sub, which their answer demonstrated very well.



          One thing to keep in mind when you're making "helper" functions is whether you may want to reuse them in another project. Take a look at this function from Narcissistic Answers' implementation:



          Private Function getIPMMeetingRequests(FolderName As String, Inbox As String) As Collection

          Dim myFolder As Outlook.Folder
          Dim Folders As Outlook.Folders
          Dim Item As Object
          Dim Subfolder As Outlook.Folder
          Dim col As New Collection

          Set myFolder = Application.GetNamespace("MAPI").Folders(FolderName)
          Set Folders = myFolder.Folders
          Set Subfolder = Folders.Item(Inbox)

          For Each Item In Subfolder.items
          If Item.MessageClass = "IPM.Schedule.Meeting.Request" Then
          col.Add Item
          End If
          Next

          Set getIPMMeetingRequests = col

          End Function


          The function is incredibly specific to this particular problem. It can only loop through a folder ("FolderName") that has a subfolder ("Inbox"), and it can only look for "IPM.Schedule.Meeting.Request" items.



          With a few tweaks, however, you can make the function general enough to reuse in a variety of situations:



          Function getItems(folder As Outlook.Folder, itemType As String) As Collection

          Dim item As Object
          Dim results As New Collection
          For Each item In folder.Items
          If item.MessageClass = itemType Then
          results.Add Item
          End If
          Next
          Set getItems = results

          End Function


          And if you're really thinking ahead, you can make the function incredibly flexible. You could specify more than one item type, use partial/wildcard matches when checking the item types, or even loop through more than one folder at once:



          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function


          The other thing I'll mention is to watch out for instances where a function is unnecessarily called in every iteration of a loop. In Narcissistic Answers' post, the function that formats the Subject/Body portions of the JSON string is called once for every recipient:



          For Each recip In Item.Recipients
          If isValidAddressEntry(recip.AddressEntry) Then
          'Creating JSON - Not so scary
          JSON = getJSON( _
          CustomReplace(Item.Subject), _
          CustomReplace(Item.Body), _
          "Test", _
          recip.AddressEntry.GetExchangeUser().Alias, _
          AppointmentItem.Start, _
          AppointmentItem.End, _
          "")

          createJIRATask "username", "password", JSON
          End If
          Next


          However, these strings are determined by the Item, not the recipient, so they should be formatted before entering the inner loop. That way you just have to format them once.



          In this particular case, it's not a huge deal. But it's good practice to watch out for unnecessary function calls.



          EDIT: Adding the full version of how I'd recommend approaching the problem.



          Sub AcceptMeeting(ActiveFolder As String, Inbox As String)

          If Not ActiveFolder = "Application Management Linux1, I351" Then
          Exit Sub
          End If

          'Set up objects used in each pass of outer loop
          Dim myFolder As Outlook.Folder
          Dim regEx As New RegExp
          Set myFolder = Application.GetNamespace("MAPI").Folders(ActiveFolder)
          regEx.Pattern = "^w+sw+,sI351$"

          'Get collection of meeting items and loop through
          Dim i As Long
          Dim message As Object
          Dim messages As Collection
          Set messages = getItems(myFolder.Folders.Item(Inbox), "IPM.Schedule.Meeting.Request")
          For Each message In messages
          'Determine if message fits criteria
          If InStr(LCase(message.Subject), "change") > 0 And message.UnRead Then
          'Accept appointment
          Dim appt As Outlook.AppointmentItem
          Set appt = message.GetAssociatedAppointment(True)
          appt.Respond olResponseAccepted, True
          message.UnRead = False

          'Format JSON components for message by removing illegal characters and surrounding elements with quotes
          'Since they stay the same for each pass of inner loop...
          '...doing it here saves execution time
          Dim jiraLabel As String
          Dim customBody As String
          Dim customSubject As String
          Dim startDate As String
          Dim endDate As String
          jiraLabel = parseSubject(message)
          customBody = formatForJSON(message.Body)
          customSubject = formatForJSON(message.Subject)
          startDate = formatDate(appt.Start)
          endDate = formatDate(appt.End)

          'Send response for each matching recipient
          Dim recipient As Outlook.Recipient
          For Each recipient In message.Recipients
          If addressMatches(recipient.AddressEntry, regEx) Then
          Dim JSON As String
          JSON = createJSON( _
          exchangeID:="""" & recipient.AddressEntry.GetExchangeUser().Alias & """", _
          label:=jiraLabel, _
          subject:=customSubject, _
          body:=customBody, _
          startDate:=startDate, _
          endDate:=endDate)

          Call sendJIRA(JSON, "username", "password")
          End If
          Next
          message.Move myfolder.Folders("*** SPAM")
          i = i + 1
          End If
          Next

          MsgBox Inbox & ": " & i & " Meetings accepted", vbOKOnly, ActiveFolder

          End Sub
          Function getItems(folders As Variant, itemTypes As Variant) As Collection
          'Loops through one or more outlook folders (folders), which can be passed as:
          ' - An Outlook.Folder object,
          ' - An array of Outlook.Folder objects, or
          ' - An Outlook.Folders Collection
          'Adds items that meet one or more type criteria (itemTypes), which can be passed as:
          ' - A string, or
          ' - An array of strings

          Dim objects As Variant
          If IsArray(folders) Then
          objects = folders
          ElseIf TypeOf folders Is Outlook.Folders Then
          Set objects = folders
          ElseIf TypeOf folders Is Outlook.Folder Then
          ReDim objects(1 To 1) As Variant
          Set objects(1) = folders
          Else
          Exit Function
          End If

          Dim types As Variant
          If IsArray(itemTypes) Then
          types = itemTypes
          ElseIf Not IsObject(itemTypes) then
          ReDim types(1 To 1) As String
          types(1) = CStr(itemTypes)
          Else
          Exit Function
          End If

          Dim results As New Collection
          Dim elem As Variant
          For Each elem In objects
          Dim item As Object
          For Each item In elem.Items
          Dim i As Long
          For i = LBound(types) To UBound(types)
          If item.MessageClass Like types(i) Then
          results.Add Item
          Exit For
          End If
          Next
          Next
          Next
          Set getItems = results

          End Function
          Function parseSubject(obj As Object) As String

          Dim subjectText As String
          Dim itemLabel As String
          subjectText = LCase(obj.Subject)

          If InStr(subjectText), "produktion") > 0 Then
          obj.Categories = "Change Produktion"
          itemLabel = "Produktion"
          ElseIf InStr(subjectText), "integration") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Integration"
          ElseIf InStr(subjectText, "test") > 0 Then
          obj.Categories = "Change Integration"
          itemLabel = "Testing"
          Else
          obj.Categories = "Change Info"
          itemLabel = "Info"
          End If

          parseSubject = """" & itemLabel & """"

          End Function
          Function formatForJSON(str As String) As String

          Dim resultStr As String
          resultStr = Replace(str, """", "'")
          resultStr = Replace(resultStr, vbCr & vbLf, "n")
          resultStr = Replace(resultStr, vbCr, "n")
          resultStr = Replace(resultStr, vbLf, "n")
          formatForJSON = """" & resultStr & """"

          End Function
          Function createJSON(exchangeID As String, label As String, subject As String, _
          body As String, startDate As String, endDate As String) As String

          Dim JSON As String
          JSON = JSON & """fields: " & vbCrLf
          JSON = JSON & " ""project"": " & vbCrLf
          JSON = JSON & " ""id"": 30611" & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""summary"": " & subject & "," & vbCrLf
          JSON = JSON & " ""description"": " & body & "," & vbCrLf
          JSON = JSON & " ""issuetype"": " & vbCrLf
          JSON = JSON & " ""name"": " & exchangeID & vbCrLf
          JSON = JSON & " ," & vbCrLf
          JSON = JSON & " ""customfield_10021"": " & startDate & "," & vbCrLf
          JSON = JSON & " ""customfield_12760"": " & endDate & "," & vbCrLf
          JSON = JSON & " ""labels"": [" & label & "]" & vbCrLf
          JSON = JSON & "" & vbCrLf & ""

          createJSON = JSON

          End Function
          Function formatDate(dt As Date) As String

          formatDate = """" & Format(dt, "yyyy-mm-dd") & "T" & _
          Format(dt, "hh:mm") & ":00.000+0200" & """"

          End Function
          Sub sendJIRA(JSON As String, username As String, pw As String)

          Dim URL As String
          URL = "https://jira.app.com/rest/api/2/issue/"
          Set xhr = CreateObject("MSXML2.XMLHTTP.6.0")
          xhr.Open "POST", URL, False
          xhr.setRequestHeader "Content-Type", "application/json"
          xhr.setRequestHeader "User-Agent", "Outlook"
          xhr.setRequestHeader "Authorization", "Basic " + Base64Encode(username & ":" & pw)
          xhr.Send JSON

          End Sub
          Function addressMatches(address As String, regEx As RegExp) As Boolean

          If address = "Application Management Linux1, I351" Then
          addressMatches = False
          Else
          addressMatches = regEx.Test(address)
          End If

          End Function






          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited May 23 at 21:07


























          answered May 23 at 18:48









          Daniel McCracken

          226112




          226112











          • You are commentary on code reuse is "Spot On" . It seems to me that a JIRA is setup per recipient and that the JSON changes for each recipient. As evidenced by recip.AddressEntry.GetExchangeUser().Alias which is passed to my getJSON function as the recipAlias parameter and used in JSON string of the OP's post (JSON = .... """" + recip.AddressEntry.GetExchangeUser().Alias + """" ). +1
            – user109261
            May 23 at 19:46










          • The only part that changes is the recipAlias parameter, the Subject/Body portions stay the same. I'll edit the post to show what I mean.
            – Daniel McCracken
            May 23 at 21:03










          • Your Full Version is solid. The intermediate variables do make the code read and test better. I'm still not a big fan of the JSON string concatenation but you handled it well.
            – user109261
            May 24 at 2:49










          • Fair enough! I don't usually work with JSON but when it comes to SQL strings I have a couple of approaches I normally use. Typically I just import a .sql file from our network drive + do string replacement (though I surround my parameters <like this> rather than using @). If I can't be sure I'll have local network access, I have a macro that can take a text file and convert it to a SQL query string suitable for copy/pasting directly into a VBA module. In this case, my answer was already pretty long, and the JSON string was pretty short, so I didn't bother with a more complex solution.
            – Daniel McCracken
            May 24 at 4:08

















          • You are commentary on code reuse is "Spot On" . It seems to me that a JIRA is setup per recipient and that the JSON changes for each recipient. As evidenced by recip.AddressEntry.GetExchangeUser().Alias which is passed to my getJSON function as the recipAlias parameter and used in JSON string of the OP's post (JSON = .... """" + recip.AddressEntry.GetExchangeUser().Alias + """" ). +1
            – user109261
            May 23 at 19:46










          • The only part that changes is the recipAlias parameter, the Subject/Body portions stay the same. I'll edit the post to show what I mean.
            – Daniel McCracken
            May 23 at 21:03










          • Your Full Version is solid. The intermediate variables do make the code read and test better. I'm still not a big fan of the JSON string concatenation but you handled it well.
            – user109261
            May 24 at 2:49










          • Fair enough! I don't usually work with JSON but when it comes to SQL strings I have a couple of approaches I normally use. Typically I just import a .sql file from our network drive + do string replacement (though I surround my parameters <like this> rather than using @). If I can't be sure I'll have local network access, I have a macro that can take a text file and convert it to a SQL query string suitable for copy/pasting directly into a VBA module. In this case, my answer was already pretty long, and the JSON string was pretty short, so I didn't bother with a more complex solution.
            – Daniel McCracken
            May 24 at 4:08
















          You are commentary on code reuse is "Spot On" . It seems to me that a JIRA is setup per recipient and that the JSON changes for each recipient. As evidenced by recip.AddressEntry.GetExchangeUser().Alias which is passed to my getJSON function as the recipAlias parameter and used in JSON string of the OP's post (JSON = .... """" + recip.AddressEntry.GetExchangeUser().Alias + """" ). +1
          – user109261
          May 23 at 19:46




          You are commentary on code reuse is "Spot On" . It seems to me that a JIRA is setup per recipient and that the JSON changes for each recipient. As evidenced by recip.AddressEntry.GetExchangeUser().Alias which is passed to my getJSON function as the recipAlias parameter and used in JSON string of the OP's post (JSON = .... """" + recip.AddressEntry.GetExchangeUser().Alias + """" ). +1
          – user109261
          May 23 at 19:46












          The only part that changes is the recipAlias parameter, the Subject/Body portions stay the same. I'll edit the post to show what I mean.
          – Daniel McCracken
          May 23 at 21:03




          The only part that changes is the recipAlias parameter, the Subject/Body portions stay the same. I'll edit the post to show what I mean.
          – Daniel McCracken
          May 23 at 21:03












          Your Full Version is solid. The intermediate variables do make the code read and test better. I'm still not a big fan of the JSON string concatenation but you handled it well.
          – user109261
          May 24 at 2:49




          Your Full Version is solid. The intermediate variables do make the code read and test better. I'm still not a big fan of the JSON string concatenation but you handled it well.
          – user109261
          May 24 at 2:49












          Fair enough! I don't usually work with JSON but when it comes to SQL strings I have a couple of approaches I normally use. Typically I just import a .sql file from our network drive + do string replacement (though I surround my parameters <like this> rather than using @). If I can't be sure I'll have local network access, I have a macro that can take a text file and convert it to a SQL query string suitable for copy/pasting directly into a VBA module. In this case, my answer was already pretty long, and the JSON string was pretty short, so I didn't bother with a more complex solution.
          – Daniel McCracken
          May 24 at 4:08





          Fair enough! I don't usually work with JSON but when it comes to SQL strings I have a couple of approaches I normally use. Typically I just import a .sql file from our network drive + do string replacement (though I surround my parameters <like this> rather than using @). If I can't be sure I'll have local network access, I have a macro that can take a text file and convert it to a SQL query string suitable for copy/pasting directly into a VBA module. In this case, my answer was already pretty long, and the JSON string was pretty short, so I didn't bother with a more complex solution.
          – Daniel McCracken
          May 24 at 4:08













           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194943%2fcreating-jira-task-from-email-in-ms-outlook%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Greedy Best First Search implementation in Rust

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          C++11 CLH Lock Implementation