In this example, we will create the same listing, but in a slightly different way. This time we’ll add some more complexity.

Generate a Listing

To generate the listing, we will still need just two files:

  • A macro driver script
  • A template listing program

Macro Driver Script

Here is the macro driver script. What is different is that the macro driver is written in standard R code:

#***********************************#
#* Define Macro Variables
#***********************************#
sponsor_name. <- "Acme"
study_name. <- "ABC"
prog_name. <- "l_dm"
base_dir. <- "./examples"
output_dir. <- file.path(base_dir., "output")
data_dir. <- file.path(base_dir., "data")
data_file. <- "dm.rda"
data_name. <- "dm"
titles. <- c("Listing 1.0", "SDTM Demographics")
footnotes. <- paste0("'Program: ", prog_name., ".R'")
output_type. <- "PDF"
preview. <- TRUE

#***********************************#
#* Macro Source Listing Template Code
#***********************************#
msource(file.path(base_dir., "templates/lst02.R"),
        file.path(base_dir., "code/l_dm.R"), 
        debug = TRUE)

Note the following in the above driver:

  • Macro variables can be set in regular R code. One stipulation is that they must be set before msource() is called. Also, the variable names must have a trailing dot (“.”).
  • All text variable values are quoted to conform to standard R syntax.
  • The macro variables are still regular R variables, and you can use them in other functions like paste() or file.path().
  • The above approach allows you to execute msource() directly from the driver script. This approach avoids having to run it on the command line. Instead, you can run it from the “Source” or “Run” button in your development environment.
  • The above call to msource() includes the debug = TRUE parameter. This option will generate debug information in the console. The debug information will be shown below.

Otherwise, the macro driver performs the exact same tasks as the previous listing example. It sets the macro variable values and executes the template program.

Template Listing Program

Here is the template program for the second listing. This template listing has a few more macro statements than the previous one:

#####################################################################
# Program Name: prog_name.
# Study: study_name.
#####################################################################

library(reporter)

# Output path
out_pth <- "output_dir./prog_name."

# Get listing data
load("data_dir./data_file.")

# Create table object
tbl <- create_table(data_name.) |>
  define(USUBJID, id_var = TRUE)

#% Assign default output type
#%if (%symexist(output_type) == FALSE)
#%let output_type <- RTF
#%end

# Create report object
rpt <- create_report(out_pth, font = "Courier", output_type = "output_type.") |>
  page_header("Sponsor: sponsor_name.", "Study: study_name.") |>
  titles(titles.) |>
  add_content(tbl, align = "left") |>
  footnotes(footnotes.) |>
  page_footer(Sys.time(), "CONFIDENTIAL", "Page [pg] of [tpg]")

# Write report to file
#%if (preview. == TRUE)
write_report(rpt, preview = 1)
#%else
write_report(rpt)
#%end

One piece of logic added to this template is to set the output_type. macro variable to “RTF” if it does not exist. This example demonstrates the use of the %symexist() function.

Another piece of macro logic added is to optionally preview the report. If preview. is set to TRUE, the macro will append a parameter to write_report() to only print the first page of the report. This option can reduce the amount of time the program runs while you are developing.

How To Run

Since the call to msource() is included directly in the macro driver script, you can source the script normally in RStudio or another editor. When executed, the script will write the following to the console:

