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

DRAFT: bump poi #188

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3571958
fix color implementation change
colearendt Jan 29, 2022
6641b20
fix enum for horizontal alignment
colearendt Jan 29, 2022
5e33297
fix a bunch of other enums
colearendt Jan 29, 2022
e9d00a0
improve lookups
colearendt Jan 29, 2022
3ef89ff
fix silly whitespace issues
colearendt Jan 29, 2022
4abb10d
implement enum lookup behavior
colearendt Jan 29, 2022
6c4a982
allow passing java enums explicitly
colearendt Jan 29, 2022
02db8e8
make test actually report success
colearendt Jan 29, 2022
5445fdf
add xlsxjars dependency update
colearendt Jan 29, 2022
052176c
Merge remote-tracking branch 'origin/main' into bump-poi
colearendt Jan 29, 2022
e450f08
bump version in a noteworthy fashion
colearendt Jan 29, 2022
eb4a216
fix new typed enum for CellType retrieval
colearendt Jan 30, 2022
da52ff4
fix whitespace
colearendt Jan 30, 2022
e14bc9a
add a hyperlink enum
colearendt Jan 30, 2022
79fd9e5
fix addHyperlink and setZoom
colearendt Jan 30, 2022
500fa0d
clean up whitespace and FILL_STYLES_ reference
colearendt Jan 30, 2022
65087dc
add some TODO items for later
colearendt Jan 30, 2022
f3c6307
still broken.. weirdly
colearendt Jan 30, 2022
82d63ea
add a TODO
colearendt Jan 30, 2022
086c534
fix whitespace
colearendt Jan 30, 2022
6d06765
Merge remote-tracking branch 'origin/main' into bump-poi
colearendt Jan 30, 2022
e8aaf6f
Merge remote-tracking branch 'origin/main' into bump-poi
colearendt Jan 30, 2022
2bcfe62
tweak some cell style, enums, etc in RCellBlock.java
colearendt Apr 29, 2022
d9a3d4f
skip password protection test
colearendt Apr 29, 2022
db3f525
tweak pom.xml...
colearendt Apr 29, 2022
a7e9a75
add log4j test dependency
colearendt Apr 29, 2022
ddfa8ec
address enum changes in java code
colearendt Apr 29, 2022
77239b7
fix issues with pom.xml
colearendt Apr 29, 2022
22ee60c
add a build-java action
colearendt Apr 29, 2022
e0b249b
Merge remote-tracking branch 'origin/main' into bump-poi
colearendt Apr 29, 2022
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
31 changes: 31 additions & 0 deletions .github/workflows/build-java.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

name: build-java

jobs:
build-java:
runs-on: ${{ matrix.config.os }}

name: ${{ matrix.config.os }} (${{ matrix.config.java }})

strategy:
fail-fast: false
matrix:
config:
- {os: ubuntu-latest, java: '8' }
- {os: ubuntu-latest, java: '11' }
- {os: ubuntu-latest, java: '17' }

steps:
- uses: actions/checkout@v3

- uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: ${{ matrix.config.java }}

