Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide wb_dims() #691

Merged
merged 4 commits into from
Jul 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export(wb_color)
export(wb_colour)
export(wb_copy_cells)
export(wb_data)
export(wb_dims)
export(wb_freeze_pane)
export(wb_get_active_sheet)
export(wb_get_base_font)
Expand Down
9 changes: 8 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@

* remove deprecated arguments
* `xy` argument
* arguments `col`, `row`, `cols`, `rows`. `start_col`, `start_row` and `gridExpand` were deprecated in favor of `dims`. Numeric vectors can be converted to `dims` using `rowcol_to_dims()`
* arguments `col`, `row`, `cols`, `rows`. `start_col`, `start_row` and `gridExpand` were deprecated in favor of `dims`. Row and column vectors can be converted to `dims` using `wb_dims()`.

* deprecating function
* `convertToExcelDate()` for `convert_to_excel_date()`

* make `get_cell_refs()`, `get_date_origin()`, `guess_col_type()`, and `write_file()` internal functions
* make classes `styles_mgr()`, `wbSheetData`, `wbWorksheet`, `wbChartsheet`, `wbComment`, `wbHyperlink` internal

## New features

* `wb_dims()` was added as a more convenient replacement for `rowcol_to_dims()`. The new function can take either numeric (for rows or columns) or character (column) vectors, in addition it is able to create dimensions for R objects that are coerceable to data frame. This allows the following variants:
* `wb_dims(1:5, letters)`
* `wb_dims(1:5, 1:26)`
* `wb_dims(matrix(1, 5, 26))` with an added row for column names

## Refactoring

* Cleanup / revisit documentation and vignettes ([682](https://github.com/JanMarvin/openxlsx2/pull/682), @olivroy)
Expand Down
79 changes: 79 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,85 @@ rowcol_to_dim <- function(row, col) {
# we will always return something like "A1"
stringi::stri_join(min_col, min_row)
}

#' @rdname dims_helper
#' @param ... construct dims arguments, from rows/cols vectors or objects that can be coerced to data frame
#' @examples
#' # either vectors
#' wb_dims(rows = 1:10, cols = 1:10)
#' # or objects
#' wb_dims(mtcars)
#' @export
wb_dims <- function(...) {

args <- list(...)
nams <- names(args)

col_names <- args$col_names
row_names <- args$row_names

cnam_null <- is.null(col_names)
rnam_null <- is.null(row_names)

srow <- args$start_row
scol <- args$start_col

scol_null <- is.null(scol)
srow_null <- is.null(srow)

if (srow_null) srow <- 0 else srow <- srow - 1L
if (scol_null) scol <- 0 else scol <- col2int(scol) - 1L

x <- args[[1]]
exp_name <- inherits(x, "data.frame") || inherits(x, "matrix")

# wb_dims(rows, cols)
if (length(args) >= 2 && !exp_name) {
rows <- 1L
cols <- 2L

# wb_dims(rows = rows, cols = cols)
sel <- pmatch(nams, c("rows", "cols"))
valid <- length(sel[!is.na(sel)])
if (valid == 2) {
rows <- sel[rows]
cols <- sel[cols]
} else if (valid == 1) {
stop("found only one cols/rows argument")
}

rows <- args[[rows]]
cols <- col2int(args[[cols]])

} else {

if (cnam_null) col_names <- exp_name
if (rnam_null) row_names <- FALSE

assert_class(col_names, "logical")
assert_class(row_names, "logical")

# wb_dims(data.frame())
x <- as.data.frame(x)
rows <- seq_len(nrow(x) + col_names)
cols <- seq_len(ncol(x) + row_names)

}

rows <- rows + srow
cols <- cols + scol

if (length(rows) == 1 && length(cols) == 1) {
# A1
dims <- rowcol_to_dim(rows, cols)
} else {
# A1:B2
dims <- rowcol_to_dims(rows, cols)
}

dims
}

# Relationship helpers --------------------
#' removes entries from worksheets_rels
#' @param x character string
Expand Down
9 changes: 9 additions & 0 deletions man/dims_helper.Rd

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

27 changes: 27 additions & 0 deletions tests/testthat/test-utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,33 @@ test_that("dims to col & row and back", {

})

test_that("wb_dims() works", {

expect_equal(wb_dims(mtcars), "A1:K33")
expect_equal(wb_dims(mtcars, col_names = FALSE, row_names = TRUE), "A1:L32")

expect_equal(wb_dims(letters), "A1:A26")

expect_equal(wb_dims(t(letters)), "A1:Z2")

expect_equal(wb_dims(1), "A1")

expect_equal(wb_dims(rows = 1:10, cols = 5:7), "E1:G10")
expect_equal(wb_dims(cols = 1:10, rows = 5:7), "A5:J7")
expect_error(
wb_dims(cols = 1:10, col = 5:7),
"found only one cols/rows argument"
)

expect_equal(wb_dims(row = 5, col = 7), "G5")

expect_equal(wb_dims(1:10, LETTERS), "A1:Z10")
expect_equal(wb_dims(1:10, 1:26), "A1:Z10")

expect_equal(wb_dims(1:2, 1:4, start_row = 2, start_col = "B"), "B2:E3")
expect_equal(wb_dims(mtcars, start_row = 2, start_col = "B"), "B2:L34")

})

test_that("create_char_dataframe", {

Expand Down
27 changes: 27 additions & 0 deletions vignettes/openxlsx2.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,33 @@ wb$save("mtcars.xlsx")
try(wb$save("mtcars.xlsx", overwrite = FALSE))
```

## `dims`

In `openxlsx2` functions that interact with worksheet cells are using `dims` as argument and require the users to provide these. `dims` are cells or cell ranges in A1 notation. The single argument `dims` hereby replaces `col`/`row`, `cols`/`rows` and `xy`. Since A1 notation is rather simple in the first few columns it might get confusing after the 26. Therefore we provide a wrapper to construct it:

```{r}
# various options
wb_dims(4)

wb_dims(row = 4, col = 4)

wb_dims(row = 4:10, col = 5:9)

wb_dims(row = 4:10, col = "A:D")

wb_dims(mtcars)

# in a wb chain
wb <- wb_workbook()$
add_worksheet()$
add_data(x = mtcars)$
add_fill(
dims = wb_dims(mtcars, start_row = 5),
color = wb_color("yellow")
)
```


## A note on speed and memory usage

The current state of `openxlsx2` is that it is reasonably fast. That is, it works well with reasonably large input data when reading or writing. It may not work well with data that tests the limits of the openxml specification. Things may slow down on the R side of things, and performance and usability will depend on the speed and size of the local operating system's CPU and memory.
Expand Down