run-time error 449 Argument Not Optional (1 Viewer)

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
Hello all,

I'm new to Access and currently work as a data system manager at an HIV research lab. We use Qualtrics to create surveys for participants to take online, and we use Access to call Qualtrics API to add participants to Qualtrics contact panel, automatically generate survey links for them, email survey distribution links to the participants, and store their responses through exported files.

Here is the link to the Qualtrics API documentation:
api.qualtrics.com

I'm migrating all the Qualtrics function to v3, and run into this run-time argument not optional error when trying to generate survey distribution links for participants & send them emails with their survey links.

Here is the API documentation link to the Qualtrics function I'm working on - CreateSurveyDistributionLinks:
api.qualtrics.com/reference#distribution-create-1

api.qualtrics.com/reference#email-mailing-list

The following screenshots shows my function and the sub where I try to call the function (the error message pops up on the line highlighted in yellow:

View attachment 78512
View attachment 78513

I would truly appreciate all your insights, really hope my code works!!

Best,
Jess
 

Ranman256

Well-known member
Local time
Today, 02:25
Joined
Apr 9, 2015
Messages
4,336
can you show the code where the error breaks?
the attachements dont work.
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
can you show the code where the error breaks?
the attachements dont work.

Dear Ranman256, thank you so much for your quick reply! I copied my code in the following:

UG Added Code Tags
Code:
Public Function createSurveyDistributionLinks(strSubject As String, strMessageID As String, strRecipients As String, strSurveyID As String, dtSendDate As Date, dtExpirationDate As Date)
'note: this function does not contain message feature as it is not used in 1KS. Can add for other uses by including a dicMessage object
Dim strURL As String
Dim JSON As Object
Dim dicMessage As Dictionary
Dim dicHeader As Dictionary
Dim strBodyJson As String
Dim strFromEmail As String
Dim strFromName As String


    Me.initObject
    strURL = "https://az1.qualtrics.com/API/v3/distributions"
    
    strFromEmail = "day2day%40chestnyc.org"
    strFromName = "day2day"
    strFromName = Replace(strFromName, " ", "%20") 'Convert spaces
    strSubject = Replace(strSubject, " ", "%20") 'Convert spaces
    
    
    Set dicHeader = New Dictionary
    
    dicHeader("fromEmail") = strFromEmail
    dicHeader("fromName") = strFromName
    dicHeader("subject") = strSubject
    
    Set dicMessage = New Dictionary
    dicMessage("messageId") = strMessageID
    dicMessage("libraryId") = strLibID
    
    dicMessage("header") = dicHeader
    
    
    Set dicBody = New Dictionary
    dicBody("recipients") = strRecipients
    dicBody("surveyId") = strSurveyID
    dicBody("sendDate") = formatQualtricsTimes(dtSendDate)
    dicBody("expirationDate") = formatQualtricsTimes(Nz(dtExpirationDate, "2050-01-01 00:00:00"))
    dicBody("message") = dicMessage

    strBodyJson = JsonConverter.ConvertToJson(dicBody)
    Debug.Print strBodyJson
    
    With xmlhttprequester
        .Open "POST", strURL
        .setRequestHeader "X-API-TOKEN", strToken
        .setRequestHeader "Content-Type", "application/json"
        .send strBodyJson
        
        .waitForResponse
        If InStr(.responseText, "EMD_") > 0 Then
            'it worked!
            Set JSON = JsonConverter.ParseJson(.responseText)
            Dim strrand As String
            createSurveyDistributionLinks = JSON("result")("id")
            Debug.Print JSON("result")("id")
        Else
            Debug.Print "an error has occurred" & vbNewLine & .responseText
            createSurveyDistributionLinks = "false"
        End If
    End With
    
End Function


The following shows the sub when I tried to call the function, that's where my code breaks too:

strDistributionID = oQual.createSurveyDistributionLinks(strSubject, strMessageID, strRecipientID, strSurveyID, CStr(dtExpTime), CStr(dtTime))[/QUOTE]
 
Last edited by a moderator:

MajP

You've got your good things, and you've got mine.
Local time
Today, 02:25
Joined
May 21, 2018
Messages
8,439
Part of the issue maybe is
These are declared as dates: dtSendDate As Date, dtExpirationDate As Date
But you pass them in as strings
CStr(dtExpTime), CStr(dtTime))
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
Part of the issue maybe is
These are declared as dates: dtSendDate As Date, dtExpirationDate As Date
But you pass them in as strings
CStr(dtExpTime), CStr(dtTime))[/QUOTE

Hi MajP, thank you for your reply! Just tried to pass them as dates and still run into the same error..
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 02:25
Joined
May 21, 2018
Messages
8,439
If you use the number sign tags it makes it easier to read and also keep indentations.

Code:
strDistributionID = oQual.createSurveyDistributionLinks(strSubject, strMessageID, strRecipientID, strSurveyID, CStr(dtExpTime), CStr(dtTime))[/QUOTE]


Code:
Public Function createSurveyDistributionLinks(strSubject As String, strMessageID As String, strRecipients As String, strSurveyID As String, dtSendDate As Date, dtExpirationDate As Date)
'note: this function does not contain message feature as it is not used in 1KS. Can add for other uses by including a dicMessage object
Dim strURL As String
Dim JSON As Object
Dim dicMessage As Dictionary
Dim dicHeader As Dictionary
Dim strBodyJson As String
Dim strFromEmail As String
Dim strFromName As String


Me.initObject
strURL = "https://az1.qualtrics.com/API/v3/distributions"

strFromEmail = "day2day%40chestnyc.org"
strFromName = "day2day"
strFromName = Replace(strFromName, " ", "%20") 'Convert spaces
strSubject = Replace(strSubject, " ", "%20") 'Convert spaces


Set dicHeader = New Dictionary

dicHeader("fromEmail") = strFromEmail
dicHeader("fromName") = strFromName
dicHeader("subject") = strSubject

Set dicMessage = New Dictionary
dicMessage("messageId") = strMessageID
dicMessage("libraryId") = strLibID

dicMessage("header") = dicHeader


Set dicBody = New Dictionary
dicBody("recipients") = strRecipients
dicBody("surveyId") = strSurveyID
dicBody("sendDate") = formatQualtricsTimes(dtSendDate)
dicBody("expirationDate") = formatQualtricsTimes(Nz(dtExpirationDate, "2050-01-01 00:00:00"))
dicBody("message") = dicMessage

strBodyJson = JsonConverter.ConvertToJson(dicBody)
Debug.Print strBodyJson

With xmlhttprequester
.Open "POST", strURL
.setRequestHeader "X-API-TOKEN", strToken
.setRequestHeader "Content-Type", "application/json"
.send strBodyJson

.waitForResponse
If InStr(.responseText, "EMD_") > 0 Then
'it worked!
Set JSON = JsonConverter.ParseJson(.responseText)
Dim strrand As String
createSurveyDistributionLinks = JSON("result")("id")
Debug.Print JSON("result")("id")
Else
Debug.Print "an error has occurred" & vbNewLine & .responseText
createSurveyDistributionLinks = "false"
End If
End With

End Function

So where exactly is it failing that gets the error? Also appears you want senddate and expirationdate but you are sending ExpTime and dtTime.
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
If you use the number sign tags it makes it easier to read and also keep indentations.

Code:
strDistributionID = oQual.createSurveyDistributionLinks(strSubject, strMessageID, strRecipientID, strSurveyID, CStr(dtExpTime), CStr(dtTime))[/QUOTE]


Code:
Public Function createSurveyDistributionLinks(strSubject As String, strMessageID As String, strRecipients As String, strSurveyID As String, dtSendDate As Date, dtExpirationDate As Date)
'note: this function does not contain message feature as it is not used in 1KS. Can add for other uses by including a dicMessage object
Dim strURL As String
Dim JSON As Object
Dim dicMessage As Dictionary
Dim dicHeader As Dictionary
Dim strBodyJson As String
Dim strFromEmail As String
Dim strFromName As String


Me.initObject
strURL = "https://az1.qualtrics.com/API/v3/distributions"

strFromEmail = "day2day%40chestnyc.org"
strFromName = "day2day"
strFromName = Replace(strFromName, " ", "%20") 'Convert spaces
strSubject = Replace(strSubject, " ", "%20") 'Convert spaces


Set dicHeader = New Dictionary

dicHeader("fromEmail") = strFromEmail
dicHeader("fromName") = strFromName
dicHeader("subject") = strSubject

Set dicMessage = New Dictionary
dicMessage("messageId") = strMessageID
dicMessage("libraryId") = strLibID

dicMessage("header") = dicHeader


Set dicBody = New Dictionary
dicBody("recipients") = strRecipients
dicBody("surveyId") = strSurveyID
dicBody("sendDate") = formatQualtricsTimes(dtSendDate)
dicBody("expirationDate") = formatQualtricsTimes(Nz(dtExpirationDate, "2050-01-01 00:00:00"))
dicBody("message") = dicMessage

strBodyJson = JsonConverter.ConvertToJson(dicBody)
Debug.Print strBodyJson

With xmlhttprequester
.Open "POST", strURL
.setRequestHeader "X-API-TOKEN", strToken
.setRequestHeader "Content-Type", "application/json"
.send strBodyJson

.waitForResponse
If InStr(.responseText, "EMD_") > 0 Then
'it worked!
Set JSON = JsonConverter.ParseJson(.responseText)
Dim strrand As String
createSurveyDistributionLinks = JSON("result")("id")
Debug.Print JSON("result")("id")
Else
Debug.Print "an error has occurred" & vbNewLine & .responseText
createSurveyDistributionLinks = "false"
End If
End With

End Function

So where exactly is it failing that gets the error? Also appears you want senddate and expirationdate but you are sending ExpTime and dtTime.

Dear MajP, thank you so much for formatting it, it does look much more organized and clean haha!

The line that breaks is when I call the "createSurveyDistributionLinks" from the module I declared as oQual.

I don't think the problem happens for how I define & call "sendDate" and "expirationDate"? Since I'm calling this function in a new sub, I assume the variable names don't have to be exactly the same, I'm just simply passing the dates. Let me know if that helps, thanks for helping me!

Any other insights?

Best,
Jessica
 

theDBguy

I’m here to help
Staff member
Local time
Yesterday, 23:25
Joined
Oct 29, 2018
Messages
21,322
Hi Jessica. Pardon me for jumping in, but have you tried stepping through the code during execution to examine all variable contents and see if it's doing what you're expecting? Just curious...
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 02:25
Joined
May 21, 2018
Messages
8,439
don't think the problem happens for how I define & call "sendDate" and "expirationDate"? Since I'm calling this function in a new sub, I assume the variable names don't have to be exactly the same, I'm just simply passing the dates.

The names do not have to be the same, but the number of arguments and the argument types have to be the same. Since it is failing when you call the procedure there is only one thing that can be the issue. There is a problem with the arguments you are passing. Normally if you forget to pass a required argument you get the error
like "missing argument". If you do not pass the correct data type you get "Type Mismatch error"

So looking at the names and the conversion it does not look like the datatypes match up.

Code:
(strSubject, strMessageID, strRecipientID, strSurveyID, CStr(dtExpTime), CStr(dtTime))

Code:
(strSubject As String, strMessageID As String, strRecipients As String, strSurveyID As String, dtSendDate As Date, dtExpirationDate As Date)

You need to be passing in string, string, string, string, date, date

For sure that was not happening since you converted the dates to string. So my next question are all those IDs really passed as strings or are they possibly numeric.

Again I would have expected a type mismatch and not a missing argument.

before calling the procedure debug.print all of your arguments and verify datatypes. You can print that out too.
example
Debug.print "Message ID " & strMessageID & " " & varType(strMessageID)
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
Hi Jessica. Pardon me for jumping in, but have you tried stepping through the code during execution to examine all variable contents and see if it's doing what you're expecting? Just curious...

Hi there, thank you so much for your reply! I put some stops and tried to debug my function, the error message shows after this line of code:

Code:
    dicMessage("header") = dicHeader

I've changed the dates back to dates instead of converting them into strings, and still have the same error. Please help! Thanks a lot!

Best,
Jess
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 02:25
Joined
May 21, 2018
Messages
8,439
Just to be very clear the error is in
Code:
dicMessage("header") = dicHeader
and the error is argument not optional?

There is not an error on the call line.
Code:
strDistributionID = oQual.createSurveyDistributionLinks(strSubject, strMessageID, strRecipientID, strSurveyID, CStr(dtExpTime), CStr(dtTime))
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
The names do not have to be the same, but the number of arguments and the argument types have to be the same. Since it is failing when you call the procedure there is only one thing that can be the issue. There is a problem with the arguments you are passing. Normally if you forget to pass a required argument you get the error
like "missing argument". If you do not pass the correct data type you get "Type Mismatch error"

So looking at the names and the conversion it does not look like the datatypes match up.

Code:
(strSubject, strMessageID, strRecipientID, strSurveyID, CStr(dtExpTime), CStr(dtTime))

Code:
(strSubject As String, strMessageID As String, strRecipients As String, strSurveyID As String, dtSendDate As Date, dtExpirationDate As Date)

You need to be passing in string, string, string, string, date, date

For sure that was not happening since you converted the dates to string. So my next question are all those IDs really passed as strings or are they possibly numeric.

Again I would have expected a type mismatch and not a missing argument.

before calling the procedure debug.print all of your arguments and verify datatypes. You can print that out too.
example
Debug.print "Message ID " & strMessageID & " " & varType(strMessageID)

Thank you again for your reply!! I'm debugging each line of code and yes they are passed as strings and dates. I delete the Cstr() function, try to run the code again and still have the same issue, this time the error message pops up on this line of code:

Code:
dicMessage("header") = dicHeader

I'm not sure why this is the case, my goal is to combine all the dictionary objects into one named "dicBody". Please help!! Thank you so much!

Best,
Jess
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
Just to be very clear the error is in
Code:
dicMessage("header") = dicHeader
and the error is argument not optional?

There is not an error on the call line.
Code:
strDistributionID = oQual.createSurveyDistributionLinks(strSubject, strMessageID, strRecipientID, strSurveyID, CStr(dtExpTime), CStr(dtTime))


Hi hi again! Yes you're correct when I follow your method and debug each line, the error is in
Code:
dicMessage("header") = dicHeader
and not on the call line anymore

Best,
Jess
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 02:25
Joined
May 21, 2018
Messages
8,439
Code:
dicMessage("header") = dicHeader
I am out of Ideas if the message is still "Argument not optional" at this line.
In this line you are assigning the created dictionary "dicHeader" to the cell "Header" in the dictionary "dicMessage". That looks perfectly fine to me, and can not see how you could get the error your describe. Any chance the error is something different after fixing the signatures?

The only thing I think could fail here is if somehow dicHeader was Nothing. But I do not see how that could happen and would expect a different error.
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
Code:
dicMessage("header") = dicHeader
I am out of Ideas if the message is still "Argument not optional" at this line.
In this line you are assigning the created dictionary "dicHeader" to the cell "Header" in the dictionary "dicMessage". That looks perfectly fine to me, and can not see how you could get the error your describe. Any chance the error is something different after fixing the signatures?

The only thing I think could fail here is if somehow dicHeader was Nothing. But I do not see how that could happen and would expect a different error.

Dear MajP,

I tried to declare a collection named colBody to add "dicHeader" and "dicMessage" and the error is gone! But now I run into a different error, here is the error message:
Code:
{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Expected param not found: sendDate","errorCode":"RP_10"},"requestId":"563d7dd0-4dca-4ed6-8e6b-084b4078ed02"}}


And here is the updated function:

Code:
Public Function createSurveyDistributionLinks(strSubject As String, strMessageID As String, strRecipients As String, strSurveyID As String, dtSendDate As Date, dtExpirationDate As Date)
'note: this function does not contain message feature as it is not used in 1KS. Can add for other uses by including a dicMessage object
Dim strURL As String
Dim JSON As Object
Dim dicMessage As Dictionary
Dim dicHeader As Dictionary
Dim strBodyJson As String
Dim strFromEmail As String
Dim strFromName As String

Dim colBody As Collection

    Me.initObject
    strURL = "https://az1.qualtrics.com/API/v3/distributions"
    
    strFromEmail = "day2day%40chestnyc.org"
    strFromName = "day2day"
    strFromName = Replace(strFromName, " ", "%20") 'Convert spaces
    strSubject = Replace(strSubject, " ", "%20") 'Convert spaces
    
    
    Set dicHeader = New Dictionary
    dicHeader("fromEmail") = strFromEmail
    Debug.Print "fromEmail " & strFromEmail & " " & VarType(strFromEmail)
    dicHeader("fromName") = strFromName
    Debug.Print "fromName " & strFromName & " " & VarType(strFromName)
    dicHeader("subject") = strSubject
    Debug.Print "Subject " & strSubject & " " & VarType(strSubject)
       
       
    Set dicMessage = New Dictionary
    dicMessage("messageId") = strMessageID
    Debug.Print "Message ID " & strMessageID & " " & VarType(strMessageID)
    dicMessage("recipients") = strRecipients
    Debug.Print "Recipients " & strRecipients & " " & VarType(strRecipients)
    dicMessage("surveyId") = strSurveyID
    Debug.Print "surveyId " & strSurveyID & " " & VarType(strSurveyID)
    dicMessage("sendDate") = formatQualtricsTimes(dtSendDate)
    Debug.Print "sendDate " & dtSendDate & " " & VarType(dtSendDate)
    dicMessage("expirationDate") = formatQualtricsTimes(Nz(dtExpirationDate, "2050-01-01 00:00:00"))
    Debug.Print "Expiration Date " & dtExpirationDate & " " & VarType(dtExpirationDate)
    
    Set colBody = New Collection
    colBody.Add dicHeader
    colBody.Add dicMessage
    
    Set dicBody = New Dictionary
    Set dicBody("Message") = colBody
    strBodyJson = JsonConverter.ConvertToJson(dicBody)
    Debug.Print strBodyJson
    

    With xmlhttprequester
        .Open "POST", strURL
        .setRequestHeader "X-API-TOKEN", strToken
        .setRequestHeader "Content-Type", "application/json"
        .send strBodyJson
        
        .waitForResponse
        If InStr(.responseText, "EMD_") > 0 Then
            'it worked!
            Set JSON = JsonConverter.ParseJson(.responseText)
            Dim strrand As String
            createSurveyDistributionLinks = JSON("result")("id")
            Debug.Print JSON("result")("id")
        Else
            Debug.Print "an error has occurred" & vbNewLine & .responseText
            createSurveyDistributionLinks = "false"
        End If
    End With
    
End Function


Please let me know if you have any questions, I really really appreciate your assistance on this!!

Best,
Jess
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 02:25
Joined
May 21, 2018
Messages
8,439
Sorry I am not much help. I am guessing here since not familiar with this API. That error message I assume is not a vba error but an API error
Code:
{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Expected param not found: sendDate","errorCode":"RP_10"},"requestId":"563d7dd0-4dca-4ed6-8e6b-084b4078ed02"}}

But reading it, I am assuming that there is no sendDate in the JSON formatted message? Is it possible to look at StrBodyJson to see if it is properly formatted?
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
Sorry I am not much help. I am guessing here since not familiar with this API. That error message I assume is not a vba error but an API error
Code:
{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Expected param not found: sendDate","errorCode":"RP_10"},"requestId":"563d7dd0-4dca-4ed6-8e6b-084b4078ed02"}}

But reading it, I am assuming that there is no sendDate in the JSON formatted message? Is it possible to look at StrBodyJson to see if it is properly formatted?

Hey there, please don't say that you've been very helpful!!

Here is the strBodyJson:

Code:
{"Message":[{"fromEmail":"day2day%40chestnyc.org","fromName":"day2day","subject":"day2day%20Afternoon%20Survey"},{"sendDate":"2020-01-24T12:00:00Z"},{"messageId":"MS_3f7Y9QJmoQmR6q9","recipients":"MLRP_9oTXqBsMs6bdbpz","surveyId":"SV_4SAKPbbRMWxdVR3","expirationDate":"2020-01-24T16:00:00Z"}]}


Thank you again for looking into this!!

Best,
Jess
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 02:25
Joined
May 21, 2018
Messages
8,439
Well the send date is there. So my only guess it is another format problem with the JSON. Can you compare what is being sent to the documentation to see if the format matches up?

I do not do any JSON work. The moderator Isladogs is very conversant in JSON and may have an idea. I will PM him to take a look and see if he has any ideas.
 

yuenling1995

Registered User.
Local time
Yesterday, 23:25
Joined
Jan 22, 2020
Messages
20
Well the send date is there. So my only guess it is another format problem with the JSON. Can you compare what is being sent to the documentation to see if the format matches up?

I do not do any JSON work. The moderator Isladogs is very conversant in JSON and may have an idea. I will PM him to take a look and see if he has any ideas.


Omg thank you so much for doing this I really appreciate it!

The Qualtrics API documentation isn't much help tho.. Here's what they have on the page:

Code:
curl -XPOST -H 'X-API-TOKEN: <API Key>' -H 'Content-Type: application/json' https://co1.qualtrics.com/API/v3/distributions -d '{
        "message": {
                "libraryId": "UR_8cRedheujEbcxgN",
                "messageId": "MS_1Mt2Nj5kczdnjMh"
        },
        "recipients": {
                "mailingListId": "CG_6F1gRt186CZOVoh"
        },
        "header": {
                "fromName": "Qualtrics",
                "replyToEmail": "noreply@qualtrics.com",
                "fromEmail": "noreply@qualtrics.com",
                "subject": "Survey Distribution"
        },
        "surveyLink": {
                "surveyId": "SV_ebdf20QralHTzQF",
                "expirationDate": "2019-09-13T00:00:00Z",
                "type": "Individual"
        },
        "sendDate": "2018-12-04T11:13:35Z"
}'


Best,
Jess
 

isladogs

MVP / VIP
Local time
Today, 06:25
Joined
Jan 14, 2017
Messages
18,164
Jess
MajP sent me a PM asking me to look at this thread.
To save me time needing to read through the whole thread in detail, can you please summarise what the issue is.
Is it your code or have you downloaded and adapted it from somewhere - if so where?
Also have you checked whether the JSON file you are trying to upload is valid?
 

Users who are viewing this thread

Top Bottom