- run: mvn -f ./other/pom.xml package
6 changes: 4 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Type: Package
Package: xlsx
Title: Read, Write, Format Excel 2007 and Excel 97/2000/XP/2003
Files
Version: 0.6.5.9000
Version: 0.6.5.9100
Authors@R:
c(person(given = "Adrian",
family = "Dragulescu",
Expand All @@ -21,7 +21,7 @@ Imports:
grDevices,
rJava,
utils,
xlsxjars
xlsxjars (>= 0.8.0.9000)
Suggests:
covr,
knitr,
Expand All @@ -35,3 +35,5 @@ Encoding: UTF-8
LazyLoad: yes
RoxygenNote: 7.1.0
SystemRequirements: java (>= 1.6)
Remotes:
colearendt/xlsxjars@bump-poi
48 changes: 34 additions & 14 deletions R/Alignment.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ is.Alignment <- function(x) inherits(x, "Alignment")


######################################################################
# Create an Alignment.
# Create an Alignment.
#
#' Create an Alignment object.
#'
#'
#' Create an Alignment object, useful when working with cell styles.
#'
#'
#'
#'
#' @param horizontal a character value specifying the horizontal alignment.
#' Valid values come from constant \code{HALIGN_STYLES_}.
#' @param vertical a character value specifying the vertical alignment. Valid
Expand All @@ -26,28 +26,48 @@ is.Alignment <- function(x) inherits(x, "Alignment")
#' @return \code{Alignment} returns a list with components from the input
#' argument, and a class attribute "Alignment". Alignment objects are used
#' when constructing cell styles.
#'
#'
#' \code{is.Alignment} returns \code{TRUE} if the argument is of class
#' "Alignment" and \code{FALSE} otherwise.
#' @author Adrian Dragulescu
#' @seealso \code{\link{CellStyle}} for using the a \code{Alignment} object.
#' @examples
#'
#'
#'
#'
#' # you can just use h for horizontal, since R does the matching for you
#' a1 <- Alignment(h="ALIGN_CENTER", rotation=90) # centered and rotated!
#'
#'
#' @export
Alignment <- function(horizontal=NULL, vertical=NULL, wrapText=FALSE,
rotation=0, indent=0)
{
if (!is.null(horizontal) && !(horizontal %in% names(HALIGN_STYLES_)))
stop("Not a valid horizontal value. See help page.")
if (
!is.null(horizontal) &&
!(horizontal %in% names(style_horizontal))
# !.jinherits(horizontal, "org.apache.poi.ss.usermodel.HorizontalAlignment")
) {
# TODO: figure out a way to allow java objects to be passed...
if (horizontal %in% names(HALIGN_STYLES_)) {
lifecycle::deprecate_soft("0.7.0", "HALIGN_STYLES_()", "style_horizontal()", "Try removing the 'ALIGN_' prefix")
} else {
stop("Not a valid horizontal value. See `style_horizontal` or `?POI_constants`")
}
}

if (
!is.null(vertical) &&
!(vertical %in% names(style_vertical))
# !.jinherits(vertical, "org.apache.poi.ss.usermodel.VerticalAlignment")
) {
# TODO: figure out a way to allow java objects to be passed...
if (vertical %in% names(VALIGN_STYLES_)) {
lifecycle::deprecate_soft("0.7.0", "VALIGN_STYLES_()", "style_vertical()")
} else {
stop("Not a valid vertical value. See `style_vertical` or `?POI_constants`")
}
}

if (!is.null(vertical) && !(vertical %in% names(VALIGN_STYLES_)))
stop("Not a valid vertical value. See help page.")

structure(list(horizontal=horizontal, vertical=vertical,
wrapText=wrapText, rotation=rotation, indent=indent),
class="Alignment")
class="Alignment")
}
149 changes: 84 additions & 65 deletions R/Cell.R
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#' Functions to manipulate cells.
#'
#'
#' Functions to manipulate cells.
#'
#'
#' \code{setCellValue} writes the content of an R variable into the cell.
#' \code{Date} and \code{POSIXct} objects are passed in as numerical values.
#' To format them as dates in Excel see \code{\link{CellStyle}}.
#'
#'
#' These functions are not vectorized and should be used only for small
#' spreadsheets. Use \code{CellBlock} functionality to efficiently read/write
#' parts of a spreadsheet.
#'
#'
#' @param row a list of row objects. See \code{Row}.
#' @param colIndex a numeric vector specifying the index of columns.
#' @param simplify a logical value. If \code{TRUE}, the result will be
Expand All @@ -25,59 +25,59 @@
#' @param encoding A character value to set the encoding, for example "UTF-8".
#' @param cell a \code{Cell} object.
#' @return
#'
#'
#' \code{createCell} creates a matrix of lists, each element of the list being
#' a java object reference to an object of type Cell representing an empty
#' cell. The dimnames of this matrix are taken from the names of the rows and
#' the \code{colIndex} variable.
#'
#'
#' \code{getCells} returns a list of java object references for all the cells
#' in the row if \code{colIndex} is \code{NULL}. If you want to extract only a
#' specific columns, set \code{colIndex} to the column indices you are
#' interested.
#'
#'
#' \code{getCellValue} returns the value in the cell as an R object. Type
#' conversions are done behind the scene. This function is not vectorized.
#' @author Adrian Dragulescu
#' @seealso To format cells, see \code{\link{CellStyle}}. For rows see
#' \code{\link{Row}}, for sheets see \code{\link{Sheet}}.
#' @examples
#'
#'
#'
#'
#' file <- system.file("tests", "test_import.xlsx", package = "xlsx")
#'
#' wb <- loadWorkbook(file)
#'
#' wb <- loadWorkbook(file)
#' sheets <- getSheets(wb)
#'
#'
#' sheet <- sheets[['mixedTypes']] # get second sheet
#' rows <- getRows(sheet) # get all the rows
#'
#'
#' cells <- getCells(rows) # returns all non empty cells
#'
#'
#' values <- lapply(cells, getCellValue) # extract the values
#'
#'
#' # write the months of the year in the first column of the spreadsheet
#' ind <- paste(2:13, ".2", sep="")
#' mapply(setCellValue, cells[ind], month.name)
#'
#'
#' ####################################################################
#' # make a new workbook with one sheet and 5x5 cells
#' wb <- createWorkbook()
#' sheet <- createSheet(wb, "Sheet1")
#' rows <- createRow(sheet, rowIndex=1:5)
#' cells <- createCell(rows, colIndex=1:5)
#'
#' cells <- createCell(rows, colIndex=1:5)
#'
#' # populate the first column with Dates
#' days <- seq(as.Date("2013-01-01"), by="1 day", length.out=5)
#' mapply(setCellValue, cells[,1], days)
#'
#'
#'
#'
#'
#'
#' @name Cell
NULL

######################################################################
# Create some cells in the row object. "cell" is the index of columns.
# Create some cells in the row object. "cell" is the index of columns.
# You can pass in a list of rows.
# Return a matrix of lists. Each element is a cell object.
#' @export
Expand All @@ -86,34 +86,34 @@ createCell <- function(row, colIndex=1:5)
{
cells <- matrix(list(), nrow=length(row), ncol=length(colIndex),
dimnames=list(names(row), colIndex))

for (ir in seq_along(row))
for (ic in seq_along(colIndex))
cells[[ir,ic]] <- .jcall(row[[ir]], "Lorg/apache/poi/ss/usermodel/Cell;",
"createCell", as.integer(colIndex[ic]-1))

cells
}

######################################################################
# Get the cells for a list of rows. Users who want basic things only
# don't need to use this function.
#
# don't need to use this function.
#
#' @export
#' @rdname Cell
getCells <- function(row, colIndex=NULL, simplify=TRUE)
{
nC <- length(colIndex)
if (!is.null(colIndex))
colIx <- as.integer(colIndex-1) # ugly, have to do it here

res <- row
for (ir in seq_along(row)){
if (is.null(colIndex)){ # get all columns
minColIx <- .jcall(row[[ir]], "T", "getFirstCellNum") # 0-based
maxColIx <- .jcall(row[[ir]], "T", "getLastCellNum")-1 # 0-based
# actual col index; if the row is empty do nothing
colIx <- if (minColIx < 0) numeric(0) else seq.int(minColIx, maxColIx)
colIx <- if (minColIx < 0) numeric(0) else seq.int(minColIx, maxColIx)
}
nC <- length(colIx)
rowCells <- vector("list", length=nC)
Expand All @@ -132,15 +132,15 @@ getCells <- function(row, colIndex=NULL, simplify=TRUE)

if (simplify)
res <- unlist(res)

res
}


######################################################################
# Only one cell and one value.
# Only one cell and one value.
# You vectorize outside this function if you want.
#
#
# Date = .jnew("java/text/SimpleDateFormat",
# "yyyy-MM-dd")$parse(as.character(value)), # does not format it!
#
Expand All @@ -153,18 +153,18 @@ setCellValue <- function(cell, value, richTextString=FALSE, showNA=TRUE)
return(invisible(.jcall(cell, "V", "setCellErrorValue", .jbyte(42))))
} else { return(invisible()) }
}

