--- title: "An Overview of readODS" output: rmarkdown::html_vignette author: - Chung-hong Chan ^[GESIS Leibniz-Institut für Sozialwissenschaften] vignette: > %\VignetteIndexEntry{An Overview of readODS} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(readODS) ``` You probably only need to use two functions from this package: `read_ods` and `write_ods`. Write the data PlantGrowth (from the built-in `datasets` package) as a new file `plant.ods` in the current working directory of the user's session. ```{r write_ods1} write_ods(PlantGrowth, "plant.ods") ``` You can then read it back from `plant.ods` ```{r read_ods1} read_ods("plant.ods") ``` ## Update and Append You can append another sheet into an existing ods file with the sheet name being "mtcars_ods". ```{r write_ods_append} write_ods(mtcars, "plant.ods", sheet = "mtcars_ods", append = TRUE) ``` Read from a specific sheet. Notice row names are missing. ```{r read_ods_mtcars} read_ods("plant.ods", sheet = "mtcars_ods") ``` You can also integer for `sheet`, e.g. 2 for the second sheet. ```{r read_ods_mtcars2} read_ods("plant.ods", sheet = 2) ``` Update an existing sheet and preserve row names ```{r write_ods_update} write_ods(mtcars, "plant.ods", sheet = "mtcars_ods", update = TRUE, row_names = TRUE) ``` Notice the information from the sheet `mtcars_ods` is updated. ```{r read_ods_mtcars3} read_ods("plant.ods", sheet = "mtcars_ods") ``` Read from a specific range ```{r read_ods_mtcars_range} read_ods("plant.ods", sheet = "mtcars_ods", range = "A1:C10") ``` You cannot append to an existing sheet. ```{r append_error, error = TRUE, purl = FALSE} write_ods(iris, "plant.ods", sheet = "mtcars_ods", append = TRUE) ``` You cannot update a missing sheet. ```{r update_error, error = TRUE, purl = FALSE} write_ods(iris, "plant.ods", sheet = "iris", update = TRUE) ``` ## Writing multiple sheets simultaneously It is much faster to write data frames into the same file by putting them in a (named) list. ```{r writelist} write_ods(list("iris" = iris, "plant" = PlantGrowth), "plant_multi.ods") read_ods("plant_multi.ods", sheet = "plant") ``` ## Flat ODS files (`.xml` or `.fods`) Can be read with `read_ods()` [^1] (note that the same function is used to read flat files, no matter the extension). This has the same behaviour and arguments as `read_ods()` ```{r read fods, eval = file.exists("plant.fods")} read_fods("plant.fods") ``` `write_ods()` can be used to write Flat ODS files ```{r write_fods} write_ods(PlantGrowth, "plant.fods") ``` ## Misc. Use the function `list_ods_sheets()` to list out all sheets in an (F)ODS file. ```{r, list_ods_sheets} list_ods_sheets("plant.ods") ``` ## readODS 2.0.0 Starting from 2.0.0, `write_ods` writes `NA` as empty by default. ```{r, empty1} PlantGrowth2 <- tibble::as_tibble(PlantGrowth) PlantGrowth2[1,1] <- NA PlantGrowth2$group <- as.character(PlantGrowth2$group) ## NA is preseved; weight is still read_ods(write_ods(PlantGrowth2)) ``` If you want `NA` to be written literally as the string "NA", use `na_as_string`. You should literally see the string "NA" when the file is opened with LibreOffice, for example. But the string "NA" messes up the automatic type inference of `read_ods`. ```{r, empty2} ## NA is preseved; but weight is now read_ods(write_ods(PlantGrowth2, na_as_string = TRUE)) ``` Of course you can fix this by specifying `col_types`. ```{r, empty3} ## NA is preseved; but weight is now read_ods(write_ods(PlantGrowth2, na_as_string = TRUE), col_types = readr::cols(weight = readr::col_double())) ``` Several functions were removed in readODS 2.0.0. Please consider the API of `readODS` mature and there should not be any breaking change until readODS 3.0.0. ### `ods_sheets` Please use `list_ods_sheets(path = "plant.ods")` instead. ```{r, list_ods_sheets20} ## ods_sheets("plant.ods") list_ods_sheets("plant.ods") ``` ### `get_num_sheets_in_ods` and `getNrOfSheetsInODS` Please use `list_ods_sheets` ```{r, getnum20} ##get_num_sheets_in_ods("plant.ods") length(list_ods_sheets("plant.ods")) ``` ### `read.ods` Please use `read_ods`. In order to emulate the behaviours of `read.ods`, the followings are recommended ```{r, readdotods17} ## read.ods from 1.6 to 1.8 read_ods("plant.ods", col_names = FALSE, skip = 0, na = NULL, col_types = NA, as_tibble = FALSE) ``` ```{r, readotods16} ## read.ods older than 1.6 lapply(list_ods_sheets("plant.ods"), function(x) read_ods(path = "plant.ods", sheet = x, col_names = FALSE, skip = 0, na = NULL, col_types = NA, as_tibble = FALSE)) ``` ```{r, echo = FALSE, message = FALSE} unlink("plant.ods") unlink("plant.fods") unlink("plant_multi.ods") ``` --- [^1]: `read_fods()` and `list_fods_sheets()` are also available. But since version 2.2.0 `read_ods()` and `list_ods_sheets()` can determine whether the file at the `path` argument is flat or not.