# Moving from SAS, SSRS or Crystal

> Migrate reporting from SAS, SSRS, Crystal or SQL with dre-port: dependency assessment, database SQL, business-rule validation and optional output parity.

Most teams that adopt DRE already have reports somewhere else: SQL Server Reporting Services (SSRS), SAS programs, Power BI paginated reports, Crystal Reports, or a SQL script and a spreadsheet someone fills in by hand. The [`dre-port` agent skill](https://github.com/get-dre/dre/blob/57ea0a09f187a936c1c6a5d89ae128aec7bdaf29/skills/README.md) moves them over with you, one report at a time. It checks the report specification and, when an old output is available, compares keyed records and totals for matching inputs, parameters and dates. Guided SAS support is included in skills 5.1; SAS execution is not required.

DRE has no converter command. Your coding agent reads the old report, translates it with the skill’s mapping reference, asks you about anything the files don’t say, and writes ordinary DRE files you can read and change.

## What it reads

You have

What the agent reads

SAS `.sas` source and referenced files

programs, includes, macro definitions, inputs, parameters and formats; missing dependencies and unsupported constructs remain explicit blockers

a report specification without source or old output

business rules and supplied schemas; results are business-rule validation, not verified SAS equivalence

SSRS, Power BI paginated or Report Builder `.rdl` / `.rdlc` files

datasets (query text or stored procedure), parameters, groups, expressions, page header and footer

SSRS subscriptions

a csv you export from the report server’s catalog database (the skill has the read-only query)

Crystal Reports

an XML export of the report definition, or a “Report Definition” text export. Not a binary `.rpt`: Crystal’s file format needs SAP’s SDK, so export it first

anything else (Jasper, BI Publisher, Access, an Excel macro)

the SQL, a screenshot or PDF of the output, its parameters, and who gets it when; the agent asks for the rest

## Where your data lives

DRE reads DuckDB, Postgres, Databricks, Snowflake, BigQuery and ClickHouse. Its optional [JDBC source](https://getdre.com/docs/plugin-jdbc/) also connects Oracle and SQL Server with a user-supplied vendor JAR and operator-maintained Java 17+. Preparation runs inside the source database. The agent uses authorized live catalog metadata or supplied schema definitions, and marks unknown names, types and relationships as unresolved. It explains generated statements and obtains review before executing data-changing SQL, including temporary preparation.

## SAS scope and worked example

The bounded reporting path covers PROC SQL selection/joins/aggregation, simple row-local filters and derived columns, scalar parameters, deterministic sorting/deduplication, basic summaries and tabular output. The agent reviews missing values, dates, ordering, merge cardinality and rounding explicitly. Stateful DATA steps, complex macro execution, local SAS datasets and specialist procedures need supplied business rules or remain unsupported; DRE is not a SAS interpreter or a replacement for the full SAS suite.

The [synthetic overdue-loan project](https://github.com/get-dre/dre/blob/57ea0a09f187a936c1c6a5d89ae128aec7bdaf29/examples/overdue-loans/README.md) shows an unexecuted SAS reference beside runnable Oracle and SQL Server variants, independent expected results and both ordinary and template-designed workbooks. Its checks establish DRE business-rule results, not executed SAS parity. Use it without a SAS installation or company data. Layout changes and unsupported logic are part of the migration assessment, not silently accepted equivalence.

## How a report maps

Old report

DRE

a dataset’s query

a `.sql` file in the report folder

a stored procedure

its logic as SQL (temp tables in a setup file)

parameters, with defaults and available values

[variables](https://getdre.com/docs/templates/) with `var_schema`; “last month” defaults come from `run.date`

a table or list

an xlsx tab, or a table in a [PDF template](https://getdre.com/docs/plugin-document/)

groups with subtotals

`ROLLUP` in SQL, or a PDF template with a heading and subtotal per group

expressions and formulas (`IIf`, `Format`, Crystal `{@formulas}`)

SQL columns, and column formats in the output

page header, footer, “Page N of M”

the PDF template’s `@page` rules

“no rows” message

[`on_empty`](https://getdre.com/docs/building-reports/#when-theres-no-data)

email and file share subscriptions, schedules

destinations and `schedules.yml`

data-driven subscriptions, bursting per customer

[per-row outputs](https://getdre.com/docs/per-row-outputs/) (`for_each`)

one copy of a report per region or client

one report with [Sets](https://getdre.com/docs/building-reports/)

interactive sort, drill-through, toggles, charts

no direct equivalent: DRE makes files. The agent asks what to do instead

## Validation and optional parity

When an old output is available, export the old report for one set of parameter values (the last complete month, say) as csv or xlsx. The agent runs the DRE report with the same values, writing its rows with `dre run <report> --no-deliver --output-json parity`, and compares the two with a small script bundled with the skill. It reports:

-   **row counts** on each side;
-   **column totals** for every numeric column;
-   a **cell diff** keyed on the columns that identify a row, each difference explained as a real _value_ difference, _rounding_ (within a tolerance), _formatting_ (the same date or number written another way) or _order_;
-   rows only on one side, and duplicate keys.

With no reference output, the agent instead checks explicit expected keyed records, boundary dates, classifications, counts, totals and rounding from the business specification. It reports expected versus actual values and labels SAS equivalence unverified. Missing dependencies and unresolved semantics keep a migration partial, even if its DRE configuration validates.

Real differences are fixed (or one of the two reports is shown to be wrong) and the check runs again, until it matches. For a PDF or a styled workbook you also compare the old and new files side by side.

## A whole estate

Pointed at a folder of `.rdl` files and Crystal exports, the skill first lists every report: its sources, parameters, subscriptions and an effort estimate (S to XL, with the reasons, such as stored procedures, custom code or charts). It groups near-duplicates (a copy per region) as candidates for one report with Sets, and suggests an order, simplest first. Then reports are ported one at a time. SAS estates include a source/dependency inventory by reading the programs; the bundled XML inventory script does not parse SAS.

## Practices

The skill follows the porting rules in [DRE practices](https://getdre.com/docs/practices/#porting-reports-from-other-tools): logic in SQL, not templates (PORT-1); explicit validation evidence before switching over (PORT-2); one report at a time, simplest first (PORT-3); first deliveries held or on dev (PORT-4); a record of where each report came from (PORT-5); and dependency/semantic review before a complete-port claim (PORT-6).

## Try it

Install the [agent skills](https://github.com/get-dre/dre/blob/57ea0a09f187a936c1c6a5d89ae128aec7bdaf29/skills/README.md), then ask your agent something like “port this SSRS report to DRE” with the `.rdl` file in your project, or “list the reports in ./ssrs-export and suggest where to start”.

New to DRE? [What reports as code means](https://getdre.com/reports-as-code/) · [DRE and dbt](https://getdre.com/dbt/) · [How DRE compares](https://getdre.com/compare/)

[Edit page](https://github.com/get-dre/dre/edit/master/docs/moving-from-ssrs-or-crystal.md)

[Previous  
Tested examples](https://getdre.com/docs/examples/)[Next  
Connections and targets](https://getdre.com/docs/connections/)
