Generate a PDF file of the answered form

I'd like to know if I understood correctly. Is it possible to generate a PDF file of the answered form, from the mobile application? Do you have a test form

1 Like

Generating a PDF from a form in Collect is not currently supported. What I described above is how we do it in our (proprietary) XForms app. It is certainly technically possible (eg I do it by converting the submission to HTML and getting the on-device web browser tools to 'print' the resulting HTML page into a PDF), but this would be a new feature in ODK Collect requiring development work to implement.

1 Like

I understand. It would be very interesting to have that option available. Many times I have cases where the respondent requests (in the field) to have a document that "checks" or "supports" the answers to the form.

4 Likes

We would also really like the ability to send individual completed forms to PDF from ODK Collect.

We have the need to sign hard copies of the forms for legislative purposes and it would be great to allow the users to print forms on an ad-hoc basis to allow them to do this.

@Xiphware - can I ask if it is possible to modify the ODK Collect app to allow submission to HTML? Or is it only possible via a proprietary app? Apologies, I´m very new to the ODK world and just finding my way around.

Many thanks

P.s. Hi from one kiwi to another :slight_smile:

Edit: From reading around a bit more I´m thinking that perhaps we need to go down the ODK-X route. We only really need that one extra feature - perhaps we can copy and paste most of the code from ODK Collect and just add our feature? (Or possibly that´s frowned upon...)

1 Like

Well, ODK Collect is Open Source, so yes its technically possible to modify the source code to have it submit/send submissions in any format you desire... But at present it submits in standard XForm XML format, and that's what the ODK servers - ODK Aggregate and ODK Central - expect to receive. So although its not rocket science (eg I did it) to render an XForm definition and its submission data to HTML, and then 'print' it to a PDF file, this is not a feature the Collect app as-shipped presently supports.

Another existing alternative might to to explore using Enketo to fill in your forms; this is a browser-based ODK compatible XForm front-end, from which you could then use your browser's 'Print' option to generate a PDF from your completed form.

Great thanks for the reply @Xiphware.

After reading around a bit more I´m thinking that we may need to go down the ODK-X path and basically copy and paste the source code from ODK Collect and just add our one required feature. Hopefully that´s not frowned upon!

I did look at Enketo briefly but couldn´t see a way to remove all the unselected options in a completed form which means that our printed PDFs would be huge (we have a lot of options)

Adding a 'Save to PDF' option to Collect is certainly a option that a bunch of folks might desire, and probably wouldn't be terribly controversial. So you might consider putting in a Feature Request; more so if your organization has funding to support the ODK development team to do so (rather than having to roll your own), or if you do implement the feature and would like to submit a PR to pull it in.

1 Like

Perfect, thanks @Xiphware - will chat to the person that pulls the financial strings and see what our options are :slight_smile:

1 Like

If you can do the conversion on a computer instead of on the phone, it might be easier to explore an integration with ODK Briefcase that can convert the form definition and submission data into a PDF.

Here's an example of a custom tool to help print XLSForms in a pretty format:

1 Like

Thank you @danbjoseph - looks interesting.

At the moment we were hoping to cause as minimal disruption as possible to the existing workflows as the end users are not so IT literate.

So if we can make a minor change to the app that they already use (or create a new app that looks very similar to the one they use) then that would be the ideal.

But we are also toying with the idea of printing from a desktop too. Our current ODK platform ONA is unfortunately not very printer-friendly, so we may look at other options, such as ODK Briefcase but this would also require re-training of staff (on top of the re-deployment costs) so also hoping to avoid this!

1 Like

