1.5. SAS PROCEDURES -> Equivalent in R
1.5.10. PROC EXPORT Excel in SAS vs R equivalent
1. Basic Excel Export: One Dataset, One Sheet
| Feature | SAS (PROC EXPORT) |
R (openxlsx) |
|---|---|---|
| Export one dataset | PROC EXPORT DATA=... OUTFILE=... DBMS=XLSX |
write.xlsx(df, "file.xlsx") |
| Sheet name control | SHEET="SUBJECTS" |
sheetName = "SUBJECTS" |
| File overwrite | REPLACE option |
overwrite = TRUE (default in openxlsx) |
SAS Example
proc export data=subjects
outfile="&path./subjects.xlsx"
dbms=xlsx replace;
sheet="SUBJECTS";
run;
Explanation (SAS):
PROC EXPORTcreates Excel files from SAS datasets.data=subjectsspecifies the input dataset.outfile="&path./subjects.xlsx"defines the output file path.dbms=xlsxindicates Excel format output.replaceoverwrites any existing file.sheet="SUBJECTS"names the worksheet.
R Example
# Dummy data and package
library(openxlsx)
subjects <- data.frame(
ID = 1:5,
Name = c("Alice", "Bob", "Carol", "David", "Eve"),
Age = c(23, 31, 27, 29, 35)
)
write.xlsx(subjects, "./output/subjects.xlsx", sheetName = "SUBJECTS")
Explanation (R):
- Uses the
openxlsxpackage for Excel output functionality. write.xlsx()exports a data frame to an Excel file.sheetName = "SUBJECTS"names the worksheet within the Excel file.- By default,
overwrite = TRUEreplaces any existing file with the same name.
2. Exporting Multiple Sheets
| Feature | SAS | R |
|---|---|---|
| Multiple sheets | Multiple PROC EXPORT calls with same file, different sheet= names |
Named list of dataframes |
| Sheet order control | Order of PROC EXPORT calls |
Order of list elements |
SAS Example
proc export data=subjects
outfile="&path./subjects_ca2.xlsx"
dbms=xlsx replace;
sheet="SUBJECTS";
run;
proc export data=base_ca
outfile="&path./subjects_ca2.xlsx"
dbms=xlsx replace;
sheet="BASELINE_CA";
run;
Explanation (SAS):
- Requires multiple
PROC EXPORTstatements to create multiple sheets. - The first call uses
replaceto create a new file. - Subsequent calls add new sheets to the same file.
- Each call specifies a different
sheet=name. - Sheet order is determined by the sequence of
PROC EXPORTcalls.
R Example
# Dummy data and package
library(openxlsx)
subjects <- data.frame(
ID = 1:5,
Name = c("Alice", "Bob", "Carol", "David", "Eve"),
Age = c(23, 31, 27, 29, 35)
)
base_ca <- data.frame(
ID = 1:5,
Baseline = c(100, 110, 120, 130, 140)
)
l2 <- list("SUBJECTS" = subjects, "BASELINE_CA" = base_ca)
write.xlsx(l2, file = "./output/subjects_ca2.xlsx")
Explanation (R):
- Creates a named list containing multiple data frames.
- Each list element becomes a separate worksheet.
- Sheet names are taken from the list names.
- The order of sheets follows the order in the list.
write.xlsx()automatically handles the multi-sheet export.
3. Beyond Basics: Formatting, Styling, and Formulas
| Feature | SAS (ODS EXCEL) |
R (openxlsx) |
|---|---|---|
| Cell formatting | STYLE= in PROC PRINT/REPORT |
addStyle(), createStyle() |
| Conditional formatting | CALL DEFINE in PROC REPORT |
conditionalFormatting() |
| Excel formulas | TAGATTR="formula:..." |
writeFormula() |
| Column widths, freeze panes | ODS EXCEL options |
setColWidths(), freezePane() |
| Merged cells | BREAK/RBREAK in PROC REPORT |
mergeCells() |
SAS Example: Styled Export
ods excel file="styled_subjects.xlsx" style=statistical;
proc print data=subjects style(header)={background=lightblue foreground=white};
run;
ods excel close;
Explanation (SAS):
- Opens an Excel destination with
ods exceland applies the "statistical" style. - Uses
PROC PRINTto output the dataset to Excel. - The
style(header)=option formats just the header row with light blue background and white text. - After outputting data,
ods excel closefinalizes and saves the Excel file.
R Example: Styled Export
# Dummy data and package
library(openxlsx)
subjects <- data.frame(
ID = 1:5,
Name = c("Alice", "Bob", "Carol", "David", "Eve"),
Age = c(23, 31, 27, 29, 35)
)
wb <- createWorkbook()
addWorksheet(wb, "Styled")
writeData(wb, "Styled", subjects)
style <- createStyle(fontColour = "#FFFFFF", fgFill = "#4F81BD", halign = "center")
addStyle(wb, "Styled", style, rows = 1, cols = 1:3, gridExpand = TRUE)
saveWorkbook(wb, "./output/styled_subjects.xlsx", overwrite = TRUE)
Explanation (R):
- Creates a new Excel workbook using
createWorkbook(). - Adds a worksheet named "Styled" with
addWorksheet(). - Writes the data to that worksheet with
writeData(). - Creates a style with white font on blue background and center alignment.
- Applies that style to the first row (headers) across columns 1-3.
- Saves the workbook to disk, overwriting any existing file.
4. Metadata-Driven Export Automation
| Feature | SAS | R |
|---|---|---|
| Config-driven export | Use macro variables + %DO loop |
Use YAML/Excel + purrr::pwalk() |
| Dynamic sheet naming | sheet="&sheetname" in macro loop |
names(list) <- config$sheet_names |
SAS Example
%macro export_loop;
%let n = 2;
%do i = 1 %to &n;
%let ds = %scan(subjects base_ca, &i);
%let sh = %scan(SUBJECTS BASELINE_CA, &i);
proc export data=&ds
outfile="&path./multi_export.xlsx"
dbms=xlsx replace;
sheet="&sh";
run;
%end;
%mend;
%export_loop;
Explanation (SAS):
- Creates a macro called
export_loopto automate the export process. - Sets
n = 2to define how many datasets to export. - Uses a
%doloop to iterate from 1 to n. - For each iteration, extracts the dataset name and sheet name from space-delimited lists.
- Executes
PROC EXPORTwith the selected dataset and sheet name. - The macro approach enables programmatic control of exports.
R Example
# Dummy data and package
library(purrr)
library(openxlsx)
library(readxl)
subjects <- data.frame(
ID = 1:5,
Name = c("Alice", "Bob", "Carol", "David", "Eve"),
Age = c(23, 31, 27, 29, 35)
)
base_ca <- data.frame(
ID = 1:5,
Baseline = c(100, 110, 120, 130, 140)
)
ae_data <- data.frame(
ID = 1:3,
AE = c("Headache", "Nausea", "Fatigue")
)
vitals <- data.frame(
ID = 1:3,
BP = c("120/80", "130/85", "110/70")
)
config <- data.frame(
data = c("subjects", "base_ca", "ae_data", "vitals"),
sheet = c("SUBJECTS", "BASELINE_CA", "ADVERSE", "VITALS"),
file = c("./output/report1.xlsx", "./output/report1.xlsx", "./output/safety.xlsx", "./output/safety.xlsx"),
stringsAsFactors = FALSE
)
write.xlsx(config, "export_config.xlsx")
pwalk(config, function(data, sheet, file) {
write.xlsx(get(data), file = file, sheetName = sheet, append = TRUE)
})
Input Example (export_config.xlsx):
| data | sheet | file | additional_options |
|---|---|---|---|
| subjects | SUBJECTS | ./output/report1.xlsx | row.names = FALSE |
| base_ca | BASELINE_CA | ./output/report1.xlsx | startCol = 2 |
| ae_data | ADVERSE | ./output/safety.xlsx | na.string = "MISSING" |
| vitals | VITALS | ./output/safety.xlsx | colNames = TRUE |
Explanation (R):
- Uses
purrrpackage for functional programming and iteration. - Reads a configuration Excel file that contains dataset names, sheet names, and output file paths.
pwalk()iterates through each row of the config file, applying the function to export each dataset.- Inside the function,
get()retrieves the dataset by name, then writes it to the specified sheet and file. append = TRUEallows adding sheets to existing files without overwriting them.- The configuration approach makes exports maintainable and self-documenting.
5. Real-World Clinical Use Cases
| Scenario | SAS Approach | R Approach |
|---|---|---|
| Exporting listings for review | PROC EXPORT or ODS EXCEL with PROC REPORT |
write.xlsx(listings, "ae_listing.xlsx") |
| Annotated CRF export | ODS EXCEL with STYLE= and TAGATTR= |
openxlsx with merged cells, comments, and styles |
| Exporting validation reports | PROC COMPARE + ODS EXCEL |
pointblank::export_report() or write.xlsx() |
| Exporting SDTM/ADaM metadata | PROC EXPORT from metadata datasets |
write.xlsx(metadata_list, "define_metadata.xlsx") |
Explanation:
- Listings for review: SAS typically uses more complex
PROC REPORTfor formatting, while R uses a simpler one-function call. - Annotated CRF: SAS can export Case Report Forms with annotations using
ODS EXCEL, while R offers more flexible styling options throughopenxlsx. - Validation reports: SAS typically uses
PROC COMPAREresults exported to Excel, while R'spointblankpackage provides specialized validation reports. - Metadata exports: SAS exports from metadata datasets, while R's approach is often more concise using list structures.
6. Lightweight Export Options
SAS Example (CSV alternative)
proc export data=subjects
outfile="&path./subjects.csv"
dbms=csv replace;
run;
Explanation (SAS):
- When Excel formatting isn't crucial, CSV export can be faster and more reliable.
- CSV files can be opened directly in Excel by end users.
- This approach avoids potential Excel engine complexities.
R Example
# Dummy data and package
library(writexl)
subjects <- data.frame(
ID = 1:5,
Name = c("Alice", "Bob", "Carol", "David", "Eve"),
Age = c(23, 31, 27, 29, 35)
)
write_xlsx(subjects, "./output/subjects.xlsx")
Explanation (R):
- The
writexlpackage provides a faster, simpler alternative toopenxlsxwhen formatting isn't needed. write_xlsx()quickly exports a data frame to Excel format.- No styling or advanced features are supported.
- Best used for quick exports, draft outputs, or large datasets where speed is critical.
7. Summary: SAS vs R Excel Export Capabilities
| Capability | SAS (PROC EXPORT, ODS EXCEL) |
R (openxlsx, writexl) |
|---|---|---|
| Basic export | ✓ PROC EXPORT |
✓ write.xlsx() |
| Multi-sheet export | ⚠ Multiple PROC EXPORT calls |
✓ Named list |
| Formatting & styling | ⚠ Limited via STYLE= |
✓ Full control with openxlsx |
| Conditional formatting | ⚠ CALL DEFINE in PROC REPORT |
✓ conditionalFormatting() |
| Excel formulas | ⚠ TAGATTR="formula:..." |
✓ writeFormula() |
| Freeze panes, column widths | ✓ ODS EXCEL options |
✓ freezePane(), setColWidths() |
| Metadata-driven automation | ⚠ Macro loop with hardcoded logic | ✓ pmap() / pwalk() + config sheet |
| Merged cells | ⚠ BREAK/RBREAK only in grouped reports |
✓ mergeCells() |
| Cross-platform compatibility | ⚠ Windows dependency for Excel engine | ✓ Fully cross-platform |
Explanation:
- SAS requires more code for multi-sheet exports and advanced formatting.
- R generally provides more flexible and programmer-friendly Excel export capabilities.
- Both systems handle basic exports well, but R has an advantage for complex styling and metadata-driven approaches.
- SAS can be more challenging in cross-platform environments due to Windows dependencies for the Excel engine.
**Resource download links**
1.5.10.-PROC-EXPORT-Excel-in-SAS-vs-R-equivalent.zip
⁂