diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 0805e5af..f614f7dd 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -8,4 +8,15 @@ RUN apt-get install -y libqpdf28 qpdf ghostscript
RUN install2.r --error devtools rJava RUnit zoo qpdf languageserver
RUN installGithub.r r-lib/revdepcheck
RUN apt-get install -y pandoc
-RUN install2.r --error ggplot2
+RUN install2.r --error ggplot2 tinytex
+RUN Rscript -e "{\
+ library(tinytex);\
+ tlmgr_install('datetime');\
+ tlmgr_install('inputenc');\
+ tlmgr_install('hyperref');\
+ tlmgr_install('url');\
+ tlmgr_install('fmtcount');\
+ tlmgr_install('float');\
+ tlmgr_install('natbib');\
+ tinytex:::install_yihui_pkgs();\
+}"
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 0eb1be67..493b0c1a 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -8,14 +8,14 @@
"customizations": {
"vscode": {
// Add the IDs of extensions you want installed when the container is created.
- "extensions": [
- "eamodio.gitlens",
- "REditorSupport.r",
- "github.vscode-pull-request-github",
- "github.vscode-github-actions"
- ]
- }
+ "extensions": [
+ "eamodio.gitlens",
+ "REditorSupport.r",
+ "github.vscode-pull-request-github",
+ "github.vscode-github-actions"
+ ]
}
+ }
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
@@ -28,4 +28,10 @@
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
// "remoteUser": "vscode"
+
+ // The below may help when using podman instead of docker as the container backend
+ // (see https://github.com/microsoft/vscode-remote-release/issues/7175#issuecomment-1645498699)
+ // ,"runArgs": [
+ // "--log-driver=none"
+ // ]
}
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 7858c0f2..0a3a18ec 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -31,7 +31,6 @@ jobs:
r-version: oldrel
java: 17 #8
vignettes: true
- xlc-repo: https://jcenter.bintray.com
timezone-name: Europe/Zurich
- os-name: ubuntu # windows-2019, macos-10.15]
os-version: latest
@@ -44,7 +43,6 @@ jobs:
r-version: devel
java: 17
vignettes: true
- xlc-repo: https://jcenter.bintray.com
timezone-name: Pacific/Marquesas
- os-name: macos # TODO fix java / R interaction
os-version: latest
diff --git a/.lintr b/.lintr
new file mode 100644
index 00000000..f3f0d12e
--- /dev/null
+++ b/.lintr
@@ -0,0 +1,3 @@
+linters: linters_with_defaults() # see vignette("lintr")
+encoding: "UTF-8"
+exclusions: list("R", "demo", "inst", "tests") # disables linting with lintr, as we have not decided yet which linters to use
diff --git a/DESCRIPTION b/DESCRIPTION
index 5121f46d..4148cf00 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
Package: XLConnect
Type: Package
Title: Excel Connector for R
-Version: 1.0.8.9999
+Version: 1.1.0.9999
Authors@R: c(person("Mirai Solutions GmbH", role = "aut",
email = "xlconnect@mirai-solutions.com"),
person("Martin", "Studer", role = "cre",
diff --git a/R/dataframeFromJava.R b/R/dataframeFromJava.R
index 4165a505..f7c343dd 100644
--- a/R/dataframeFromJava.R
+++ b/R/dataframeFromJava.R
@@ -72,9 +72,13 @@ dataframeFromJava <- function(df, check.names) {
res[[i]] = v
}
+ # Apply attributes
+ toSet = (attributes(df))[!names(attributes(df)) %in% c("jobj", "jclass", "class", "package")]
# Apply names
- names(res) = columnNames
+ attributes(res) = toSet
+ names(res) = columnNames
+ result = data.frame(res, check.names = check.names, stringsAsFactors = FALSE)
- data.frame(res, check.names = check.names, stringsAsFactors = FALSE)
+ result
})
}
diff --git a/R/extractRownames.R b/R/extractRownames.R
index 740070d8..c01ae64c 100644
--- a/R/extractRownames.R
+++ b/R/extractRownames.R
@@ -30,7 +30,10 @@
extractRownames <- function(x, col) {
if(is(x, "list")) {
if(is.null(col)) col = list(NULL)
- mapply(extractRownames, x, col, SIMPLIFY = FALSE)
+ res <- mapply(extractRownames, x, col, SIMPLIFY = FALSE)
+ attributes(res) <- attributes(x)
+ res
+
} else{
# use attr(x, "row.names") instead of row.names or rownames
# since row.names coerces to character for backward compatibility
diff --git a/R/withAttributesFromJava.R b/R/withAttributesFromJava.R
new file mode 100644
index 00000000..69e11180
--- /dev/null
+++ b/R/withAttributesFromJava.R
@@ -0,0 +1,43 @@
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2021 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Utility function for converting XLConnect java objects with added attributes
+# to R variables with the corresponding attributes.
+#
+# Author: Simon Poltier, Mirai Solutions GmbH
+#
+#############################################################################
+
+withAttributesFromJava <- function(jobj) {
+
+ # jni <- .jcall(jobj, "S", "jni")
+ # unwrapped <- .jcall(jobj, jni, "getValue")
+ unwrapped <- jobj$getValue()
+
+ allANames = .jcall(jobj, "[S", "getAttributeNames")
+ # allAValues = .jcall(jobj, "[S", "getAttributeValues")
+
+ for(i in seq(along = allANames)) {
+ attr(unwrapped, allANames[i]) <- jobj$getAttributeValue(allANames[i])
+ }
+ unwrapped
+ }
\ No newline at end of file
diff --git a/R/workbook.addImage.R b/R/workbook.addImage.R
index 3b7f9978..6d0defd8 100644
--- a/R/workbook.addImage.R
+++ b/R/workbook.addImage.R
@@ -26,13 +26,13 @@
#
#############################################################################
-setGeneric("addImage",
- function(object, filename, name, originalSize = FALSE) standardGeneric("addImage"))
+setGeneric("addImage",
+ function(object, filename, name, originalSize = FALSE, worksheetScope = NULL) standardGeneric("addImage"))
-setMethod("addImage",
- signature(object = "workbook"),
- function(object, filename, name, originalSize = FALSE) {
- xlcCall(object, "addImage", filename, name, originalSize)
+setMethod("addImage",
+ signature(object = "workbook"),
+ function(object, filename, name, originalSize = FALSE, worksheetScope = NULL) {
+ xlcCall(object, "addImage", filename, name, originalSize, worksheetScope %||% .jnull())
invisible()
}
)
diff --git a/R/workbook.appendNamedRegion.R b/R/workbook.appendNamedRegion.R
index 210e300e..e2aaf6ec 100644
--- a/R/workbook.appendNamedRegion.R
+++ b/R/workbook.appendNamedRegion.R
@@ -28,17 +28,17 @@
setGeneric("appendNamedRegion",
function(object, data, name, header = FALSE, overwriteFormulaCells = TRUE,
- rownames = NULL) standardGeneric("appendNamedRegion"))
+ rownames = NULL, worksheetScope = NULL) standardGeneric("appendNamedRegion"))
setMethod("appendNamedRegion",
signature(object = "workbook", data = "ANY"),
function(object, data, name, header = FALSE, overwriteFormulaCells = TRUE,
- rownames = NULL) {
+ rownames = NULL, worksheetScope = NULL) {
if(is.character(rownames))
data <- includeRownames(data, rownames)
# pass data.frame's to Java - construct RDataFrameWrapper Java object references
data <- lapply(wrapList(data), dataframeToJava)
- xlcCall(object, "appendNamedRegion", data, name, header, overwriteFormulaCells, .simplify = FALSE)
+ xlcCall(object, "appendNamedRegion", data, name, worksheetScope %||% .jnull(), header, overwriteFormulaCells, .simplify = FALSE)
invisible()
}
)
diff --git a/R/workbook.clearNamedRegion.R b/R/workbook.clearNamedRegion.R
index 4fa5eb96..fec19b0e 100644
--- a/R/workbook.clearNamedRegion.R
+++ b/R/workbook.clearNamedRegion.R
@@ -1,38 +1,38 @@
-#############################################################################
-#
-# XLConnect
-# Copyright (C) 2010-2024 Mirai Solutions GmbH
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-#############################################################################
-
-#############################################################################
-#
-# Clearing a named region
-#
-# Author: Nicola Lambiase, Mirai Solutions GmbH
-#
-#############################################################################
-
-setGeneric("clearNamedRegion",
- function(object, name) standardGeneric("clearNamedRegion"))
-
-setMethod("clearNamedRegion",
- signature(object = "workbook", name = "character"),
- function(object, name) {
- xlcCall(object, "clearNamedRegion", name)
- invisible()
- }
-)
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2024 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Clearing a named region
+#
+# Author: Nicola Lambiase, Mirai Solutions GmbH
+#
+#############################################################################
+
+setGeneric("clearNamedRegion",
+ function(object, name, worksheetScope = NULL) standardGeneric("clearNamedRegion"))
+
+setMethod("clearNamedRegion",
+ signature(object = "workbook", name = "character"),
+ function(object, name, worksheetScope = NULL) {
+ xlcCall(object, "clearNamedRegion", name, worksheetScope %||% .jnull(), .simplify = FALSE)
+ invisible()
+ }
+)
diff --git a/R/workbook.cloneSheet.R b/R/workbook.cloneSheet.R
index c72cf225..ac76470f 100644
--- a/R/workbook.cloneSheet.R
+++ b/R/workbook.cloneSheet.R
@@ -29,6 +29,7 @@
setGeneric("cloneSheet",
function(object, sheet, name) standardGeneric("cloneSheet"))
+# TODO make cloning names optional
setMethod("cloneSheet",
signature(object = "workbook", sheet = "numeric"),
function(object, sheet, name) {
diff --git a/R/workbook.createName.R b/R/workbook.createName.R
index 3ad23ca1..6c4c0519 100644
--- a/R/workbook.createName.R
+++ b/R/workbook.createName.R
@@ -1,38 +1,38 @@
-#############################################################################
-#
-# XLConnect
-# Copyright (C) 2010-2024 Mirai Solutions GmbH
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-#############################################################################
-
-#############################################################################
-#
-# Creating names in a workbook
-#
-# Author: Martin Studer, Mirai Solutions GmbH
-#
-#############################################################################
-
-setGeneric("createName",
- function(object, name, formula, overwrite = FALSE) standardGeneric("createName"))
-
-setMethod("createName",
- signature(object = "workbook"),
- function(object, name, formula, overwrite = FALSE) {
- xlcCall(object, "createName", name, formula, overwrite)
- invisible()
- }
-)
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2024 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Creating names in a workbook
+#
+# Author: Martin Studer, Mirai Solutions GmbH
+#
+#############################################################################
+
+setGeneric("createName",
+ function(object, name, formula, overwrite = FALSE, worksheetScope = NULL) standardGeneric("createName"))
+
+setMethod("createName",
+ signature(object = "workbook"),
+ function(object, name, formula, overwrite = FALSE, worksheetScope = NULL) {
+ xlcCall(object, "createName", name, worksheetScope %||% .jnull(), formula, overwrite)
+ invisible()
+ }
+)
diff --git a/R/workbook.existsName.R b/R/workbook.existsName.R
index 1d6ea36e..664a1e80 100644
--- a/R/workbook.existsName.R
+++ b/R/workbook.existsName.R
@@ -1,37 +1,37 @@
-#############################################################################
-#
-# XLConnect
-# Copyright (C) 2010-2024 Mirai Solutions GmbH
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-#############################################################################
-
-#############################################################################
-#
-# Checking existence of names in a workbook
-#
-# Author: Martin Studer, Mirai Solutions GmbH
-#
-#############################################################################
-
-setGeneric("existsName",
- function(object, name) standardGeneric("existsName"))
-
-setMethod("existsName",
- signature(object = "workbook"),
- function(object, name) {
- xlcCall(object, "existsName", name)
- }
-)
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2024 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Checking existence of names in a workbook
+#
+# Author: Martin Studer, Mirai Solutions GmbH
+#
+#############################################################################
+
+setGeneric("existsName",
+ function(object, name, worksheetScope = NULL) standardGeneric("existsName"))
+
+setMethod("existsName",
+ signature(object = "workbook"),
+ function(object, name, worksheetScope = NULL) {
+ xlcCall(object, "existsName", name, worksheetScope %||% .jnull(), .withAttributes = TRUE)
+ }
+)
diff --git a/R/workbook.getDefinedNames.R b/R/workbook.getDefinedNames.R
index c2904183..2fdf96a6 100644
--- a/R/workbook.getDefinedNames.R
+++ b/R/workbook.getDefinedNames.R
@@ -27,11 +27,11 @@
#############################################################################
setGeneric("getDefinedNames",
- function(object, validOnly = TRUE) standardGeneric("getDefinedNames"))
+ function(object, validOnly = TRUE, worksheetScope = NULL) standardGeneric("getDefinedNames"))
setMethod("getDefinedNames",
signature(object = "workbook"),
- function(object, validOnly = TRUE) {
- xlcCall(object, "getDefinedNames", validOnly, .recycle = FALSE)
+ function(object, validOnly = TRUE, worksheetScope = NULL) {
+ xlcCall(object, "getDefinedNames", validOnly, worksheetScope %||% .jnull(), .recycle = TRUE)
}
)
diff --git a/R/workbook.getReferenceCoordinatesForName.R b/R/workbook.getReferenceCoordinatesForName.R
index 24b15865..4cab6e9c 100644
--- a/R/workbook.getReferenceCoordinatesForName.R
+++ b/R/workbook.getReferenceCoordinatesForName.R
@@ -27,12 +27,14 @@
#############################################################################
setGeneric("getReferenceCoordinatesForName",
- function(object, name) standardGeneric("getReferenceCoordinatesForName"))
+ function(object, name, worksheetScope = NULL) standardGeneric("getReferenceCoordinatesForName"))
setMethod("getReferenceCoordinatesForName",
signature(object = "workbook"),
- function(object, name) {
- res <- xlcCall(object, "getReferenceCoordinatesForName", name)
+ function(object, name, worksheetScope = NULL) {
+ # print(paste("about to xlc call get reference coordinates for name", worksheetScope))
+ res <- xlcCall(object, "getReferenceCoordinatesForName", name, worksheetScope %||% .jnull())
+ # print(paste("called get reference coordinates for name" , worksheetScope))
if(is.numeric(res)) { matrix(res, nrow = 2, byrow = TRUE) + 1 } else { res }
}
)
diff --git a/R/workbook.getReferenceFormula.R b/R/workbook.getReferenceFormula.R
index 1eed1561..f7f4a648 100644
--- a/R/workbook.getReferenceFormula.R
+++ b/R/workbook.getReferenceFormula.R
@@ -27,11 +27,11 @@
#############################################################################
setGeneric("getReferenceFormula",
- function(object, name) standardGeneric("getReferenceFormula"))
+ function(object, name, worksheetScope = NULL) standardGeneric("getReferenceFormula"))
-setMethod("getReferenceFormula",
- signature(object = "workbook"),
- function(object, name) {
- xlcCall(object, "getReferenceFormula", name)
+setMethod("getReferenceFormula",
+ signature(object = "workbook"),
+ function(object, name, worksheetScope = NULL) {
+ xlcCall(object, "getReferenceFormula", name, worksheetScope %||% .jnull())
}
)
diff --git a/R/workbook.readNamedRegion.R b/R/workbook.readNamedRegion.R
index f87aa68b..fda8d34e 100644
--- a/R/workbook.readNamedRegion.R
+++ b/R/workbook.readNamedRegion.R
@@ -32,7 +32,7 @@ setGeneric("readNamedRegion",
function(object, name, header = TRUE, rownames = NULL, colTypes = character(0),
forceConversion = FALSE, dateTimeFormat = getOption("XLConnect.dateTimeFormat"),
check.names = TRUE, useCachedValues = FALSE, keep = NULL, drop = NULL, simplify = FALSE,
- readStrategy = "default")
+ readStrategy = "default", worksheetScope = NULL)
standardGeneric("readNamedRegion"))
@@ -41,28 +41,31 @@ setMethod("readNamedRegion",
function(object, name, header = TRUE, rownames = NULL, colTypes = character(0),
forceConversion = FALSE, dateTimeFormat = getOption("XLConnect.dateTimeFormat"),
check.names = TRUE, useCachedValues = FALSE, keep = NULL, drop = NULL, simplify = FALSE,
- readStrategy = "default") {
+ readStrategy = "default", worksheetScope = NULL) {
- # returns a list of RDataFrameWrapper Java object references
- sheet = as.vector(extractSheetName(getReferenceFormula(object, name)))
- namedim = matrix(as.vector(t(getReferenceCoordinatesForName(object, name))), nrow=4, byrow=FALSE)
- startRow = namedim[1,]
- startCol = namedim[2,]
- endRow = namedim[3,]
- endCol = namedim[4,]
- numcols = endCol-startCol+1
+ # returns a list of RDataFrameWrapper Java object references
+ sheet = as.vector(extractSheetName(getReferenceFormula(object, name, worksheetScope)))
+
+ namedim = matrix(as.vector(t(getReferenceCoordinatesForName(object, name, worksheetScope))), nrow=4, byrow=FALSE)
+ startRow = namedim[1,]
+ startCol = namedim[2,]
+ endRow = namedim[3,]
+ endCol = namedim[4,]
+ numcols = endCol-startCol+1
- subset <- getColSubset(object, sheet, startRow, endRow, startCol, endCol, header, numcols, keep, drop)
- dataFrame <- xlcCall(object, "readNamedRegion", name, header, .jarray(classToXlcType(colTypes)),
- forceConversion, dateTimeFormat, useCachedValues, subset, readStrategy, .simplify = FALSE)
-
+ subset <- getColSubset(object, sheet, startRow, endRow, startCol, endCol, header, numcols, keep, drop)
+
+ dataFrame <- xlcCall(object, "readNamedRegion", name, header, .jarray(classToXlcType(colTypes)),
+ forceConversion, dateTimeFormat, useCachedValues, subset, readStrategy, worksheetScope %||% .jnull(),
+ .simplify = FALSE, .withAttributes = TRUE
+ )
+
# get data.frames from Java
dataFrame = lapply(dataFrame, dataframeFromJava, check.names = check.names)
# extract rownames
dataFrame = extractRownames(dataFrame, rownames)
- names(dataFrame) <- name
-
+ names(dataFrame) <- rep(name, length.out = length(dataFrame))
# simplify
dataFrame =
mapply(df = dataFrame, simplify = rep(simplify, length.out = length(dataFrame)),
@@ -71,7 +74,6 @@ setMethod("readNamedRegion",
else df
}, SIMPLIFY = FALSE
)
-
# Return data.frame directly in case only one data.frame is read
if(length(dataFrame) == 1) dataFrame[[1]]
else dataFrame
diff --git a/R/workbook.removeName.R b/R/workbook.removeName.R
index d26cab13..27104d08 100644
--- a/R/workbook.removeName.R
+++ b/R/workbook.removeName.R
@@ -27,12 +27,12 @@
#############################################################################
setGeneric("removeName",
- function(object, name) standardGeneric("removeName"))
+ function(object, name, worksheetScope = NULL) standardGeneric("removeName"))
setMethod("removeName",
signature(object = "workbook"),
- function(object, name) {
- xlcCall(object, "removeName", name)
+ function(object, name, worksheetScope) {
+ xlcCall(object, "removeName", name, worksheetScope %||% .jnull())
invisible()
}
)
diff --git a/R/workbook.writeNamedRegion.R b/R/workbook.writeNamedRegion.R
index 35852a01..6e17676d 100644
--- a/R/workbook.writeNamedRegion.R
+++ b/R/workbook.writeNamedRegion.R
@@ -27,15 +27,15 @@
#############################################################################
setGeneric("writeNamedRegion",
- function(object, data, name, header = TRUE, overwriteFormulaCells = TRUE, rownames = NULL) standardGeneric("writeNamedRegion"))
+ function(object, data, name, header = TRUE, overwriteFormulaCells = TRUE, rownames = NULL, worksheetScope = NULL) standardGeneric("writeNamedRegion"))
setMethod("writeNamedRegion",
signature(object = "workbook", data = "ANY"),
- function(object, data, name, header = TRUE, overwriteFormulaCells = TRUE, rownames = NULL) {
+ function(object, data, name, header = TRUE, overwriteFormulaCells = TRUE, rownames = NULL, worksheetScope = NULL) {
data <- includeRownames(data, rownames)
# pass data.frame's to Java - construct RDataFrameWrapper Java object references
data <- lapply(wrapList(data), dataframeToJava)
- xlcCall(object, "writeNamedRegion", data, name, header, overwriteFormulaCells, .simplify = FALSE)
+ xlcCall(object, "writeNamedRegion", data, name, header, overwriteFormulaCells, worksheetScope %||% .jnull(), .simplify = FALSE)
invisible()
}
)
diff --git a/R/writeNamedRegionToFile.R b/R/writeNamedRegionToFile.R
index 11762c87..2ccc3960 100644
--- a/R/writeNamedRegionToFile.R
+++ b/R/writeNamedRegionToFile.R
@@ -1,51 +1,54 @@
-#############################################################################
-#
-# XLConnect
-# Copyright (C) 2010-2024 Mirai Solutions GmbH
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-#############################################################################
-
-#############################################################################
-#
-# Wrapper function to write data to an Excel file in one line.
-#
-# Author: Thomas Themel, Mirai Solutions GmbH
-#
-#############################################################################
-
-
-writeNamedRegionToFile <- function(file, data, name, formula = NA, ...,
- styleAction = XLC$STYLE_ACTION.XLCONNECT,clearNamedRegions=FALSE) {
-
- wb <- loadWorkbook(file, create = !file.exists(file))
- setStyleAction(wb, styleAction)
-
- # clear existing named regions
- existingNames <- getDefinedNames(wb)
- toClear <- intersect(name[clearNamedRegions], existingNames)
- clearNamedRegion(wb, toClear)
-
- if(!is.na(formula)) {
- sheets = extractSheetName(formula)
- createSheet(wb, sheets[sheets != ""])
- createName(wb, name, formula)
- }
-
- writeNamedRegion(wb, data, name, ...)
-
- saveWorkbook(wb)
- invisible(wb)
-}
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2024 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Wrapper function to write data to an Excel file in one line.
+#
+# Author: Thomas Themel, Mirai Solutions GmbH
+#
+#############################################################################
+
+
+writeNamedRegionToFile <- function(file, data, name, formula = NA , ..., worksheetScope = NULL,
+ styleAction = XLC$STYLE_ACTION.XLCONNECT,clearNamedRegions=FALSE) {
+
+ wb <- loadWorkbook(file, create = !file.exists(file))
+ setStyleAction(wb, styleAction)
+
+ # clear existing named regions
+ nameExists <- existsName(wb, name, worksheetScope = worksheetScope)
+ clearExistingName <- function(n, wsScope, clearExisting) {
+ if(clearExisting) clearNamedRegion(wb, n, worksheetScope = wsScope)
+ }
+ mapply(clearExistingName, name, worksheetScope %||% list(NULL), nameExists & clearNamedRegions)
+
+
+ if(!is.na(formula)) {
+ sheets = extractSheetName(formula)
+ createSheet(wb, sheets[sheets != ""])
+ createName(wb, name, formula, worksheetScope = worksheetScope)
+ }
+
+ writeNamedRegion(wb, data, name, worksheetScope = worksheetScope, ...)
+
+ saveWorkbook(wb)
+ invisible(wb)
+}
diff --git a/R/xlcAttributesCall.R b/R/xlcAttributesCall.R
new file mode 100644
index 00000000..ea08bfb1
--- /dev/null
+++ b/R/xlcAttributesCall.R
@@ -0,0 +1,80 @@
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2021 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Utility function for vectorizing argument lists and default Java exception
+# handling (jTryCatch)
+#
+# Atomic objects are replicated as is, others are wrapped in a list as defined
+# by wrapList and then replicated
+#
+# Author: Martin Studer, Mirai Solutions GmbH
+#
+#############################################################################
+
+xlcAttributesCall <-
+ function(obj,
+ fun,
+ ...,
+ .recycle = TRUE,
+ .simplify = TRUE) {
+ res <- xlcCall(obj, fun, ..., .recycle = TRUE, .simplify = TRUE)
+ definedNames <- names(res)[!is.na(names(res))]
+ names(res) <- rep(definedNames, length.out = length(names(res)))
+
+ jni <- mapply(function(resw) {
+ .jcall(resw, "S", "jni")
+ }, res)
+
+ unwrapped <- mapply(function(resw, jtype) {
+ .jcall(resw, jtype, "getValue")
+ }, res, jni)
+
+ allANames = unique(Reduce(function(resw1, resw2) {
+ append(
+ .jcall(resw1, "[S", "getAttributeNames"),
+ .jcall(resw2, "[S", "getAttributeNames")
+ )
+ }, res))
+
+
+ attributeRows <- Map(function(aName) {
+ Map(function(resw) {
+ thev <- .jcall(resw, "S", "getAttributeValue", aName)
+ if (is.null(thev))
+ NA
+ else
+ thev
+ }, res)
+ }, allANames)
+
+ attrMtx <- Reduce(rbind, attributeRows)
+ if (length(allANames) > 1) {
+ colnames(attrMtx) <- allANames
+
+ Map(function(aName) {
+ attr(unwrapped, aName) <- attrMtx[, aName]
+ }, allANames)
+ }
+ else
+ attr(unwrapped, allANames[1]) <- attrMtx
+ unwrapped
+ }
\ No newline at end of file
diff --git a/R/xlcCall.R b/R/xlcCall.R
index 20e6fbc1..1bfb966d 100644
--- a/R/xlcCall.R
+++ b/R/xlcCall.R
@@ -31,22 +31,39 @@
#############################################################################
xlcCall <- function(obj, fun, ..., .recycle = TRUE, .simplify = TRUE,
- .checkWarnings = TRUE) {
- f = eval(parse(text = paste("obj@jobj$", fun, sep = "")))
+ .checkWarnings = TRUE, .withAttributes = FALSE) {
+
+ g = eval(parse(text = paste("obj@jobj$", fun, sep = "")))
+ f <- if (.withAttributes) function(...) withAttributesFromJava(g(...)) else g
args <- list(...)
- if(.recycle) {
- args <- lapply(args, function(x) {
- if(is.atomic(x)) x
- else wrapList(x)
- })
- res = jTryCatch(do.call("mapply", args = c(FUN = f, args, SIMPLIFY = .simplify)))
+
+ if (.recycle) {
+ args <- lapply(args, function(x) {
+ if (is.atomic(x)) x
+ else wrapList(x)
+ })
+
+ res = jTryCatch(do.call("mapply", args = c(FUN = f, args, SIMPLIFY = FALSE)))
+
+ if (.simplify) {
+ if (.withAttributes) {
+ res_attr <- Reduce(function(atts1, atts2) {
+ aNames <- unique(c(names(atts1), names(atts2)))
+ sapply(aNames, function(aName) { list(c(atts1[aName][[1]], atts2[aName][[1]])) })
+ } ,lapply(res, attributes))
+ res <- simplify2array(res)
+ attributes(res) <- res_attr
+ } else {
+ res <- simplify2array(res)
+ }
+ }
} else {
- res = jTryCatch(do.call(f, args))
+ res = jTryCatch(do.call(f, args))
}
-
+
if (.checkWarnings) {
- warnings = .jcall(obj@jobj, "[S", "retrieveWarnings")
- for(w in warnings) warning(w, call. = FALSE)
+ warnings = .jcall(obj@jobj, "[S", "retrieveWarnings")
+ for(w in warnings) warning(w, call. = FALSE)
}
res
diff --git a/R/xlcOperators.R b/R/xlcOperators.R
new file mode 100644
index 00000000..1cc89039
--- /dev/null
+++ b/R/xlcOperators.R
@@ -0,0 +1,34 @@
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2021 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+#############################################################################
+#
+# Operators used internally
+#
+#
+#############################################################################
+
+# Replace `NULL` with a default value
+#
+# Operator that replaces the left-hand side with the right-hand side if the
+# left-hand side is NULL.
+#
+`%||%` <- function(x, y) {
+ if (is.null(x)) y else x
+}
diff --git a/R/xlcWithAttributesCall.R b/R/xlcWithAttributesCall.R
new file mode 100644
index 00000000..ed945fe7
--- /dev/null
+++ b/R/xlcWithAttributesCall.R
@@ -0,0 +1,63 @@
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2021 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Utility function for vectorizing argument lists and default Java exception
+# handling (jTryCatch)
+#
+# Atomic objects are replicated as is, others are wrapped in a list as defined
+# by wrapList and then replicated
+#
+# Extracts attributes from a wrapper Java type and sets them on the R object.
+#
+# Author: Martin Studer & Simon Poltier, Mirai Solutions GmbH
+#
+#############################################################################
+
+xlcWithAttributesCall <- function(obj, fun, ..., .recycle = TRUE, .simplify = TRUE, .checkWarnings = TRUE) {
+ g = eval(parse(text = paste("obj@jobj$", fun, sep = "")))
+ f <- function(...) withAttributesFromJava(g(...))
+ args <- list(...)
+ if(.recycle) {
+ args <- lapply(args, function(x) {
+ if(is.atomic(x)) x
+ else wrapList(x)
+ })
+ res = jTryCatch(do.call("mapply", args = c(FUN = f, args, SIMPLIFY = FALSE)))
+ if(.simplify) {
+ res_attr <- Reduce(function(atts1, atts2) {
+ aNames <- unique(c(names(atts1), names(atts2)))
+ sapply(aNames, function(aName) { list(c(atts1[aName][[1]], atts2[aName][[1]])) })
+ } ,lapply(res, attributes))
+ res <- simplify2array(res)
+ attributes(res) <- res_attr
+ }
+ } else {
+ res = jTryCatch(do.call(f, args))
+ }
+
+ if (.checkWarnings) {
+ warnings = .jcall(obj@jobj, "[S", "retrieveWarnings")
+ for(w in warnings) warning(w, call. = FALSE)
+ }
+
+ res
+}
diff --git a/inst/java/XLConnect-2.0.0-SNAPSHOT.jar b/inst/java/XLConnect-2.0.0-SNAPSHOT.jar
index 874704ec..41407dba 100644
Binary files a/inst/java/XLConnect-2.0.0-SNAPSHOT.jar and b/inst/java/XLConnect-2.0.0-SNAPSHOT.jar differ
diff --git a/inst/unitTests/resources/test37.xlsx b/inst/unitTests/resources/test37.xlsx
new file mode 100644
index 00000000..7737684e
Binary files /dev/null and b/inst/unitTests/resources/test37.xlsx differ
diff --git a/inst/unitTests/resources/testWorkbookCloneSheet.xls b/inst/unitTests/resources/testWorkbookCloneSheet.xls
index feea71c1..fea42428 100644
Binary files a/inst/unitTests/resources/testWorkbookCloneSheet.xls and b/inst/unitTests/resources/testWorkbookCloneSheet.xls differ
diff --git a/inst/unitTests/runit.workbook.clearNamedRegion.R b/inst/unitTests/runit.workbook.clearNamedRegion.R
index c21f9cdf..7d53e176 100644
--- a/inst/unitTests/runit.workbook.clearNamedRegion.R
+++ b/inst/unitTests/runit.workbook.clearNamedRegion.R
@@ -1,55 +1,74 @@
-#############################################################################
-#
-# XLConnect
-# Copyright (C) 2010-2024 Mirai Solutions GmbH
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-#############################################################################
-
-#############################################################################
-#
-# Tests around clearing named regions from an Excel Workbook
-#
-# Author: Nicola Lambiase, Mirai Solutions GmbH
-#
-#############################################################################
-
-test.workbook.clearNamedRegion <- function() {
-
- # Create workbooks
- wb.xls <- loadWorkbook(rsrc("resources/testWorkbookClearCells.xls"), create = FALSE)
- wb.xlsx <- loadWorkbook(rsrc("resources/testWorkbookClearCells.xlsx"), create = FALSE)
-
- checkDf <- data.frame(
- "one" = 1:5,
- "two" = 6:10,
- "three" = 11:15,
- "four" = 16:20,
- "five" = 21:25,
- "six" = 26:30,
- "seven" = 31:35,
- stringsAsFactors = F
- )
-
- # Check that clearing 2 of 3 named regions in a sheet returns only the third one (*.xls)
- clearNamedRegion(wb.xls, c("region1", "region2"))
- res <- readWorksheet(wb.xls, "clearNamedRegion", header = TRUE)
- checkEquals(res, checkDf)
-
- # Check that clearing 2 of 3 named regions in a sheet returns only the third one (*.xlsx)
- clearNamedRegion(wb.xlsx, c("region1", "region2"))
- res <- readWorksheet(wb.xlsx, "clearNamedRegion", header = TRUE)
- checkEquals(res, checkDf)
-}
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2024 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Tests around clearing named regions from an Excel Workbook
+#
+# Author: Nicola Lambiase, Mirai Solutions GmbH
+#
+#############################################################################
+
+test.workbook.clearNamedRegion <- function() {
+
+ # Create workbooks
+ wb.xls <- loadWorkbook(rsrc("resources/testWorkbookClearCells.xls"), create = FALSE)
+ wb.xlsx <- loadWorkbook(rsrc("resources/testWorkbookClearCells.xlsx"), create = FALSE)
+
+ checkDf <- data.frame(
+ "one" = 1:5,
+ "two" = 6:10,
+ "three" = 11:15,
+ "four" = 16:20,
+ "five" = 21:25,
+ "six" = 26:30,
+ "seven" = 31:35,
+ stringsAsFactors = F
+ )
+
+ # Check that clearing 2 of 3 named regions in a sheet returns only the third one (*.xls)
+ clearNamedRegion(wb.xls, c("region1", "region2"))
+ res <- readWorksheet(wb.xls, "clearNamedRegion", header = TRUE)
+ checkEquals(res, checkDf)
+
+ # Check that clearing 2 of 3 named regions in a sheet returns only the third one (*.xlsx)
+ clearNamedRegion(wb.xlsx, c("region1", "region2"))
+ res <- readWorksheet(wb.xlsx, "clearNamedRegion", header = TRUE)
+ checkEquals(res, checkDf)
+
+ #reset
+ wb.xls <- loadWorkbook(rsrc("resources/testWorkbookClearCells.xls"), create = FALSE)
+ wb.xlsx <- loadWorkbook(rsrc("resources/testWorkbookClearCells.xlsx"), create = FALSE)
+
+ # check that specifying the worksheet name doesn't find globally scoped names
+ checkException(clearNamedRegion(wb.xls, c("region1", "region2"), worksheetScope = "clearNamedRegion"))
+
+ # Check that clearing 2 of 3 named regions in a sheet returns only the third one (*.xls)
+ clearNamedRegion(wb.xls, c("region1", "region2"))
+ res <- readWorksheet(wb.xls, "clearNamedRegion", header = TRUE)
+ checkEquals(res, checkDf)
+
+ # Check that clearing 2 of 3 named regions in a sheet returns only the third one (*.xlsx)
+ clearNamedRegion(wb.xlsx, c("region1", "region2"))
+ res <- readWorksheet(wb.xlsx, "clearNamedRegion", header = TRUE)
+ checkEquals(res, checkDf)
+
+
+}
diff --git a/inst/unitTests/runit.workbook.cloneSheet.R b/inst/unitTests/runit.workbook.cloneSheet.R
index dda06c01..05f19269 100644
--- a/inst/unitTests/runit.workbook.cloneSheet.R
+++ b/inst/unitTests/runit.workbook.cloneSheet.R
@@ -1,56 +1,57 @@
-#############################################################################
-#
-# XLConnect
-# Copyright (C) 2010-2024 Mirai Solutions GmbH
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-#############################################################################
-
-#############################################################################
-#
-# Tests around cloning Excel worksheets
-#
-# Author: Martin Studer, Mirai Solutions GmbH
-#
-#############################################################################
-
-test.workbook.cloneSheet <- function() {
-
- # Create workbooks
- wb.xls <- loadWorkbook(rsrc("resources/testWorkbookCloneSheet.xls"), create = FALSE)
- wb.xlsx <- loadWorkbook(rsrc("resources/testWorkbookCloneSheet.xlsx"), create = FALSE)
-
- # Check cloning of worksheet (*.xls)
- checkNoException(cloneSheet(wb.xls, sheet = "Test1", name = "Clone1"))
- checkNoException(readWorksheet(wb.xls, sheet = "Clone1"))
-
- # Check cloning of worksheet (*.xlsx)
- checkNoException(cloneSheet(wb.xlsx, sheet = "Test1", name = "Clone1"))
- checkNoException(readWorksheet(wb.xlsx, sheet = "Clone1"))
-
- # Check that attempting to clone a non-existing worksheet throws an exception (*.xls)
- checkException(cloneSheet(wb.xls, sheet = "NotThere", name = "MyClone"))
-
- # Check that attempting to clone a non-existing worksheet throws an exception (*.xlsx)
- checkException(cloneSheet(wb.xlsx, sheet = "NotThere", name = "MyClone"))
-
- # Check that attempting to assign an invalid name to a cloned sheet throws an exception (*.xls)
- checkException(cloneSheet(wb.xls, sheet = "Test1", name = "'illegal"))
-
- # Check that attempting to assign an invalid name to a cloned sheet throws an exception (*.xlsx)
- checkException(cloneSheet(wb.xlsx, sheet = "Test1", name = "'illegal"))
-
-}
-
+#############################################################################
+#
+# XLConnect
+# Copyright (C) 2010-2024 Mirai Solutions GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#############################################################################
+
+#############################################################################
+#
+# Tests around cloning Excel worksheets
+#
+# Author: Martin Studer, Mirai Solutions GmbH
+#
+#############################################################################
+
+test.workbook.cloneSheet <- function() {
+
+ # Create workbooks
+ wb.xls <- loadWorkbook(rsrc("resources/testWorkbookCloneSheet.xls"), create = FALSE)
+ wb.xlsx <- loadWorkbook(rsrc("resources/testWorkbookCloneSheet.xlsx"), create = FALSE)
+
+ # Check cloning of worksheet (*.xls)
+ checkNoException(cloneSheet(wb.xls, sheet = "Test1", name = "Clone1"))
+ checkNoException(readWorksheet(wb.xls, sheet = "Clone1"))
+ checkNoException(readNamedRegion(wb.xls, 'testName', worksheetScope = 'Clone1'))
+
+ # Check cloning of worksheet (*.xlsx)
+ checkNoException(cloneSheet(wb.xlsx, sheet = "Test1", name = "Clone1"))
+ checkNoException(readWorksheet(wb.xlsx, sheet = "Clone1"))
+
+ # Check that attempting to clone a non-existing worksheet throws an exception (*.xls)
+ checkException(cloneSheet(wb.xls, sheet = "NotThere", name = "MyClone"))
+
+ # Check that attempting to clone a non-existing worksheet throws an exception (*.xlsx)
+ checkException(cloneSheet(wb.xlsx, sheet = "NotThere", name = "MyClone"))
+
+ # Check that attempting to assign an invalid name to a cloned sheet throws an exception (*.xls)
+ checkException(cloneSheet(wb.xls, sheet = "Test1", name = "'illegal"))
+
+ # Check that attempting to assign an invalid name to a cloned sheet throws an exception (*.xlsx)
+ checkException(cloneSheet(wb.xlsx, sheet = "Test1", name = "'illegal"))
+
+}
+
diff --git a/inst/unitTests/runit.workbook.createName.R b/inst/unitTests/runit.workbook.createName.R
index 4075532d..b98ef610 100644
--- a/inst/unitTests/runit.workbook.createName.R
+++ b/inst/unitTests/runit.workbook.createName.R
@@ -35,12 +35,12 @@ test.workbook.createName <- function() {
# Check that creating a legal name works ok (*.xls)
# (this test assumes 'existsName' is working fine)
createName(wb.xls, "Test", "Test!$C$5")
- checkTrue(existsName(wb.xls, "Test"))
+ checkEquals(existsName(wb.xls, "Test"), TRUE, check.attributes = FALSE)
# Check that creating a legal name works ok (*.xlsx)
# (this test assumes 'existsName' is working fine)
createName(wb.xlsx, "Test", "Test!$C$5")
- checkTrue(existsName(wb.xlsx, "Test"))
+ checkEquals(existsName(wb.xlsx, "Test"), TRUE, check.attributes = FALSE)
# Check that trying to create an illegal name throws
# an exception (*.xls)
@@ -72,19 +72,19 @@ test.workbook.createName <- function() {
createName(wb.xls, "CurrentlyHere", "CurrentlyHere!$D$8")
createName(wb.xls, "CurrentlyHere", "NowThere!$C$3", overwrite = TRUE)
# TODO: Should actually rather check that new formula is correct
- checkTrue(existsName(wb.xls, "CurrentlyHere"))
+ checkEquals(existsName(wb.xls, "CurrentlyHere"), TRUE, check.attributes = FALSE)
# Check that overwriting an existing name works ok (*.xlsx)
createName(wb.xlsx, "CurrentlyHere", "CurrentlyHere!$D$8")
createName(wb.xlsx, "CurrentlyHere", "NowThere!$C$3", overwrite = TRUE)
# TODO: Should actually rather check that new formula is correct
- checkTrue(existsName(wb.xlsx, "CurrentlyHere"))
+ checkEquals(existsName(wb.xlsx, "CurrentlyHere"), TRUE, check.attributes = FALSE)
# Check that after trying to write a name with an illegal formula
# (which throws an exception), the name remains available (*.xls)
checkException(createName(wb.xls, "aName", "Test!A1A4"))
checkNoException(createName(wb.xls, "aName", "Test!A1"))
- checkTrue(existsName(wb.xls, "aName"))
+ checkEquals(existsName(wb.xls, "aName"), TRUE, check.attributes = FALSE)
# Check that after trying to write a name with an illegal formula
# (which throws an exception), the name remains available (*.xlsx)
@@ -93,6 +93,6 @@ test.workbook.createName <- function() {
# name with an invalid formula does not throw an exception anymore!
# checkException(createName(wb.xlsx, "aName", "Test!A1A4"))
# checkNoException(createName(wb.xlsx, "aName", "Test!A1"))
- # checkTrue(existsName(wb.xlsx, "aName"))
+ # checkEquals(existsName(wb.xlsx, "aName"), TRUE, check.attributes = FALSE)
}
diff --git a/inst/unitTests/runit.workbook.existsName.R b/inst/unitTests/runit.workbook.existsName.R
index b185d517..4280b36c 100644
--- a/inst/unitTests/runit.workbook.existsName.R
+++ b/inst/unitTests/runit.workbook.existsName.R
@@ -33,22 +33,24 @@ test.workbook.existsName <- function() {
wb.xlsx <- loadWorkbook(rsrc("resources/testWorkbookExistsNameAndSheet.xlsx"), create = FALSE)
# Check that the following names exists (*.xls)
- checkTrue(existsName(wb.xls, "AA"))
- checkTrue(existsName(wb.xls, "BB"))
- checkTrue(existsName(wb.xls, "CC"))
+ checkEquals(existsName(wb.xls, "AA"), TRUE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xls, "BB"), TRUE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xls, "CC"), TRUE, check.attributes = FALSE)
# Check that the following do NOT exists (*.xls)
- checkTrue(!existsName(wb.xls, "DD"))
- checkTrue(!existsName(wb.xls, "'illegal name"))
- checkTrue(!existsName(wb.xls, "%&$$-^~@afk20 235-??a?"))
+ checkEquals(existsName(wb.xls, "DD"), FALSE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xls, "'illegal name"), FALSE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xls, "%&$$-^~@afk20 235-??a?"), FALSE, check.attributes = FALSE)
# Check that the following names exists (*.xlsx)
- checkTrue(existsName(wb.xlsx, "AA"))
- checkTrue(existsName(wb.xlsx, "BB"))
- checkTrue(existsName(wb.xlsx, "CC"))
+ checkEquals(existsName(wb.xlsx, "AA"), TRUE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xlsx, "BB"), TRUE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xlsx, "CC"), TRUE, check.attributes = FALSE)
# Check that the following do NOT exists (*.xlsx)
- checkTrue(!existsName(wb.xlsx, "DD"))
- checkTrue(!existsName(wb.xlsx, "'illegal name"))
- checkTrue(!existsName(wb.xlsx, "%&$$-^~@afk20 235-??a?"))
+ checkEquals(existsName(wb.xlsx, "DD"), FALSE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xlsx, "'illegal name"), FALSE, check.attributes = FALSE)
+ checkEquals(existsName(wb.xlsx, "%&$$-^~@afk20 235-??a?"), FALSE, check.attributes = FALSE)
+
+ # TODO check with attributes - where was the name found ?
}
diff --git a/inst/unitTests/runit.workbook.readNamedRegion.R b/inst/unitTests/runit.workbook.readNamedRegion.R
index b3d2b6bc..de0c7cfe 100644
--- a/inst/unitTests/runit.workbook.readNamedRegion.R
+++ b/inst/unitTests/runit.workbook.readNamedRegion.R
@@ -47,6 +47,15 @@ test.workbook.readNamedRegion <- function() {
# Check that the read named region equals the defined data.frame (*.xlsx)
res <- readNamedRegion(wb.xlsx, "Test", header = TRUE)
checkEquals(res, checkDf)
+
+ # Check that the same works when explicitly specifying global scope (*.xls)
+ res <- readNamedRegion(wb.xls, "Test", header = TRUE, worksheetScope = "")
+ checkEquals(res, checkDf)
+
+ # Check that the same works when explicitly specifying global scope (*.xlsx)
+ res <- readNamedRegion(wb.xlsx, "Test", header = TRUE, worksheetScope = "")
+ checkEquals(res, checkDf)
+
# Check that attempting to read a non-existing named region throws an exception (*.xls)
checkException(readNamedRegion(wb.xls, "NameThatDoesNotExist"))
@@ -387,4 +396,18 @@ test.workbook.readNamedRegion <- function() {
expected = data.frame(B = 1:5, row.names = letters[1:5])
res <- readNamedRegionFromFile(rsrc("resources/testBug49.xlsx"), name = "test", rownames = "A")
checkEquals(expected, res)
+
+ # Check that named region can be read within a worksheet scope (see github issue #37)
+
+ wb37xlsx <- loadWorkbook(rsrc("resources/test37.xlsx"), create = FALSE)
+ read1 <- readNamedRegion(wb37xlsx, 'Bla', worksheetScope = 'Sheet1')
+ read2 <- readNamedRegion(wb37xlsx, 'Bla', worksheetScope = 'Sheet2')
+ checkEquals(colnames(read1), c("bla1"))
+ checkEquals(colnames(read2), c("bla2"))
+ readBoth <- readNamedRegion(wb37xlsx, 'Bla', worksheetScope = c('Sheet1', 'Sheet2'))
+ checkEquals(colnames(readBoth[[1]]), 'bla1')
+ checkEquals(colnames(readBoth[[2]]), 'bla2')
+
+ checkException(readNamedRegion(wb37xlsx, 'Bla', worksheetScope = 'Sheet3'))
}
+
diff --git a/inst/unitTests/runit.writeAndReadNamedRegion.R b/inst/unitTests/runit.writeAndReadNamedRegion.R
index ed69330b..c11b4978 100644
--- a/inst/unitTests/runit.writeAndReadNamedRegion.R
+++ b/inst/unitTests/runit.writeAndReadNamedRegion.R
@@ -36,12 +36,32 @@ test.writeAndReadNamedRegion <- function() {
testDataFrame <- function(wb, df, lref) {
namedRegion <- deparse(substitute(df))
createSheet(wb, name = namedRegion)
- createName(wb, name = namedRegion, formula = paste(namedRegion, lref, sep = "!"))
- writeNamedRegion(wb, df, name = namedRegion, header = TRUE)
- res <- readNamedRegion(wb, namedRegion)
+ createName(wb, name = namedRegion, formula = paste(namedRegion, lref, sep = "!"), worksheetScope = namedRegion)
+ writeNamedRegion(wb, df, name = namedRegion, worksheetScope = namedRegion, header = TRUE)
+ res <- readNamedRegion(wb, namedRegion, worksheetScope = namedRegion)
checkEquals(normalizeDataframe(df, replaceInf = TRUE), res, check.attributes = FALSE, check.names = TRUE)
}
+ testDataFrameNameScope <- function(wb, df, lref) {
+ namedRegion <- paste(deparse(substitute(df)), "1", sep = "")
+ worksheetScopeName <- paste(namedRegion, "2", sep = "")
+ createSheet(wb, name = namedRegion)
+ createSheet(wb, name = worksheetScopeName)
+ createName(wb, name = namedRegion, formula = paste(namedRegion, lref, sep = "!"), worksheetScope = worksheetScopeName)
+ writeNamedRegion(wb, df, name = namedRegion, worksheetScope = worksheetScopeName, header = TRUE)
+ res <- readNamedRegion(wb, namedRegion, worksheetScope = worksheetScopeName)
+ checkEquals(normalizeDataframe(df, replaceInf = TRUE), res, check.attributes = FALSE, check.names = TRUE)
+ }
+
+ testDataFrameGlobalExplicit <- function(wb, df, lref) {
+ namedRegion <- paste(deparse(substitute(df)), "forGlobal", sep = "")
+ createSheet(wb, name = namedRegion)
+ createName(wb, name = namedRegion, formula = paste(namedRegion, lref, sep = "!"), worksheetScope = "")
+ writeNamedRegion(wb, df, name = namedRegion, worksheetScope = "", header = TRUE)
+ res <- readNamedRegion(wb, namedRegion, worksheetScope = "")
+ checkEquals(normalizeDataframe(df, replaceInf = TRUE), res, check.attributes = FALSE, check.names = TRUE)
+ }
+
if(getOption("FULL.TEST.SUITE")) {
# built-in dataset mtcars (*.xls)
testDataFrame(wb.xls, mtcars, "$C$8")
@@ -58,11 +78,21 @@ test.writeAndReadNamedRegion <- function() {
# built-in dataset attenu (*.xlsx)
testDataFrame(wb.xlsx, attenu, "$A$8")
+ # built-in dataset attenu (*.xls) - explicit global scope
+ testDataFrameGlobalExplicit(wb.xls, attenu, "$A$8")
+ # built-in dataset attenu (*.xlsx) - explicit global scope
+ testDataFrameGlobalExplicit(wb.xlsx, attenu, "$A$8")
+
# built-in dataset ChickWeight (*.xls)
testDataFrame(wb.xls, ChickWeight, "$BQ$7")
# built-in dataset ChickWeight (*.xlsx)
testDataFrame(wb.xlsx, ChickWeight, "$BQ$7")
+ # built-in dataset ChickWeight (*.xls) - explicit global scope
+ testDataFrameGlobalExplicit(wb.xls, ChickWeight, "$BQ$7")
+ # built-in dataset ChickWeight (*.xlsx) - explicit global scope
+ testDataFrameGlobalExplicit(wb.xlsx, ChickWeight, "$BQ$7")
+
# built-in dataset CO2 (*.xls)
CO = CO2 # CO2 seems to be an illegal name
testDataFrame(wb.xls, CO, "$L$1")
@@ -84,10 +114,20 @@ test.writeAndReadNamedRegion <- function() {
# built-in dataset morley (*.xlsx)
testDataFrame(wb.xlsx, morley, "$K$4")
+ # built-in dataset morley (*.xls)
+ testDataFrameNameScope(wb.xls, morley, "$K$4")
+ # built-in dataset morley (*.xlsx)
+ testDataFrameNameScope(wb.xlsx, morley, "$K$4")
+
# built-in dataset swiss (*.xls)
testDataFrame(wb.xls, swiss, "$M$2")
# built-in dataset swiss (*.xlsx)
testDataFrame(wb.xlsx, swiss, "$M$2")
+
+ # built-in dataset swiss (*.xls)
+ testDataFrameNameScope(wb.xls, swiss, "$M$2")
+ # built-in dataset swiss (*.xlsx)
+ testDataFrameNameScope(wb.xlsx, swiss, "$M$2")
}
# custom test dataset
diff --git a/inst/unitTests/runit.writeNamedRegionToFile.R b/inst/unitTests/runit.writeNamedRegionToFile.R
index ec2fbd67..010581f5 100644
--- a/inst/unitTests/runit.writeNamedRegionToFile.R
+++ b/inst/unitTests/runit.writeNamedRegionToFile.R
@@ -139,7 +139,6 @@ test.writeNamedRegionToFile <- function() {
formula = "'My Cars'!$A$1", header = TRUE))
checkTrue(file.exists(file2.xlsx))
-
# test clearNamedRegions
testClearNamedRegions <- function(file, df) {
df.short <- df[1,]
@@ -155,10 +154,46 @@ test.writeNamedRegionToFile <- function() {
# overwrite name with shorter version & clearing
writeNamedRegionToFile(file, data=df.short, name="cdfRegion", clearNamedRegions=TRUE)
# should be cleared
- #checkEquals(nrow(readNamedRegionFromFile(file, name="cdfRegion")), 1)
- #checkEquals(nrow(readWorksheetFromFile(file, sheet="cdf")), 1)
+ checkEquals(nrow(readNamedRegionFromFile(file, name="cdfRegion")), 1)
+ checkEquals(nrow(readWorksheetFromFile(file, sheet="cdf")), 1)
}
testClearNamedRegions(file.xls, cdf)
testClearNamedRegions(file.xlsx, cdf)
+
+ testClearNamedRegionsScoped <- function(file, df) {
+ scope <- c('scope1', 'scope2')
+ clearParam <- c(TRUE, FALSE)
+ df.short <- df[1,]
+
+ wb <- loadWorkbook(file, create = TRUE)
+ createSheet(wb, scope)
+ saveWorkbook(wb, file)
+
+ writeNamedRegionToFile(file, data=df, name="cdfRegionScoped", formula=paste(scope[1], "A1", sep="!"), worksheetScope = scope[1])
+ writeNamedRegionToFile(file, data=df, name="cdfRegionScoped", formula=paste(scope[2], "A1", sep="!"), worksheetScope = scope[2])
+ # overwrite named region with shorter version
+ writeNamedRegionToFile(file, data=df.short, name="cdfRegionScoped", worksheetScope = scope)
+ # default behaviour: not cleared, only named region is shortened
+ checkEquals(nrow(readNamedRegionFromFile(file, name="cdfRegionScoped", worksheetScope = scope)[[1]]), 1)
+ checkEquals(nrow(readNamedRegionFromFile(file, name="cdfRegionScoped", worksheetScope = scope)[[2]]), 1)
+ checkEquals(nrow(readWorksheetFromFile(file, sheet=scope)[[1]]), nrow(df))
+ checkEquals(nrow(readWorksheetFromFile(file, sheet=scope)[[2]]), nrow(df))
+
+ # rewrite longer version
+ writeNamedRegionToFile(file, data=df, name="cdfRegionScoped", worksheetScope = scope)
+ # overwrite name with shorter version & clearing
+ writeNamedRegionToFile(file, data=df.short, name="cdfRegionScoped", clearNamedRegions=clearParam, worksheetScope = scope)
+ # should be cleared
+ checkEquals(nrow(readNamedRegionFromFile(file, name="cdfRegionScoped", worksheetScope = scope)[[1]]), 1)
+ checkEquals(nrow(readNamedRegionFromFile(file, name="cdfRegionScoped", worksheetScope = scope)[[2]]), 1)
+ checkEquals(nrow(readWorksheetFromFile(file, sheet=scope)[[1]]), 1)
+ checkEquals(nrow(readWorksheetFromFile(file, sheet=scope)[[2]]), nrow(df))
+ }
+
+ scopedfile.xls <- "testWriteNamedRegionToFileWorkbookScoped.xls"
+ scopedfile.xlsx <- "testWriteNamedRegionToFileWorkbookScoped.xlsx"
+
+ testClearNamedRegionsScoped(scopedfile.xls, cdf)
+ testClearNamedRegionsScoped(scopedfile.xlsx, cdf)
}
diff --git a/man/addImage-methods.Rd b/man/addImage-methods.Rd
index 6c3503bf..a951688a 100644
--- a/man/addImage-methods.Rd
+++ b/man/addImage-methods.Rd
@@ -8,7 +8,7 @@
Adds an image to a worksheet using a named region.
}
\usage{
- \S4method{addImage}{workbook}(object, filename, name, originalSize)
+ \S4method{addImage}{workbook}(object, filename, name, originalSize, worksheetScope)
}
\arguments{
@@ -20,6 +20,8 @@ Adds an image to a worksheet using a named region.
inserted in the top left corner of the named region and not
scaled. Otherwise, the image is scaled to fit the named region.
The default value for \code{originalSize} is \code{FALSE}.}
+ \item{worksheetScope}{Optional - the name of the worksheet in which the name is scoped;
+ useful if different sheets have scoped regions with the same name.}
}
\author{
diff --git a/man/clearNamedRegion-methods.Rd b/man/clearNamedRegion-methods.Rd
index a817dc19..ef075ef8 100644
--- a/man/clearNamedRegion-methods.Rd
+++ b/man/clearNamedRegion-methods.Rd
@@ -1,65 +1,71 @@
-\name{clearNamedRegion-methods}
-\docType{methods}
-\alias{clearNamedRegion}
-\alias{clearNamedRegion-methods}
-\alias{clearNamedRegion,workbook,character-method}
-\title{Clearing named regions in a workbook}
-\description{
-Clears named regions in a \code{\linkS4class{workbook}}.
-}
-\usage{
- \S4method{clearNamedRegion}{workbook,character}(object, name)
-}
-
-\arguments{
- \item{object}{The \code{\linkS4class{workbook}} to use}
- \item{name}{The name of the named region to clear}
-}
-
-\details{
-Clearing a named region/range means to clear all the cells associated with that named
-region. Clearing named regions can be useful if (named) data sets in a worksheet need
-to be replaced, i.e. data is first read, modified in R and finally written back to the
-the same named region. Without clearing the named region first, (parts of) the original
-data may still be visible if they occupied a larger range in the worksheet.
-}
-
-\author{
-Nicola Lambiase\cr
-Mirai Solutions GmbH \url{https://mirai-solutions.ch}
-}
-\seealso{
-\code{\linkS4class{workbook}}, \code{\link[=clearSheet-methods]{clearSheet}},
-\code{\link[=clearRange-methods]{clearRange}},
-\code{\link[=clearRangeFromReference-methods]{clearRangeFromReference}},
-\code{\link[=clearSheet-methods]{clearSheet}}
-}
-\examples{
- \dontrun{
-# mtcars xlsx file from demoFiles subfolder of
-# package XLConnect
-demoExcelFile <- system.file("demoFiles/mtcars.xlsx",
- package = "XLConnect")
-
-# Load workbook
-wb <- loadWorkbook(demoExcelFile)
-
-# Read named region 'mtcars'
-data <- readNamedRegion(wb, name = "mtcars", header = TRUE)
-
-# Only consider cars with a weight >= 5
-data <- data[data$wt >= 5, ]
-
-# Clear original named region
-clearNamedRegion(wb, name = "mtcars")
-
-# Write subsetted data back
-# Note: this is covering a smaller area now -
-# writeNamedRegion automatically redefines the named region
-# to the size/area of the data
-writeNamedRegion(wb, data = data, name = "mtcars",
- header = TRUE)
-}
-}
-\keyword{methods}
-\keyword{utilities}
+\name{clearNamedRegion-methods}
+\docType{methods}
+\alias{clearNamedRegion}
+\alias{clearNamedRegion-methods}
+\alias{clearNamedRegion,workbook,character-method}
+\title{Clearing named regions in a workbook}
+\description{
+Clears named regions in a \code{\linkS4class{workbook}}.
+}
+\usage{
+ \S4method{clearNamedRegion}{workbook,character}(object, name, worksheetScope)
+}
+
+\arguments{
+ \item{object}{The \code{\linkS4class{workbook}} to use}
+ \item{name}{The name of the named region to clear}
+ \item{worksheetScope}{Optional - the name of the worksheet in which the region is scoped;
+ useful if different sheets have scoped regions with the same name.}
+}
+
+\details{
+Clearing a named region/range means to clear all the cells associated with that named
+region. Clearing named regions can be useful if (named) data sets in a worksheet need
+to be replaced, i.e. data is first read, modified in R and finally written back to the
+the same named region. Without clearing the named region first, (parts of) the original
+data may still be visible if they occupied a larger range in the worksheet.
+
+If \code{worksheetScope} is unspecified, the first matching name found anywhere in the workbook
+will be cleared. Otherwise, only a name specifically scoped to the worksheet may be cleared.
+To only clear a name in global scope, pass \code{""} as the value.
+}
+
+\author{
+Nicola Lambiase\cr
+Mirai Solutions GmbH \url{https://mirai-solutions.ch}
+}
+\seealso{
+\code{\linkS4class{workbook}}, \code{\link[=clearSheet-methods]{clearSheet}},
+\code{\link[=clearRange-methods]{clearRange}},
+\code{\link[=clearRangeFromReference-methods]{clearRangeFromReference}},
+\code{\link[=clearSheet-methods]{clearSheet}}
+}
+\examples{
+ \dontrun{
+# mtcars xlsx file from demoFiles subfolder of
+# package XLConnect
+demoExcelFile <- system.file("demoFiles/mtcars.xlsx",
+ package = "XLConnect")
+
+# Load workbook
+wb <- loadWorkbook(demoExcelFile)
+
+# Read named region 'mtcars'
+data <- readNamedRegion(wb, name = "mtcars", header = TRUE)
+
+# Only consider cars with a weight >= 5
+data <- data[data$wt >= 5, ]
+
+# Clear original named region
+clearNamedRegion(wb, name = "mtcars")
+
+# Write subsetted data back
+# Note: this is covering a smaller area now -
+# writeNamedRegion automatically redefines the named region
+# to the size/area of the data
+writeNamedRegion(wb, data = data, name = "mtcars",
+ header = TRUE)
+}
+}
+\keyword{methods}
+\keyword{utilities}
diff --git a/man/createName-methods.Rd b/man/createName-methods.Rd
index 9c19e535..b32778a1 100644
--- a/man/createName-methods.Rd
+++ b/man/createName-methods.Rd
@@ -1,75 +1,77 @@
-\name{createName-methods}
-\docType{methods}
-\alias{createName}
-\alias{createName-methods}
-\alias{createName,workbook-method}
-\title{Creating names in a workbook}
-\description{
-Creates a name for a specified formula in a \code{\linkS4class{workbook}}.
-}
-\usage{
-\S4method{createName}{workbook}(object, name, formula, overwrite)
-}
-
-\arguments{
- \item{object}{The \code{\linkS4class{workbook}} to use}
- \item{name}{The name's name to create}
- \item{formula}{Excel formula specifying the name}
- \item{overwrite}{If a name with the same \code{name} already exists
- and \code{overwrite = TRUE}, then this name is removed first before
- the new one is created. If a name already exists and
- \code{overwrite = FALSE}, then an exception is thrown. The default
- value for \code{overwrite} is \code{FALSE}.}
-}
-
-\details{
-Creates a name named \code{name} for the specified \code{formula}.
-
-The \code{formula} should be specified as you would type it
-in Excel. Make sure that the worksheets, functions, ...
-exist that you are referring to in the \code{formula}.
-
-The \code{name}, \code{formula} and \code{overwrite} arguments are
-vectorized such that multiple names can be created in one method call.
-}
-
-\references{
-What are named regions/ranges?\cr
-\url{https://www.officearticles.com/excel/named_ranges_in_microsoft_excel.htm}\cr
-How to create named regions/ranges?\cr
-\url{https://www.youtube.com/watch?v=iAE9a0uRtpM}
-}
-\author{
-Martin Studer\cr
-Mirai Solutions GmbH \url{https://mirai-solutions.ch}
-}
-\seealso{
-\code{\linkS4class{workbook}},
-\code{\link[=removeName-methods]{removeName}},
-\code{\link[=existsName-methods]{existsName}},
-\code{\link[=getDefinedNames-methods]{getDefinedNames}},\cr
-\code{\link[=readNamedRegion-methods]{readNamedRegion}},
-\code{\link[=writeNamedRegion-methods]{writeNamedRegion}}
-}
-\examples{\dontrun{
-# Load workbook (create if not existing)
-wb <- loadWorkbook("createName.xlsx", create = TRUE)
-
-# Create a worksheet named 'mtcars'
-createSheet(wb, name = "mtcars")
-
-# Create a named region called 'mtcars' on the sheet called 'mtcars'
-createName(wb, name = "mtcars", formula = "mtcars!$A$1")
-
-# Write built-in data set 'mtcars' to the above defined named region
-writeNamedRegion(wb, mtcars, name = "mtcars")
-
-# Save workbook
-saveWorkbook(wb)
-
-# clean up
-file.remove("createName.xlsx")
-}
-}
-\keyword{methods}
-\keyword{utilities}
+\name{createName-methods}
+\docType{methods}
+\alias{createName}
+\alias{createName-methods}
+\alias{createName,workbook-method}
+\title{Creating names in a workbook}
+\description{
+Creates a name for a specified formula in a \code{\linkS4class{workbook}}.
+}
+\usage{
+\S4method{createName}{workbook}(object, name, formula, overwrite, worksheetScope)
+}
+
+\arguments{
+ \item{object}{The \code{\linkS4class{workbook}} to use}
+ \item{name}{The name's name to create}
+ \item{formula}{Excel formula specifying the value / data the name refers to}
+ \item{overwrite}{If a name with the same \code{name} already exists
+ and \code{overwrite = TRUE}, then this name is removed first before
+ the new one is created. If a name already exists and
+ \code{overwrite = FALSE}, then an exception is thrown. The default
+ value for \code{overwrite} is \code{FALSE}.}
+ \item{worksheetScope}{Optional - specific worksheet the name should be scoped to.
+ If unspecified the name will be scoped to the whole workbook.}
+}
+
+\details{
+Creates a name named \code{name} for the specified \code{formula}.
+
+The \code{formula} should be specified as you would type it
+in Excel. Make sure that the worksheets, functions, ...
+exist that you are referring to in the \code{formula}.
+
+The \code{name}, \code{formula} and \code{overwrite} arguments are
+vectorized such that multiple names can be created in one method call.
+}
+
+\references{
+What are named regions/ranges?\cr
+\url{https://www.officearticles.com/excel/named_ranges_in_microsoft_excel.htm}\cr
+How to create named regions/ranges?\cr
+\url{https://www.youtube.com/watch?v=iAE9a0uRtpM}
+}
+\author{
+Martin Studer\cr
+Mirai Solutions GmbH \url{https://mirai-solutions.ch}
+}
+\seealso{
+\code{\linkS4class{workbook}},
+\code{\link[=removeName-methods]{removeName}},
+\code{\link[=existsName-methods]{existsName}},
+\code{\link[=getDefinedNames-methods]{getDefinedNames}},\cr
+\code{\link[=readNamedRegion-methods]{readNamedRegion}},
+\code{\link[=writeNamedRegion-methods]{writeNamedRegion}}
+}
+\examples{\dontrun{
+# Load workbook (create if not existing)
+wb <- loadWorkbook("createName.xlsx", create = TRUE)
+
+# Create a worksheet named 'mtcars'
+createSheet(wb, name = "mtcars")
+
+# Create a named region called 'mtcars' on the sheet called 'mtcars'
+createName(wb, name = "mtcars", formula = "mtcars!$A$1")
+
+# Write built-in data set 'mtcars' to the above defined named region
+writeNamedRegion(wb, mtcars, name = "mtcars")
+
+# Save workbook
+saveWorkbook(wb)
+
+# clean up
+file.remove("createName.xlsx")
+}
+}
+\keyword{methods}
+\keyword{utilities}
diff --git a/man/existsName-methods.Rd b/man/existsName-methods.Rd
index 11ad2e14..a54fabbe 100644
--- a/man/existsName-methods.Rd
+++ b/man/existsName-methods.Rd
@@ -1,49 +1,54 @@
-\name{existsName-methods}
-\docType{methods}
-\alias{existsName}
-\alias{existsName-methods}
-\alias{existsName,workbook-method}
-\title{Checking existence of names in a workbook}
-\description{
-Checks the existence of a name in a \code{\linkS4class{workbook}}.
-}
-
-\usage{
-\S4method{existsName}{workbook}(object, name)
-}
-
-\arguments{
- \item{object}{The \code{\linkS4class{workbook}} to use}
- \item{name}{The name to check for}
-}
-
-\details{
-Returns \code{TRUE} if the specified \code{name} exists and \code{FALSE}
-otherwise. Note that the \code{name} argument is vectorized and
-therefore multiple names can be checked for existence in one method call.
-}
-
-\author{
-Martin Studer\cr
-Mirai Solutions GmbH \url{https://mirai-solutions.ch}
-}
-\seealso{
-\code{\linkS4class{workbook}}, \code{\link[=createName-methods]{createName}}, \code{\link[=removeName-methods]{removeName}},
-\code{\link[=getDefinedNames-methods]{getDefinedNames}}, \code{\link[=readNamedRegion-methods]{readNamedRegion}},\cr
-\code{\link[=writeNamedRegion-methods]{writeNamedRegion}}
-}
-\examples{
-\dontrun{
-# mtcars xlsx file from demoFiles subfolder of package XLConnect
-mtcarsFile <- system.file("demoFiles/mtcars.xlsx", package = "XLConnect")
-
-# Load workbook
-wb <- loadWorkbook(mtcarsFile)
-
-# Check if the name 'mtcars' exists
-# (should return TRUE since the name is defined as 'mtcars!$A$1:$K$33')
-existsName(wb, name = "mtcars")
-}
-}
-\keyword{methods}
-\keyword{utilities}
+\name{existsName-methods}
+\docType{methods}
+\alias{existsName}
+\alias{existsName-methods}
+\alias{existsName,workbook-method}
+\title{Checking existence of names in a workbook}
+\description{
+Checks the existence of a name in a \code{\linkS4class{workbook}}.
+}
+
+\usage{
+\S4method{existsName}{workbook}(object, name, worksheetScope)
+}
+
+\arguments{
+ \item{object}{The \code{\linkS4class{workbook}} to use}
+ \item{name}{The name to check for}
+ \item{worksheetScope}{Optional - the specific worksheet to check}
+}
+
+\details{
+Returns \code{TRUE} if the specified \code{name} exists and \code{FALSE}
+otherwise. Note that the \code{name} argument is vectorized and
+therefore multiple names can be checked for existence in one method call.
+
+If \code{worksheetScope} is provided, TRUE will be returned only if a matching
+name exists in the local scope of the specified sheet. To explicitly match only
+ in the global scope, pass \code{""} as the value.
+}
+
+\author{
+Martin Studer\cr
+Mirai Solutions GmbH \url{https://mirai-solutions.ch}
+}
+\seealso{
+\code{\linkS4class{workbook}}, \code{\link[=createName-methods]{createName}}, \code{\link[=removeName-methods]{removeName}},
+\code{\link[=getDefinedNames-methods]{getDefinedNames}}, \code{\link[=readNamedRegion-methods]{readNamedRegion}},\cr
+\code{\link[=writeNamedRegion-methods]{writeNamedRegion}}
+}
+\examples{
+\dontrun{
+# mtcars xlsx file from demoFiles subfolder of package XLConnect
+mtcarsFile <- system.file("demoFiles/mtcars.xlsx", package = "XLConnect")
+
+# Load workbook
+wb <- loadWorkbook(mtcarsFile)
+
+# Check if the name 'mtcars' exists
+# (should return TRUE since the name is defined as 'mtcars!$A$1:$K$33')
+existsName(wb, name = "mtcars")
+}
+}
+\keyword{methods}
+\keyword{utilities}
diff --git a/man/getDefinedNames-methods.Rd b/man/getDefinedNames-methods.Rd
index 619296f6..f6b21c43 100644
--- a/man/getDefinedNames-methods.Rd
+++ b/man/getDefinedNames-methods.Rd
@@ -8,7 +8,7 @@
Retrieves the defined names in a \code{\linkS4class{workbook}}.
}
\usage{
-\S4method{getDefinedNames}{workbook}(object, validOnly)
+\S4method{getDefinedNames}{workbook}(object, validOnly, worksheetScope)
}
\arguments{
@@ -17,6 +17,8 @@ Retrieves the defined names in a \code{\linkS4class{workbook}}.
are returned. Valid references are ones not starting with #REF! or
#NULL! - which could result e.g. due to a missing sheet reference. The default
value for \code{validOnly} is \code{TRUE}.}
+ \item{worksheetScope}{Optional - the name of the worksheet in which the names are scoped;
+ for names in the global scope, use the value \code{""}}
}
\author{
diff --git a/man/getReferenceCoordinatesForName-methods.Rd b/man/getReferenceCoordinatesForName-methods.Rd
index 10c854cd..eebb21c3 100644
--- a/man/getReferenceCoordinatesForName-methods.Rd
+++ b/man/getReferenceCoordinatesForName-methods.Rd
@@ -8,13 +8,18 @@
Queries the coordinates of an Excel name in a \code{\linkS4class{workbook}}.
}
\usage{
-\S4method{getReferenceCoordinatesForName}{workbook}(object,name)
+\S4method{getReferenceCoordinatesForName}{workbook}(object,name, worksheetScope)
}
\arguments{
\item{object}{The \code{\linkS4class{workbook}} to use}
\item{name}{The name to query. This argument is vectorized such that
multiple names can be queried with one method call.}
+ \item{worksheetScope}{Optional, the name of the worksheet to use for resolving the named region}
+}
+\details{
+ If \code{worksheetScope} is defined, only coordinates for a name scoped strictly to the specified worksheet are
+ returned. To explicitly match only if the name is in the global scope, pass \code{""} as the value.
}
\author{
diff --git a/man/getReferenceFormula-methods.Rd b/man/getReferenceFormula-methods.Rd
index 87296536..bee3c393 100644
--- a/man/getReferenceFormula-methods.Rd
+++ b/man/getReferenceFormula-methods.Rd
@@ -8,13 +8,15 @@
Queries the reference formula of an Excel name in a \code{\linkS4class{workbook}}.
}
\usage{
-\S4method{getReferenceFormula}{workbook}(object,name)
+\S4method{getReferenceFormula}{workbook}(object,name, worksheetScope)
}
\arguments{
\item{object}{The \code{\linkS4class{workbook}} to use}
\item{name}{The name to query. This argument is vectorized such that
multiple names can be queried with one method call.}
+ \item{worksheetScope}{Optional - the name of the worksheet in which the name is scoped;
+ if undefined any name can be returned. To specify global scope, use the value \code{""}}
}
\author{
diff --git a/man/readNamedRegion-methods.Rd b/man/readNamedRegion-methods.Rd
index 2d637005..6a7f1ea4 100644
--- a/man/readNamedRegion-methods.Rd
+++ b/man/readNamedRegion-methods.Rd
@@ -8,8 +8,9 @@
Reads named regions from a \code{\linkS4class{workbook}}.
}
\usage{
-\S4method{readNamedRegion}{workbook}(object, name, header, rownames, colTypes, forceConversion,
-dateTimeFormat, check.names, useCachedValues, keep, drop, simplify, readStrategy)
+\S4method{readNamedRegion}{workbook}(object, name, header, rownames, colTypes,
+forceConversion, dateTimeFormat, check.names, useCachedValues, keep, drop, simplify,
+readStrategy, worksheetScope)
}
\arguments{
@@ -79,6 +80,7 @@ dateTimeFormat, check.names, useCachedValues, keep, drop, simplify, readStrategy
fractional days represent hours, minutes, and seconds) and only blank cells are recognized as missing (missing value
identifiers as set in \code{\link[=setMissingValue-methods]{setMissingValue}} are ignored)
}}
+ \item{worksheetScope}{Optional, the name of the worksheet to use for resolving the named region}
}
\details{
@@ -92,6 +94,9 @@ When reading dates, if your system uses a time zone that has / had daylight savi
certain dates / timestamps will not be read exactly as they were written. See
\url{https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/DateUtil.html#getJavaDate-double-}
+If \code{worksheetScope} is unspecified, the contents of the name found anywhere in the workbook will be read.
+Otherwise, only a name specifically scoped to the specified sheet may be read.
+To read only names defined in the global scope, pass \code{""} as the value.
}
\references{
What are named regions/ranges?\cr
diff --git a/man/removeName-methods.Rd b/man/removeName-methods.Rd
index faf2a6d8..4daff01b 100644
--- a/man/removeName-methods.Rd
+++ b/man/removeName-methods.Rd
@@ -8,17 +8,20 @@
Removes a name from a \code{\linkS4class{workbook}}.
}
\usage{
-\S4method{removeName}{workbook}(object,name)
+\S4method{removeName}{workbook}(object,name,worksheetScope)
}
\arguments{
\item{object}{The \code{\linkS4class{workbook}} to use}
\item{name}{The name to delete}
+ \item{worksheetScope}{Optional - the name of the worksheet in which the name is scoped;
+ useful if different sheets have scoped regions with the same name.}
}
\details{
Removes the name named \code{name} from the specified workbook
\code{object} if it does exist. Multiple names can be specified to be removed.
+Use \code{worksheetScope = ""} to only target names defined in the global scope.
}
\author{
Martin Studer\cr
diff --git a/man/writeNamedRegionToFile.Rd b/man/writeNamedRegionToFile.Rd
index d5c8070f..6311a822 100644
--- a/man/writeNamedRegionToFile.Rd
+++ b/man/writeNamedRegionToFile.Rd
@@ -5,7 +5,7 @@
Writes named regions to an Excel file.
}
\usage{
-writeNamedRegionToFile(file, data, name, formula=NA, ...,
+writeNamedRegionToFile(file, data, name, formula=NA, ..., worksheetScope = NULL,
styleAction = XLC$STYLE_ACTION.XLCONNECT, clearNamedRegions=FALSE)
}
\arguments{
@@ -16,6 +16,7 @@ styleAction = XLC$STYLE_ACTION.XLCONNECT, clearNamedRegions=FALSE)
the named region identified by the corresponding entry of
\code{name}. Use this if you want to create the document from scratch
instead of writing to a template!}
+\item{worksheetScope}{The scope of validity for the named region. If not specified, the named region has global scope.}
\item{...}{Additional arguments passed to \code{\link[=writeNamedRegion-methods]{writeNamedRegion}}}
\item{styleAction}{Style action to be used when writing the data.\cr
The default is \code{XLC$STYLE_ACTION.XLCONNECT}.
diff --git a/man/xlcCall.Rd b/man/xlcCall.Rd
index 1546b4c3..548cacd5 100644
--- a/man/xlcCall.Rd
+++ b/man/xlcCall.Rd
@@ -8,20 +8,20 @@ Performs automatic argument vectorization, provides default Java
exception and warnings handling for \pkg{XLConnect}.
}
\usage{
-xlcCall(obj, fun, ..., .recycle = TRUE, .simplify = TRUE, .checkWarnings = TRUE)
+xlcCall(obj, fun, ..., .recycle = TRUE, .simplify = TRUE, .checkWarnings = TRUE, .withAttributes = FALSE)
}
\arguments{
\item{obj}{
\pkg{XLConnect} S4 object (e.g \code{\linkS4class{workbook}}, \code{\linkS4class{cellstyle}}) which
has a slot \code{jobj} representing a \pkg{rJava} \code{jobjRef} object whose method represented
by the argument \code{fun} should be called.
-}
+ }
\item{fun}{
Name of Java method to be called.
-}
+ }
\item{\dots}{
Arguments to the Java method to be called.
-}
+ }
\item{.recycle}{
If \code{TRUE} (default), arguments passed through \dots will be automatically vectorized using \code{\link{mapply}} and
\code{fun} will be called the appropriate amount of times.
@@ -31,10 +31,13 @@ xlcCall(obj, fun, ..., .recycle = TRUE, .simplify = TRUE, .checkWarnings = TRUE)
\item{.simplify}{
Only relevant if \code{.recycle = TRUE}. Argument to internal \code{\link{mapply}} to set if there should be an attempt to
reduce the result to a vector or matrix.
-}
+ }
\item{.checkWarnings}{
Whether to check for warnings registered on the underlying Java object.
}
+ \item{.withAttributes}{
+ Whether the function being called returns a Java object with attributes. If so, the attributes will be processed and set on the resulting R object.
+ }
}
\details{
This function makes use of \code{\link{mapply}} to perform automatic argument vectorization. Non-atomic arguments are