Solved

Create multiple PDFs (in a loop) and attach all of them to one email


Userlevel 2
Badge +6

Here’s what I’m trying to do: within a Loop for each action, generate a PDF document - then attach each PDF from the loop to a single email.

I’m creating a workflow for an employee incident report (for example, when an employee slips and falls at work). There are three elements to it: the employee’s own report, their supervisor’s report, and one or more witness reports (depending on how many witnesses there were).

The employee and supervisor reports are no problem since there is only one of each. For the witness report(s), I’m using the Loop for each action for each witness named. Within the loop, a component workflow is called to get the data from each witness (the parent and child workflows run concurrently). The component workflow data is passed back to the parent, and I use that to create a PDF document for each witness. (I’m not creating the PDF in the child workflow because I don’t believe a PDF can be passed back to a parent.)

Once all the reports are generated in PDF, I want to send all of them to our HR department in a single email. I just don’t know how to collect the witness PDFs so that they can all be attached in the email. Ideally, each PDF would be a separate attachment, but it would be okay if they were combined. (I don’t know if that’s even possible.)

I wondered if there was a Collection action that could be involved somehow, like doing an Add item to collection action after each witness PDF is generated, but PDFs are already Collections and I don’t believe you can create a “collection of collections,” as it were.

Any suggestions?

icon

Best answer by WouterT 6 February 2023, 15:59

View original

11 replies

Userlevel 3
Badge +9

Let me try to answer you via an example as I have been in a somewhat similar situation.

I store my generated PDF files in a SharePoint library as intermediate storage (and archive) and in the following example I load them in. I also load two files into a collection (witness reports in your terms). Then I send an email with the individual files as well as the collection of files.

Note that the filename is determined by the name embedded in the PDF and not the variable name.

In detail:

The email I receive contains all files. Both the individual files A and B and also the files C and D from the collection:
 

Hope this helps.

Userlevel 2
Badge +6

Thanks, @WouterT! I’m sure this will be a big help to me … once I can get the process started. I have to confess that I don’t know how to store the generated PDFs into a SharePoint library. I’ve added attachments to a list before, but I guess I’ve never done this. What action are you using to get the generated PDF to your SharePoint library? I’ve tried several and none seem to be what I want.

Userlevel 3
Badge +9

From what I read you already did so very well. Maybe these extra steps explain:

  1. When I generate the document I get the output in a collection of files:
  2. Then I get the first file from the collection:
  3. After which I can store that file wherever I want on SharePoint by using the Store A File action:

    Please don't hesitate to ask more if you want. Happy to help.

Userlevel 2
Badge +6

Thank you for that. I have to confess I’m still a bit confused, though.

Looking at your example, it looks like you know how many files you have for the collection of files (fileC and fileD) and you set your Run parallel paths action accordingly. In my case, I won’t know; there could be none, there could be several.

I also don’t understand, in your follow-up message, why you’re getting the first file from the collection. What about the second, third, etc.?

Userlevel 4
Badge +10

I may be at a loss here jumping into the middle of this, but do you have a need to store the PDF’s in Sharepoint?  If you’re just trying to attach all the files in a single email, I would have thought in your for each loop, after you generate the document you would pull it out of the collection (index 0), then add it to a separate collection that will store all the files to be emailed. 

Userlevel 3
Badge +9

Hi @DavidAD , sorry for the delay in responding to you. Holidays and such…

In my example FileA and FileB represented to Own report and the Supervisors report as in your case.

Indeed you can generate the witness reports in a For Each loop. And even without using SharePoint as @bsikes pointed out correctly. In the loop you do the following:

  1. Generate the PDF . Result of the DocGen action is a collection. But since you request only one PDF from the Document Generation there will be only one item in that output collection from the DocGen action. Therefore….:
  2. ...you can get the first and only item of the collection (item 0) in a file variable.
  3. Then you add this file variable to the collection of attachments e.g. colFiles using the index of the loop as the item index in Add item to collection action. That index nicely counts from 0 up.

