Back to Blog

How to Generate a PDF From Any Salesforce Object, Standard or Custom

How to Generate a PDF From Any Salesforce Object, Standard or Custom

Salesforce only ships a native PDF generator for Quotes. Here are the four paths to generating a PDF from a custom object or any other standard object, and what each one costs.

ZeroExport Team

You need a PDF from a Salesforce record: an invoice from an Opportunity, a summary from a Work Order, a statement from a custom object. You go looking for the button, and it isn't there. It isn't there for most objects, and it never has been.

You are not missing something obvious. This exact question keeps resurfacing in the community, including a widely-viewed thread asking, verbatim, how to create a PDF "WITHOUT using ANY code", where the accepted answer is a URL hack around the native Quote PDF feature. Another asks how to generate PDFs from selected standard and custom objects and lands in the same place.

This guide covers what actually works in 2026, what changed with the Spring '26 platform update, and what the honest trade-off is on each path.

The short answer

Salesforce ships exactly one built-in PDF generator, and it only works on Quotes. For every other standard object and every custom object, you are choosing between a set of narrower capabilities, each with a boundary:

PathWorks on any object?Code required?Main cost
Native Quote PDF (plus URL hacks)No, bound to QuoteNoUndocumented behavior, no conditional logic
Visualforce renderAs="pdf"YesYesA page per document, CSS 2.1 engine limits
Apex Blob.toPdf() (Spring '26)YesYesSame rendering engine, HTML built in code
Omnistudio Document GenerationBroadlyMostly noExtra licenses, Word/PowerPoint templates
Third-party AppExchange docgenYesUsually noVaries by tool and pricing model

The practical question is not "does a native option exist," but "which boundary am I willing to live with." Below is what each one costs in practice.

Why there is no native "generate PDF" button

Two structural facts explain the gap.

The one PDF generator Salesforce ships is tied to a single object. The Quote PDF button renders a Quote using a Quote Template. It is a feature of the quoting model, not a document service the platform exposes to other objects. Nothing equivalent exists on Account, Work Order, or Statement__c.

Report and list-view exports produce a PDF, but not your PDF. They give you data on a page. They do not give you a branded layout, control over which fields appear, nested tables, or a section that disappears when it is empty. The moment the output has to look like a real business document, you are past what they can do.

So teams reach for one of four workarounds.

Option 1: The Quote PDF URL hack

The community trick is to enable Quotes, build the layout as a Quote Template, then reverse-engineer the URL that renders the PDF and point it at other data to produce invoice-style documents.

It works, briefly. Then it doesn't:

  • It is bound to the Quote object. The moment you need a PDF from a custom object, a Work Order, or a Statement, the trick collapses.
  • Quote Templates have no real conditional logic. You cannot cleanly hide a section when a field is empty, or group line items by category. This is the same wall teams hit when they try to conditionally hide line items in a Quote PDF.
  • URL hacks are undocumented behavior. They can break on a release, and nobody on your team will understand why six months from now.

It is a demo, not a foundation.

Option 2: Visualforce renderAs="pdf", and what Spring '26 changed

This has long been the "real" native answer for any object, and it is worth knowing where it stands now because the platform moved.

What changed: in Spring '26, Salesforce updated the Apex Blob.toPdf() method to use the Visualforce PDF rendering service instead of the older legacy engine, a release update scheduled for enforcement in Summer '26. In practice this means you can now generate a PDF from an HTML string in Apex, on any object, without maintaining a Visualforce page at all, and with materially better font and multibyte character support (CJK, Thai, Arabic).

That is a genuine improvement, and it is worth knowing about. But be clear on what it does and does not solve:

  • It removes the Visualforce page, not the rendering engine. Both paths now run through the same service, which renders CSS 2.1. No flexbox, no grid, no modern layout. Unsupported properties are silently ignored rather than erroring, which is why Visualforce PDF CSS so often "doesn't work".
  • It moves the work into Apex. You are now building HTML strings in code, escaping dynamic content by hand, and inserting page breaks manually for long tables. An admin cannot adjust the layout.
  • You still own it forever. Every document is Apex or a Visualforce page that you write, test, deploy, and maintain, for a feature that is not your product.
  • The familiar constraints remain: external stylesheets are ignored in favor of inline styles, JavaScript is not executed, and images and fonts must come from static resources with absolute URLs.

Cheap to write, expensive to keep alive. That has not changed.

Option 3: Salesforce's own document generation product

Salesforce does sell document generation: Omnistudio Document Generation, used across Industries clouds and Revenue Cloud, which generates documents from Microsoft Word (.docx) and PowerPoint (.pptx) templates.

Two things to weigh before assuming this is the native answer:

  • It is licensed separately. It requires Omnistudio licenses plus DocGen licenses (Designer, User, Runtime), or the metered DocGenPlus add-on for standalone Sales, Service, and Field Service orgs. It is not something already sitting in a typical Sales Cloud org.
  • It is a Word-template model. Which means it inherits the trade-offs of option 4 below, along with the Data Mapper and Omniscript layer you now configure and maintain.

If you are already deep in Omnistudio, this is a reasonable fit. If you are not, adopting Omnistudio to produce a PDF is a large amount of platform surface for the job.

Option 4: A Word template plus a merge tool

The most common commercial route is to maintain a .docx full of merge fields or content controls and let a tool (Conga, S-Docs, Nintex DocGen, PDF Butler, or a native merge) fill it in. It works on any object and it keeps you out of Apex, but it trades one maintenance problem for another:

Word templates are fine for a simple letter. For a document with real structure (totals, conditional sections, repeating groups), they become their own maintenance burden.

What generating from any object should actually mean

Before reaching for any tool, it is worth being precise about the bar. An approach that stays maintainable across objects should let you:

  1. Point at any object, standard or custom, not just Quotes.
  2. Design the layout visually, without writing Visualforce or Apex.
  3. Show or hide sections conditionally, so the discount block disappears when there is no discount.
  4. Handle repeating and nested data: line items, child records, subtotals that scope correctly.
  5. Render consistently, so a template edit does not silently shift the rest of your layout.
  6. Tell you what is wrong before you send it, rather than after a customer opens the file.

Points 3 through 6 are exactly where the native options fall down. That is the gap third-party tools exist to fill.

Generating from any object: a structural approach

Here is the shape of the solution that holds up, using a native document generation layer instead of a page or a template file per object. This is where ZeroExport fits, though the structure of the approach applies to any tool built around document structure rather than field placement.

Step 1: Point at the object and its related data. Choose the object you are generating from (Opportunity, Work Order, a custom Statement__c, anything queryable and accessible to the running user) and the related records you need. No Quotes enablement, no URL hack, and no pre-flattening your data into helper fields so a flat template can read it. Child data can be nested up to four levels below the primary object.

Step 2: Design the template visually. Lay the document out in a WYSIWYG builder inside Salesforce: headers, tables, totals, the way a business user expects. An admin can move a section or fix wording later without a deployment.

Step 3: Add logic declaratively. Put a condition on a section and it cascades to everything inside it, header included, so you never get an orphaned heading above an empty table. Repeating regions are detected from the structure rather than hand-marked, and aggregates (sum, count, min, max, avg) re-scope inside a repeat, so a subtotal placed under a parent totals only that parent's own rows. When a value is missing, the layout adapts instead of printing a raw token or leaving a hole.

One boundary worth stating plainly rather than discovering later: subtotals scoped to a parent record work today, because the grouping follows the relationship. Partitioning one flat list by a field value (recurring versus one-time charges, say) with a subtotal per group is on the roadmap, not shipped. If that specific layout is a hard requirement, plan around it.

Step 4: Check readiness before anyone generates. Mark which fields the template actually requires, and every record shows a live readiness gauge on the record page before anyone clicks generate: a score, and the specific fields that are missing or inaccessible under field-level security. This is the difference between finding a blank section now and finding it the way your customer does. We wrote about why this matters in document readiness.

Step 5: Generate from a button, a Flow, or Agentforce. Once the template is active, generation is a click or an automated step from any record of that object. A packaged invocable action, "Generate ZeroExport PDF," takes a record ID and a template ID, so Flow and Agentforce can call it directly. Complex documents route to an asynchronous job and return a status with a job ID rather than an immediate file link, so build your automation to handle both.

Being straight about the limits, because a plan built on a wrong assumption is worse than no plan: reusable blocks, meaning one structural section defined once and propagated across many templates, are on the roadmap rather than shipped, so today the model is one template per document family with conditional sections inside it. On raw rendering performance at high volume and pixel-exact page-break control, we publish no claims. Those are platform-level concerns worth testing against your own requirements for any candidate, including this one.

When the native path is still the right call

To be fair to the native options: if you need one simple PDF, from the Quote object, that rarely changes, the built-in Quote PDF is fine. Do not add a tool for that. If you have a developer, a single document, and no appetite for another vendor, Blob.toPdf() is now a reasonable path too.

The case for a structural approach starts when you have:

  • Multiple document types across multiple objects,
  • Templates that change often, or non-developers who need to change them,
  • Conditional sections, grouping, or nested child data,
  • Or a growing pile of Visualforce PDF pages you are tired of maintaining.

That is the point where picking a document path stops being a shortcut and starts being an architecture decision.

FAQ

How do I generate a PDF from a custom object in Salesforce?

The native paths are a Visualforce page with renderAs="pdf" or, since Spring '26, Apex Blob.toPdf(), both of which require Apex or Visualforce. Declaratively, you need a document generation package that lets you select any queryable object as the template's data source and design the layout in a builder, since nothing built into the platform generates a PDF from a custom object.

Can Salesforce generate a PDF from any object natively?

Only from Quotes. The Quote PDF button is the single built-in generator and it is bound to the Quote object. Report and list-view exports produce a PDF from other objects but not a branded, structured document. Anything else means Visualforce, Apex, an AppExchange tool, or Salesforce's separately licensed Omnistudio Document Generation.

What changed with Blob.toPdf() in Spring '26?

Salesforce updated Blob.toPdf() to use the Visualforce PDF rendering service rather than the older legacy engine, a release update scheduled for enforcement in Summer '26. It gives consistent rendering, broader font support, and reliable multibyte characters for CJK, Thai, and Arabic, and it lets you produce a PDF from Apex without a Visualforce page. It is still a code-based approach and still inherits the rendering service's CSS 2.1 constraints.

Why doesn't my CSS work in a Salesforce PDF?

Because the PDF rendering service supports CSS 2.1, not modern CSS. Flexbox, grid, and most CSS3 layout features are silently ignored rather than raising an error, so the page looks correct in a browser and wrong in the file. External stylesheets are also ignored in favor of inline styles, and JavaScript is not executed.

Is the Quote PDF URL hack safe to use in production?

It is undocumented behavior, so treat it as fragile. It is bound to the Quote object, offers no real conditional logic, and can break on a platform release with nobody on the team knowing why. It is workable for a one-off demo and a poor foundation for a document your business depends on.

Does Salesforce have its own document generation product?

Yes. Omnistudio Document Generation, used across Industries clouds and Revenue Cloud, generates documents from Word and PowerPoint templates. It requires Omnistudio licenses plus DocGen licenses, or the metered DocGenPlus add-on, so it is not available by default in a standard Sales Cloud org, and being template-file based it carries the usual Word-merge trade-offs.

Can I generate a Salesforce PDF from a Flow?

Yes, if your document tool exposes an invocable action. ZeroExport packages one called "Generate ZeroExport PDF" that accepts a record ID and a template ID, so Flow, Apex, and Agentforce can trigger generation. Complex documents run asynchronously and return a job ID rather than an immediate file link, so design the Flow to handle a queued result.

Related Reading

Ready to try ZeroExport?

Start generating documents directly in your Salesforce org. No integrations, no setup overhead, no complexity.