> source("./examples/Example2.R")
******************************************************************************** 
**  Pre-Processing
******************************************************************************** 
-    File In:  ./examples/templates/lst02.R 
-   File Out:  ./examples/code/l_dm.R 
******************************************************************************** 
[ In#][Out#]:
[   1][   1]: #####################################################################
[   2][   2]: # Program Name: l_dm
[   3][   3]: # Study: ABC
[   4][   4]: #####################################################################
[   5][   5]: 
[   6][   6]: library(reporter)
[   7][   7]: 
[   8][   8]: # Output path
[   9][   9]: out_pth <- "./examples/output/l_dm"
[  10][  10]: 
[  11][  11]: # Get listing data
[  12][  12]: load("./examples/data/dm.rda")
[  13][  13]: 
[  14][  14]: # Create table object
[  15][  15]: tbl <- create_table(dm) |>
[  16][  16]:   define(USUBJID, id_var = TRUE)
[  17][    ]: 
[  18][    ]: #% Assign default output type
[  19][    ]: #%if (TRUE == FALSE)
[  20][    ]: #%let output_type <- RTF
[  21][    ]: #%end
[  22][  17]: 
[  23][  18]: # Create report object
[  24][  19]: rpt <- create_report(out_pth, font = "Courier", output_type = "PDF") |>
[  25][  20]:   page_header("Sponsor: Acme", "Study: ABC") |>
[  26][  21]:   titles(c('Listing 1.0', 'SDTM Demographics')) |>
[  27][  22]:   add_content(tbl, align = "left") |>
[  28][  23]:   footnotes('Program: l_dm.R') |>
[  29][  24]:   page_footer(Sys.time(), "CONFIDENTIAL", "Page [pg] of [tpg]")
[  30][  25]: 
[  31][  26]: # Write report to file
[  32][    ]: #%if (preview. == TRUE)
[  33][  27]: write_report(rpt, preview = 1)
[  34][    ]: #%else
[  35][    ]: write_report(rpt)
[  36][    ]: #%end
******************************************************************************** 
**  Execution
******************************************************************************** 

> #####################################################################
> # Program Name: l_dm
> # Study: ABC
> ###################################### .... [TRUNCATED] 

> # Output path
> out_pth <- "./examples/output/l_dm"

> # Get listing data
> load("./examples/data/dm.rda")

> # Create table object
> tbl <- create_table(dm) |>
+   define(USUBJID, id_var = TRUE)

> # Create report object
> rpt <- create_report(out_pth, font = "Courier", output_type = "PDF") |>
+   page_header("Sponsor: Acme", "Study: ABC") |>
+ .... [TRUNCATED] 

> # Write report to file
> write_report(rpt, preview = 1)
# A report specification: 1 pages  PREVIEW
- file_path: './examples/output/l_dm.pdf'
- output_type: PDF
- units: inches
- orientation: landscape
- margins: top 0.5 bottom 0.5 left 1 right 1
- line size/count: 9/47
- page_header: left=Sponsor: Acme right=Study: ABC
- title 1: 'Listing 1.0'
- title 2: 'SDTM Demographics'
- footnote 1: 'Program: l_dm.R'
- page_footer: left=2025-09-29 15:43:51.038448 center=CONFIDENTIAL right=Page [pg] of [tpg]
- content: 
# A table specification:
- data: tibble 'dm' 87 rows 24 cols
- show_cols: all
- use_attributes: all
- define: USUBJID id_var='TRUE' 

******************************************************************************** 
**  End
******************************************************************************** 

The debug information contains a pre-processor section and a section for execution of the generated code. These two sections can help you isolate problems with your program.

For more information on debugging, see the debugging vignette.

Generated Code

Upon execution, the generated code file will look like this:

#####################################################################
# Program Name: l_dm
# Study: ABC
#####################################################################

library(reporter)

# Output path
out_pth <- "./examples/output/l_dm"

# Get listing data
load("./examples/data/dm.rda")

# Create table object
tbl <- create_table(dm) |> 
  define(USUBJID, id_var = TRUE)

# Create report object
rpt <- create_report(out_pth, font = "Courier", output_type = "PDF") |> 
  page_header("Sponsor: Acme", "Study: ABC") |> 
  titles(c("Listing 1.0", "SDTM Demographics")) |> 
  add_content(tbl, align = "left") |> 
  footnotes(c("Program: l_dm.R")) |> 
  page_footer(Sys.time(), "CONFIDENTIAL", "Page [pg] of [tpg]")

# Write report to file
write_report(rpt, preview = 1)
  

The listing code above is identical to the previous listing, except the output type is “PDF” and the preview parameter is set on the call to write_report().

Output Report

Here is the output report for the modified listing:

Next: Example 3: Table