One thing to consider (which I share from experience...) is soon as you start generating what is effectively a 'report', is that you invariably open a pandora's box where everybody wants their own particular custom report format (!). eg display a feild-list as questions in a boxed/tabular format vs question-on-a-line + response-on-next-line, show question hint or not, yadda, yadda.
So you probably need to keep in mind the resulting HTML/PDF initially needs to be rather generic looking - just get the captured data documented on the page irregardless of the particular form. Then worry about tweaking the layout (eg via new appearance=...'s?) later.

Also, XForms are inherently hierarchical, whereas with a PDF/printed doc you need to render a strictly linear output. (again, formatting decisions you'll have to make at some point).

2 Likes

Yes, that's true!

I think to start we would do as you suggest - a simple dump of all the available captured data.

Ok, so I thought I'd have a go at this to see how far I can get with my rudimentary (read: non-existant) coding skills.

I can get a button up on a completed form in the 'View Sent Form' section ok, but having trouble working out how to extract the data that is currently been shown in the ViewOnlyFormHierarchyActivity Activity.

My current placeholder code is:

public class ViewOnlyFormHierarchyActivity extends FormHierarchyActivity {
/**
 * Hides buttons to jump to the beginning and to the end of the form instance to edit it. Adds
 * an extra exit button that exits this activity.
 */
@Override
void configureButtons(FormController formController) {
    Button exitButton = findViewById(R.id.exitButton);
    exitButton.setOnClickListener(v -> {
        setResult(RESULT_OK);
        finish();

    });

    Button printButton = findViewById(R.id.printButton);
    printButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v) {
            // Perform action on click
            Toast.makeText(ViewOnlyFormHierarchyActivity.this, "Button Clicked", Toast.LENGTH_SHORT).show();
        }
    });

    exitButton.setVisibility(View.VISIBLE);
    printButton.setVisibility(View.VISIBLE);

Does anyone know if there's a simple trick to retrieve the data being shown in the form so that I can use it for printing?

Edit; oh right, there is a XML file of the form stored locally. Perhaps I can use that...

The 'trick' is writing an XForm renderer, like ODK Collect (or Enketo, or iXForms)... :grin:

Basically, you need the submission data - which is ultimately an XML document containing all the raw values that will be submitted (ie what gets sent over-the-wire to ODK Aggregate, ODK Central, KoboToolbox, ...), But you also need the form definition (or an extracted version thereof) too because this contains the actual question text, hint, question type (select vs text vs number...) in order to know how to correctly display each piece of submitted data in your PDF. ODK Collect does all this for you - its parses the original XML XForm to extract the submission XML template, all the question data, their label prompts, etc, so all the data you need is squirreled away in various places in the source code, but you will need to figure out how to get at it to re-render (the XForm + submission data) as a PDF.

I'd probably start by making sure you understand how an XForm is structured (ie instances, bindings, body, etc) because that will help a great deal in deciphering what ODK Collect is doing, and how it internally structures the data that you need to get at.

[oh, and my advice would be to ignore handling repeat groups, at least initially. These will not insignificantly complicate how you go about rendering your PDF, but hopefully your forms dont need them?]

I can get a button up on a completed form in the 'View Sent Form' section ok

Well done! You are well on your way to becoming an ODK Developer. :slight_smile:

1 Like

Haha, I thought an answer like that might be coming :grin:

I had a thought before I left off for the day - I might try and use XSLT to translate the XML file in the local storage to HTML and then work out how to print that.

I might even do it in a separate app to ODK Collect to begin with as there's lots of extra stuff in Collect that is just confusing me at the minute.

Anyway, will see how I get on tomorrow!

Yes, that is certainly an alternative, especially if you dont want to delve into the murky waters of javaRosa.... Translating an XForm definition - suitably populated with its submission data - via a suitable XSLT script is certainly possible (I didnt take that approach simply because I already had ready access to extracted form controls/questions in my code, and it was simple for me to pull out the response value associated with each to display. But I have translated XForm submissions via XSLT to other formats for special purposes, so taking an XSLT approach is also do-able).

You'll still need to understand the structure of an XForm to know how to write your XSLT script to navigate to all the pieces in it you need, so studying up on XForms wont be a wasted effort either way. Good luck!

1 Like

Cool, good to know - will have a deeper look into XForms. Thanks for the pointers!

Ok, so (somehow miraculously) I've managed to get my app to take a hardcoded XML file in res/raw, transform it using XSLT to HTML and get Google's WebView print service to print out the result.

Now the challenge is to work out how to select the appropriate XML file rather than using the hardcoded file.

I was originally thinking I'd get the user to select the XML file manually, but I'm just wondering if there would be a way for the correct file to be selected automatically?

E.g. if I kick off my print process using the 'Print' button within the Form instance screen, is there a way to get the relevant XML file automatically via a URI?

52b75a741bccdac5d6f8d890ed58bad4a7a02204_2_281x500

I guess this is getting a bit technical now. I'll move over to the development forum while I work out the nitty gritty and post back here when I have a result one way or the other!

See Printing a Form from ODK Collect using XSLT

Ok! So managed to have some success with this in the end - quite pleased!

Am now able to print out Form Instances directly from a mobile device to a Wi-Fi printer using the little print button when viewing a 'Sent Form':

Screenshot_20200214-164902 (1)


It's definitely not perfect as it requires that the XSLT file is updated for each Form Template that you want to print out but we don't often create new Form Templates so not a huge issue for us at the moment.

I can share the code if anyone is interested once I've tidied it up a bit! (Ok, I don't think any amount of tidying is going to improve it - it´s over on the dev forum if anyone is interested; Printing a Form from ODK Collect using XSLT - #6 by chewDK)