Skip to content

Commit

Permalink
Fix #151
Browse files Browse the repository at this point in the history
  • Loading branch information
chainsawriot committed Dec 28, 2023
1 parent ace1dfe commit b89f2bb
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 7 deletions.
3 changes: 2 additions & 1 deletion DESCRIPTION
Expand Up @@ -29,7 +29,8 @@ Imports:
stringi,
tibble,
vctrs (>= 0.4.2),
zip
zip,
tools
LinkingTo:
cpp11 (>= 0.4.6)
Suggests:
Expand Down
44 changes: 39 additions & 5 deletions R/read_ods.R
Expand Up @@ -83,9 +83,6 @@
strings_as_factors = FALSE,
verbose = FALSE,
as_tibble = TRUE) {
if (missing(path) || !is.character(path)) {
stop("No file path was provided for the 'path' argument. Please provide a path to a file to import.", call. = FALSE)
}
if (!file.exists(path)) {
stop("file does not exist", call. = FALSE)
}
Expand Down Expand Up @@ -246,6 +243,30 @@
return(res)
}

.determine_ods_format <- function(path, guess = FALSE) {
ext <- tolower(tools::file_ext(path))
formats <- c(
ods = "ods",
fods = "fods",
xml = "fods"
)
if (!isTRUE(guess)) {
ext <- unname(formats[ext])
if (is.na(ext)) {
return("ods")
}
return(ext)
}
zip_sig <- as.raw(c(
"0x50", "0x4B", "0x03", "0x04"
))
if (identical(zip_sig, readBin(path, n = 4, what = "raw"))) {
return("ods")
} else {
return("fods")
}
}

#' Read Data From (F)ODS File
#'
#' read_ods is a function to read a single sheet from an (f)ods file and return a data frame. For flat ods files (.fods or .xml),
Expand Down Expand Up @@ -273,6 +294,10 @@
#'
#' Default is `"unique"`.
#'
#' @param ods_format character, must be "auto", "ods" or "fods". The default "auto" is to determine the format automatically. By default, the format is determined by file extension, unless `guess` is `FALSE`.
#' @param guess logical. If the file extension is absent or not recognized, this
#' controls whether we attempt to guess format based on the file signature or
#' "magic number".
#' @return A tibble (\code{tibble}) or data frame (\code{data.frame}) containing a representation of data in the (f)ods file.
#' @author Peter Brohan <peter.brohan+cran@@gmail.com>, Chung-hong Chan <chainsawtiney@@gmail.com>, Gerrit-Jan Schutten <phonixor@@gmail.com>
#' @examples
Expand Down Expand Up @@ -309,7 +334,16 @@ read_ods <- function(path,
strings_as_factors = FALSE,
verbose = FALSE,
as_tibble = TRUE,
.name_repair = "unique") {
.name_repair = "unique",
ods_format = c("auto", "ods", "fods"),
guess = FALSE) {
ods_format <- match.arg(ods_format)
if (missing(path) || !is.character(path)) {
stop("No file path was provided for the 'path' argument. Please provide a path to a file to import.", call. = FALSE)
}
if (ods_format == "auto") {
ods_format <- .determine_ods_format(path, guess = guess)
}
## Should use match.call but there's a weird bug if one of the variable names is 'file'
.read_ods(path = path,
sheet = sheet,
Expand All @@ -324,7 +358,7 @@ read_ods <- function(path,
verbose = verbose,
as_tibble = as_tibble,
.name_repair = .name_repair,
flat = FALSE)
flat = ods_format == "fods")
}

#' @rdname read_ods
Expand Down
10 changes: 9 additions & 1 deletion man/read_ods.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions tests/testthat/test_determine.R
@@ -0,0 +1,10 @@
test_that(".determine_ods_format works", {
expect_equal(.determine_ods_format(readODS::write_ods(iris)), "ods")
expect_equal(.determine_ods_format(readODS::write_fods(iris)), "fods")
expect_equal(.determine_ods_format(readODS::write_ods(iris, tempfile(fileext = ".fods"))), "fods")
expect_equal(.determine_ods_format(readODS::write_ods(iris, tempfile(fileext = ".fods")), guess = TRUE), "ods")
expect_equal(.determine_ods_format(readODS::write_fods(iris, tempfile(fileext = ".xml"))), "fods")
expect_equal(.determine_ods_format(readODS::write_ods(iris, tempfile(fileext = ".fods")), guess = TRUE), "ods")
expect_equal(.determine_ods_format(readODS::write_ods(iris, tempfile(fileext = ".xml"))), "fods")
expect_equal(.determine_ods_format(readODS::write_ods(iris, tempfile(fileext = ".xml")), guess = TRUE), "ods")
})

0 comments on commit b89f2bb

Please sign in to comment.