value <- switch(class(value)[1],
integer = as.numeric(value),
numeric = value,
numeric = value,
Date = as.numeric(value) + 25569, # add Excel origin
POSIXct = as.numeric(value)/86400 + 25569,
POSIXct = as.numeric(value)/86400 + 25569,
as.character(value)) # for factors and other types

if (richTextString)
value <- .jnew("org/apache/poi/sf/usermodel/RichTextString",
as.character(value)) # do I need to convert to as.character ?!!

invisible(.jcall(cell, "V", "setCellValue", value))
}

Expand All @@ -178,36 +178,55 @@ setCellValue <- function(cell, value, richTextString=FALSE, showNA=TRUE)
#' @rdname Cell
getCellValue <- function(cell, keepFormulas=FALSE, encoding="unknown")
{
cellType <- .jcall(cell, "I", "getCellType") + 1
value <- switch(cellType,
.jcall(cell, "D", "getNumericCellValue"), # 1 = numeric

{strVal <- .jcall(.jcall(cell, # 2 = string
"Lorg/apache/poi/ss/usermodel/RichTextString;",
"getRichStringCellValue"), "S", "toString");
if (encoding=="unknown") {strVal} else {Encoding(strVal) <- encoding; strVal}
},

ifelse(keepFormulas, .jcall(cell, "S", "getCellFormula"), # if a formula
tryCatch(.jcall(cell, "D", "getNumericCellValue"), # try to extract
error=function(e){ # contents
tryCatch(.jcall(cell, "S", "getStringCellValue"),
error=function(e){
tryCatch(.jcall(cell, "Z", "getBooleanCellValue"),
error=function(e)e,
finally=NA)
}, finally=NA)
}, finally=NA)
),

NA, # blank cell

.jcall(cell, "Z", "getBooleanCellValue"), # boolean

NA, #ifelse(keepErrors, .jcall(cell, "B", "getErrorCellValue"), NA), # error

"Error" # catch all
)
cellType <- .jcall(cell, "Lorg/apache/poi/ss/usermodel/CellType;", "getCellType")
cellTypeStr <- .jstrVal(cellType)

if (cellTypeStr == "NUMERIC") {
value <- .jcall(cell, "D", "getNumericCellValue")
} else if (cellTypeStr == "STRING") {
strVal <- .jcall(.jcall(cell, # 2 = string
"Lorg/apache/poi/ss/usermodel/RichTextString;",
"getRichStringCellValue"), "S", "toString");
if (encoding=="unknown") {
value <- strVal
} else {
Encoding(strVal) <- encoding
value <- strVal
}
} else if (cellTypeStr == "FORMULA") {
value <- ifelse(
keepFormulas,
.jcall(cell, "S", "getCellFormula"), # if a formula
tryCatch(
.jcall(cell, "D", "getNumericCellValue"), # try to extract
error=function(e){ # contents
tryCatch(
.jcall(cell, "S", "getStringCellValue"),
error=function(e){
tryCatch(
.jcall(cell, "Z", "getBooleanCellValue"),
error=function(e)e,
finally=NA
)
},
finally=NA
)
},
finally=NA
)
)
} else if (cellTypeStr == "BLANK") {
value <- NA
} else if (cellTypeStr == "BOOLEAN") {
value <- .jcall(cell, "Z", "getBooleanCellValue")
} else if (cellTypeStr == "ERROR") {
# previous attempt to capture error data
# ifelse(keepErrors, .jcall(cell, "B", "getErrorCellValue"), NA), # error
value <- NA
} else {
# catch all for other cases
value <- "Error"
}

value
}
Loading