Skip to content

Instantly share code, notes, and snippets.

@scarnecchia
Last active October 5, 2023 05:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scarnecchia/be1aa85f576cc82ffd7461a5b37fcea9 to your computer and use it in GitHub Desktop.
Save scarnecchia/be1aa85f576cc82ffd7461a5b37fcea9 to your computer and use it in GitHub Desktop.
This script uses an input file `tabvars` to write a SAS program which then reads in CSV files, formats them, and outputs them as sas7bdat datasets
#' Runs a SAS program using the specified SAS executable and program file.
#'
#' @param executable The path to the SAS executable.
#' @param saspath The path to the SAS program file.
#'
#' @return Returns nothing, but prints a message to the console indicating whether the execution was successful or not.
#'
#' @examples
#' run_sas("C:/Program Files/SASHome/SASFoundation/9.4/sas.exe", "C:/my_sas_program.sas")
#'
#' @importFrom xfun normalize_path in_dir msg_cat
#' @importFrom fs path_dir
run_sas <- function(executable, saspath) {
saspath <- xfun::normalize_path(saspath)
executable <- xfun::normalize_path(executable)
log <- fs::path_dir(executable)
xfun::in_dir(saspath, {
return.code <-
shell(paste("sas.exe -SYSIN", executable, "-log", log, "-print", log))
})
if (return.code == 0) {
xfun::msg_cat(paste("Execution of", executable, "successful!"))
} else {
message(paste("SAS Process returned nonzero return code:", return.code))
}
}
#' Extracts SAS errors from a log file and checks for empty output files
#'
#' This function takes in a path to a SAS log file and a path to a directory containing
#' output files generated by the SAS process. It reads the log file, extracts any lines
#' that start with "ERROR", and returns them as a character vector. It also checks each
#' output file in the directory to see if it is empty, and prints a message if it is.
#'
#' @param log A character string specifying the path to the SAS log file
#' @param msoc A character string specifying the path to the directory containing output files
#' @return A character vector containing any lines from the log file that start with "ERROR"
#' @export
sas_errors <- function(log, msoc) {
log <- xfun::normalize_path(log)
msoc <- xfun::normalize_path(msoc)
log <- suppressWarnings(try(readLines(log), silent = TRUE))
errors <- log %>%
stringi::stri_subset_regex('^ERROR.*:')
msoc <- fs::dir_ls(msoc)
for (i in msoc){
print(i)
if(isTRUE(file.size(i) == 0L)){
message('SAS process returned empty file:', i)
}
}
return(errors)
}
# Initialize a vector containing table identifiers ("enr", "dem", "dth")
tablist <- c("enr", "dem", "dth")
# Write the SAS 'libname' statement to the 'create_tables.sas' file
# The path for the 'libname' is obtained using `fs::path_wd()`
readr::write_file(glue::glue('libname msoc "{fs::path_wd("output")}/";\n\n'),
file=fs::path_wd("SAS", "create_tables.sas"), append=FALSE)
# Loop over each table identifier in 'tablist' using purrr::map
purrr::map(tablist, function(tabid) {
# Get the current working directory
path <- fs::path_wd()
# Filter 'tabvars' data frame to keep only rows where 'TabCD' matches the current 'tabid'
.tmp <- dplyr::filter(tabvars, TabCD == toupper({{tabid}}))
# Open a sink to append the SAS code to 'create_tables.sas'
sink(file="SAS/create_tables.sas", append=TRUE)
# Generate and write SAS code for creating a table
cat(paste0("\n", "data msoc.", tabid, ";", "\n"),
paste('infile', paste0('"', xfun::normalize_path(fs::path(path, "output", tabid, ext = "csv")),'"'), 'dlm="," dsd truncover firstobs=2;', "\n"),
paste0("length ", paste0(.tmp$Variable, " ", .tmp$length, collapse = " "), ";\n"),
paste0("informat ", paste0(.tmp$Variable, " ", .tmp$informat, collapse = " "), ";\n"),
paste0("format ", paste0(.tmp$Variable, " ", .tmp$format, collapse = " "), ";\n"),
paste0("input ", paste0(.tmp$Variable, " ", .tmp$input, collapse = " "), ";\n"),
"run;\n\n"
)
# Close the sink
sink()
})
# Run the generated SAS program
# This assumes a specific path for the SAS executable
run_sas(fs::path_wd("SAS", "create_tables.sas"), saspath = "C:/Program Files/SASHome/SASFoundation/9.4")
# Check the SAS log for errors
# This assumes a specific log path and output directory
sas_errors(log="SAS/create_tables.log", msoc = "output")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment