Member tips

How to auto-export form responses to PDF and file in a SharePoint document library

  • 3 February 2023
  • 4 replies
  • 478 views
How to auto-export form responses to PDF and file in a SharePoint document library
Userlevel 2
Badge

Automatically export Typeform results to PDF and file in SharePoint document library programmatically using API webhooks in real time

 

Skip ahead: 

General Info

Disclaimer: I have no affiliation with any of the products listed here and benefit in no way from you using them. They are just the products I’ve found that solve my issues.

We use Typeform to collect information from our clients before we do their tax return. Our tax preparers need this information in PDF format to file with their work papers, make notes, highlight, and reference, etc. You can accomplish PDF export one-by-one by manually reviewing the responses in Typeform and printing them to PDF one at a time. This present several challenges which I will address in the comments if anyone cares. 😉 The short version is that we want computers to work for us, not the other way around.

Goal

Automatically export form responses to PDF and file in our SharePoint document library.

Prerequisites

  

  • Microsoft 365
    • This assumes you have a Microsoft 365 account. If you don’t, you’ll need one.
    • Link: Microsoft 365
    • Word document with plain text fillable fields saved to your a SharePoint library
    • If you need help with a template, hit me up in the comments.
  • Postman.com provides all the tools needed to test and develop API calls
  • https://webhook.site/​​​​​​ this site allows you to quickly see how the webhook will come through to you. I find it useful when using existing templates to create JSON schemas based on a payload (more information on this later)
    • Use the temporary link to point your webhook for testing

       

  • Azure.com provides the tools for consumption-based logic apps (like Zapier on steroids)
    • Link: Sign up for Azure
    • Pick a region and stick with it
    • Pick “Pay as you go” and “Consumption” whenever presented with the choice
    • Add a resource group
    • Add an integration account (free tier)
    • The only screen that matters for this project is the first one when creating things in Azure. Feel free to skip tags, etc.:
    • Create a logic app (follow the guidelines above about tags, consumption, region, and pay-as-you-go)
    • Connect your logic app with your integration account (Link: Instructions)
  • Office365.com

Method

  

  1. When HTTP request received
    1. The requests connector will give you a URL after you save it the first time. Copy this URL and use it to point the Typeform webhook when you create it.
    2. Use https://webhook.site/ to capture a webhook payload and paste it in “Use sample payload to generate schema
    3. If your Typeform has conditional data, the webhook only returns what was answered. We’ll address this situation further down the workflow. Adding the schema here helps with all constant data like hidden fields, form titles, etc.
  2. Initialize client variable
    1. You add a field here from your request schema
      var j=workflowContext.actions.compose_this_loop_answer_module.outputs,
      k=Object.keys(j),
      t=j["type"],
      a=[];
      switch(t){
      case 'choice':
      if(j[t].hasOwnProperty('label')){a=[].concat(a,j[t]['label'])}
      if(j[t].hasOwnProperty('other')){a=[].concat(a,'Other answer: '+j[t]['other'])}
      a=a.join('\n');
      break;
      case 'choices':
      if(j[t].hasOwnProperty('labels')){a=[].concat(a,j[t]['labels'])}
      if(j[t].hasOwnProperty('other')){a=[].concat(a,'Other answer: '+j[t]['other'])}
      a=a.join('\n');
      break;
      default:
      a=j[k[1]];
      break;
      }
      return a+'';

       

    2. My client names have problematic characters, so I use this function to remove them
  3. Compose this loop answer module
    1. You’ll see that questions and answers are returned in different areas. I use this for each loop to concatenate them together
    2. The loop works through the question headings, and this compose connector pulls in the corresponding answer JSON element.
    3. Here’s the code: 
      triggerBody()?['form_response']?['answers'][variables('varCount')]

      this section:

    4. get keys of the JSON object as an array
      1. This connector helps with conditional form responses by checking for “Choice” and “Choices” type answers and returning the “labels” and “other” answers as a string, one per line
      2. Here’s the code. My JavaScript is rusty and there’s a character limit in the connector… no comments and single character variables 😒.
        var j=workflowContext.actions.compose_this_loop_answer_module.outputs,
        k=Object.keys(j),
        t=j["type"],
        a=[];
        switch(t){
        case 'choice':
        if(j[t].hasOwnProperty('label')){a=[].concat(a,j[t]['label'])}
        if(j[t].hasOwnProperty('other')){a=[].concat(a,'Other answer: '+j[t]['other'])}
        a=a.join('\n');
        break;
        case 'choices':
        if(j[t].hasOwnProperty('labels')){a=[].concat(a,j[t]['labels'])}
        if(j[t].hasOwnProperty('other')){a=[].concat(a,'Other answer: '+j[t]['other'])}
        a=a.join('\n');
        break;
        default:
        a=j[k[1]];
        break;
        }
        return a+'';
    5. Append to string variable
      1. This fun combines the question heading and answer in this format:
        QUESTION HEADING
        -----------
        Answer1
        Answer2
        etc.
        Here’s the code that goes in the expression box:
        concat(variables('varQuestion'),'
        ----------
        ',outputs('get_keys_of_the_json_object_as_an_array')['body'],'

        ')
    6. The rest of the fields for your SharePoint folders and template files you’ll have to add manually​​

Conclusion

I’m sure I missed some steps… 😁 Hit me up in the comments with questions or issues.


4 replies

Userlevel 7
Badge +5

Ah! This is so great, @the other max . Thanks for sharing this! I should share this with my accountant because I’d love it if they used Typeform. 😍

Userlevel 2
Badge

We love typeform. 😊 We came from Forms on M365. I’m a huge proponent of sticking to the fewest number of platforms as possible, so that’s a testament to what you’ve built with Typeform. 😁

Userlevel 7
Badge +5

Ah, glad to hear it, @the other max ! I’m so impressed with what you built here! It’s really cool. 

Userlevel 7
Badge +5

Hey @the other max thanks so much for sharing this awesome solution 🙇 We really appreciate you taking the time to share what’s worked for you with others! 

Have bumped this to be one of our “featured” posts for this week on the Community home page 🙂 Hopefully others can benefit from the fruits of your labours 🤗

Reply