BookmarkSubscribeRSS Feed

From SAS Visual Analytics to Pixel‑Perfect PDFs with a Local LLM (Part 3): Automating the Process

Started ‎06-30-2026 by
Modified ‎06-30-2026 by
Views 170

In the previous article, we built the full pipeline to extract content from SAS Visual Analytics, optionally enrich it with a local LLM, and generate polished PDFs using ReportLab.

 

At that point, everything was working — but still organized as individual steps. In this post, we take the next logical step: wrapping the entire workflow into a single function: generate_report. Thus automating the process.

 

 

From Script to Function

 

Instead of executing steps one by one manually in main.py, the full workflow is now encapsulated into a reusable function. This makes it possible to execute the same pipeline multiple times with different configurations.

 

This transformation may seem simple, but it introduces two key capabilities:

 

  • Encapsulating the full logic into a reusable unit
  • Enabling parameter-driven report generation

 

 

A Key Enhancement: Working with a Temporary Report

 

One important improvement introduced in generate_report is how it handles parameterized reports.

 

Instead of modifying the original SAS Visual Analytics report, the function:

 

  1. Creates a temporary copy of the original report
  2. Applies parameter changes on the copy
  3. Generates the PDF from that temporary version
  4. Deletes the temporary report once done

 

 

Why create a temporary copy?

 

This design ensures that:

 

  • The original report remains unchanged
  • Multiple executions can run safely with different parameters
  • There is no risk of overwriting user-defined report states

 

 

Step-by-Step Behavior Inside generate_report

 

1. Create a temporary report

The function begins by duplicating the original report:

 
new_report_id = duplicate_report(
    session=session,
    source_report_id=report_config.source_report_id,
    new_report_name=new_report_name,
    result_name_conflict=ResultNameConflict.replace,
)

 

This temporary report acts as a sandbox for modifications.

 

2. Update report parameters

Once the copy is created, its parameters are updated dynamically:

 
update_report_parameters(
    session=session,
    report_id=new_report_id,
    report_name=new_report_name,
    result_name_conflict=ResultNameConflict.replace,
    parameters=[SetParameterValueRequest(name=param["name"], value=param["value"]) for param in report_config.parameters]
)

 

This allows you to:

 

  • Filter data
  • Change selections
  • Adapt report behavior programmatically

 

This is where the pipeline becomes fully dynamic.

 

3. Generate the PDF from the temporary report

All extraction steps (image + data) now target the temporary report. 

 
The rest of the pipeline (table or summary + PDF generation) remains unchanged.

 

4. Delete the temporary report

Once the PDF has been generated:

 
delete_report(
    session=session,
    report_id=new_report_id,
)

 

This ensures:

 

  • No unnecessary content remains in the environment
  • The process is clean and repeatable

 

 

Putting It All Together

 

Here is a simplified version of the orchestration:
 
def generate_report(report_config: ReportConfig) -> None:
    with create_session(...) as session:
        new_report_id = duplicate_report(...)
        update_report_parameters(...)
        image = retrieve_image_from_report_object_uri(...)
        data = retrieve_data_from_report_object_uri(...)
        create_single_page_pdf_report(...)
        delete_report(..., report_id=new_report_id)

 

 

Managing Multiple Reports in main.py

 

With generate_report in place, adding new reports becomes straightforward.

 

Instead of modifying code logic, you simply define configurations:
 
report_list: list[ReportConfig] = [
    ReportConfig(source_report_id="c81f64e1-46fd-48c9-a396-c3c85e27cb6d",
                 visual_element_name="ve26",
                 parameters=[{"name": "Origin Parameter", "value": "Europe"}, {"name": "Type Parameter", "value": "Sedan"}],
                 pdf_report_name="Report Summary for Sedan in Europe"),
    ReportConfig(source_report_id="c81f64e1-46fd-48c9-a396-c3c85e27cb6d",
                 visual_element_name="ve26",
                 parameters=[{"name": "Origin Parameter", "value": "Asia"}, {"name": "Type Parameter", "value": "SUV"}],
                 pdf_report_name="Report Summary for SUV in Asia"),
]
 
Then execute:
 
for report in report_list:
    generate_report(report)

 

 

Why This Matters

 

This evolution brings several key advantages:

 

1. Reusability

The same pipeline can now be applied to any report just by changing configuration.

 

2. Parameter-driven automation

You can generate:

 

  • Regional reports
  • Time-based snapshots
  • Scenario-based analyses

 

…without duplicating code.

 

3. Safe execution

Using temporary reports ensures:

 

  • No impact on original content
  • Clean, repeatable workflows

 

4. Scalability

This pattern is ready for:

 

  • Batch processing
  • Scheduling
  • Integration into CI/CD pipelines or SAS Viya Jobs

 

 

Final Thoughts

 

Wrapping the pipeline into generate_report is more than a refactoring step.

 

It introduces a new way of thinking about reporting:

 

Treat reports as templates, and generate outputs dynamically through parameters.

 

Combined with:

 

  • SAS Visual Analytics APIs
  • Python orchestration
  • Optional AI enrichment

 

…it becomes a powerful foundation for automated and industrialized reporting.

 

The code related to this article is available here.

 

Articles in this series:

 

From SAS Visual Analytics to Pixel‑Perfect PDFs with a Local LLM (Part 1): Meet the Tech Stack

From SAS Visual Analytics to Pixel‑Perfect PDFs with a Local LLM (Part 3): Automating the Process (this article)

 

Find more articles from SAS Global Enablement and Learning here.

Contributors
Version history
Last update:
‎06-30-2026 09:58 AM
Updated by:

Viya Copilot Motion Graphic.gifViya Copilot Motion Graphic

Ready to see what SAS Viya Copilot can do?

Visit the Tips & Tricks page for setup guidance, demos, and practical examples that show how Copilot supports your workflows.

Get Started →

SAS AI and Machine Learning Courses

The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.

Get started

Article Tags