After the loop you have all your witness reports stored as items in the colFiles collection. Each collection item being a file variable containing the PDF you generated as a witness report.

My example illustrates how you can then attach both the colFiles collection as well as the separate Own report and Supervisor report as an attachment to the email and the mail action will take each element of the collection and add it as attachment to the email as well.

I am more than happy to share screens at some time. Just contact me via w.terlunen@gmail.com

 

Userlevel 2
Badge +6

Thanks to both of you. I had more or less independently arrived at that approach, but both of you have helped me nail down some specifics.

It’s still not working, though. Part of the problem seems to be that I need each witness to complete their report before the workflow moves on, but I’d like the component workflow to run concurrently with the parent workflow so that each witness can complete their report at more or less the same time (as opposed to one witness having to complete a report before the next one can). However, if I set the component workflow to run concurrently, the parent workflow moves to the next step as soon as the first witness report is completed.

I’m guessing I may need to use a Start a loop action instead of a Loop for each action. But I’m not sure what condition to use for the loop. Keep running the loop until … what?

Userlevel 4
Badge +10

Unfortunately, I think if you have a component workflow run in parallel with the parent workflow, I don’t think the parent workflow will ever get any information directly back from that component workflow.  If you needed to keep it as a component workflow, I think you’d conceptually have 2 options:

  1. Wait for the component workflow to finish and have it pass the generated document back to the parent. This would obviously sacrifice some efficiency as each witness would need to finish their form before moving to the next. You could make things kind of complicated by splitting the witnesses up into multiple collections, then use the “Run Parallel Paths” action to handle each collection, but the component workflow step in each branch would be set to wait for it to finish before moving on. So if you had 4 collections, 4 witnesses and 4 parallel paths, each collection would have one witness in it and they would all process in parallel. If you had 8 witnesses, then each collection would have 2 witnesses, meaning each branch would need to get through 2 witnesses before completing. A bit confusing, but it would be faster than going through each witness 1 at a time. 
  2. Have each component workflow store the generated document somewhere that the parent workflow is expecting. Then in the parent workflow, after all component workflows have been started, it can wait for each generated document to be available before grabbing each one, storing it in a collection, then emailing the collection. 
Userlevel 2
Badge +6

Okay, I’ve scrapped the component workflow piece and am going instead with an Assign a task action. But something is still wrong. In my final email, to which each PDF is supposed to be attached, I’m getting only one witness report - and it seems to be the one from whichever witness was the last one to complete a report.

Following the Assign a task action I am using a Loop for each action, using the task responses as the collection to loop through. Inside this loop, after a couple of steps to get and format the user’s information, I get my file (a Word doc) from SharePoint and then generate the document. I save the generated file like this:

Then, using the Get item from collection action, I use index 0 and store the item like this:

Finally, using the Add item to collection action, I add the file to the collection:

The index variable is that of the loop that all of this is in. The loop ends here and I generate the email to which all files are to be attached. But, as I say, the only witness report attached is the most recent one to be generated.

Can’t figure out where I’m going astray here.

Userlevel 4
Badge +10

Am I reading it right that your doc gen action is storing the generated files into the “Witness report PDF” collection, your then taking a file out of that collection, and then putting it right back into that collection? If so, I’m betting each time you do the DocGen action, it’s overwriting the collection that you just added an item to - resulting in you only receiving the last task completed. Instead, when you’re adding the item to a collection, you need to choose a different collection that’s probably only getting referenced in that action as well as the final email.

 

Also, I think in my testing I’ve figured out that using an Index of 999 for the Add item to collection action will always add the item to the end of the collection. May be easier to use that then Index. 

Userlevel 2
Badge +6

Ahh, yes. You know, @bsikes, I wondered about that and should have tested that scenario before posting again. You’re correct about what I had the doc gen action doing. I guess what I envisioned was that it was taking that collection and adding to it each time. But with a new variable, as both target collection and output, it’s finally working. Thanks to both of you for taking the time to help me with this!

Reply