Conga Composer is an app for SalesForce that pulls data from records and combines it with a template to create a final document. For a basic report, pulling data directly out of SalesForce and generating it as a PDF, the below items I discuss are probably overkill. To persons working with complex documents with data sourced from numerous related objects and highly-variable layout and formatting, the below information may be of use.
Many of the issues I’m talking about come down to deciding where to handle a requirement. The Microsoft Word merge field “language” is actually fairly capable, if difficult to use (no code completion or easy catching of syntax errors here!). Conga provides a few methods of its own to handle common situations and bits of functionality. And of course, you can make almost anything happen in SalesForce given enough time and Apex code.
Sourcing Data – Reports vs Queries
My main beef with using Reports to populate data from SalesForce to Conga is with Report Types. They are limited in the relationship “direction” they can traverse, and unintuitive (at least to this developer). Maybe I’m just too used to joins in SQL and direct referential relationships between C# objects, but Report Types in SalesForce feel incredibly limiting. However, they do allow you to create a data feed using essentially a point and click interface. Of course reports are not the only option.
In the implementation I’ve been involved with, we did not use SOQL queries to provide data as a very early on design decision, but I’d sure like to revisit that decision now. Besides the report type limitations, reports also offer no way to “sample” the results as is offered with the Conga query builder – “What data would I get back for this record ID?” SOQL definitely isn’t perfect, but if I could pull more information across many objects in a single query, I’d be a lot happier.
Also be aware of URL length limits if you have a complicated Conga document pulling data from many reports. These can be especially easy to hit if you’re using reports to hide data. Speaking of hiding data…
Show / Hide and Differing Data Types
Oftentimes users will ask for a particular section to not be shown when the data is in a particular state.
The core of this situation is when the user wants to treat a single object type differently depending on its state. So if I have a Cat object in SalesForce, I want a report for it to have Full Accounting Data if it has an Age of greater than 3 but only Partial Accounting Data otherwise. Not a different record type, but structurally the display of data will be different based on field values. This leads to a choice on how to show and hide the relevant sections: a TABLEHIDE statement based on a report, a conditional statement using merge fields, or totally separate templates.
Conga provides a
TABLEHIDE merge field that can take out a whole table when a report or SOQL data feed is empty, and this can be brutalized to hide a non-tabular data table or section based on a particular query. You simply add a report to the Conga URL, and set the logic on that report as such that will return no records when whatever condition you’re considering is met. This method works okay for hiding data, but if you want to show an alternative section things are trickier.
In general, I’d avoid this method unless using it for its intended purpose of hiding an empty table.
You can use merge field conditional logic to not show a section given a value. This can make the document’s configuration less immediately obvious as Word’s default behavior is to roll-up these conditional statements into a single label and hide the data that would be shown (ALT-F9 is your friend!). Also, make sure to surround all IF statement component fields in double quotes; Word has trouble with the conga merge fields inside them otherwise.
You might want to kick complex conditions out into a SalesForce formula field. Also, nested if/else statements can become unwieldy if you need more than two choices I might recommend…
You can create a new template and adjust the special Conga URL based on your object’s field values. You can do this with a formula field setup with whatever conditional logic you want, and the result should be a conga template ID. You can then point the TemplateId in the Conga URL string at the
The big downside here is if you’ve got a ton of similar sections between differing templates, changes made to one will have to be manually duplicated across all. I wish Conga would let us modularize the documents – so we can pick and choose say a beginning, middle, and end template at runtime, and have Conga merge the pieces into a single document during generation. It can generate multiple docs at once, but I’m looking for them to be a single PDF when we’re finished.
You can format in SalesForce or in the template. Particularly complex formatting can be handled in SalesForce, although the merge field formatting is actually fairly capable if you’re willing to deal with. Currency formatting, in particular, is fairly easily handled using the merge fields. You also have the “Tattoo or Formula?” choice to make if you decide a field should be formatted in SalesForce (see below).
I come down on the side that says all formatting should be in the Conga document. As long as there is no calculation being done, just text being added or displayed in a certain way, then let Conga do the work as that’s one of the things it’s not half bad at. One exception might be if you want to select a different, large block of text based on a field value. If there are many choices, it may be simpler and cleaner to handle that as a formula field and to avoid the nested if/else in the template. Another exception – if they want to see identically formatted data within the SalesForce user interface.
What about data calculations, sums and totals, averages and differences? I’d put these in SalesForce. Not only are any calculations used in a Conga doc probably going to be desirable to have available in the SalesForce user interface, you get a lot more visibility into the values when you make them formula fields or workflow fields. You can also setup automated tests for calculations (as you should) in SalesForce.
Tattoo or Formula?
If you decide to store a calculation or formatted field on a SalesForce object for Conga consumption, you’ll have an additional consideration: tattoo the object with the data using a trigger or workflow rule, or setup a formula field to hold the data so it’s always up to date. This discussion probably goes outside the focus of this article, but it’s definitely something to keep in mind while developing a Conga template. I tend to error on the side of a formula field – to me it provides more immediate visibility into where the value comes from. If you do setup a tattoo field, I’d recommend writing a quick unit test or two to confirm it’s getting set as expected. Speaking of tests…
There isn’t much to be done in the way of testing, and that’s sad. Even sadder, there is no way that I’ve thought of to automate tests at all. If most calculations and complex formatting are handled within SalesForce, then those items can and should be tested within automated test classes and methods there. This means only the document structure and basic formatting would be handled by Conga, which is probably as it should be. These things would have to be manually verified during a normal development cycle QA and UAT process.
If any of this has been of interest to you, and you’re doing “Advanced” Conga template work, I’d encourage you to sit back and think about using VisualForce instead. A custom page can pull together data from many related sources and present it in a particularly formatted view, just as Conga does. VisualForce pages have the benefit of being available anytime online, and also that they can provide immediate, up-to-the-minute views of the data instead of static point-in-time documents. It may not strictly be easier or simpler, but it’s certainly more testable, standardized, and easier to find help and training for.
Conga-Specific Detail Object
While I find the idea of plastering Conga-specific formatting fields all over a SalesForce object, and idea I’ve pondered from time to time is creating a detail record specifically to hold the “Conga settings” for a given master object. This way you isolate the Conga-specific code, making maintenance easier and also making the delineation of responsibilities more concrete. Personally, just not having Conga fields in the field list is almost reason enough. I haven’t had time to test this idea out in great depth, but it seems like it’d work… in theory.
Not much to add. Conga is a powerful tool with tons of options that need to be considered before using it to creating any documents with significant complexity in order to create a maintainable solution.