diff --git a/R/class-workbook-wrappers.R b/R/class-workbook-wrappers.R index 79b256f24..359b97ffb 100644 --- a/R/class-workbook-wrappers.R +++ b/R/class-workbook-wrappers.R @@ -59,6 +59,10 @@ wb_workbook <- function( #' @param wb A `wbWorkbook` object to write to file #' @param path A path to save the workbook to #' @param overwrite If `FALSE`, will not overwrite when `path` exists +#' @param password an optional password to encrypt the input file. The input is +#' encrypted once the output file is written. The password is expected to be +#' plain text. If security is of importance, do not use this argument. If the +#' password is lost, opening the file will be impossible. #' #' @export #' @family workbook wrappers @@ -74,9 +78,9 @@ wb_workbook <- function( #' \donttest{ #' wb_save(wb, path = temp_xlsx(), overwrite = TRUE) #' } -wb_save <- function(wb, path = NULL, overwrite = TRUE) { +wb_save <- function(wb, path = NULL, overwrite = TRUE, password = NULL) { assert_workbook(wb) - wb$clone()$save(path = path, overwrite = overwrite) + wb$clone()$save(path = path, overwrite = overwrite, password = password) } # add data ---------------------------------------------------------------- diff --git a/R/class-workbook.R b/R/class-workbook.R index 5f4edd688..e92cc11ca 100644 --- a/R/class-workbook.R +++ b/R/class-workbook.R @@ -1490,6 +1490,7 @@ wbWorkbook <- R6::R6Class( #' @param sheet sheet #' @param data_only data_only #' @param calc_chain calc_chain + #' @param password password #' @param ... additional arguments #' @return The `wbWorkbook` object invisibly load = function( @@ -1498,6 +1499,7 @@ wbWorkbook <- R6::R6Class( sheet, data_only = FALSE, calc_chain = FALSE, + password = NULL, ... ) { if (missing(file)) file <- substitute() @@ -1521,8 +1523,9 @@ wbWorkbook <- R6::R6Class( #' Save the workbook #' @param path The path to save the workbook to #' @param overwrite If `FALSE`, will not overwrite when `path` exists + #' @param password password #' @return The `wbWorkbook` object invisibly - save = function(path = self$path, overwrite = TRUE) { + save = function(path = self$path, overwrite = TRUE, password = NULL) { assert_class(path, "character") assert_class(overwrite, "logical") @@ -2206,6 +2209,10 @@ wbWorkbook <- R6::R6Class( stop("Failed to save workbook") } + if (!is.null(password)) { + msoc("enc", inFile = path, outFile = path, pass = password) + } + # (re)assign file path (if successful) self$path <- path invisible(self) diff --git a/R/wb_load.R b/R/wb_load.R index 29d9a5309..6c793da35 100644 --- a/R/wb_load.R +++ b/R/wb_load.R @@ -12,6 +12,12 @@ #' chain will be created upon the next time the worksheet is loaded in #' spreadsheet software. Keeping it, might only speed loading time in said #' software. +#' @param password an optional password to decrypt the input file. The input is +#' decrypted into a temporary folder on the hard drive. Afterwards it is loaded +#' into a wbWorkbook object and can be interacted with. Unless it is saved with +#' [wb_save()] argument `password` it remains decrypted. And the password is +#' expected to be plain text. If security is of importance, do not use this +#' argument. #' @param ... additional arguments #' @description wb_load returns a workbook object conserving styles and #' formatting of the original .xlsx file. @@ -33,15 +39,22 @@ #' wb$add_worksheet("A new worksheet") wb_load <- function( file, - xlsx_file = NULL, + xlsx_file = NULL, sheet, - data_only = FALSE, + data_only = FALSE, calc_chain = FALSE, + password = NULL, ... ) { standardize_case_names(...) + if (!is.null(password)) { + temp <- temp_xlsx() + msoc("dec", inFile = file, outFile = temp, pass = password) + file <- temp + } + file <- xlsx_file %||% file file <- getFile(file) diff --git a/man/wbWorkbook.Rd b/man/wbWorkbook.Rd index c2a4a15f2..509b57d3c 100644 --- a/man/wbWorkbook.Rd +++ b/man/wbWorkbook.Rd @@ -914,6 +914,7 @@ load workbook sheet, data_only = FALSE, calc_chain = FALSE, + password = NULL, ... )}\if{html}{\out{}} } @@ -931,6 +932,8 @@ load workbook \item{\code{calc_chain}}{calc_chain} +\item{\code{password}}{password} + \item{\code{...}}{additional arguments} } \if{html}{\out{}} @@ -945,7 +948,7 @@ The \code{wbWorkbook} object invisibly \subsection{Method \code{save()}}{ Save the workbook \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{wbWorkbook$save(path = self$path, overwrite = TRUE)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{wbWorkbook$save(path = self$path, overwrite = TRUE, password = NULL)}\if{html}{\out{
}} } \subsection{Arguments}{ @@ -954,6 +957,8 @@ Save the workbook \item{\code{path}}{The path to save the workbook to} \item{\code{overwrite}}{If \code{FALSE}, will not overwrite when \code{path} exists} + +\item{\code{password}}{password} } \if{html}{\out{}} } diff --git a/man/wb_load.Rd b/man/wb_load.Rd index 4badaebd0..4e2a9cd96 100644 --- a/man/wb_load.Rd +++ b/man/wb_load.Rd @@ -10,6 +10,7 @@ wb_load( sheet, data_only = FALSE, calc_chain = FALSE, + password = NULL, ... ) } @@ -31,6 +32,13 @@ chain will be created upon the next time the worksheet is loaded in spreadsheet software. Keeping it, might only speed loading time in said software.} +\item{password}{an optional password to decrypt the input file. The input is +decrypted into a temporary folder on the hard drive. Afterwards it is loaded +into a wbWorkbook object and can be interacted with. Unless it is saved with +\code{\link[=wb_save]{wb_save()}} argument \code{password} it remains decrypted. And the password is +expected to be plain text. If security is of importance, do not use this +argument.} + \item{...}{additional arguments} } \value{ diff --git a/man/wb_save.Rd b/man/wb_save.Rd index f763029c0..6fe2bc244 100644 --- a/man/wb_save.Rd +++ b/man/wb_save.Rd @@ -4,7 +4,7 @@ \alias{wb_save} \title{Save Workbook to file} \usage{ -wb_save(wb, path = NULL, overwrite = TRUE) +wb_save(wb, path = NULL, overwrite = TRUE, password = NULL) } \arguments{ \item{wb}{A \code{wbWorkbook} object to write to file} @@ -12,6 +12,11 @@ wb_save(wb, path = NULL, overwrite = TRUE) \item{path}{A path to save the workbook to} \item{overwrite}{If \code{FALSE}, will not overwrite when \code{path} exists} + +\item{password}{an optional password to encrypt the input file. The input is +encrypted once the output file is written. The password is expected to be +plain text. If security is of importance, do not use this argument. If the +password is lost, opening the file will be impossible.} } \value{ the \code{wbWorkbook} object, invisibly diff --git a/tests/testthat/test-cryptography.R b/tests/testthat/test-cryptography.R index 0e6b57c70..f6e6cc541 100644 --- a/tests/testthat/test-cryptography.R +++ b/tests/testthat/test-cryptography.R @@ -31,4 +31,14 @@ test_that("test that encryption works", { 0 ) + tmp <- temp_xlsx() + wbin <- wb_workbook()$add_worksheet()$ + add_data(x = head(iris))$save(tmp, password = "openxlsx2") + + wbout <- wb_load(tmp, password = "openxlsx2") + exp <- wb_to_df(wbin) + got <- wb_to_df(wbout) + + expect_equal(exp, got) + })