Skip to content

Commit

Permalink
Refactor to ease the development of #56
Browse files Browse the repository at this point in the history
Also reduce cyclomatic complexity
  • Loading branch information
chainsawriot committed Aug 23, 2023
1 parent 7dd35ad commit 3fc7427
Showing 1 changed file with 66 additions and 57 deletions.
123 changes: 66 additions & 57 deletions R/write_ods.R
Expand Up @@ -5,13 +5,17 @@
## .FODS_FOOTER <- paste(readLines("benchmark/fods_footer.xml"), collapse = "\n")
## usethis::use_data(.CONTENT, .FOOTER, .FODS_HEADER, .FODS_FOOTER, internal = TRUE, overwrite = TRUE)

.zip_tmp_to_path <- function(temp_ods_dir, path, overwrite = TRUE) {
.zip_tmp_to_path <- function(temp_ods_dir, path, overwrite = TRUE, flat = FALSE) {
if (flat) {
return(path) ## do nothing
}
wd <- getwd()
on.exit(setwd(wd), add = TRUE)
setwd(temp_ods_dir)
zip::zip(basename(path), include_directories = FALSE, recurse = TRUE, files = dir(), mode = "cherry-pick")
setwd(wd)
file.copy(file.path(temp_ods_dir, basename(path)), path, overwrite = overwrite)
return(path)
}

.find_sheet_node_by_sheet <- function(spreadsheet_node, sheet) {
Expand All @@ -35,12 +39,11 @@
.silent_read_xml(sprintf('<table:table table:name="%s" table:style-name="ta1"><table:table-column table:style-name="co1" table:number-columns-repeated="16384" table:default-cell-style-name="ce1"/></table:table>', sheet))
}

.convert_df_to_sheet <- function(x, sheet = "Sheet1", row_names = FALSE, col_names = FALSE, na_as_string = FALSE, padding = FALSE) {
throwaway_xml_file <- file.path(tempfile(fileext = ".xml"))
write_sheet_(x = x, filename = throwaway_xml_file, sheet = sheet, row_names = row_names, col_names = col_names,
na_as_string = na_as_string, padding = padding,
header = "",
footer = "")
.convert_df_to_sheet <- function(x, sheet = "Sheet1", row_names = FALSE, col_names = FALSE, na_as_string = FALSE, padding = FALSE, xml_file = file.path(tempfile(fileext = ".xml"))) {
write_sheet_(x = x, filename = xml_file, sheet = sheet, row_names = row_names, col_names = col_names,
na_as_string = na_as_string, padding = padding,
header = "",
footer = "")
}

.preprocess_x <- function(x) {
Expand All @@ -67,66 +70,72 @@
return(normalized_path)
}

.update_ods <- function(x, path = tempfile(fileext = ".ods"), sheet = "Sheet1", append = FALSE, update = FALSE, row_names = FALSE, col_names = TRUE, na_as_string = FALSE, padding = FALSE, flat = FALSE, temp_ods_dir = NULL) {
if (!file.exists(path)) {
stop("File does not exist: ", path, call. = FALSE)
}
if (isFALSE(flat)) {
zip::unzip(path, exdir = temp_ods_dir)
contentfile <- file.path(temp_ods_dir, "content.xml")
sheet_exist <- sheet %in% list_ods_sheets(path, include_external_data = TRUE)
} else {
contentfile <- path
sheet_exist <- sheet %in% list_fods_sheets(path, include_external_data = TRUE)
}
if ((sheet_exist && append && !update) || (sheet_exist && !update)) {
## Sheet exists so we cannot append
stop(paste0("Sheet ", sheet, " exists. Set update to TRUE is you want to update this sheet."), call. = FALSE)
}
if (!sheet_exist && update) {
stop(paste0("Sheet ", sheet, " does not exist. Cannot update."), call. = FALSE)
}
content <- xml2::read_xml(contentfile)
spreadsheet_node <- xml2::xml_children(xml2::xml_children(content)[[which(!is.na(xml2::xml_find_first(xml2::xml_children(content),"office:spreadsheet")))]])[[1]]
if (update) {
## clean up the sheet
sheet_node <- .find_sheet_node_by_sheet(spreadsheet_node, sheet)
xml2::xml_remove(xml2::xml_children(sheet_node)[2:length(xml2::xml_children(sheet_node))])
}
if (append) {
## Add a new sheet
sheet_node <- xml2::xml_add_child(spreadsheet_node, .silent_add_sheet_node(sheet))
}
throwaway_xml_file <- .convert_df_to_sheet(x = x, sheet = sheet, row_names = row_names, col_names = col_names,
na_as_string = na_as_string, padding = padding)
xml2::xml_replace(sheet_node, .silent_read_xml(throwaway_xml_file))
## write xml to contentfile
xml2::write_xml(content, contentfile)
}


.write_ods <- function(x, path = tempfile(fileext = ".ods"), sheet = "Sheet1", append = FALSE, update = FALSE, row_names = FALSE, col_names = TRUE, na_as_string = FALSE, padding = FALSE, flat = FALSE) {
temp_ods_dir <- NULL
if (isFALSE(flat)) {
temp_ods_dir <- file.path(tempdir(), stringi::stri_rand_strings(1, 20, pattern = "[A-Za-z0-9]"))
dir.create(temp_ods_dir)
on.exit(unlink(temp_ods_dir))
}
x <- .preprocess_x(x)
if (!file.exists(path) || (!append && !update)) {
path <- .preprocess_path(path)
if (isFALSE(flat)) {
templatedir <- system.file("template", package = "readODS")
file.copy(dir(templatedir, full.names = TRUE), temp_ods_dir, recursive = TRUE, copy.mode = FALSE)
filename <- file.path(temp_ods_dir, "content.xml")
header <- paste0(.CONTENT[1], .CONTENT[2])
footer <- .FOOTER
} else {
filename <- path
header <- .FODS_HEADER
footer <- .FODS_FOOTER
}
write_sheet_(filename = filename, x = x, sheet = sheet, row_names = row_names, col_names = col_names, na_as_string = na_as_string, padding = padding, header = header, footer = footer)
} else {
if (isFALSE(flat)) {
zip::unzip(path, exdir = temp_ods_dir)
contentfile <- file.path(temp_ods_dir, "content.xml")
sheet_exist <- sheet %in% list_ods_sheets(path, include_external_data = TRUE)

} else {
contentfile <- path
sheet_exist <- sheet %in% list_fods_sheets(path, include_external_data = TRUE)
}
if ((sheet_exist && append && !update) || (sheet_exist && !update)) {
## Sheet exists so we cannot append
stop(paste0("Sheet ", sheet, " exists. Set update to TRUE is you want to update this sheet."), call. = FALSE)
}
if (!sheet_exist && update) {
stop(paste0("Sheet ", sheet, " does not exist. Cannot update."), call. = FALSE)
}
content <- xml2::read_xml(contentfile)
spreadsheet_node <- xml2::xml_children(xml2::xml_children(content)[[which(!is.na(xml2::xml_find_first(xml2::xml_children(content),"office:spreadsheet")))]])[[1]]
if (update) {
## clean up the sheet
sheet_node <- .find_sheet_node_by_sheet(spreadsheet_node, sheet)
xml2::xml_remove(xml2::xml_children(sheet_node)[2:length(xml2::xml_children(sheet_node))])
}
if (append) {
## Add a new sheet
sheet_node <- xml2::xml_add_child(spreadsheet_node, .silent_add_sheet_node(sheet))
}
throwaway_xml_file <- .convert_df_to_sheet(x = x, sheet = sheet, row_names = row_names, col_names = col_names,
na_as_string = na_as_string, padding = padding)
xml2::xml_replace(sheet_node, .silent_read_xml(throwaway_xml_file))
## write xml to contentfile
xml2::write_xml(content, contentfile)
if (append || update) {
.update_ods(x = x, path = path, sheet = sheet, append = append, update = update, row_names = row_names,
col_names = col_names, na_as_string = na_as_string, padding = padding, flat = flat,
temp_ods_dir = temp_ods_dir)
return(invisible(.zip_tmp_to_path(temp_ods_dir, path, flat = flat)))
}
path <- .preprocess_path(path)
if (isFALSE(flat)) {
## zip up ODS archive
.zip_tmp_to_path(temp_ods_dir, path)
templatedir <- system.file("template", package = "readODS")
file.copy(dir(templatedir, full.names = TRUE), temp_ods_dir, recursive = TRUE, copy.mode = FALSE)
filename <- file.path(temp_ods_dir, "content.xml")
header <- paste0(.CONTENT[1], .CONTENT[2])
footer <- .FOOTER
} else {
filename <- path
header <- .FODS_HEADER
footer <- .FODS_FOOTER
}
invisible(path)
write_sheet_(filename = filename, x = x, sheet = sheet, row_names = row_names, col_names = col_names, na_as_string = na_as_string, padding = padding, header = header, footer = footer)
return(invisible(.zip_tmp_to_path(temp_ods_dir, path, flat = flat)))
}

#' Write Data to (F)ODS File
Expand Down

0 comments on commit 3fc7427

Please sign in to comment.