├── .github ├── .gitignore ├── workflows │ ├── test-coverage.yaml │ ├── pkgdown.yaml │ ├── check-standard.yaml │ └── pr-commands.yaml ├── SUPPORT.md └── CONTRIBUTING.md ├── revdep ├── failures.md ├── problems.md ├── .gitignore ├── revdep.R └── README.md ├── resources ├── README ├── issue7.xlsx ├── issue12.xlsx ├── issue22.xlsx ├── issue25.xlsx ├── issue57.xlsx ├── issue58.xlsx ├── issue32_bad.xlsx ├── xlxs2Test.xlsx ├── issue32_good.xlsx ├── test_template1.xlsx ├── read_xlsx2_example.xlsx ├── issue49_password=test.xlsx └── test_template1_stale.xlsx ├── renv ├── .gitignore └── settings.dcf ├── tests ├── testthat.R └── testthat │ ├── ref │ ├── README │ ├── issue12.xlsx │ ├── issue22.xlsx │ ├── issue25.xlsx │ ├── issue57.xlsx │ ├── issue58.xlsx │ ├── issue68.xlsx │ ├── issue7.xlsx │ ├── log_plot.jpeg │ ├── xlxs2Test.xlsx │ ├── issue32_bad.xlsx │ ├── issue32_good.xlsx │ ├── test_import.xls │ ├── test_import.xlsx │ ├── read_xlsx2_example.xlsx │ └── issue49_password=test.xlsx │ ├── test-aaa_setup.R │ ├── test-zzz_teardown.R │ ├── test-examples.R │ ├── test-addPicture.R │ ├── helper-file.R │ ├── helper-format.R │ ├── test-addAutoFilter.R │ ├── test-misc.R │ ├── test-Workbook.R │ ├── test-CellProtection.R │ ├── test-utils.R │ ├── test-setCellValue.R │ ├── test-write.xlsx.R │ ├── test-addDataFrame.R │ ├── test-chart.R │ ├── test-cellBlock.R │ ├── test-CellStyle.R │ └── test-read.xlsx.R ├── inst ├── java │ └── rexcel-0.5.1.jar ├── tests │ ├── log_plot.jpeg │ ├── test_import.xls │ ├── test_import.xlsx │ ├── crash_write_xlsx.R │ └── test.import.R ├── xlsx.bib └── xlsx.Rmd ├── vignettes ├── excel_report.png └── excel_report.Rmd ├── R ├── ExcelConstants.R ├── write.xlsx2.R ├── CellProtection.R ├── read.xlsx2.R ├── DataFormat.R ├── Fill.R ├── Alignment.R ├── Border.R ├── Picture.R ├── readRows.R ├── xlsx-package.R ├── comment.R ├── PrintSetup.R ├── Font.R ├── write.xlsx.R ├── readColumns.R └── NamedRanges.R ├── java └── README ├── .gitignore ├── codecov.yml ├── .Rbuildignore ├── xlsx.Rproj ├── man ├── set_java_tmp_dir.Rd ├── POI_constants.Rd ├── CellProtection.Rd ├── CellStyle-plus.Rd ├── Sheet.Rd ├── addHyperlink.Rd ├── autoRefresh.Rd ├── Picture.Rd ├── Border.Rd ├── DataFormat.Rd ├── Fill.Rd ├── Comment.Rd ├── Alignment.Rd ├── readRows.Rd ├── PrintSetup.Rd ├── Workbook.Rd ├── Row.Rd ├── NamedRanges.Rd ├── Font.Rd ├── xlsx-package.Rd ├── CellStyle.Rd ├── write.xlsx.Rd ├── readColumns.Rd ├── Cell.Rd ├── addDataFrame.Rd ├── OtherEffects.Rd ├── CellBlock.Rd └── read.xlsx.Rd ├── DESCRIPTION ├── .gitattributes ├── other ├── make.package.R └── src │ └── test │ └── java │ └── org │ └── cran │ └── rexcel │ ├── TestRInterface.java │ ├── TestRCellBlock.java │ └── DebugRexcel.java ├── NAMESPACE ├── README.md └── CODE_OF_CONDUCT.md /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /revdep/failures.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /revdep/problems.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | checks/ 2 | data.sqlite 3 | library/ 4 | .nfs* 5 | -------------------------------------------------------------------------------- /resources/README: -------------------------------------------------------------------------------- 1 | Keep track of problem spreadsheet issues as reported. 2 | -------------------------------------------------------------------------------- /renv/.gitignore: -------------------------------------------------------------------------------- 1 | cellar/ 2 | library/ 3 | local/ 4 | lock/ 5 | python/ 6 | staging/ 7 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(xlsx) 3 | 4 | test_check("xlsx") 5 | -------------------------------------------------------------------------------- /tests/testthat/ref/README: -------------------------------------------------------------------------------- 1 | Keep track of problem spreadsheet issues as reported. 2 | -------------------------------------------------------------------------------- /resources/issue7.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue7.xlsx -------------------------------------------------------------------------------- /resources/issue12.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue12.xlsx -------------------------------------------------------------------------------- /resources/issue22.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue22.xlsx -------------------------------------------------------------------------------- /resources/issue25.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue25.xlsx -------------------------------------------------------------------------------- /resources/issue57.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue57.xlsx -------------------------------------------------------------------------------- /resources/issue58.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue58.xlsx -------------------------------------------------------------------------------- /inst/java/rexcel-0.5.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/inst/java/rexcel-0.5.1.jar -------------------------------------------------------------------------------- /inst/tests/log_plot.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/inst/tests/log_plot.jpeg -------------------------------------------------------------------------------- /inst/tests/test_import.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/inst/tests/test_import.xls -------------------------------------------------------------------------------- /resources/issue32_bad.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue32_bad.xlsx -------------------------------------------------------------------------------- /resources/xlxs2Test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/xlxs2Test.xlsx -------------------------------------------------------------------------------- /tests/testthat/test-aaa_setup.R: -------------------------------------------------------------------------------- 1 | 2 | ## Remove tmp directory if already present 3 | remove_tmp() 4 | -------------------------------------------------------------------------------- /tests/testthat/test-zzz_teardown.R: -------------------------------------------------------------------------------- 1 | 2 | ## Remove tmp directory when finished 3 | ## remove_tmp() 4 | -------------------------------------------------------------------------------- /vignettes/excel_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/vignettes/excel_report.png -------------------------------------------------------------------------------- /inst/tests/test_import.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/inst/tests/test_import.xlsx -------------------------------------------------------------------------------- /resources/issue32_good.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue32_good.xlsx -------------------------------------------------------------------------------- /resources/test_template1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/test_template1.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue12.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue12.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue22.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue22.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue25.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue25.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue57.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue57.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue58.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue58.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue68.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue68.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue7.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue7.xlsx -------------------------------------------------------------------------------- /R/ExcelConstants.R: -------------------------------------------------------------------------------- 1 | # This file defines Excel specific constants 2 | 3 | .EXCEL_LIMIT_MAX_CHARS_IN_CELL <- 32767 4 | -------------------------------------------------------------------------------- /resources/read_xlsx2_example.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/read_xlsx2_example.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/log_plot.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/log_plot.jpeg -------------------------------------------------------------------------------- /tests/testthat/ref/xlxs2Test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/xlxs2Test.xlsx -------------------------------------------------------------------------------- /resources/issue49_password=test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/issue49_password=test.xlsx -------------------------------------------------------------------------------- /resources/test_template1_stale.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/resources/test_template1_stale.xlsx -------------------------------------------------------------------------------- /revdep/revdep.R: -------------------------------------------------------------------------------- 1 | revdepcheck::revdep_check(quiet = FALSE, timeout = as.difftime(60, units = "mins"), num_workers = 1) 2 | -------------------------------------------------------------------------------- /tests/testthat/ref/issue32_bad.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue32_bad.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/issue32_good.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue32_good.xlsx -------------------------------------------------------------------------------- /tests/testthat/ref/test_import.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/test_import.xls -------------------------------------------------------------------------------- /tests/testthat/ref/test_import.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/test_import.xlsx -------------------------------------------------------------------------------- /java/README: -------------------------------------------------------------------------------- 1 | Make CRAN quiet about: 2 | Package has FOSS license, installs .class/.jar but has no 'java' directory. 3 | -------------------------------------------------------------------------------- /tests/testthat/ref/read_xlsx2_example.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/read_xlsx2_example.xlsx -------------------------------------------------------------------------------- /tests/testthat/test-examples.R: -------------------------------------------------------------------------------- 1 | context('test examples') 2 | 3 | test_that('examples succeed', { 4 | test_examples() 5 | }) 6 | 7 | -------------------------------------------------------------------------------- /tests/testthat/ref/issue49_password=test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colearendt/xlsx/HEAD/tests/testthat/ref/issue49_password=test.xlsx -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rhistory* 2 | out/ 3 | .Rproj.user* 4 | tests/testthat/tmp 5 | xlsx.Rcheck/ 6 | xlsx*.tar.gz 7 | xlsx*.tgz 8 | project.Rproj 9 | .RData* 10 | .Rprofile* 11 | .Rproj.user 12 | -------------------------------------------------------------------------------- /renv/settings.dcf: -------------------------------------------------------------------------------- 1 | external.libraries: 2 | ignored.packages: 3 | package.dependency.fields: Imports, Depends, LinkingTo 4 | r.version: 5 | snapshot.type: implicit 6 | use.cache: TRUE 7 | vcs.ignore.library: TRUE 8 | vcs.ignore.local: TRUE 9 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^renv$ 2 | ^renv\.lock$ 3 | ^appveyor\.yml$ 4 | ^\.travis\.yml$ 5 | ^other$ 6 | ^resources$ 7 | ^out$ 8 | .git/.* 9 | .gitignore 10 | ^.*\.Rproj$ 11 | ^\.Rproj\.user$ 12 | ^packrat/ 13 | ^\.Rprofile$ 14 | ^xlsx\.Rcheck$ 15 | ^xlsx.*\.tar\.gz$ 16 | ^xlsx.*\.tgz$ 17 | ^revdep$ 18 | ^codecov\.yml$ 19 | ^\.github$ 20 | ^CODE_OF_CONDUCT\.md$ 21 | -------------------------------------------------------------------------------- /tests/testthat/test-addPicture.R: -------------------------------------------------------------------------------- 1 | context('addPicture') 2 | 3 | test_that('works with basic image', { 4 | 5 | f <- test_ref('log_plot.jpeg') 6 | wb <- createWorkbook() 7 | sheet <- createSheet(wb, "Image") 8 | 9 | pic <- addPicture(file=f, sheet) 10 | saveWorkbook(wb, file=test_tmp("addPicture.xlsx")) 11 | 12 | expect_true(.jinstanceof(pic,'org/apache/poi/xssf/usermodel/XSSFPicture')) 13 | }) 14 | -------------------------------------------------------------------------------- /xlsx.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | -------------------------------------------------------------------------------- /inst/tests/crash_write_xlsx.R: -------------------------------------------------------------------------------- 1 | 2 | options(java.parameters="-Xmx4096m") 3 | require(xlsx) 4 | 5 | N <- 500 # crash with N=5000, at sheet 20 6 | 7 | x <- as.data.frame(matrix(1:N, nrow=N, ncol=59)) 8 | 9 | wb <- createWorkbook() 10 | for (k in 1:100) { 11 | cat("On sheet", k, "\n") 12 | sheetName <- paste("Sheet", k, sep="") 13 | sheet <- createSheet(wb, sheetName) 14 | 15 | addDataFrame(x, sheet) 16 | } 17 | 18 | saveWorkbook(wb, "/tmp/junk.xlsx") 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/testthat/helper-file.R: -------------------------------------------------------------------------------- 1 | 2 | test_ref <- function(file) { 3 | rprojroot::is_testthat$find_file(paste0('ref/',file)) 4 | } 5 | 6 | test_tmp <- function(file) { 7 | tmp_folder <- rprojroot::is_testthat$find_file('tmp') 8 | if (!file.exists(tmp_folder)) 9 | dir.create(tmp_folder) 10 | rprojroot::is_testthat$find_file(paste0('tmp/',file)) 11 | } 12 | 13 | remove_tmp <- function() { 14 | tmp_folder <- rprojroot::is_testthat$find_file('tmp') 15 | if (file.exists(tmp_folder)) 16 | unlink(tmp_folder, recursive=TRUE) 17 | } 18 | -------------------------------------------------------------------------------- /tests/testthat/helper-format.R: -------------------------------------------------------------------------------- 1 | read_data_format <- function(cell) { 2 | cs <- getCellStyle(cell) 3 | 4 | rJava::.jcall(cs,'S','getDataFormatString') 5 | } 6 | 7 | read_fill_foreground <- function(cell) { 8 | cs <- getCellStyle(cell) 9 | 10 | col <- rJava::.jcall(cs,'Lorg/apache/poi/xssf/usermodel/XSSFColor;','getFillForegroundXSSFColor') 11 | 12 | if (!is.null(col)) { 13 | barr <- rJava::.jcall(col,'[B','getRgb') 14 | return(paste(as.character(barr),collapse='')) 15 | } else { 16 | return(NULL) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Platform 2 | 3 | |field |value | 4 | |:--------|:----------------------------| 5 | |version |R version 3.6.1 (2019-07-05) | 6 | |os |Ubuntu 18.04.3 LTS | 7 | |system |x86_64, linux-gnu | 8 | |ui |X11 | 9 | |language |en_US:en | 10 | |collate |en_US.UTF-8 | 11 | |ctype |en_US.UTF-8 | 12 | |tz |Etc/UTC | 13 | |date |2020-02-27 | 14 | 15 | # Dependencies 16 | 17 | |package |old |new |Δ | 18 | |:-------|:-----|:-----|:--| 19 | |xlsx |0.6.2 |0.6.3 |* | 20 | 21 | # Revdeps 22 | 23 | -------------------------------------------------------------------------------- /tests/testthat/test-addAutoFilter.R: -------------------------------------------------------------------------------- 1 | context('addAutoFilter') 2 | 3 | test_that('works in simple example', { 4 | ## issue #47 5 | hours <- seq(as.POSIXct("2011-01-01 01:00:00", tz="GMT"), 6 | as.POSIXct("2011-01-01 10:00:00", tz="GMT"), by="1 hour") 7 | data <- data.frame(x=1:10, type=rep(c("A", "B"), 5), datetime=hours) 8 | 9 | 10 | wb <- createWorkbook(type="xlsx") 11 | sheet <- createSheet(wb, sheetName="Sheet1") 12 | addDataFrame(data, sheet, startRow=3, startColumn=2) 13 | af <- addAutoFilter(sheet, "C3:E3") 14 | saveWorkbook(wb, test_tmp("issue47.xlsx")) 15 | 16 | expect_true(.jinstanceof(af,'org/apache/poi/xssf/usermodel/XSSFAutoFilter')) 17 | }) 18 | -------------------------------------------------------------------------------- /R/write.xlsx2.R: -------------------------------------------------------------------------------- 1 | # Write a data.frame to a new xlsx file. 2 | # with a java back-end 3 | # 4 | 5 | #' @export 6 | #' @rdname write.xlsx 7 | write.xlsx2 <- function(x, file, sheetName="Sheet1", 8 | col.names=TRUE, row.names=TRUE, append=FALSE, 9 | password=NULL, ...) 10 | { 11 | if (append && file.exists(file)){ 12 | wb <- loadWorkbook(file, password=password) 13 | } else { 14 | ext <- gsub(".*\\.(.*)$", "\\1", basename(file)) 15 | wb <- createWorkbook(type=ext) 16 | } 17 | sheet <- createSheet(wb, sheetName) 18 | 19 | addDataFrame(x, sheet, col.names=col.names, row.names=row.names, 20 | startRow=1, startColumn=1, colStyle=NULL, colnamesStyle=NULL, 21 | rownamesStyle=NULL) 22 | 23 | saveWorkbook(wb, file, password=password) 24 | 25 | invisible() 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - uses: r-lib/actions/setup-r@v1 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v1 25 | with: 26 | extra-packages: covr 27 | 28 | - name: Test coverage 29 | run: covr::codecov() 30 | shell: Rscript {0} 31 | -------------------------------------------------------------------------------- /man/set_java_tmp_dir.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utilities.R 3 | \name{set_java_tmp_dir} 4 | \alias{set_java_tmp_dir} 5 | \alias{get_java_tmp_dir} 6 | \title{Set Java Temp Directory} 7 | \usage{ 8 | set_java_tmp_dir(tmp_dir = tempdir()) 9 | 10 | get_java_tmp_dir() 11 | } 12 | \arguments{ 13 | \item{tmp_dir}{optional. The new temp directory. Defaults to the R temp 14 | directory} 15 | } 16 | \value{ 17 | The previous java temp directory (prior to any changes). 18 | } 19 | \description{ 20 | Java sets the java temp directory to `/tmp` by default. However, this is 21 | usually not desirable in R. As a result, this function allows changing that 22 | behavior. Further, this function is fired on package load to ensure all 23 | temp files are written to the R temp directory. 24 | } 25 | \details{ 26 | On package load, we use `getOption("xlsx.tempdir", tempdir())` for the 27 | default value, in case you want to have this value set by an option. 28 | } 29 | -------------------------------------------------------------------------------- /tests/testthat/test-misc.R: -------------------------------------------------------------------------------- 1 | context('basic functions') 2 | 3 | test_that('work in pipeline', { 4 | test_basicFunctions('xls') 5 | test_basicFunctions('xlsx') 6 | }) 7 | 8 | test_that('add onto existing workbook', { 9 | test_addOnExistingWorkbook('xls') 10 | test_addOnExistingWorkbook('xlsx') 11 | }) 12 | 13 | context('Memory Crash') 14 | 15 | test_that('crashes with memory volume', { 16 | skip('do not worry at present') 17 | orig <- getOption('java.parameters') 18 | 19 | options(java.parameters="-Xmx4096m") 20 | require(xlsx) 21 | 22 | N <- 500 # crash with N=5000, at sheet 20 23 | 24 | x <- as.data.frame(matrix(1:N, nrow=N, ncol=59)) 25 | 26 | wb <- createWorkbook() 27 | for (k in 1:100) { 28 | cat("On sheet", k, "\n") 29 | sheetName <- paste("Sheet", k, sep="") 30 | sheet <- createSheet(wb, sheetName) 31 | 32 | addDataFrame(x, sheet) 33 | } 34 | 35 | saveWorkbook(wb, test_tmp("junk.xlsx")) 36 | 37 | options(java.parameters = orig) 38 | }) 39 | 40 | 41 | -------------------------------------------------------------------------------- /tests/testthat/test-Workbook.R: -------------------------------------------------------------------------------- 1 | context('Workbook') 2 | 3 | test_that('fails on incorrect type', { 4 | expect_error(createWorkbook('mine'),'Unknown format') 5 | }) 6 | 7 | test_that("save a workbook", { 8 | wb <- createWorkbook() 9 | tf <- test_tmp("test_save.xlsx") 10 | 11 | saveWorkbook(wb, tf) 12 | wb_read <- loadWorkbook(tf) 13 | }) 14 | 15 | test_that('password protect workbook', { 16 | wb <- createWorkbook() 17 | s <- createSheet(wb,'test123') 18 | addDataFrame(iris,s) 19 | 20 | filename <- test_tmp('password_test.xlsx') 21 | expect_null(saveWorkbook(wb,file=filename,password='test')) 22 | 23 | wb2 <- loadWorkbook(filename, password='test') 24 | 25 | expect_identical(names(getSheets(wb2)) 26 | , names(getSheets(wb))) 27 | }) 28 | 29 | context('getSheets') 30 | 31 | test_that('returns null with no sheets', { 32 | wb <- createWorkbook() 33 | 34 | expect_null(suppressMessages(getSheets(wb))) 35 | expect_output(getSheets(wb),'no sheets') 36 | }) 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Type: Package 2 | Package: xlsx 3 | Title: Read, Write, Format Excel 2007 and Excel 97/2000/XP/2003 4 | Files 5 | Version: 0.6.5.9000 6 | Authors@R: 7 | c(person(given = "Adrian", 8 | family = "Dragulescu", 9 | role = "aut", 10 | email = "adrian.dragulescu@gmail.com"), 11 | person(given = "Cole", 12 | family = "Arendt", 13 | role = c("aut", "cre"), 14 | email = "cole.arendt@outlook.com")) 15 | Description: Provide R functions to read/write/format Excel 2007 16 | and Excel 97/2000/XP/2003 file formats. 17 | License: GPL-3 18 | URL: https://github.com/colearendt/xlsx 19 | BugReports: https://github.com/colearendt/xlsx/issues 20 | Imports: 21 | grDevices, 22 | rJava, 23 | utils, 24 | xlsxjars 25 | Suggests: 26 | covr, 27 | knitr, 28 | rmarkdown, 29 | rprojroot, 30 | testthat, 31 | tibble 32 | VignetteBuilder: 33 | knitr 34 | Encoding: UTF-8 35 | LazyLoad: yes 36 | RoxygenNote: 7.1.0 37 | SystemRequirements: java (>= 1.6) 38 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | release: 7 | types: [published] 8 | workflow_dispatch: 9 | 10 | name: pkgdown 11 | 12 | jobs: 13 | pkgdown: 14 | runs-on: ubuntu-latest 15 | env: 16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - uses: r-lib/actions/setup-pandoc@v1 21 | 22 | - uses: r-lib/actions/setup-r@v1 23 | with: 24 | use-public-rspm: true 25 | 26 | - uses: r-lib/actions/setup-r-dependencies@v1 27 | with: 28 | extra-packages: pkgdown 29 | needs: website 30 | 31 | - name: Deploy package 32 | run: | 33 | git config --local user.name "$GITHUB_ACTOR" 34 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 35 | Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)' 36 | -------------------------------------------------------------------------------- /man/POI_constants.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utilities.R 3 | \docType{data} 4 | \name{POI_constants} 5 | \alias{POI_constants} 6 | \alias{HALIGN_STYLES_} 7 | \alias{VALIGN_STYLES_} 8 | \alias{BORDER_STYLES_} 9 | \alias{FILL_STYLES_} 10 | \alias{CELL_STYLES_} 11 | \alias{INDEXED_COLORS_} 12 | \title{Constants used in the project.} 13 | \format{ 14 | An object of class \code{numeric} of length 7. 15 | 16 | An object of class \code{numeric} of length 4. 17 | 18 | An object of class \code{numeric} of length 14. 19 | 20 | An object of class \code{numeric} of length 19. 21 | 22 | An object of class \code{numeric} of length 44. 23 | 24 | An object of class \code{numeric} of length 48. 25 | } 26 | \usage{ 27 | HALIGN_STYLES_ 28 | 29 | VALIGN_STYLES_ 30 | 31 | BORDER_STYLES_ 32 | 33 | FILL_STYLES_ 34 | 35 | CELL_STYLES_ 36 | 37 | INDEXED_COLORS_ 38 | } 39 | \value{ 40 | A named vector. 41 | } 42 | \description{ 43 | Document some Apache POI constants used in the project. 44 | } 45 | \seealso{ 46 | \code{\link{CellStyle}} for using the \code{POI_constants}. 47 | } 48 | \author{ 49 | Adrian Dragulescu 50 | } 51 | \keyword{datasets} 52 | -------------------------------------------------------------------------------- /man/CellProtection.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/CellProtection.R 3 | \name{is.CellProtection} 4 | \alias{is.CellProtection} 5 | \alias{CellProtection} 6 | \title{Create a CellProtection object.} 7 | \usage{ 8 | is.CellProtection(x) 9 | 10 | CellProtection(locked = TRUE, hidden = FALSE) 11 | } 12 | \arguments{ 13 | \item{x}{A CellProtection object, as returned by \code{CellProtection}.} 14 | 15 | \item{locked}{a logical indicating the cell is locked.} 16 | 17 | \item{hidden}{a logical indicating the cell is hidden.} 18 | } 19 | \value{ 20 | \code{CellProtection} returns a list with components from the input 21 | argument, and a class attribute "CellProtection". CellProtection objects 22 | are used when constructing cell styles. 23 | 24 | \code{is.CellProtection} returns \code{TRUE} if the argument is of class 25 | "CellProtection" and \code{FALSE} otherwise. 26 | } 27 | \description{ 28 | Create a CellProtection object used for cell styles. 29 | } 30 | \examples{ 31 | 32 | 33 | font <- CellProtection(locked=TRUE) 34 | 35 | } 36 | \seealso{ 37 | \code{\link{CellStyle}} for using the a \code{CellProtection} 38 | object. 39 | } 40 | \author{ 41 | Adrian Dragulescu 42 | } 43 | -------------------------------------------------------------------------------- /inst/xlsx.bib: -------------------------------------------------------------------------------- 1 | 2 | @Manual{R-base, 3 | title = {R: A Language and Environment for Statistical Computing}, 4 | author = {{R Core Team}}, 5 | organization = {R Foundation for Statistical Computing}, 6 | address = {Vienna, Austria}, 7 | year = {2016}, 8 | ISBN="3-900051-07-0", 9 | url = {https://www.R-project.org/}, 10 | } 11 | 12 | @Manual{RODBC 13 | , title = {RODBC: ODBC Database Access} 14 | , author = {Brian Ripley, Michael Lapsley} 15 | , year = {2009} 16 | , version = {1.3-1} 17 | , url = {https://CRAN.R-project.org/package=RODBC} 18 | } 19 | 20 | @Manual{RExcelXML 21 | , title = {RExcelXML: Read and manipulate new-style (Office '07) Excel files.} 22 | , author = {Duncan Temple Lang} 23 | , year = {2009} 24 | , url = {http://www.omegahat.net/RExcelXML/} 25 | } 26 | 27 | @Manual{rJava 28 | , title = {rJava: Low-level R to Java interface.} 29 | , author = {Simon Urbanek} 30 | , year = {2009} 31 | , version = {0.8-1} 32 | , url = {https://CRAN.R-project.org/package=rJava}} 33 | 34 | @Manual{readxl 35 | , title = {Read Excel Files} 36 | , author={Hadley Wickham, Jennifer Bryan} 37 | , year = {2017} 38 | , version = {1.0.0} 39 | , url = {https://CRAN.R-project.org/package=readxl} 40 | } 41 | -------------------------------------------------------------------------------- /tests/testthat/test-CellProtection.R: -------------------------------------------------------------------------------- 1 | context('Cell Protection') 2 | 3 | test_that('locks cells appropriately', { 4 | ## issue #70 5 | 6 | wb <- createWorkbook() 7 | sheet <- createSheet(wb, "Sheet1") 8 | rows <- createRow(sheet, rowIndex=1) 9 | cell.1 <- createCell(rows, colIndex=1)[[1,1]] 10 | cell.2 <- createCell(rows, colIndex=2)[[1,1]] 11 | 12 | setCellValue(cell.1, "just some text") 13 | setCellValue(cell.2, 'more text') 14 | 15 | cellStyle1 <- CellStyle(wb) + 16 | Font(wb, heightInPoints=20, isBold=TRUE, isItalic=TRUE, 17 | name="Courier New", color="green") + 18 | Alignment(h="ALIGN_RIGHT") + 19 | CellProtection(locked = T) #the cell protection part 20 | 21 | cellStyle2 <- cellStyle1 + CellProtection(locked=FALSE) 22 | 23 | setCellStyle(cell.1, cellStyle1) 24 | setCellStyle(cell.2, cellStyle2) 25 | 26 | expect_true(.jcall(getCellStyle(cell.1),'Z','getLocked')) 27 | expect_false(.jcall(getCellStyle(cell.2),'Z','getLocked')) 28 | 29 | saveWorkbook(wb, test_tmp('issue70.xlsx')) 30 | }) 31 | 32 | 33 | test_that('tests correctly', { 34 | expect_true(is.CellProtection(CellProtection())) 35 | 36 | wb <- createWorkbook() 37 | expect_false(is.CellProtection(CellStyle(wb))) 38 | }) 39 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | context(".onLoad") 2 | 3 | test_java_version <- function(version){ 4 | testthat::with_mock( 5 | `rJava::.jcall` = function(...){return(version)} 6 | ,xlsx:::.onLoad('.','xlsx') 7 | ) 8 | } 9 | test_that("version comparison works", { 10 | skip("no longer checking version") 11 | # the previous version comparison failed in some locales 12 | expect_error(test_java_version("0.99.0")) 13 | expect_error(test_java_version("1.0.0")) 14 | expect_error(test_java_version("1.4.0")) 15 | expect_error(test_java_version("1.4.99")) 16 | test_java_version("1.5.0") 17 | test_java_version("1.6.0") 18 | test_java_version("1.7.0") 19 | test_java_version("1.9.0") 20 | test_java_version("7.0.0") 21 | test_java_version("10.0.2") 22 | test_java_version("14.0.4") 23 | test_java_version("100.0.4") 24 | test_java_version("1.8.0_121") 25 | }) 26 | 27 | 28 | test_that("set_java_tmp_dir works", { 29 | new_tmp_dir <- tempfile("java_tmp_dir_") 30 | dir.create(new_tmp_dir, recursive = TRUE) 31 | 32 | current_tmp_dir <- get_java_tmp_dir() 33 | 34 | expect_equal(set_java_tmp_dir(new_tmp_dir), current_tmp_dir) 35 | expect_equal(get_java_tmp_dir(), new_tmp_dir) 36 | 37 | # set back 38 | set_java_tmp_dir(current_tmp_dir) 39 | 40 | }) 41 | -------------------------------------------------------------------------------- /man/CellStyle-plus.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/CellStyle.R 3 | \name{CellStyle-plus} 4 | \alias{CellStyle-plus} 5 | \alias{+.CellStyle} 6 | \title{CellStyle construction.} 7 | \usage{ 8 | \method{+}{CellStyle}(cs1, object) 9 | } 10 | \arguments{ 11 | \item{cs1}{a \code{\link{CellStyle}} object.} 12 | 13 | \item{object}{an object to add. The object can be another 14 | \code{\link{CellStyle}}, a \code{\link{DataFormat}}, a 15 | \code{\link{Alignment}}, a \code{\link{Border}}, a \code{\link{Fill}}, a 16 | \code{\link{Font}}, or a \code{\link{CellProtection}} object.} 17 | } 18 | \value{ 19 | A CellStyle object. 20 | } 21 | \description{ 22 | Create cell styles. 23 | } 24 | \details{ 25 | The style of the argument object takes precedence over the style of argument 26 | cs1. 27 | } 28 | \examples{ 29 | 30 | \dontrun{ 31 | cs <- CellStyle(wb) + 32 | Font(wb, heightInPoints=20, isBold=TRUE, isItalic=TRUE, 33 | name="Courier New", color="orange") + 34 | Fill(backgroundColor="lavender", foregroundColor="lavender", 35 | pattern="SOLID_FOREGROUND") + 36 | Alignment(h="ALIGN_RIGHT") 37 | 38 | setCellStyle(cell.1, cellStyle1) 39 | 40 | # you need to save the workbook now if you want to see this art 41 | } 42 | 43 | } 44 | \author{ 45 | Adrian Dragulescu 46 | } 47 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Handle line endings automatically for files detected as text 2 | # and leave all files detected as binary untouched. 3 | * text=auto 4 | 5 | # Basic .gitattributes for a R repo. 6 | 7 | # Source files 8 | # ============ 9 | *.Rdata text 10 | *.rdb binary 11 | *.rds binary 12 | *.Rd text 13 | *.Rdx binary 14 | *.Rmd text 15 | *.R text 16 | DESCRIPTION text 17 | 18 | # Basic .gitattributes for a Java repo 19 | 20 | # These files are text and should be normalized (Convert crlf => lf) 21 | *.css text 22 | *.df text 23 | *.htm text 24 | *.html text 25 | *.java text 26 | *.js text 27 | *.json text 28 | *.jsp text 29 | *.jspf text 30 | *.jspx text 31 | *.properties text 32 | *.sh text 33 | *.tld text 34 | *.txt text 35 | *.tag text 36 | *.tagx text 37 | *.xml text 38 | *.yml text 39 | 40 | # These files are binary and should be left untouched 41 | # (binary is a macro for -text -diff) 42 | *.class binary 43 | *.dll binary 44 | *.ear binary 45 | *.gif binary 46 | *.ico binary 47 | *.jar binary 48 | *.jpg binary 49 | *.jpeg binary 50 | *.png binary 51 | *.so binary 52 | *.war binary 53 | -------------------------------------------------------------------------------- /R/CellProtection.R: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Deal with CellProtection 3 | #' @rdname CellProtection 4 | #' @export 5 | is.CellProtection <- function(x) inherits(x, "CellProtection") 6 | 7 | 8 | ###################################################################### 9 | # Create an CellProtection 10 | # 11 | #' Create a CellProtection object. 12 | #' 13 | #' Create a CellProtection object used for cell styles. 14 | #' 15 | #' @param locked a logical indicating the cell is locked. 16 | #' @param hidden a logical indicating the cell is hidden. 17 | #' @param x A CellProtection object, as returned by \code{CellProtection}. 18 | #' @return 19 | #' 20 | #' \code{CellProtection} returns a list with components from the input 21 | #' argument, and a class attribute "CellProtection". CellProtection objects 22 | #' are used when constructing cell styles. 23 | #' 24 | #' \code{is.CellProtection} returns \code{TRUE} if the argument is of class 25 | #' "CellProtection" and \code{FALSE} otherwise. 26 | #' @author Adrian Dragulescu 27 | #' @seealso \code{\link{CellStyle}} for using the a \code{CellProtection} 28 | #' object. 29 | #' @examples 30 | #' 31 | #' 32 | #' font <- CellProtection(locked=TRUE) 33 | #' 34 | #' @export 35 | CellProtection <- function(locked=TRUE, hidden=FALSE) 36 | { 37 | structure(list(locked=locked, hidden=hidden), 38 | class="CellProtection") 39 | } 40 | -------------------------------------------------------------------------------- /man/Sheet.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Workbook.R 3 | \name{Sheet} 4 | \alias{Sheet} 5 | \alias{Worksheet} 6 | \alias{getSheets} 7 | \alias{createSheet} 8 | \alias{removeSheet} 9 | \title{Functions to manipulate worksheets.} 10 | \usage{ 11 | getSheets(wb) 12 | 13 | createSheet(wb, sheetName = "Sheet1") 14 | 15 | removeSheet(wb, sheetName = "Sheet1") 16 | } 17 | \arguments{ 18 | \item{wb}{a workbook object as returned by \code{createWorksheet} or 19 | \code{loadWorksheet}.} 20 | 21 | \item{sheetName}{a character specifying the name of the worksheet to create, 22 | or remove.} 23 | } 24 | \value{ 25 | \code{createSheet} returns the created \code{Sheet} object. 26 | 27 | \code{getSheets} returns a list of java object references each pointing to 28 | an worksheet. The list is named with the sheet names. 29 | } 30 | \description{ 31 | Functions to manipulate worksheets. 32 | } 33 | \examples{ 34 | 35 | 36 | file <- system.file("tests", "test_import.xlsx", package = "xlsx") 37 | 38 | wb <- loadWorkbook(file) 39 | sheets <- getSheets(wb) 40 | 41 | sheet <- sheets[[2]] # extract the second sheet 42 | 43 | # see all the available java methods that you can call 44 | rJava::.jmethods(sheet) 45 | 46 | # for example 47 | sheet$getLastRowNum() 48 | 49 | } 50 | \seealso{ 51 | To extract rows from a given sheet, see \code{\link{Row}}. 52 | } 53 | \author{ 54 | Adrian Dragulescu 55 | } 56 | -------------------------------------------------------------------------------- /tests/testthat/test-setCellValue.R: -------------------------------------------------------------------------------- 1 | context('cell') 2 | 3 | test_that('works in complex pipeline', { 4 | test_complex_cell('xlsx') 5 | test_complex_cell('xls') 6 | }) 7 | 8 | context('setCellValue') 9 | 10 | test_that( 11 | 'NA can be output as empty', { 12 | ## issue #6 13 | tfile <- tempfile(fileext=".xlsx") 14 | 15 | wb <- createWorkbook() 16 | sheet <- createSheet(wb) 17 | rows <- createRow(sheet, rowIndex=1:5) 18 | cells <- createCell(rows) 19 | mapply(setCellValue, cells[,1], c(1,2,NA,4,5)) 20 | setCellValue(cells[[2,2]], "Hello") 21 | mapply(setCellValue, cells[,3], c(1,2,NA,4,5), showNA=FALSE) 22 | setCellValue(cells[[3,3]], NA, showNA=FALSE) 23 | saveWorkbook(wb, tfile) 24 | 25 | expect_identical( 26 | read.xlsx2(tfile,1,header=FALSE,stringsAsFactors=FALSE) 27 | , data.frame( 28 | X1=c('1','2','ERROR','4','5') 29 | ,X2=c('','Hello','','','') 30 | ,X3=c('1','2','','4','5') 31 | ,X4=c('','','','','') 32 | ,X5=c('','','','','') 33 | , stringsAsFactors=FALSE 34 | ) 35 | ) 36 | 37 | aux <- data.frame(x=c(1,2,NA,4,5)) 38 | write.xlsx(aux, file=tfile, showNA=FALSE) 39 | 40 | expect_identical( 41 | read.xlsx(tfile,1,colIndex=2, stringsAsFactors=FALSE) 42 | , data.frame( 43 | x=c(1,2,NA,4,5) 44 | , stringsAsFactors=FALSE 45 | ) 46 | ) 47 | } 48 | ) 49 | -------------------------------------------------------------------------------- /man/addHyperlink.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/otherEffects.R 3 | \name{addHyperlink} 4 | \alias{addHyperlink} 5 | \title{Add a hyperlink to a cell.} 6 | \usage{ 7 | addHyperlink( 8 | cell, 9 | address, 10 | linkType = c("URL", "DOCUMENT", "EMAIL", "FILE"), 11 | hyperlinkStyle = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{cell}{a \code{\link{Cell}} object.} 16 | 17 | \item{address}{a string pointing to the resource.} 18 | 19 | \item{linkType}{a the type of the resource.} 20 | 21 | \item{hyperlinkStyle}{a \code{\link{CellStyle}} object. If \code{NULL} a 22 | default cell style is created, blue underlined font.} 23 | } 24 | \value{ 25 | None. The modification to the cell is done in place. 26 | } 27 | \description{ 28 | Add a hyperlink to a cell to point to an external resource. 29 | } 30 | \details{ 31 | The cell needs to have content before you add a hyperlink to it. The 32 | contents of the cells don't need to be the same as the address of the 33 | hyperlink. See the examples. 34 | } 35 | \examples{ 36 | 37 | 38 | wb <- createWorkbook() 39 | sheet1 <- createSheet(wb, "Sheet1") 40 | rows <- createRow(sheet1, 1:10) # 10 rows 41 | cells <- createCell(rows, colIndex=1:8) # 8 columns 42 | 43 | ## Add hyperlinks to a cell 44 | cell <- cells[[1,1]] 45 | address <- "https://poi.apache.org/" 46 | setCellValue(cell, "click me!") 47 | addHyperlink(cell, address) 48 | 49 | # Don't forget to save the workbook ... 50 | 51 | } 52 | \author{ 53 | Adrian Dragulescu 54 | } 55 | -------------------------------------------------------------------------------- /man/autoRefresh.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/autoRefresh.R 3 | \name{forceFormulaRefresh} 4 | \alias{forceFormulaRefresh} 5 | \alias{forcePivotTableRefresh} 6 | \title{Force Refresh Pivot Tables and Formulae} 7 | \usage{ 8 | forceFormulaRefresh(file, output = NULL, verbose = FALSE) 9 | 10 | forcePivotTableRefresh(file, output = NULL, verbose = FALSE) 11 | } 12 | \arguments{ 13 | \item{file}{the path of the source file where formulae/pivot table needs to be refreshed} 14 | 15 | \item{output}{the path of the output file. If it is \code{NULL} then the source file will be overwritten} 16 | 17 | \item{verbose}{Whether to make logging more verbose} 18 | } 19 | \value{ 20 | Does not return any results 21 | } 22 | \description{ 23 | Functions to force formula calculation or refresh of pivot 24 | tables when the Excel file is opened. 25 | } 26 | \details{ 27 | \code{forcePivotTableRefresh} forces pivot tables to be refreshed when the Excel file is opened. 28 | \code{forceFormulaRefresh} forces formulae to be recalculated when the Excel file is opened. 29 | } 30 | \examples{ 31 | # Patch a file where its pivot tables are not recalculated when the file is opened 32 | \dontrun{ 33 | forcePivotTableRefresh("/tmp/file.xlsx") 34 | forcePivotTableRefresh("/tmp/file.xlsx", "/tmp/fixed_file.xlsx") 35 | } 36 | # Patch a file where its formulae are not recalculated when the file is opened 37 | \dontrun{ 38 | forceFormulaRefresh("/tmp/file.xlsx") 39 | forceFormulaRefresh("/tmp/file.xlsx", "/tmp/fixed_file.xlsx") 40 | } 41 | 42 | 43 | } 44 | \author{ 45 | Tom Kwong 46 | } 47 | -------------------------------------------------------------------------------- /other/make.package.R: -------------------------------------------------------------------------------- 1 | # Automate the making of the package 2 | # 3 | # 4 | 5 | 6 | ################################################################## 7 | # 8 | .build.java <- function() 9 | { 10 | # build maven project 11 | # and put the jars (package and its dependencies) to the inst/java/ directory 12 | system(paste("mvn -f ", file.path(pkgdir,'other', 'pom.xml'), ' package' ) ) 13 | 14 | invisible() 15 | } 16 | 17 | 18 | ################################################################## 19 | # 20 | .setEnv <- function() 21 | { 22 | pkgdir <<- "/home/adrian/Documents/repos/git/dragua/xlsx/" 23 | outdir <<- "/tmp" 24 | Rcmd <<- "R CMD" 25 | invisible() 26 | } 27 | 28 | ################################################################## 29 | ################################################################## 30 | 31 | ## .build.java() 32 | 33 | version <- "0.6.1" 34 | package.gz <- paste("xlsx_", version, ".tar.gz", sep="") 35 | .setEnv() 36 | 37 | # make the package 38 | setwd(outdir) 39 | cmd <- paste(Rcmd, "build --force --md5", pkgdir) 40 | print(cmd); system(cmd) 41 | 42 | # check source with --as-cran on the tarball before submitting it 43 | cmd <- paste(Rcmd, "check --as-cran", package.gz) 44 | print(cmd); system(cmd) 45 | 46 | 47 | # install the package 48 | install.packages(package.gz, repos=NULL, type="source", clean=TRUE) 49 | 50 | # Run the tests from inst/tests/lib_tests_xlsx.R 51 | 52 | 53 | # make the package for CRAN 54 | cmd <- paste(Rcmd, "build --compact-vignettes", pkgdir) 55 | print(cmd); system(cmd) 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /man/Picture.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Picture.R 3 | \name{Picture} 4 | \alias{Picture} 5 | \alias{addPicture} 6 | \title{Functions to manipulate images in a spreadsheet.} 7 | \usage{ 8 | addPicture(file, sheet, scale = 1, startRow = 1, startColumn = 1) 9 | } 10 | \arguments{ 11 | \item{file}{the absolute path to the image file.} 12 | 13 | \item{sheet}{a worksheet object as returned by \code{createSheet} or by 14 | subsetting \code{getSheets}. The picture will be added on this sheet at 15 | position \code{startRow}, \code{startColumn}.} 16 | 17 | \item{scale}{a numeric specifying the scale factor for the image.} 18 | 19 | \item{startRow}{a numeric specifying the row of the upper left corner of the 20 | image.} 21 | 22 | \item{startColumn}{a numeric specifying the column of the upper left corner 23 | of the image.} 24 | } 25 | \value{ 26 | \code{addPicture} a java object references pointing to the picture. 27 | } 28 | \description{ 29 | For now, the following image types are supported: dib, emf, jpeg, pict, png, 30 | wmf. Please note, that scaling works correctly only for workbooks with the 31 | default font size (Calibri 11pt for .xlsx). If the default font is changed 32 | the resized image can be streched vertically or horizontally. 33 | } 34 | \details{ 35 | Don't know how to remove an existing image yet. 36 | } 37 | \examples{ 38 | 39 | 40 | file <- system.file("tests", "log_plot.jpeg", package = "xlsx") 41 | 42 | wb <- createWorkbook() 43 | sheet <- createSheet(wb, "Sheet1") 44 | 45 | addPicture(file, sheet) 46 | 47 | # don't forget to save the workbook! 48 | 49 | 50 | } 51 | \author{ 52 | Adrian Dragulescu 53 | } 54 | -------------------------------------------------------------------------------- /man/Border.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Border.R 3 | \name{is.Border} 4 | \alias{is.Border} 5 | \alias{Border} 6 | \title{Create an Border object.} 7 | \usage{ 8 | is.Border(x) 9 | 10 | Border(color = "black", position = "BOTTOM", pen = "BORDER_THIN") 11 | } 12 | \arguments{ 13 | \item{x}{An Border object, as returned by \code{Border}.} 14 | 15 | \item{color}{a character vector specifiying the font color. Any color names 16 | as returned by \code{\link[grDevices]{colors}} can be used. Or, a hex 17 | character, e.g. "#FF0000" for red. For Excel 95 workbooks, only a subset of 18 | colors is available, see the constant \code{INDEXED_COLORS_}.} 19 | 20 | \item{position}{a character vector specifying the border position. Valid 21 | values are "BOTTOM", "LEFT", "TOP", "RIGHT".} 22 | 23 | \item{pen}{a character vector specifying the pen style. Valid values come 24 | from constant \code{BORDER_STYLES_}.} 25 | } 26 | \value{ 27 | \code{Border} returns a list with components from the input 28 | argument, and a class attribute "Border". Border objects are used when 29 | constructing cell styles. 30 | 31 | \code{is.Border} returns \code{TRUE} if the argument is of class "Border" 32 | and \code{FALSE} otherwise. 33 | } 34 | \description{ 35 | Create an Border object, useful when working with cell styles. 36 | } 37 | \details{ 38 | The values for the color, position, or pen arguments are replicated to the 39 | longest of them. 40 | } 41 | \examples{ 42 | 43 | 44 | border <- Border(color="red", position=c("TOP", "BOTTOM"), 45 | pen=c("BORDER_THIN", "BORDER_THICK")) 46 | 47 | } 48 | \seealso{ 49 | \code{\link{CellStyle}} for using the a \code{Border} object. 50 | } 51 | \author{ 52 | Adrian Dragulescu 53 | } 54 | -------------------------------------------------------------------------------- /man/DataFormat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/DataFormat.R 3 | \name{is.DataFormat} 4 | \alias{is.DataFormat} 5 | \alias{DataFormat} 6 | \title{Create an DataFormat object.} 7 | \usage{ 8 | is.DataFormat(df) 9 | 10 | DataFormat(x) 11 | } 12 | \arguments{ 13 | \item{df}{An DataFormat object, as returned by \code{DataFormat}.} 14 | 15 | \item{x}{a character value specifying the data format.} 16 | } 17 | \value{ 18 | \code{DataFormat} returns a list one component dataFormat, and a 19 | class attribute "DataFormat". DataFormat objects are used when constructing 20 | cell styles. 21 | 22 | \code{is.DataFormat} returns \code{TRUE} if the argument is of class 23 | "DataFormat" and \code{FALSE} otherwise. 24 | } 25 | \description{ 26 | Create an DataFormat object, useful when working with cell styles. 27 | } 28 | \details{ 29 | Specifying the \code{dataFormat} argument allows you to format the cell. 30 | For example, "#,##0.00" corresponds to using a comma separator for powers of 31 | 1000 with two decimal places, "m/d/yyyy" can be used to format dates and is 32 | the equivalent of 's MM/DD/YYYY format. To format datetimes use "m/d/yyyy 33 | h:mm:ss;@". To show negative values in red within parantheses with two 34 | decimals and commas after power of 1000 use "#,##0.00_);[Red](#,##0.00)". I 35 | am not aware of an official way to discover these strings. I find them out 36 | by recording a macro that formats a specific cell and then checking out the 37 | resulting VBA code. From there you can read the \code{dataFormat} code. 38 | } 39 | \examples{ 40 | 41 | df <- DataFormat("#,##0.00") 42 | 43 | } 44 | \seealso{ 45 | \code{\link{CellStyle}} for using the a \code{DataFormat} object. 46 | } 47 | \author{ 48 | Adrian Dragulescu 49 | } 50 | -------------------------------------------------------------------------------- /man/Fill.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Fill.R 3 | \name{is.Fill} 4 | \alias{is.Fill} 5 | \alias{Fill} 6 | \title{Create an Fill object.} 7 | \usage{ 8 | is.Fill(x) 9 | 10 | Fill( 11 | foregroundColor = "lightblue", 12 | backgroundColor = "lightblue", 13 | pattern = "SOLID_FOREGROUND" 14 | ) 15 | } 16 | \arguments{ 17 | \item{x}{a Fill object, as returned by \code{Fill}.} 18 | 19 | \item{foregroundColor}{a character vector specifiying the foreground color. 20 | Any color names as returned by \code{\link[grDevices]{colors}} can be used. 21 | Or, a hex character, e.g. "#FF0000" for red. For Excel 95 workbooks, only a 22 | subset of colors is available, see the constant \code{INDEXED_COLORS_}.} 23 | 24 | \item{backgroundColor}{a character vector specifiying the foreground color. 25 | Any color names as returned by \code{\link[grDevices]{colors}} can be used. 26 | Or, a hex character, e.g. "#FF0000" for red. For Excel 95 workbooks, only a 27 | subset of colors is available, see the constant \code{INDEXED_COLORS_}.} 28 | 29 | \item{pattern}{a character vector specifying the fill pattern style. Valid 30 | values come from constant \code{FILL_STYLES_}.} 31 | } 32 | \value{ 33 | \code{Fill} returns a list with components from the input argument, 34 | and a class attribute "Fill". Fill objects are used when constructing cell 35 | styles. 36 | 37 | \code{is.Fill} returns \code{TRUE} if the argument is of class "Fill" and 38 | \code{FALSE} otherwise. 39 | } 40 | \description{ 41 | Create an Fill object, useful when working with cell styles. 42 | } 43 | \examples{ 44 | 45 | fill <- Fill() 46 | 47 | } 48 | \seealso{ 49 | \code{\link{CellStyle}} for using the a \code{Fill} object. 50 | } 51 | \author{ 52 | Adrian Dragulescu 53 | } 54 | -------------------------------------------------------------------------------- /man/Comment.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/comment.R 3 | \name{Comment} 4 | \alias{Comment} 5 | \alias{createCellComment} 6 | \alias{removeCellComment} 7 | \alias{getCellComment} 8 | \title{Functions to manipulate cell comments.} 9 | \usage{ 10 | createCellComment(cell, string, author = NULL, visible = TRUE) 11 | 12 | removeCellComment(cell) 13 | 14 | getCellComment(cell) 15 | } 16 | \arguments{ 17 | \item{cell}{a \code{Cell} object.} 18 | 19 | \item{string}{a string for the comment.} 20 | 21 | \item{author}{a string with the author's name} 22 | 23 | \item{visible}{a logical value. If \code{TRUE} the comment will be visible.} 24 | } 25 | \value{ 26 | \code{createCellComment} creates a \code{Comment} object. 27 | 28 | \code{getCellComment} returns a the \code{Comment} object if it exists. 29 | 30 | \code{removeCellComment} removes a comment from the given cell. 31 | } 32 | \description{ 33 | These functions are not vectorized. 34 | } 35 | \examples{ 36 | 37 | 38 | wb <- createWorkbook() 39 | sheet1 <- createSheet(wb, "Sheet1") 40 | rows <- createRow(sheet1, rowIndex=1:10) # 10 rows 41 | cells <- createCell(rows, colIndex=1:8) # 8 columns 42 | 43 | cell1 <- cells[[1,1]] 44 | setCellValue(cell1, 1) # add value 1 to cell A1 45 | 46 | # create a cell comment 47 | createCellComment(cell1, "Cogito", author="Descartes") 48 | 49 | 50 | # extract the comments 51 | comment <- getCellComment(cell1) 52 | stopifnot(comment$getAuthor()=="Descartes") 53 | stopifnot(comment$getString()$toString()=="Cogito") 54 | 55 | # don't forget to save your workbook! 56 | 57 | } 58 | \seealso{ 59 | For cells, see \code{\link{Cell}}. To format cells, see 60 | \code{\link{CellStyle}}. 61 | } 62 | \author{ 63 | Adrian Dragulescu 64 | } 65 | -------------------------------------------------------------------------------- /man/Alignment.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Alignment.R 3 | \name{is.Alignment} 4 | \alias{is.Alignment} 5 | \alias{Alignment} 6 | \title{Create an Alignment object.} 7 | \usage{ 8 | is.Alignment(x) 9 | 10 | Alignment( 11 | horizontal = NULL, 12 | vertical = NULL, 13 | wrapText = FALSE, 14 | rotation = 0, 15 | indent = 0 16 | ) 17 | } 18 | \arguments{ 19 | \item{x}{An Alignment object, as returned by \code{Alignment}.} 20 | 21 | \item{horizontal}{a character value specifying the horizontal alignment. 22 | Valid values come from constant \code{HALIGN_STYLES_}.} 23 | 24 | \item{vertical}{a character value specifying the vertical alignment. Valid 25 | values come from constant \code{VALIGN_STYLES_}.} 26 | 27 | \item{wrapText}{a logical indicating if the text should be wrapped.} 28 | 29 | \item{rotation}{a numerical value indicating the degrees you want to rotate 30 | the text in the cell.} 31 | 32 | \item{indent}{a numerical value indicating the number of spaces you want to 33 | indent the text in the cell.} 34 | } 35 | \value{ 36 | \code{Alignment} returns a list with components from the input 37 | argument, and a class attribute "Alignment". Alignment objects are used 38 | when constructing cell styles. 39 | 40 | \code{is.Alignment} returns \code{TRUE} if the argument is of class 41 | "Alignment" and \code{FALSE} otherwise. 42 | } 43 | \description{ 44 | Create an Alignment object, useful when working with cell styles. 45 | } 46 | \examples{ 47 | 48 | 49 | # you can just use h for horizontal, since R does the matching for you 50 | a1 <- Alignment(h="ALIGN_CENTER", rotation=90) # centered and rotated! 51 | 52 | } 53 | \seealso{ 54 | \code{\link{CellStyle}} for using the a \code{Alignment} object. 55 | } 56 | \author{ 57 | Adrian Dragulescu 58 | } 59 | -------------------------------------------------------------------------------- /man/readRows.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/readRows.R 3 | \name{readRows} 4 | \alias{readRows} 5 | \title{Read a contiguous set of rows into an R matrix} 6 | \usage{ 7 | readRows(sheet, startRow, endRow, startColumn, endColumn = NULL) 8 | } 9 | \arguments{ 10 | \item{sheet}{a \code{\link{Worksheet}} object.} 11 | 12 | \item{startRow}{a numeric value for the starting row.} 13 | 14 | \item{endRow}{a numeric value for the ending row. If \code{NULL} it reads 15 | all the rows in the sheet.} 16 | 17 | \item{startColumn}{a numeric value for the starting column.} 18 | 19 | \item{endColumn}{a numeric value for the ending column. Empty cells will be 20 | returned as "".} 21 | } 22 | \value{ 23 | A character matrix. 24 | } 25 | \description{ 26 | Read a contiguous set of rows into an R character matrix. Uses the 27 | \code{RInterface} for speed. 28 | } 29 | \details{ 30 | Use the \code{readRows} function when you want to read a row or a block 31 | block of data from an Excel worksheet. Internally, the loop over rows is 32 | done in R, and the loop over columns is done in Java, so this function 33 | achieves good performance when number of rows << number of columns. 34 | 35 | In general, you should prefer the function \code{\link{readColumns}} over 36 | this one. 37 | } 38 | \examples{ 39 | 40 | \dontrun{ 41 | 42 | file <- system.file("tests", "test_import.xlsx", package = "xlsx") 43 | 44 | wb <- loadWorkbook(file) 45 | sheets <- getSheets(wb) 46 | 47 | sheet <- sheets[["all"]] 48 | res <- readRows(sheet, startRow=3, endRow=7, startColumn=3, endColumn=10) 49 | 50 | 51 | 52 | } 53 | 54 | } 55 | \seealso{ 56 | \code{\link{read.xlsx2}} for reading entire sheets. See also 57 | \code{\link{addDataFrame}} for writing a \code{data.frame} to a sheet. 58 | } 59 | \author{ 60 | Adrian Dragulescu 61 | } 62 | -------------------------------------------------------------------------------- /tests/testthat/test-write.xlsx.R: -------------------------------------------------------------------------------- 1 | context('write.xlsx') 2 | 3 | test_that("can write to home directory", { 4 | # issue #108 5 | skip("broken at present") 6 | skip_on_cran() 7 | dat <- data.frame(1:10) 8 | filepath <- "~/__xx__xlsx__test_homedir.xlsx" 9 | 10 | # how can you protect such an operation? 11 | expect_null(write.xlsx(dat, file = filepath)) 12 | read.xlsx(filepath) 13 | unlink(filepath) 14 | }) 15 | 16 | test_that('DateTime classes work', { 17 | ## issue #45 18 | hours <- seq(as.POSIXct("2011-01-01 01:00:00", tz="GMT"), 19 | as.POSIXct("2011-01-01 10:00:00", tz="GMT"), by="1 hour") 20 | df <- data.frame(x=1:10, datetime=hours) 21 | 22 | write.xlsx(df, test_tmp("issue45.xlsx")) 23 | 24 | df.in <- read.xlsx2(test_tmp("issue45.xlsx"), sheetIndex=1, 25 | colClasses=c("numeric", "numeric", "POSIXct")) 26 | df.in$datetime <- round(df.in$datetime) 27 | 28 | expect_identical(as.numeric(df.in$datetime),as.numeric(hours)) 29 | }) 30 | 31 | test_that('works in pipeline', { 32 | test_complex_export('xls') 33 | test_complex_export('xlsx') 34 | }) 35 | 36 | context('write.xlsx2') 37 | 38 | test_that('write password protected workbook succeeds', { 39 | ## issue #49 40 | 41 | x <- data.frame(values=c(1,2,3),stringsAsFactors=FALSE) 42 | filename <- test_tmp('issue49.xlsx') 43 | 44 | ## write 45 | write.xlsx2(x, filename, password='test', row.names=FALSE) 46 | 47 | ## read 48 | r <- read.xlsx2(filename, sheetIndex = 1, password='test' 49 | , stringsAsFactors=FALSE 50 | , colClasses = 'numeric') 51 | 52 | expect_identical(x, r) 53 | }) 54 | 55 | context('low-level interface') 56 | 57 | test_that('works in pipeline', { 58 | skip_on_os(c("linux")) 59 | test_basic_export('xls') 60 | test_basic_export('xlsx') 61 | }) 62 | 63 | 64 | -------------------------------------------------------------------------------- /other/src/test/java/org/cran/rexcel/TestRInterface.java: -------------------------------------------------------------------------------- 1 | package org.cran.rexcel; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.io.File; 6 | 7 | //import java.io.InputStream; 8 | 9 | import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 10 | import org.apache.poi.ss.usermodel.Sheet; 11 | import org.apache.poi.ss.usermodel.Workbook; 12 | import org.apache.poi.ss.usermodel.WorkbookFactory; 13 | import org.junit.Test; 14 | 15 | public class TestRInterface { 16 | @Test 17 | public void readXLSX() throws InvalidFormatException, IOException { 18 | FileInputStream in = new FileInputStream(new File("../inst/tests/test_import.xlsx") ); 19 | Workbook wb = WorkbookFactory.create(in); 20 | Sheet sheet = wb.getSheetAt(7); 21 | 22 | RInterface R = new RInterface(); 23 | 24 | //String[] res = R.readRowStrings(sheet, 0, 10, 0); 25 | //String[] res = R.readColStrings(sheet, 1, 20, 1); 26 | double[] res = R.readColDoubles(sheet, 1, 10, 4); 27 | //double[] res = R.readColDoubles(sheet, 0, 2006, 0); 28 | for (int i=0; i trueEndColumn) { 79 | ## warning(paste("First row requested has only", trueEndColumn, "columns.")) 80 | ## endColumn <- min(endColumn, trueEndColumn) 81 | ## } 82 | 83 | -------------------------------------------------------------------------------- /tests/testthat/test-chart.R: -------------------------------------------------------------------------------- 1 | context('chart') 2 | 3 | test_that('basic example works', { 4 | ## issue #64 5 | skip('not currently supported') 6 | 7 | wb <- createWorkbook() 8 | sheet <- createSheet(wb, "mtcars") 9 | 10 | 11 | x <- 1:nrow(mtcars) 12 | y <- sort(mtcars$mpg) 13 | 14 | jDrawing <- sheet$createDrawingPatriarch(); 15 | anchor <- structure(c(0, 0, 0, 0, 0, 5, 10, 5), 16 | names=c('dx1', 'dx2', 'dy1', 'dy2', 'col1', 'row1', 'col2', 'row2')) 17 | jAnchor <- jDrawing$createAnchor(as.integer(anchor[1]), 18 | as.integer(anchor[2]), 19 | as.integer(anchor[3]), 20 | as.integer(anchor[4]), 21 | as.integer(anchor[5]), 22 | as.integer(anchor[6]), 23 | as.integer(anchor[7]), 24 | as.integer(anchor[8])) 25 | 26 | jChart <- jDrawing$createChart(jAnchor) 27 | 28 | # make the legend 29 | jLegend <- jChart$getOrCreateLegend() 30 | jLegend$setPosition(J('org.apache.poi.ss.usermodel.charts.LegendPosition')$TOP_RIGHT) 31 | 32 | 33 | # set up the data 34 | jX <- .jcall('org.apache.poi.ss.usermodel.charts.DataSources', 35 | "Lorg/apache/poi/ss/usermodel/charts/ChartDataSource;", 36 | "fromArray", 37 | .jcast(.jarray(x), '[Ljava/lang/Object;')) 38 | 39 | jY <- .jcall('org.apache.poi.ss.usermodel.charts.DataSources', 40 | "Lorg/apache/poi/ss/usermodel/charts/ChartDataSource;", 41 | "fromArray", 42 | .jcast(.jarray(y), '[Ljava/lang/Object;')) 43 | 44 | jData <- jChart$getChartDataFactory()$createScatterChartData() 45 | jData$addSerie(jX, jY) 46 | 47 | # now you can make axes 48 | jXAxis <- jChart$createValueAxis(J('org.apache.poi.ss.usermodel.charts.AxisPosition')$BOTTOM) 49 | jYAxis <- jChart$createValueAxis(J('org.apache.poi.ss.usermodel.charts.AxisPosition')$LEFT) 50 | 51 | # plot the chart 52 | # [8] "public void org.apache.poi.xssf.usermodel.XSSFChart.plot(org.apache.poi.ss.usermodel.charts.ChartData,org.apache.poi.ss.usermodel.charts.ChartAxis[])" 53 | 54 | jAxes <- .jarray(c(jXAxis, jYAxis)) 55 | 56 | # NOT WORKING YET! 57 | .jcall(jChart, 58 | "V", 59 | "plot", 60 | jData, 61 | .jcast(jAxes, "[Lorg/apache/poi/ss/usermodel/charts/ChartAxis;")) 62 | 63 | .jcall(jChart, 64 | "V", 65 | "plot", 66 | jData, 67 | jAxes) 68 | 69 | 70 | 71 | jChart$plot(jData, .jcast(.jarray(c(jXAxis, jYAxis)), '[Lorg/apache/poi/ss/usermodel/charts/ChartAxis;')) 72 | 73 | 74 | 75 | #addDataFrame(mtcars, sheet, row.names=FALSE) 76 | 77 | saveWorkbook(wb, test_tmp("issue64.xlsx")) 78 | }) 79 | -------------------------------------------------------------------------------- /man/xlsx-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/xlsx-package.R 3 | \docType{package} 4 | \name{xlsx-package} 5 | \alias{xlsx-package} 6 | \alias{xlsx} 7 | \title{Read, write, format Excel 2007 and Excel 97/2000/XP/2003 files} 8 | \description{ 9 | The \code{xlsx} package gives programatic control of Excel files using R. A 10 | high level API allows the user to read a sheet of an xlsx document into a 11 | \code{data.frame} and write a \code{data.frame} to a file. Lower level 12 | functionality permits the direct manipulation of sheets, rows and cells. 13 | For example, the user has control to set colors, fonts, data formats, add 14 | borders, hide/unhide sheets, add/remove rows, add/remove sheets, etc. 15 | } 16 | \details{ 17 | Behind the scenes, the \code{xlsx} package uses a java library from the 18 | Apache project, \url{https://poi.apache.org/index.html}. This Apache project 19 | provides a Java API to Microsoft Documents (Excel, Word, PowerPoint, 20 | Outlook, Visio, etc.) By using the \code{rJava} package that links and 21 | Java, we can piggyback on the excellent work already done by the folks at 22 | the Apache project and provide this functionality in R. The \code{xlsx} 23 | package uses only a subset of the Apache POI project, namely the one dealing 24 | with Excel files. All the necessary jar files are kept in package 25 | \code{xlsxjars} that is imported by package \code{xlsx}. 26 | 27 | A collection of tests that can be used as examples are located in folder 28 | \code{/tests/}. They are a good source of examples of how to use the 29 | package. 30 | 31 | Please see \url{https://github.com/colearendt/xlsx/} for a Wiki and the 32 | development version. To report a bug, use the Issues page at 33 | \url{https://github.com/colearendt/xlsx/issues}. 34 | 35 | \tabular{ll}{ Package: \tab xlsx\cr Type: \tab Package\cr Version: \tab 36 | 0.6.0\cr Date: \tab 2015-11-29\cr License: \tab GPL-3\cr } 37 | } 38 | \examples{ 39 | 40 | \dontrun{ 41 | 42 | library(xlsx) 43 | 44 | # example of reading xlsx sheets 45 | file <- system.file("tests", "test_import.xlsx", package = "xlsx") 46 | res <- read.xlsx(file, 2) # read the second sheet 47 | 48 | # example of writing xlsx sheets 49 | file <- paste(tempfile(), "xlsx", sep=".") 50 | write.xlsx(USArrests, file=file) 51 | 52 | } 53 | 54 | } 55 | \references{ 56 | Apache POI project for Microsoft Excel format: 57 | \url{https://poi.apache.org/components/spreadsheet/index.html}. 58 | 59 | The Java Doc detailing the classes: 60 | \url{https://poi.apache.org/apidocs/index.html}. This can be useful if you 61 | are looking for something that is not exposed in R as it may be available on 62 | the Java side. Inspecting the source code for some the the functions in 63 | this package can show you how to do it (even if you are Java shy.) 64 | } 65 | \seealso{ 66 | \code{\link{Workbook}} for ways to work with \code{Workbook} 67 | objects. 68 | } 69 | \keyword{package} 70 | -------------------------------------------------------------------------------- /tests/testthat/test-cellBlock.R: -------------------------------------------------------------------------------- 1 | context('setMatrixData') 2 | 3 | test_that('accepts character matrix', { 4 | # issue #19 5 | 6 | wb <- createWorkbook() 7 | sheet <- createSheet(wb) 8 | mtx <- matrix(c("hello", "world", "check1", "check2"), ncol=2) 9 | cb <- CellBlock(sheet, 1, 1, 2, 2) 10 | CB.setMatrixData(cb, mtx, 1, 1) 11 | fileName <- test_tmp("issue19.xlsx") 12 | saveWorkbook(wb, fileName) 13 | 14 | r <- read.xlsx2(fileName,1,header=FALSE,stringsAsFactors=FALSE) 15 | names(r) <- NULL 16 | r <- as.matrix(r) 17 | attr(r,'dimnames') <- NULL 18 | 19 | expect_identical( 20 | as.matrix(r) 21 | , mtx 22 | ) 23 | }) 24 | 25 | test_that('preserves existing formats', { 26 | ## issue #22 27 | 28 | fileIn <- test_ref("issue22.xlsx") 29 | fileOut <- test_tmp("issue22_out.xlsx") 30 | 31 | wb <- loadWorkbook(fileIn) 32 | sheets <- getSheets(wb) 33 | 34 | mat <- matrix(1:9, 3, 3) 35 | for (sheet in sheets) { 36 | if (sheet$getSheetName() == "Sheet1" ){ 37 | # need to create the rows for Sheet1 as it is empty! 38 | cb <- CellBlock(sheet, 1, 1, 3, 3, create = TRUE) 39 | } else { 40 | cb <- CellBlock(sheet, 1, 1, 3, 3, create = FALSE) 41 | } 42 | CB.setMatrixData(cb, mat, 1, 1) 43 | } 44 | saveWorkbook(wb, fileOut) 45 | 46 | wb <- loadWorkbook(fileOut) 47 | sheets <- getSheets(wb) 48 | 49 | cell1 <- getCells(getRows(sheets[[1]])) 50 | cell2 <- getCells(getRows(sheets[[2]])) 51 | cell3 <- getCells(getRows(sheets[[3]])) 52 | 53 | expect_null(unlist(unique(lapply(cell1,read_fill_foreground)))) 54 | expect_identical(as.character(unique(lapply(cell2,read_fill_foreground))),'ffff00') 55 | expect_identical(as.character(lapply(cell3,read_fill_foreground)) 56 | , c('ffff00','NULL','ffff00' 57 | ,'NULL','ffff00','NULL' 58 | ,'NULL','NULL','ffff00') 59 | ) 60 | }) 61 | 62 | 63 | test_that('formating applied to whole columns should not get lost in cell block formatting', { 64 | ## issue #32 65 | 66 | skip('not presently addressed') 67 | 68 | #using formatting on entire columns (A to L) 69 | wb <- loadWorkbook(test_ref("issue32_bad.xlsx")) 70 | sh <- getSheets(wb) 71 | s1 <- sh[[1]] 72 | 73 | cb <- CellBlock(sheet = s1, startRow = 1, startCol = 1, 74 | noRows = 11, noColumns = 50, create = FALSE) 75 | # some of the formatting is lost (col I to L, rows 1 to 11) 76 | saveWorkbook(wb, test_tmp("issue32_format_lost.xlsx") ) 77 | 78 | # the formatting is kept 79 | # using cells formatting only (columns A to L rows 1 to 10,000) 80 | wb <- loadWorkbook(test_ref("issue32_good.xlsx")) 81 | sh <- getSheets(wb) 82 | s1 <- sh[[1]] 83 | 84 | cb <- CellBlock(sheet = s1, startRow = 1, startCol = 1, 85 | noRows = 11, noColumns = 50, create = FALSE) 86 | saveWorkbook(wb, test_tmp("issue32_format_kept.xlsx")) 87 | 88 | expect_true(TRUE) 89 | }) 90 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to xlsx 2 | 3 | This outlines how to propose a change to xlsx. 4 | For more detailed info about contributing to this, and other tidyverse packages, please see the 5 | [**development contributing guide**](https://rstd.io/tidy-contrib). 6 | 7 | ## Fixing typos 8 | 9 | You can fix typos, spelling mistakes, or grammatical errors in the documentation directly using the GitHub web interface, as long as the changes are made in the _source_ file. 10 | This generally means you'll need to edit [roxygen2 comments](https://roxygen2.r-lib.org/articles/roxygen2.html) in an `.R`, not a `.Rd` file. 11 | You can find the `.R` file that generates the `.Rd` by reading the comment in the first line. 12 | 13 | ## Bigger changes 14 | 15 | If you want to make a bigger change, it's a good idea to first file an issue and make sure someone from the team agrees that it’s needed. 16 | If you’ve found a bug, please file an issue that illustrates the bug with a minimal 17 | [reprex](https://www.tidyverse.org/help/#reprex) (this will also help you write a unit test, if needed). 18 | 19 | ### Pull request process 20 | 21 | * Fork the package and clone onto your computer. If you haven't done this before, we recommend using `usethis::create_from_github("colearendt/xlsx", fork = TRUE)`. 22 | 23 | * Install all development dependences with `devtools::install_dev_deps()`, and then make sure the package passes R CMD check by running `devtools::check()`. 24 | If R CMD check doesn't pass cleanly, it's a good idea to ask for help before continuing. 25 | * Create a Git branch for your pull request (PR). We recommend using `usethis::pr_init("brief-description-of-change")`. 26 | 27 | * Make your changes, commit to git, and then create a PR by running `usethis::pr_push()`, and following the prompts in your browser. 28 | The title of your PR should briefly describe the change. 29 | The body of your PR should contain `Fixes #issue-number`. 30 | 31 | * For user-facing changes, add a bullet to the top of `NEWS.md` (i.e. just below the first header). Follow the style described in . 32 | 33 | ### Code style 34 | 35 | * New code should follow the tidyverse [style guide](https://style.tidyverse.org). 36 | You can use the [styler](https://CRAN.R-project.org/package=styler) package to apply these styles, but please don't restyle code that has nothing to do with your PR. 37 | 38 | * We use [roxygen2](https://cran.r-project.org/package=roxygen2), with [Markdown syntax](https://cran.r-project.org/web/packages/roxygen2/vignettes/rd-formatting.html), for documentation. 39 | 40 | * We use [testthat](https://cran.r-project.org/package=testthat) for unit tests. 41 | Contributions with test cases included are easier to accept. 42 | 43 | ## Code of Conduct 44 | 45 | Please note that the xlsx project is released with a 46 | [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By contributing to this 47 | project you agree to abide by its terms. 48 | -------------------------------------------------------------------------------- /R/xlsx-package.R: -------------------------------------------------------------------------------- 1 | #' Read, write, format Excel 2007 and Excel 97/2000/XP/2003 files 2 | #' 3 | #' The \code{xlsx} package gives programatic control of Excel files using R. A 4 | #' high level API allows the user to read a sheet of an xlsx document into a 5 | #' \code{data.frame} and write a \code{data.frame} to a file. Lower level 6 | #' functionality permits the direct manipulation of sheets, rows and cells. 7 | #' For example, the user has control to set colors, fonts, data formats, add 8 | #' borders, hide/unhide sheets, add/remove rows, add/remove sheets, etc. 9 | #' 10 | #' Behind the scenes, the \code{xlsx} package uses a java library from the 11 | #' Apache project, \url{https://poi.apache.org/index.html}. This Apache project 12 | #' provides a Java API to Microsoft Documents (Excel, Word, PowerPoint, 13 | #' Outlook, Visio, etc.) By using the \code{rJava} package that links and 14 | #' Java, we can piggyback on the excellent work already done by the folks at 15 | #' the Apache project and provide this functionality in R. The \code{xlsx} 16 | #' package uses only a subset of the Apache POI project, namely the one dealing 17 | #' with Excel files. All the necessary jar files are kept in package 18 | #' \code{xlsxjars} that is imported by package \code{xlsx}. 19 | #' 20 | #' A collection of tests that can be used as examples are located in folder 21 | #' \code{/tests/}. They are a good source of examples of how to use the 22 | #' package. 23 | #' 24 | #' Please see \url{https://github.com/colearendt/xlsx/} for a Wiki and the 25 | #' development version. To report a bug, use the Issues page at 26 | #' \url{https://github.com/colearendt/xlsx/issues}. 27 | #' 28 | #' \tabular{ll}{ Package: \tab xlsx\cr Type: \tab Package\cr Version: \tab 29 | #' 0.6.0\cr Date: \tab 2015-11-29\cr License: \tab GPL-3\cr } 30 | #' 31 | #' @aliases xlsx-package xlsx 32 | #' @docType package 33 | #' 34 | #' @seealso \code{\link{Workbook}} for ways to work with \code{Workbook} 35 | #' objects. 36 | #' @references Apache POI project for Microsoft Excel format: 37 | #' \url{https://poi.apache.org/components/spreadsheet/index.html}. 38 | #' 39 | #' The Java Doc detailing the classes: 40 | #' \url{https://poi.apache.org/apidocs/index.html}. This can be useful if you 41 | #' are looking for something that is not exposed in R as it may be available on 42 | #' the Java side. Inspecting the source code for some the the functions in 43 | #' this package can show you how to do it (even if you are Java shy.) 44 | #' @keywords package 45 | #' @examples 46 | #' 47 | #' \dontrun{ 48 | #' 49 | #' library(xlsx) 50 | #' 51 | #' # example of reading xlsx sheets 52 | #' file <- system.file("tests", "test_import.xlsx", package = "xlsx") 53 | #' res <- read.xlsx(file, 2) # read the second sheet 54 | #' 55 | #' # example of writing xlsx sheets 56 | #' file <- paste(tempfile(), "xlsx", sep=".") 57 | #' write.xlsx(USArrests, file=file) 58 | #' 59 | #' } 60 | #' 61 | #' @import rJava 62 | #' @import xlsxjars 63 | #' @importFrom utils unzip 64 | #' @importFrom utils zip 65 | #' @name xlsx-package 66 | NULL 67 | -------------------------------------------------------------------------------- /R/comment.R: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # create ONE comment 3 | 4 | #' Functions to manipulate cell comments. 5 | #' 6 | #' These functions are not vectorized. 7 | #' 8 | #' @param cell a \code{Cell} object. 9 | #' @param string a string for the comment. 10 | #' @param author a string with the author's name 11 | #' @param visible a logical value. If \code{TRUE} the comment will be visible. 12 | #' @return 13 | #' 14 | #' \code{createCellComment} creates a \code{Comment} object. 15 | #' 16 | #' \code{getCellComment} returns a the \code{Comment} object if it exists. 17 | #' 18 | #' \code{removeCellComment} removes a comment from the given cell. 19 | #' @author Adrian Dragulescu 20 | #' @seealso For cells, see \code{\link{Cell}}. To format cells, see 21 | #' \code{\link{CellStyle}}. 22 | #' @examples 23 | #' 24 | #' 25 | #' wb <- createWorkbook() 26 | #' sheet1 <- createSheet(wb, "Sheet1") 27 | #' rows <- createRow(sheet1, rowIndex=1:10) # 10 rows 28 | #' cells <- createCell(rows, colIndex=1:8) # 8 columns 29 | #' 30 | #' cell1 <- cells[[1,1]] 31 | #' setCellValue(cell1, 1) # add value 1 to cell A1 32 | #' 33 | #' # create a cell comment 34 | #' createCellComment(cell1, "Cogito", author="Descartes") 35 | #' 36 | #' 37 | #' # extract the comments 38 | #' comment <- getCellComment(cell1) 39 | #' stopifnot(comment$getAuthor()=="Descartes") 40 | #' stopifnot(comment$getString()$toString()=="Cogito") 41 | #' 42 | #' # don't forget to save your workbook! 43 | #' 44 | #' @export 45 | #' @name Comment 46 | createCellComment <- function(cell, string, 47 | author=NULL, visible=TRUE) 48 | { 49 | sheet <- .jcall(cell, 50 | "Lorg/apache/poi/ss/usermodel/Sheet;", "getSheet") 51 | wb <- .jcall(sheet, 52 | "Lorg/apache/poi/ss/usermodel/Workbook;", "getWorkbook") 53 | 54 | factory <- .jcall(wb, 55 | "Lorg/apache/poi/ss/usermodel/CreationHelper;", "getCreationHelper") 56 | 57 | anchor <- .jcall(factory, 58 | "Lorg/apache/poi/ss/usermodel/ClientAnchor;", "createClientAnchor") 59 | 60 | drawing <- .jcall(sheet, 61 | "Lorg/apache/poi/ss/usermodel/Drawing;", "createDrawingPatriarch") 62 | 63 | comment <- .jcall(drawing, 64 | "Lorg/apache/poi/ss/usermodel/Comment;", "createCellComment", anchor) 65 | 66 | rtstring <- factory$createRichTextString(string) # rich text string 67 | 68 | comment$setString(rtstring) 69 | if (!is.null(author)) 70 | .jcall(comment, "V", "setAuthor", author) 71 | if (visible) 72 | .jcall(cell, "V", "setCellComment", comment) 73 | 74 | invisible(comment) 75 | } 76 | 77 | #' @export 78 | #' @rdname Comment 79 | removeCellComment <- function(cell){ 80 | .jcall(cell, "V", "removeCellComment") 81 | } 82 | 83 | ## setCellComment <- function(cell, comment){ 84 | ## .jcall(cell, "V", "setCellComment", comment) 85 | ## } 86 | 87 | #' @export 88 | #' @rdname Comment 89 | getCellComment <- function(cell) 90 | { 91 | comment <- .jcall(cell, "Lorg/apache/poi/ss/usermodel/Comment;", 92 | "getCellComment") 93 | 94 | comment 95 | } 96 | -------------------------------------------------------------------------------- /R/PrintSetup.R: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # work with print setup 3 | # 4 | #' Function to manipulate print setup. 5 | #' 6 | #' Other settings are available but not exposed. Please see the java docs. 7 | #' 8 | #' @aliases printSetup PrintSetup 9 | #' @param sheet a worksheet object \code{\link{Worksheet}}. 10 | #' @param fitHeight numeric value to set the number of pages high to fit the 11 | #' sheet in. 12 | #' @param fitWidth numeric value to set the number of pages wide to fit the 13 | #' sheet in. 14 | #' @param copies numeric value to set the number of copies. 15 | #' @param draft logical indicating if it's a draft or not. 16 | #' @param footerMargin numeric value to set the footer margin. 17 | #' @param headerMargin numeric value to set the header margin. 18 | #' @param landscape logical value to specify the paper orientation. 19 | #' @param pageStart numeric value from where to start the page numbering. 20 | #' @param paperSize character to set the paper size. Valid values are 21 | #' "A4_PAPERSIZE", "A5_PAPERSIZE", "ENVELOPE_10_PAPERSIZE", 22 | #' "ENVELOPE_CS_PAPERSIZE", "ENVELOPE_DL_PAPERSIZE", 23 | #' "ENVELOPE_MONARCH_PAPERSIZE", "EXECUTIVE_PAPERSIZE", "LEGAL_PAPERSIZE", 24 | #' "LETTER_PAPERSIZE". 25 | #' @param noColor logical value to indicate if the prints should be color or 26 | #' not. 27 | #' @return A reference to a java PrintSetup object. 28 | #' @author Adrian Dragulescu 29 | #' @examples 30 | #' 31 | #' 32 | #' wb <- createWorkbook() 33 | #' sheet <- createSheet(wb, "Sheet1") 34 | #' ps <- printSetup(sheet, landscape=TRUE, copies=3) 35 | #' 36 | #' 37 | #' @export 38 | #' @name PrintSetup 39 | printSetup <- function(sheet, fitHeight=NULL, 40 | fitWidth=NULL, copies=NULL, draft=NULL, footerMargin=NULL, 41 | headerMargin=NULL, landscape=FALSE, pageStart=NULL, paperSize=NULL, 42 | noColor=NULL) 43 | { 44 | ps <- .jcall(sheet, "Lorg/apache/poi/ss/usermodel/PrintSetup;", 45 | "getPrintSetup") 46 | 47 | if (!is.null(fitHeight)) 48 | .jcall(ps, "V", "setFitHeight", .jshort(fitHeight)) 49 | 50 | if (!is.null(fitWidth)) 51 | .jcall(ps, "V", "setFitWidth", .jshort(fitWidth)) 52 | 53 | if (!is.null(copies)) 54 | .jcall(ps, "V", "setCopies", .jshort(copies)) 55 | 56 | if (!is.null(draft)) 57 | .jcall(ps, "V", "setDraft", draft) 58 | 59 | if (!is.null(footerMargin)) 60 | .jcall(ps, "V", "setFooterMargin", footerMargin) 61 | 62 | if (!is.null(headerMargin)) 63 | .jcall(ps, "V", "setHeaderMargin", headerMargin) 64 | 65 | if (!is.null(landscape)) 66 | .jcall(ps, "V", "setLandscape", as.logical(landscape)) 67 | 68 | if (!is.null(pageStart)) 69 | .jcall(ps, "V", "setPageStart", .jshort(pageStart)) 70 | 71 | if (!is.null(paperSize)){ 72 | pagesizeInd <- .jfield(ps, NULL, paperSize) 73 | .jcall(ps, "V", "setPaperSize", .jshort(pagesizeInd)) 74 | } 75 | 76 | if (!is.null(noColor)) 77 | .jcall(ps, "V", "setNoColor", noColor) 78 | 79 | ps 80 | } 81 | 82 | 83 | ## if (setAutobreaks) 84 | ## .jcall(sheet, "V", "setAutobreaks", ) 85 | 86 | -------------------------------------------------------------------------------- /man/CellStyle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/CellStyle.R 3 | \name{CellStyle} 4 | \alias{CellStyle} 5 | \alias{is.CellStyle} 6 | \alias{CellStyle.default} 7 | \alias{setCellStyle} 8 | \alias{getCellStyle} 9 | \title{Functions to manipulate cells.} 10 | \usage{ 11 | CellStyle( 12 | wb, 13 | dataFormat = NULL, 14 | alignment = NULL, 15 | border = NULL, 16 | fill = NULL, 17 | font = NULL, 18 | cellProtection = NULL 19 | ) 20 | 21 | is.CellStyle(x) 22 | 23 | \method{CellStyle}{default}( 24 | wb, 25 | dataFormat = NULL, 26 | alignment = NULL, 27 | border = NULL, 28 | fill = NULL, 29 | font = NULL, 30 | cellProtection = NULL 31 | ) 32 | 33 | setCellStyle(cell, cellStyle) 34 | 35 | getCellStyle(cell) 36 | } 37 | \arguments{ 38 | \item{wb}{a workbook object as returned by \code{\link{createWorkbook}} or 39 | \code{\link{loadWorkbook}}.} 40 | 41 | \item{dataFormat}{a \code{\link{DataFormat}} object.} 42 | 43 | \item{alignment}{a \code{\link{Alignment}} object.} 44 | 45 | \item{border}{a \code{\link{Border}} object.} 46 | 47 | \item{fill}{a \code{\link{Fill}} object.} 48 | 49 | \item{font}{a \code{\link{Font}} object.} 50 | 51 | \item{cellProtection}{a \code{\link{CellProtection}} object.} 52 | 53 | \item{x}{a \code{CellStyle} object.} 54 | 55 | \item{cell}{a \code{\link{Cell}} object.} 56 | 57 | \item{cellStyle}{a \code{CellStyle} object.} 58 | } 59 | \value{ 60 | \code{createCellStyle} creates a CellStyle object. 61 | 62 | \code{is.CellStyle} returns \code{TRUE} if the argument is of class 63 | "CellStyle" and \code{FALSE} otherwise. 64 | } 65 | \description{ 66 | Create and set cell styles. 67 | } 68 | \details{ 69 | \code{setCellStyle} sets the \code{CellStyle} to one \code{Cell} object. 70 | 71 | You need to have a \code{Workbook} object to attach a \code{CellStyle} 72 | object to it. 73 | 74 | Since OS X 10.5 Apple dropped support for AWT on the main thread, so 75 | essentially you cannot use any graphics classes in R on OS X 10.5 since R is 76 | single-threaded. (verbatim from Simon Urbanek). This implies that setting 77 | colors on Mac will not work as is! A set of about 50 basic colors are still 78 | available please see the javadocs. 79 | 80 | For Excel 95/2000/XP/2003 the choice of colors is limited. See 81 | \code{INDEXED_COLORS_} for the list of available colors. 82 | 83 | Unspecified values for arguments are taken from the system locale. 84 | } 85 | \examples{ 86 | 87 | \dontrun{ 88 | wb <- createWorkbook() 89 | sheet <- createSheet(wb, "Sheet1") 90 | 91 | rows <- createRow(sheet, rowIndex=1) 92 | 93 | cell.1 <- createCell(rows, colIndex=1)[[1,1]] 94 | setCellValue(cell.1, "Hello R!") 95 | 96 | cs <- CellStyle(wb) + 97 | Font(wb, heightInPoints=20, isBold=TRUE, isItalic=TRUE, 98 | name="Courier New", color="orange") + 99 | Fill(backgroundColor="lavender", foregroundColor="lavender", 100 | pattern="SOLID_FOREGROUND") + 101 | Alignment(h="ALIGN_RIGHT") 102 | 103 | setCellStyle(cell.1, cellStyle1) 104 | 105 | # you need to save the workbook now if you want to see this art 106 | } 107 | } 108 | \author{ 109 | Adrian Dragulescu 110 | } 111 | -------------------------------------------------------------------------------- /man/write.xlsx.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/write.xlsx.R, R/write.xlsx2.R 3 | \name{write.xlsx} 4 | \alias{write.xlsx} 5 | \alias{write.xlsx2} 6 | \title{Write a data.frame to an Excel workbook.} 7 | \usage{ 8 | write.xlsx( 9 | x, 10 | file, 11 | sheetName = "Sheet1", 12 | col.names = TRUE, 13 | row.names = TRUE, 14 | append = FALSE, 15 | showNA = TRUE, 16 | password = NULL 17 | ) 18 | 19 | write.xlsx2( 20 | x, 21 | file, 22 | sheetName = "Sheet1", 23 | col.names = TRUE, 24 | row.names = TRUE, 25 | append = FALSE, 26 | password = NULL, 27 | ... 28 | ) 29 | } 30 | \arguments{ 31 | \item{x}{a \code{data.frame} to write to the workbook.} 32 | 33 | \item{file}{the path to the output file.} 34 | 35 | \item{sheetName}{a character string with the sheet name.} 36 | 37 | \item{col.names}{a logical value indicating if the column names of \code{x} 38 | are to be written along with \code{x} to the file.} 39 | 40 | \item{row.names}{a logical value indicating whether the row names of 41 | \code{x} are to be written along with \code{x} to the file.} 42 | 43 | \item{append}{a logical value indicating if \code{x} should be appended to 44 | an existing file. If \code{TRUE} the file is read from disk.} 45 | 46 | \item{showNA}{a logical value. If set to \code{FALSE}, NA values will be 47 | left as empty cells.} 48 | 49 | \item{password}{a String with the password.} 50 | 51 | \item{...}{other arguments to \code{addDataFrame} in the case of 52 | \code{read.xlsx2}.} 53 | } 54 | \description{ 55 | Write a \code{data.frame} to an Excel workbook. 56 | } 57 | \details{ 58 | This function provides a high level API for writing a \code{data.frame} to 59 | an Excel 2007 worksheet. It calls several low level functions in the 60 | process. Its goal is to provide the conveniency of 61 | \code{\link[utils]{write.csv}} by borrowing from its signature. 62 | 63 | Internally, \code{write.xlsx} uses a double loop in over all the elements of 64 | the \code{data.frame} so performance for very large \code{data.frame} may be 65 | an issue. Please report if you experience slow performance. Dates and 66 | POSIXct classes are formatted separately after the insertion. This also 67 | adds to processing time. 68 | 69 | If \code{x} is not a \code{data.frame} it will be converted to one. 70 | 71 | Function \code{write.xlsx2} uses \code{addDataFrame} which speeds up the 72 | execution compared to \code{write.xlsx} by an order of magnitude for large 73 | spreadsheets (with more than 100,000 cells). 74 | 75 | The default formats for Date and DateTime columns can be changed via the two 76 | package options \code{xlsx.date.format} and \code{xlsx.datetime.format}. 77 | They need to be specified in Java date format 78 | \url{https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html}. 79 | 80 | Writing of password protected workbooks is supported for Excel 2007 OOXML 81 | format only. Note that in Linux, LibreOffice is not able to read password 82 | protected spreadsheets. 83 | } 84 | \examples{ 85 | 86 | \dontrun{ 87 | 88 | file <- paste(tempdir(), "/usarrests.xlsx", sep="") 89 | res <- write.xlsx(USArrests, file) 90 | 91 | # to change the default date format 92 | oldOpt <- options() 93 | options(xlsx.date.format="dd MMM, yyyy") 94 | write.xlsx(x, sheet) # where x is a data.frame with a Date column. 95 | options(oldOpt) # revert back to defaults 96 | 97 | } 98 | 99 | } 100 | \seealso{ 101 | \code{\link{read.xlsx}} for reading \code{xlsx} documents. See 102 | also \code{\link{addDataFrame}} for writing a \code{data.frame} to a sheet. 103 | } 104 | \author{ 105 | Adrian Dragulescu 106 | } 107 | -------------------------------------------------------------------------------- /R/Font.R: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Deal with Fonts 3 | #' @export 4 | #' @rdname Font 5 | is.Font <- function(x) inherits(x, "Font") 6 | 7 | 8 | ###################################################################### 9 | # Create a Font. It needs a workbook object! 10 | # - color is an R color string. 11 | # 12 | #' Create a Font object. 13 | #' 14 | #' Create a Font object. 15 | #' 16 | #' Default values for \code{NULL} parameters are taken from Excel. So the 17 | #' default font color is black, the default font name is "Calibri", and the 18 | #' font height in points is 11. 19 | #' 20 | #' For Excel 95/2000/XP/2003, it is impossible to set the font to bold. This 21 | #' limitation may be removed in the future. 22 | #' 23 | #' NOTE: You need to have a \code{Workbook} object to attach a \code{Font} 24 | #' object to it. 25 | #' 26 | #' @aliases Font is.Font 27 | #' @param wb a workbook object as returned by \code{\link{createWorkbook}} or 28 | #' \code{\link{loadWorkbook}}. 29 | #' @param color a character specifiying the font color. Any color names as 30 | #' returned by \code{\link[grDevices]{colors}} can be used. Or, a hex 31 | #' character, e.g. "#FF0000" for red. For Excel 95 workbooks, only a subset of 32 | #' colors is available, see the constant \code{INDEXED_COLORS_}. 33 | #' @param heightInPoints a numeric value specifying the font height. Usual 34 | #' values are 10, 12, 14, etc. 35 | #' @param name a character value for the font to use. All values that you see 36 | #' in Excel should be available, e.g. "Courier New". 37 | #' @param isItalic a logical indicating the font should be italic. 38 | #' @param isStrikeout a logical indicating the font should be stiked out. 39 | #' @param isBold a logical indicating the font should be bold. 40 | #' @param underline a numeric value specifying the thickness of the underline. 41 | #' Allowed values are 0, 1, 2. 42 | #' @param boldweight a numeric value indicating bold weight. Normal is 400, 43 | #' regular bold is 700. 44 | #' @param x A Font object, as returned by \code{Font}. 45 | #' @return \code{Font} returns a list with a java reference to a \code{Font} 46 | #' object, and a class attribute "Font". 47 | #' 48 | #' \code{is.Font} returns \code{TRUE} if the argument is of class "Font" and 49 | #' \code{FALSE} otherwise. 50 | #' @author Adrian Dragulescu 51 | #' @seealso \code{\link{CellStyle}} for using the a \code{Font} object. 52 | #' @examples 53 | #' 54 | #' \dontrun{ 55 | #' font <- Font(wb, color="blue", isItalic=TRUE) 56 | #' } 57 | #' 58 | #' @export 59 | Font <- function(wb, color=NULL, heightInPoints=NULL, name=NULL, 60 | isItalic=FALSE, isStrikeout=FALSE, isBold=FALSE, underline=NULL, 61 | boldweight=NULL) # , setFamily=NULL 62 | { 63 | font <- .jcall(wb, "Lorg/apache/poi/ss/usermodel/Font;", 64 | "createFont") 65 | 66 | if (!is.null(color)) 67 | if (grepl("XSSF", wb$getClass()$getName())){ 68 | .jcall(font, "V", "setColor", .xssfcolor(color)) 69 | } else { 70 | .jcall(font, "V", "setColor", 71 | .jshort(INDEXED_COLORS_[toupper(color)])) 72 | } 73 | 74 | if (!is.null(heightInPoints)) 75 | .jcall(font, "V", "setFontHeightInPoints", .jshort(heightInPoints)) 76 | 77 | if (!is.null(name)) 78 | .jcall(font, "V", "setFontName", name) 79 | 80 | if (isItalic) 81 | .jcall(font, "V", "setItalic", TRUE) 82 | 83 | if (isStrikeout) 84 | .jcall(font, "V", "setStrikeout", TRUE) 85 | 86 | if (isBold & grepl("XSSF", wb$getClass()$getName())) 87 | .jcall(font, "V", "setBold", TRUE) 88 | 89 | if (!is.null(underline)) 90 | .jcall(font, "V", "setUnderline", .jbyte(underline)) 91 | 92 | if (!is.null(boldweight)) 93 | .jcall(font, "V", "setBoldweight", .jshort(boldweight)) 94 | 95 | structure(list(ref=font), class="Font") 96 | } 97 | -------------------------------------------------------------------------------- /man/readColumns.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/readColumns.R 3 | \name{readColumns} 4 | \alias{readColumns} 5 | \title{Read a contiguous set of columns from sheet into an R data.frame} 6 | \usage{ 7 | readColumns( 8 | sheet, 9 | startColumn, 10 | endColumn, 11 | startRow, 12 | endRow = NULL, 13 | as.data.frame = TRUE, 14 | header = TRUE, 15 | colClasses = NA, 16 | ... 17 | ) 18 | } 19 | \arguments{ 20 | \item{sheet}{a \code{\link{Worksheet}} object.} 21 | 22 | \item{startColumn}{a numeric value for the starting column.} 23 | 24 | \item{endColumn}{a numeric value for the ending column.} 25 | 26 | \item{startRow}{a numeric value for the starting row.} 27 | 28 | \item{endRow}{a numeric value for the ending row. If \code{NULL} it reads 29 | all the rows in the sheet. If you request more than the existing rows in 30 | the sheet, the result will be truncated by the actual row number.} 31 | 32 | \item{as.data.frame}{a logical value indicating if the result should be 33 | coerced into a \code{data.frame}. If \code{FALSE}, the result is a list 34 | with one element for each column.} 35 | 36 | \item{header}{a logical value indicating whether the first row corresponding 37 | to the first element of the \code{rowIndex} vector contains the names of the 38 | variables.} 39 | 40 | \item{colClasses}{a character vector that represents the class of each 41 | column. Recycled as necessary, or if \code{NA} an attempt is made to guess 42 | the type of each column by reading the first row of data. Only 43 | \code{numeric}, \code{character}, \code{Date}, \code{POSIXct}, column types 44 | are accepted. Anything else will be coverted to a \code{character} type. 45 | If the length is less than the number of columns requested, replicate it.} 46 | 47 | \item{...}{other arguments to \code{data.frame}, for example 48 | \code{stringsAsFactors}} 49 | } 50 | \value{ 51 | A data.frame or a list, depending on the \code{as.data.frame} 52 | argument. 53 | } 54 | \description{ 55 | Read a contiguous set of columns from sheet into an R data.frame. Uses the 56 | \code{RInterface} for speed. 57 | } 58 | \details{ 59 | Use the \code{readColumns} function when you want to read a rectangular 60 | block of data from an Excel worksheet. If you request columns which are 61 | blank, these will be read in as empty character "" columns. Internally, the 62 | loop over columns is done in R, the loop over rows is done in Java, so this 63 | function achieves good performance when number of rows >> number of columns. 64 | 65 | Excel internally stores dates and datetimes as numeric values, and does not 66 | keep track of time zones and DST. When a numeric column is formatted as a 67 | datetime, it will be converted into \code{POSIXct} class with a \emph{GMT} 68 | timezone. If you need a \code{Date} column, you need to specify explicitly 69 | using \code{colClasses} argument. 70 | 71 | For a numeric column Excels's errors and blank cells will be returned as NaN 72 | values. Excel's \code{#N/A} will be returned as NA. Formulas will be 73 | evaluated. For a chracter column, blank cells will be returned as "". 74 | } 75 | \examples{ 76 | 77 | \dontrun{ 78 | 79 | file <- system.file("tests", "test_import.xlsx", package = "xlsx") 80 | 81 | wb <- loadWorkbook(file) 82 | sheets <- getSheets(wb) 83 | 84 | sheet <- sheets[["all"]] 85 | res <- readColumns(sheet, startColumn=3, endColumn=10, startRow=3, 86 | endRow=7) 87 | 88 | sheet <- sheets[["NAs"]] 89 | res <- readColumns(sheet, 1, 6, 1, colClasses=c("Date", "character", 90 | "integer", rep("numeric", 2), "POSIXct")) 91 | 92 | 93 | } 94 | 95 | } 96 | \seealso{ 97 | \code{\link{read.xlsx2}} for reading entire sheets. See also 98 | \code{\link{addDataFrame}} for writing a \code{data.frame} to a sheet. 99 | } 100 | \author{ 101 | Adrian Dragulescu 102 | } 103 | -------------------------------------------------------------------------------- /man/Cell.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Cell.R 3 | \name{Cell} 4 | \alias{Cell} 5 | \alias{createCell} 6 | \alias{getCells} 7 | \alias{setCellValue} 8 | \alias{getCellValue} 9 | \title{Functions to manipulate cells.} 10 | \usage{ 11 | createCell(row, colIndex = 1:5) 12 | 13 | getCells(row, colIndex = NULL, simplify = TRUE) 14 | 15 | setCellValue(cell, value, richTextString = FALSE, showNA = TRUE) 16 | 17 | getCellValue(cell, keepFormulas = FALSE, encoding = "unknown") 18 | } 19 | \arguments{ 20 | \item{row}{a list of row objects. See \code{Row}.} 21 | 22 | \item{colIndex}{a numeric vector specifying the index of columns.} 23 | 24 | \item{simplify}{a logical value. If \code{TRUE}, the result will be 25 | unlisted.} 26 | 27 | \item{cell}{a \code{Cell} object.} 28 | 29 | \item{value}{an R variable of length one.} 30 | 31 | \item{richTextString}{a logical value indicating if the value should be 32 | inserted into the Excel cell as rich text.} 33 | 34 | \item{showNA}{a logical value. If \code{TRUE} the cell will contain the 35 | "#N/A" value, if \code{FALSE} they will be skipped. The default value was 36 | chosen to remain compatible with previous versions of the function.} 37 | 38 | \item{keepFormulas}{a logical value. If \code{TRUE} the formulas will be 39 | returned as characters instead of being explicitly evaluated.} 40 | 41 | \item{encoding}{A character value to set the encoding, for example "UTF-8".} 42 | } 43 | \value{ 44 | \code{createCell} creates a matrix of lists, each element of the list being 45 | a java object reference to an object of type Cell representing an empty 46 | cell. The dimnames of this matrix are taken from the names of the rows and 47 | the \code{colIndex} variable. 48 | 49 | \code{getCells} returns a list of java object references for all the cells 50 | in the row if \code{colIndex} is \code{NULL}. If you want to extract only a 51 | specific columns, set \code{colIndex} to the column indices you are 52 | interested. 53 | 54 | \code{getCellValue} returns the value in the cell as an R object. Type 55 | conversions are done behind the scene. This function is not vectorized. 56 | } 57 | \description{ 58 | Functions to manipulate cells. 59 | } 60 | \details{ 61 | \code{setCellValue} writes the content of an R variable into the cell. 62 | \code{Date} and \code{POSIXct} objects are passed in as numerical values. 63 | To format them as dates in Excel see \code{\link{CellStyle}}. 64 | 65 | These functions are not vectorized and should be used only for small 66 | spreadsheets. Use \code{CellBlock} functionality to efficiently read/write 67 | parts of a spreadsheet. 68 | } 69 | \examples{ 70 | 71 | 72 | file <- system.file("tests", "test_import.xlsx", package = "xlsx") 73 | 74 | wb <- loadWorkbook(file) 75 | sheets <- getSheets(wb) 76 | 77 | sheet <- sheets[['mixedTypes']] # get second sheet 78 | rows <- getRows(sheet) # get all the rows 79 | 80 | cells <- getCells(rows) # returns all non empty cells 81 | 82 | values <- lapply(cells, getCellValue) # extract the values 83 | 84 | # write the months of the year in the first column of the spreadsheet 85 | ind <- paste(2:13, ".2", sep="") 86 | mapply(setCellValue, cells[ind], month.name) 87 | 88 | #################################################################### 89 | # make a new workbook with one sheet and 5x5 cells 90 | wb <- createWorkbook() 91 | sheet <- createSheet(wb, "Sheet1") 92 | rows <- createRow(sheet, rowIndex=1:5) 93 | cells <- createCell(rows, colIndex=1:5) 94 | 95 | # populate the first column with Dates 96 | days <- seq(as.Date("2013-01-01"), by="1 day", length.out=5) 97 | mapply(setCellValue, cells[,1], days) 98 | 99 | 100 | 101 | } 102 | \seealso{ 103 | To format cells, see \code{\link{CellStyle}}. For rows see 104 | \code{\link{Row}}, for sheets see \code{\link{Sheet}}. 105 | } 106 | \author{ 107 | Adrian Dragulescu 108 | } 109 | -------------------------------------------------------------------------------- /tests/testthat/test-CellStyle.R: -------------------------------------------------------------------------------- 1 | context('CellStyle') 2 | 3 | test_that('Font + Fill did not set the font', { 4 | ## issue #41 5 | wb <- createWorkbook() 6 | cs <- CellStyle(wb) + 7 | Font(wb, heightInPoints=25, isBold=TRUE, isItalic=TRUE, color="red", name="Arial") + 8 | Fill(backgroundColor="lavender", foregroundColor="lavender", pattern="SOLID_FOREGROUND") + 9 | Alignment(h="ALIGN_RIGHT") 10 | 11 | expect_false(is.null(cs$font$ref)) 12 | }) 13 | 14 | test_that('CellStyle + Font overwrites font', { 15 | ## not checking attributes at present... because there is not a nice way to do so 16 | wb <- createWorkbook() 17 | 18 | f1 <- Font(wb, heightInPoints=12, isBold=TRUE, isItalic=FALSE, color='black', name='Arial') 19 | cs <- CellStyle(wb) + f1 20 | 21 | f2 <- Font(wb, heightInPoints=10, isBold=FALSE, isItalic=TRUE, color='red', name='Calibri') 22 | cs2 <- cs + f2 23 | 24 | expect_identical(cs$font,f1) 25 | expect_identical(cs2$font,f2) 26 | }) 27 | 28 | test_that('CellStyle + DataFormat overwrites DataFormat', { 29 | wb <- createWorkbook() 30 | 31 | df1 <- DataFormat('mm/dd/yyyy') 32 | cs <- CellStyle(wb) + df1 33 | 34 | df2 <- DataFormat('0.0') 35 | cs2 <- cs + df2 36 | 37 | expect_identical(df1,cs$dataFormat) 38 | expect_identical(df2,cs2$dataFormat) 39 | }) 40 | 41 | test_that('CellStyle + Fill overwrites Fill', { 42 | wb <- createWorkbook() 43 | 44 | f1 <- Fill('red','red','SOLID_FOREGROUND') 45 | cs <- CellStyle(wb) + f1 46 | 47 | f2 <- Fill('black','black','SOLID_FOREGROUND') 48 | cs2 <- cs + f2 49 | 50 | expect_identical(f1,cs$fill) 51 | expect_identical(f2,cs2$fill) 52 | }) 53 | 54 | test_that('CellStyle + Border overwrites Border', { 55 | wb <- createWorkbook() 56 | 57 | b1 <- Border(color='black',position=c('BOTTOM','TOP'),pen=c('BORDER_THIN','BORDER_THICK')) 58 | cs <- CellStyle(wb) + b1 59 | 60 | b2 <- Border(color='black', position=c('LEFT','RIGHT'),pen=c('BORDER_THICK','BORDER_THIN')) 61 | cs2 <- cs + b2 62 | 63 | expect_identical(b1,cs$border) 64 | expect_identical(b2,cs2$border) 65 | }) 66 | 67 | test_that('CellStyle + Alignment overwrites Alignment', { 68 | wb <- createWorkbook() 69 | 70 | a1 <- Alignment(horizontal='ALIGN_CENTER', vertical = 'VERTICAL_TOP', wrapText = FALSE) 71 | cs <- CellStyle(wb) + a1 72 | 73 | a2 <- Alignment(horizontal='ALIGN_LEFT', vertical='VERTICAL_CENTER', wrapText=TRUE) 74 | cs2 <- CellStyle(wb) + a2 75 | 76 | expect_identical(a1, cs$alignment) 77 | expect_identical(a2, cs2$alignment) 78 | }) 79 | 80 | test_that('CellStyle + CellProtection overwrites CellProtection', { 81 | wb <- createWorkbook() 82 | 83 | cp1 <- CellProtection(locked=FALSE,hidden=TRUE) 84 | cs <- CellStyle(wb) + cp1 85 | 86 | cp2 <- CellProtection(locked=TRUE,hidden=FALSE) 87 | cs2 <- CellStyle(wb) + cp2 88 | 89 | expect_identical(cp1, cs$cellProtection) 90 | expect_identical(cp2, cs2$cellProtection) 91 | }) 92 | 93 | context('Font') 94 | 95 | test_that('color black set properly', { 96 | ## https://bz.apache.org/bugzilla/show_bug.cgi?id=51236 97 | ## fixed in 3.14, apparently 98 | skip('Not presently working') 99 | ## issue #21 100 | wb <- createWorkbook() 101 | tmp <- Font(wb, color="black") 102 | 103 | tmp2 <- Font(wb, color=NULL) 104 | 105 | expect_match(capture_output(print(tmp$ref)),'.* 2 | [![CRAN Version](https://www.r-pkg.org/badges/version-last-release/xlsx)](https://CRAN.R-project.org/package=xlsx) 3 | [![Codecov test coverage](https://codecov.io/gh/colearendt/xlsx/branch/main/graph/badge.svg)](https://codecov.io/gh/colearendt/xlsx?branch=main) 4 | [![R-CMD-check](https://github.com/colearendt/xlsx/workflows/R-CMD-check/badge.svg)](https://github.com/colearendt/xlsx/actions) 5 | [![CRAN Activity](https://cranlogs.r-pkg.org/badges/xlsx)](https://CRAN.R-project.org/package=xlsx) 6 | [![CRAN History](https://cranlogs.r-pkg.org/badges/grand-total/xlsx)](https://CRAN.R-project.org/package=xlsx) 7 | 8 | 9 | xlsx 10 | ======== 11 | 12 | **An R package to read, write, format Excel 2007 and Excel 97/2000/XP/2003 files** 13 | 14 | The package provides R functions to read, write, and format Excel files. It depends 15 | on Java, but this makes it available on most operating systems. 16 | 17 | ## Install 18 | 19 | Stable version from CRAN 20 | 21 | ```r 22 | install.packages('xlsx') 23 | ``` 24 | 25 | Or development version from GitHub 26 | 27 | ```r 28 | devtools::install_github('colearendt/xlsx') 29 | ``` 30 | 31 | ## Common Problems 32 | 33 | This package depends on Java and the [`rJava`](https://www.rforge.net/rJava/) package to make the connection between R and Java seamless. In order to use the `xlsx` package, you will need to: 34 | 35 | - Ensure you have a `jdk` (Java Development Kit, version >= 1.5) installed for your Operating System. More information can be found on [Oracle's website](https://www.oracle.com/java/technologies/javase-downloads.html) 36 | 37 | - Ensure that the system environment variable `JAVA_HOME` is configured appropriately and points to your `jdk` of choice. Typically, this will be included in your `PATH` environment variable as well. Options and system environmental variables that are available from `R` can be seen with `Sys.getenv()` 38 | 39 | - Particularly on UNIX systems, if you continue experiencing issues, you may need to reconfigure `R`'s support for Java on your system. From a terminal, use the command `R CMD javareconf`. You may need to run this as root or prepended with `sudo` to ensure it has appropriate permission. 40 | 41 | More detail can be found in the [`rJava` docs](https://www.rforge.net/rJava/). 42 | 43 | ## Quick start 44 | 45 | To read the first sheet from spreadsheet into a data.frame 46 | 47 | ```r 48 | read.xlsx2('file.xlsx', 1) 49 | ``` 50 | To write a data.frame to a spreadsheet 51 | ```r 52 | write.xlsx2(iris, file='iris.xlsx') 53 | ``` 54 | 55 | The package has many functions that make it easy to style and 56 | formalize output into Excel, as well. 57 | 58 | ```r 59 | wb <- createWorkbook() 60 | s <- createSheet(wb,'test') 61 | 62 | cs <- CellStyle(wb) + 63 | Font(wb,heightInPoints = 16, isBold = TRUE) + 64 | Alignment(horizontal='ALIGN_CENTER') 65 | 66 | 67 | r <- createRow(s,1) 68 | cell <- createCell(r,1:ncol(iris)) 69 | 70 | setCellValue(cell[[1]],'Title for Iris') 71 | for (i in cell) { 72 | setCellStyle(i,cs) 73 | } 74 | 75 | addMergedRegion(s, 1,1, 1,ncol(iris)) 76 | 77 | addDataFrame(iris, s, row.names=FALSE, startRow=3) 78 | 79 | saveWorkbook(wb,'iris_pretty.xlsx') 80 | ``` 81 | 82 | ## Issues/Mailing list 83 | 84 | To report a bug, use the Issues page at: https://github.com/colearendt/xlsx/issues 85 | 86 | If you are wrestling with the Java dependency, there are some very good 87 | alternatives that do not require Java. Your choice will vary depending on what 88 | you are trying to accomplish. 89 | 90 | - [openxlsx](https://github.com/awalker89/openxlsx) 91 | - [readxl](https://readxl.tidyverse.org/) 92 | - [writexl](https://docs.ropensci.org/writexl/) 93 | 94 | ## Acknowledgements 95 | 96 | The package is made possible thanks to the excellent 97 | work on [Apache POI](https://poi.apache.org/components/spreadsheet/index.html). 98 | 99 | ## Code of Conduct 100 | 101 | Please note that the xlsx project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/0/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. 102 | -------------------------------------------------------------------------------- /tests/testthat/test-read.xlsx.R: -------------------------------------------------------------------------------- 1 | context('read.xlsx') 2 | 3 | test_that('#N/A values are not imported as FALSE', { 4 | ## issue #7 5 | skip('not presently working') 6 | 7 | file <- test_ref("issue7.xlsx") 8 | res <- read.xlsx(file, sheetIndex=1, rowIndex=2:5, colIndex=2:3) 9 | 10 | wb <- loadWorkbook(file) 11 | sheet <- getSheets(wb)[[1]] 12 | rows <- getRows(sheet) # get all the rows 13 | 14 | cells <- getCells(rows["4"]) # returns all non empty cells 15 | cell <- cells[["4.2"]] 16 | value <- getCellValue(cell) 17 | 18 | expect_true(is.na(value)) 19 | }) 20 | 21 | test_that('works for tables that start in the middle of the sheet', { 22 | ##issue #9 23 | file <- test_ref("test_import.xlsx") 24 | 25 | #source(paste(DIR, "rexcel/trunk/R/read.xlsx.R", sep="")) 26 | try(res <- read.xlsx(file, sheetName="issue9", rowIndex=3:5, colIndex=3:5)) 27 | 28 | expect_is(class(res),"character") 29 | }) 30 | 31 | test_that('read improperly constructed .xls files', { 32 | ## issue #11 33 | file <- test_ref("read_xlsx2_example.xlsx") 34 | res <- read.xlsx(file, sheetIndex=1, header=FALSE) 35 | 36 | expect_is(res,'data.frame') 37 | }) 38 | 39 | test_that('read does not fail on empty sheets', { 40 | ## issue #28 41 | file <- test_ref("issue25.xlsx") 42 | 43 | # reads Sheet2 which is empty 44 | res <- read.xlsx(file, sheetIndex=2) 45 | res2 <- read.xlsx2(file, sheetIndex=2) 46 | 47 | expect_null(res) 48 | expect_null(res2) 49 | }) 50 | 51 | test_that('read.xlsx fails on empty row', { 52 | ## issue #57 53 | try(aux <- read.xlsx(test_ref("issue57.xlsx"), sheetIndex=1)) 54 | 55 | expect_is(aux,'data.frame') 56 | }) 57 | 58 | test_that('works in complex pipeline', { 59 | skip("Not working on mac R 3.3.3") 60 | test_complex_read.xlsx('xls') 61 | test_complex_read.xlsx('xlsx') 62 | }) 63 | 64 | test_that('read password protected workbook succeeds', { 65 | ## issue #49 66 | filename <- test_ref('issue49_password=test.xlsx') 67 | df <- read.xlsx(filename, sheetIndex=1, password='test', stringsAsFactors=FALSE) 68 | 69 | expect_identical(df,data.frame(Values=c(1,2,3),stringsAsFactors=FALSE)) 70 | }) 71 | 72 | context('read.xlsx2') 73 | 74 | test_that('columns of data (as formulas) are not read in as NA', { 75 | ## issue #2 76 | file <- test_ref("xlxs2Test.xlsx") 77 | res <- read.xlsx2(file, sheetName="data", startRow=2, endRow=10, 78 | colIndex=c(1,3:5,7:9), colClasses=c("character",rep("numeric",6)) ) 79 | 80 | expect_false(any(is.na(res))) 81 | }) 82 | 83 | test_that('does not evaluate formulas - values are NA', { 84 | skip('does not presently work') 85 | ## issues #12 86 | file <- test_ref("test_import.xlsx") 87 | try(res <- read.xlsx2(file, sheetName="formulas", 88 | colClasses=list("numeric", "numeric", "character"))) 89 | expect_true(is.na(res[1,3])) 90 | }) 91 | 92 | test_that('read improperly constructed .xls files', { 93 | ## issue #16 94 | file <- test_ref("issue12.xlsx") 95 | try(res <- read.xlsx2(file, sheetIndex=1, colIndex=1:3, startRow=3)) 96 | 97 | expect_is(res,'data.frame') 98 | }) 99 | 100 | test_that('integer cells read as characters are read cleanly', { 101 | ## issue #25 102 | file <- test_ref("issue25.xlsx") 103 | 104 | # reads element [35,1] as a double and then transforms it to a factor 105 | res1 <- read.xlsx2(file, sheetIndex=1, header=TRUE, startRow=1, 106 | colClasses=c("character", rep("numeric", 5)), stringsAsFactors=FALSE) 107 | 108 | expect_equal(res1[35,2],250829) 109 | }) 110 | 111 | test_that('no argument rowIndex, and maybe it should be', { 112 | ## issue #58 113 | skip('need to add rowIndex argument') 114 | try(aux <- read.xlsx2(test_ref("issue58.xlsx"), sheetIndex=1, 115 | rowIndex=1:8)) 116 | }) 117 | 118 | test_that('works in complex pipeline', { 119 | test_complex_read.xlsx2('xls') 120 | test_complex_read.xlsx2('xlsx') 121 | }) 122 | 123 | test_that('read password protected workbook succeeds', { 124 | ## issue #49 125 | filename <- test_ref('issue49_password=test.xlsx') 126 | df <- read.xlsx2(filename, sheetIndex=1, password='test',stringsAsFactors=FALSE) 127 | 128 | expect_identical(df,data.frame(Values=c('1','2','3'),stringsAsFactors=FALSE)) 129 | }) 130 | 131 | context('low-level interface') 132 | 133 | test_that('works in pipeline', { 134 | test_basic_import('xlsx') 135 | test_basic_import('xls') 136 | }) 137 | -------------------------------------------------------------------------------- /man/OtherEffects.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/otherEffects.R 3 | \name{OtherEffects} 4 | \alias{OtherEffects} 5 | \alias{addAutoFilter} 6 | \alias{addMergedRegion} 7 | \alias{removeMergedRegion} 8 | \alias{autoSizeColumn} 9 | \alias{createFreezePane} 10 | \alias{createSplitPane} 11 | \alias{setColumnWidth} 12 | \alias{setPrintArea} 13 | \alias{setZoom} 14 | \title{Functions to do various spreadsheets effects.} 15 | \usage{ 16 | addAutoFilter(sheet, cellRange) 17 | 18 | addMergedRegion(sheet, startRow, endRow, startColumn, endColumn) 19 | 20 | removeMergedRegion(sheet, ind) 21 | 22 | autoSizeColumn(sheet, colIndex) 23 | 24 | createFreezePane( 25 | sheet, 26 | rowSplit, 27 | colSplit, 28 | startRow = NULL, 29 | startColumn = NULL 30 | ) 31 | 32 | createSplitPane( 33 | sheet, 34 | xSplitPos = 2000, 35 | ySplitPos = 2000, 36 | startRow = 1, 37 | startColumn = 1, 38 | position = "PANE_LOWER_LEFT" 39 | ) 40 | 41 | setColumnWidth(sheet, colIndex, colWidth) 42 | 43 | setPrintArea(wb, sheetIndex, startColumn, endColumn, startRow, endRow) 44 | 45 | setZoom(sheet, numerator = 100, denominator = 100) 46 | } 47 | \arguments{ 48 | \item{sheet}{a \code{\link{Worksheet}} object.} 49 | 50 | \item{cellRange}{a string specifying the cell range. For example a standard 51 | area ref (e.g. "B1:D8"). May be a single cell ref (e.g. "B5") in which case 52 | the result is a 1 x 1 cell range. May also be a whole row range (e.g. 53 | "3:5"), or a whole column range (e.g. "C:F")} 54 | 55 | \item{startRow}{a numeric value for the starting row.} 56 | 57 | \item{endRow}{a numeric value for the ending row.} 58 | 59 | \item{startColumn}{a numeric value for the starting column.} 60 | 61 | \item{endColumn}{a numeric value for the ending column.} 62 | 63 | \item{ind}{a numeric value indicating which merged region you want to 64 | remove.} 65 | 66 | \item{colIndex}{a numeric vector specifiying the columns you want to auto 67 | size.} 68 | 69 | \item{rowSplit}{a numeric value for the row to split.} 70 | 71 | \item{colSplit}{a numeric value for the column to split.} 72 | 73 | \item{xSplitPos}{a numeric value for the horizontal position of split in 74 | 1/20 of a point.} 75 | 76 | \item{ySplitPos}{a numeric value for the vertical position of split in 1/20 77 | of a point.} 78 | 79 | \item{position}{a character. Valid value are "PANE_LOWER_LEFT", 80 | "PANE_LOWER_RIGHT", "PANE_UPPER_LEFT", "PANE_UPPER_RIGHT".} 81 | 82 | \item{colWidth}{a numeric value to specify the width of the column. The 83 | units are in 1/256ths of a character width.} 84 | 85 | \item{wb}{a \code{\link{Workbook}} object.} 86 | 87 | \item{sheetIndex}{a numeric value for the worksheet index.} 88 | 89 | \item{numerator}{a numeric value representing the numerator of the zoom 90 | ratio.} 91 | 92 | \item{denominator}{a numeric value representing the denomiator of the zoom 93 | ratio.} 94 | } 95 | \value{ 96 | \code{addMergedRegion} returns a numeric value to label the merged 97 | region. You should use this value as the \code{ind} if you want to 98 | \code{removeMergedRegion}. 99 | } 100 | \description{ 101 | Function \code{autoSizeColumn} expands the column width to match the column 102 | contents thus removing the ###### that you get when cell contents are larger 103 | than cell width. 104 | } 105 | \details{ 106 | You may need other functionality that is not exposed. Take a look at the 107 | java docs and the source code of these functions for how you can implement 108 | it in R. 109 | } 110 | \examples{ 111 | 112 | 113 | wb <- createWorkbook() 114 | sheet1 <- createSheet(wb, "Sheet1") 115 | rows <- createRow(sheet1, 1:10) # 10 rows 116 | cells <- createCell(rows, colIndex=1:8) # 8 columns 117 | 118 | ## Merge cells 119 | setCellValue(cells[[1,1]], "A title that spans 3 columns") 120 | addMergedRegion(sheet1, 1, 1, 1, 3) 121 | 122 | ## Set zoom 2:1 123 | setZoom(sheet1, 200, 100) 124 | 125 | sheet2 <- createSheet(wb, "Sheet2") 126 | rows <- createRow(sheet2, 1:10) # 10 rows 127 | cells <- createCell(rows, colIndex=1:8) # 8 columns 128 | #createFreezePane(sheet2, 1, 1, 1, 1) 129 | createFreezePane(sheet2, 5, 5, 8, 8) 130 | 131 | sheet3 <- createSheet(wb, "Sheet3") 132 | rows <- createRow(sheet3, 1:10) # 10 rows 133 | cells <- createCell(rows, colIndex=1:8) # 8 columns 134 | createSplitPane(sheet3, 2000, 2000, 1, 1, "PANE_LOWER_LEFT") 135 | 136 | # set the column width of first column to 25 characters wide 137 | setColumnWidth(sheet1, 1, 25) 138 | 139 | # add a filter on the 3rd row, columns C:E 140 | addAutoFilter(sheet1, "C3:E3") 141 | 142 | # Don't forget to save the workbook ... 143 | 144 | } 145 | \author{ 146 | Adrian Dragulescu 147 | } 148 | -------------------------------------------------------------------------------- /inst/tests/test.import.R: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | 5 | test.import <- function(outdir="C:/Temp/", type="xlsx", 6 | speedtest=FALSE) 7 | { 8 | cat("##################################################\n") 9 | cat("Test reading xlsx files into R\n") 10 | cat("##################################################\n") 11 | filename <- paste("test_import.", type, sep="") 12 | file <- system.file("tests", filename, package="xlsx") 13 | 14 | cat("Load test_import.xlsx ... ") 15 | wb <- loadWorkbook(file) 16 | cat("OK\n") 17 | sheets <- getSheets(wb) 18 | 19 | cat("Get the second sheet with mixedTypes ... ") 20 | sheet <- sheets[[2]] 21 | rows <- getRows(sheet) 22 | cells <- getCells(rows) 23 | values <- lapply(cells, getCellValue) 24 | 25 | cat("Extract cell [5,2] and see if == 'Apr' ...") 26 | stopifnot(values[["5.2"]] == "Apr") 27 | cat("OK\n") 28 | 29 | orig <- getOption("stringsAsFactors") 30 | options(stringsAsFactors=FALSE) 31 | cat("Test high level import\n") 32 | cat("Read data in second sheet ...\n") 33 | res <- read.xlsx(file, 2) 34 | cat("First column is of class Dates ... ") 35 | stopifnot(class(res[,1])=="Date") 36 | cat("OK\n") 37 | cat("Second column is of class character ... ") 38 | stopifnot(class(res[,2])=="character") 39 | cat("OK\n") 40 | cat("Third column is of class numeric ... ") 41 | stopifnot(class(res[,3])=="numeric") 42 | cat("OK\n") 43 | cat("Fourth column is of class logical ... ") 44 | stopifnot(class(res[,4])=="logical") 45 | cat("OK\n") 46 | cat("Sixth column is of class POSIXct ... ") 47 | stopifnot(inherits(res[,6], "POSIXct")) 48 | cat("OK\n\n") 49 | options(stringsAsFactors=orig) 50 | 51 | cat("Some cells are errors because of wrong formulas\n") 52 | print(res) # some cells are errors because of wrong formulas 53 | cat("OK\n") 54 | 55 | cat("Test high level import keeping formulas... \n") 56 | res <- read.xlsx(file, 2, keepFormulas=TRUE) 57 | cat("Now showing the formulas explicitly\n") 58 | print(res) 59 | cat("OK\n") 60 | 61 | cat("Test high level import with colClasses.\n") 62 | cat("Force conversion of 5th column to numeric.\n") 63 | colClasses <- rep(NA, length=6); colClasses[5] <- "numeric" 64 | res <- read.xlsx(file, 2, colClasses=colClasses) 65 | print(res) # force convesion to numeric 66 | cat("OK\n") 67 | 68 | cat("Test you can import sheet one column... \n") 69 | res <- read.xlsx(file, "oneColumn", keepFormulas=TRUE) 70 | if (ncol(res)==1) {cat("OK\n")} else {cat("FAILED!\n")} 71 | 72 | cat("Check that you can import String formulas ... \n") 73 | res <- read.xlsx(file, "formulas", keepFormulas=FALSE) 74 | if (res[1,3]=="2010-1") {cat("OK\n")} else {cat("FAILED!\n")} 75 | 76 | if (speedtest){ 77 | require(xlsx) 78 | colClasses <- c("numeric", rep("character", 76)) 79 | res <- read.xlsx2("C:/Temp/ModelList.xlsx", sheetName="Models", 80 | colClasses=colClasses) 81 | 82 | } 83 | 84 | cat("######################################################\n") 85 | cat("Test read.xlsx2 ...\n") 86 | cat("######################################################\n") 87 | 88 | res <- read.xlsx2(file, sheetName="mixedTypes") 89 | res <- read.xlsx2(file, sheetName="mixedTypes", colClasses=c( 90 | "numeric", "character", rep("numeric", 4))) 91 | 92 | res <- read.xlsx2(file, sheetName="mixedTypes", startRow=2, noRows=3) 93 | 94 | 95 | 96 | 97 | cat("######################################################\n") 98 | cat("Test low level import ...\n") 99 | cat("######################################################\n") 100 | file <- system.file("tests", filename, package="xlsx") 101 | 102 | wb <- loadWorkbook(file) 103 | sheets <- getSheets(wb) 104 | sheet <- sheets[['deletedFields']] 105 | 106 | cat("Check that you can extract only some rows (say 5) ...") 107 | rows <- getRows(sheet, rowIndex=1:5) 108 | cells <- getCells(rows) 109 | res <- lapply(cells, getCellValue) 110 | rr <- unique(sapply(strsplit(names(res), "\\."), "[[", 1)) 111 | stopifnot(identical(rr, c("1","2","3","4", "5"))) 112 | cat("OK\n") 113 | 114 | cat("Check that you can extract only some columns (say 4) ...") 115 | rows <- getRows(sheet) 116 | cells <- getCells(rows, colIndex=1:4) 117 | res <- lapply(cells, getCellValue) 118 | cols <- unique(sapply(strsplit(names(res), "\\."), "[[", 2)) 119 | stopifnot(identical(cols, c("1","2","3","4"))) 120 | cat("OK\n") 121 | 122 | cat("Check that you can extract a matrix (say 2:3, 1:3) ... \n") 123 | sheet <- sheets[['mixedTypes']] 124 | vv <- getMatrixValues(sheet, 2:3, 1:3) 125 | print(vv) 126 | cat("OK\n") 127 | 128 | 129 | } 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /inst/xlsx.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Build Excel Reports from R" 3 | author: "Adrian A. Dragulescu" 4 | date: "`r Sys.Date()`" 5 | output: 6 | rmarkdown::html_vignette: 7 | toc: true 8 | number_sections: true 9 | Vignette: > 10 | %\VignetteIndexEntry{Read, write, format Excel 2007 (xlsx) files} 11 | %\VignetteEngine{knitr::rmarkdown} 12 | %\VignetteEncoding{UTF-8} 13 | %\VignetteKeywords{spreadsheet, Excel 2007, java} 14 | %\VignettePackage{xlsx} 15 | abstract: The `xlsx` package provides tools neccessary to interact with 16 | Excel 2007 files from R. The user can read and write xlsx files, and 17 | can control the appearance of the spreadsheet by setting data formats, 18 | fonts, colors, borders. Set the print area, the zoom control, create 19 | split and freeze panels, adding headers and footers. The package uses 20 | a java library from the Apache POI project. 21 | --- 22 | 23 | ```{r setup, echo=FALSE, message=FALSE} 24 | knitr::opts_chunk$set(echo=TRUE, collapse=T, comment='#>') 25 | library(RefManageR) 26 | bib <- ReadBib('xlsx.bib') 27 | BibOptions(check.entries = FALSE, style = "markdown", cite.style = "numeric",bib.style = "numeric") 28 | ``` 29 | 30 | # Introduction 31 | 32 | The package `xlsx` makes possible to interact with Excel 2007 files from R `r 33 | Cite(bib,'R-base')`. While a power R user usually does not need to use Excel or 34 | even avoids it altogether, there are cases when being able to generate Excel 35 | output or read Excel files into R is a must. One such case is in an office 36 | environment when you need to collaborate with co-workers who use Excel as their 37 | primary tool. Another case is to use Excel for basic reporting of results. For 38 | moderate data sets, the formatting capabilities of Excel can prove useful. A 39 | flexible way to manipulate Excel 2007 xlsx files from R would then be a nice 40 | addition. 41 | 42 | The `xlsx` package focuses on Excel 2007 because for Excel 97 there are already 43 | several solutions, `RODBC` `r Cite(bib,'RODBC')`, `readxl``r 44 | Cite(bib,'readxl')`, etc. While some of these packages work with Excel 2007 45 | files too, the contribution of the `xlsx` package is different. 46 | 47 | The xlsx Excel 2007 file format is essentially a zipped set of xml 48 | files. It is possible to interact directly with these files from R 49 | as shown by the package `RExcelXML``r Cite(bib,'RExcelXML')`. All the 50 | functionality of the `xlsx` package can be replicated with 51 | `RExcelXML` package or by extending it. Working directly with 52 | the zipped xml files, and using the xml schema to extract the useful 53 | information into R gives you ultimate control. 54 | 55 | The approach taken in the `xlsx` package is to use a proven, 56 | existing API between Java and Excel 2007 and use the `rJava` 57 | `r Cite(bib,'rJava')` package to link Java and R. The advantage of this 58 | approach is that the code on the R side is very compact, easy to 59 | maintain, and easy to extend even for people with little Java 60 | experience. All the heavy lifting of parsing XML schemas is being 61 | done in Java. We also benefit from a mature software project with 62 | many developers, test suites, and users that report issues on the Java 63 | side. In principle, this should make the maintainance of the 64 | `xlsx` package easy. The Java API used by the `xlsx` is one 65 | project of the Apache Software Foundation, called Apache POI and can 66 | be found at [https://poi.apache.org/](https://poi.apache.org/). 67 | 68 | The Apache POI Project's mission is to create and maintain Java APIs 69 | for manipulating various file formats based upon the Office Open XML 70 | standards (OOXML) and Microsoft's OLE 2 Compound Document format 71 | (OLE2). These include Excel, Word, and PowerPoint documents. While 72 | the focus of the `xlsx` package has been only on Excel files, extensions for 73 | Word and PowerPoint documents are available in the 74 | [ReporteRs](https://CRAN.R-project.org/package=ReporteRs) 75 | package. 76 | 77 | That said, sometimes using Java from R can be a bit tricky to configure and work 78 | with. While using Apache POI allows us to benefit from a robust Java community, 79 | others might prefer to use a C++ API and `Rcpp` to interact with the raw XML in 80 | a way more natural to R. For more reading on this approach, see the 81 | [openxlsx](https://CRAN.R-project.org/package=openxlsx) 82 | package or [officer](https://CRAN.R-project.org/package=officer) 83 | (for Word / PowerPoint). 84 | 85 | # High level API 86 | 87 | See `read.xlsx` for reading the sheet of an xlsx file into a 88 | data.frame. See `write.xlsx` writing a data.frame to an xlsx 89 | file. 90 | 91 | # Low level API 92 | 93 | See `Workbook` for creating workbooks. See `Worksheet` for 94 | code to manipulate worksheets. See `Cell` for manipulating 95 | cells. 96 | 97 | See `OtherEffects` for various spreadsheet effects, for example, 98 | merge cells, auto size columns, create freeze panels, create split 99 | panels, set print area, set the zoom, etc. 100 | 101 | Use `PrintSetup` for customizing the settings for printing. 102 | 103 | ## Cell Formatting 104 | 105 | See `CellStyle` for how to format a particular cell. 106 | 107 | Use `Font` to set a font. 108 | 109 | # Conclusion 110 | 111 | By adding a lightweight R layer on top of the Apache project Java 112 | interface to Excel 2007 documents, we achieve a multi-platform 113 | solution for interacting with Excel 2007 file formats from R. 114 | 115 | # References 116 | 117 | ```{r results = "asis", echo = FALSE} 118 | PrintBibliography(bib, .opts = list(check.entries = FALSE, sorting = "ynt")) 119 | ``` 120 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards 42 | of acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies 54 | when an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail 56 | address, posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at [INSERT CONTACT 63 | METHOD]. All complaints will be reviewed and investigated promptly and fairly. 64 | 65 | All community leaders are obligated to respect the privacy and security of the 66 | reporter of any incident. 67 | 68 | ## Enforcement Guidelines 69 | 70 | Community leaders will follow these Community Impact Guidelines in determining 71 | the consequences for any action they deem in violation of this Code of Conduct: 72 | 73 | ### 1. Correction 74 | 75 | **Community Impact**: Use of inappropriate language or other behavior deemed 76 | unprofessional or unwelcome in the community. 77 | 78 | **Consequence**: A private, written warning from community leaders, providing 79 | clarity around the nature of the violation and an explanation of why the 80 | behavior was inappropriate. A public apology may be requested. 81 | 82 | ### 2. Warning 83 | 84 | **Community Impact**: A violation through a single incident or series of 85 | actions. 86 | 87 | **Consequence**: A warning with consequences for continued behavior. No 88 | interaction with the people involved, including unsolicited interaction with 89 | those enforcing the Code of Conduct, for a specified period of time. This 90 | includes avoiding interactions in community spaces as well as external channels 91 | like social media. Violating these terms may lead to a temporary or permanent 92 | ban. 93 | 94 | ### 3. Temporary Ban 95 | 96 | **Community Impact**: A serious violation of community standards, including 97 | sustained inappropriate behavior. 98 | 99 | **Consequence**: A temporary ban from any sort of interaction or public 100 | communication with the community for a specified period of time. No public or 101 | private interaction with the people involved, including unsolicited interaction 102 | with those enforcing the Code of Conduct, is allowed during this period. 103 | Violating these terms may lead to a permanent ban. 104 | 105 | ### 4. Permanent Ban 106 | 107 | **Community Impact**: Demonstrating a pattern of violation of community 108 | standards, including sustained inappropriate behavior, harassment of an 109 | individual, or aggression toward or disparagement of classes of individuals. 110 | 111 | **Consequence**: A permanent ban from any sort of public interaction within the 112 | community. 113 | 114 | ## Attribution 115 | 116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 117 | version 2.0, 118 | available at https://www.contributor-covenant.org/version/2/0/ 119 | code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at https:// 128 | www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /R/write.xlsx.R: -------------------------------------------------------------------------------- 1 | # Write a data.frame to a new xlsx file. 2 | # A convenience function. 3 | # 4 | 5 | # System.gc() # to call the garbage collection in Java 6 | 7 | ####################################################################### 8 | # NO rownames for this function. Just the contents of the data.frame! 9 | # have showNA=TRUE for legacy reason 10 | # 11 | .write_block <- function(wb, sheet, y, rowIndex=seq_len(nrow(y)), 12 | colIndex=seq_len(ncol(y)), showNA=TRUE) 13 | { 14 | rows <- createRow(sheet, rowIndex) # create rows 15 | cells <- createCell(rows, colIndex) # create cells 16 | 17 | for (ic in seq_len(ncol(y))) 18 | mapply(setCellValue, cells[seq_len(nrow(cells)), colIndex[ic]], y[,ic], FALSE, showNA) 19 | 20 | # Date and POSIXct classes need to be formatted 21 | indDT <- which(sapply(y, function(x) inherits(x, "Date"))) 22 | if (length(indDT) > 0) { 23 | dateFormat <- CellStyle(wb) + DataFormat(getOption("xlsx.date.format")) 24 | for (ic in indDT){ 25 | lapply(cells[seq_len(nrow(cells)),colIndex[ic]], setCellStyle, dateFormat) 26 | } 27 | } 28 | 29 | indDT <- which(sapply(y, function(x) inherits(x, "POSIXct"))) 30 | if (length(indDT) > 0) { 31 | datetimeFormat <- CellStyle(wb) + DataFormat(getOption("xlsx.datetime.format")) 32 | for (ic in indDT){ 33 | lapply(cells[seq_len(nrow(cells)),colIndex[ic]], setCellStyle, datetimeFormat) 34 | } 35 | } 36 | 37 | } 38 | 39 | 40 | ####################################################################### 41 | # High-level API 42 | # 43 | #' Write a data.frame to an Excel workbook. 44 | #' 45 | #' Write a \code{data.frame} to an Excel workbook. 46 | #' 47 | #' 48 | #' This function provides a high level API for writing a \code{data.frame} to 49 | #' an Excel 2007 worksheet. It calls several low level functions in the 50 | #' process. Its goal is to provide the conveniency of 51 | #' \code{\link[utils]{write.csv}} by borrowing from its signature. 52 | #' 53 | #' Internally, \code{write.xlsx} uses a double loop in over all the elements of 54 | #' the \code{data.frame} so performance for very large \code{data.frame} may be 55 | #' an issue. Please report if you experience slow performance. Dates and 56 | #' POSIXct classes are formatted separately after the insertion. This also 57 | #' adds to processing time. 58 | #' 59 | #' If \code{x} is not a \code{data.frame} it will be converted to one. 60 | #' 61 | #' Function \code{write.xlsx2} uses \code{addDataFrame} which speeds up the 62 | #' execution compared to \code{write.xlsx} by an order of magnitude for large 63 | #' spreadsheets (with more than 100,000 cells). 64 | #' 65 | #' The default formats for Date and DateTime columns can be changed via the two 66 | #' package options \code{xlsx.date.format} and \code{xlsx.datetime.format}. 67 | #' They need to be specified in Java date format 68 | #' \url{https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html}. 69 | #' 70 | #' Writing of password protected workbooks is supported for Excel 2007 OOXML 71 | #' format only. Note that in Linux, LibreOffice is not able to read password 72 | #' protected spreadsheets. 73 | #' 74 | #' @param x a \code{data.frame} to write to the workbook. 75 | #' @param file the path to the output file. 76 | #' @param sheetName a character string with the sheet name. 77 | #' @param col.names a logical value indicating if the column names of \code{x} 78 | #' are to be written along with \code{x} to the file. 79 | #' @param row.names a logical value indicating whether the row names of 80 | #' \code{x} are to be written along with \code{x} to the file. 81 | #' @param append a logical value indicating if \code{x} should be appended to 82 | #' an existing file. If \code{TRUE} the file is read from disk. 83 | #' @param showNA a logical value. If set to \code{FALSE}, NA values will be 84 | #' left as empty cells. 85 | #' @param ... other arguments to \code{addDataFrame} in the case of 86 | #' \code{read.xlsx2}. 87 | #' @param password a String with the password. 88 | #' @author Adrian Dragulescu 89 | #' @seealso \code{\link{read.xlsx}} for reading \code{xlsx} documents. See 90 | #' also \code{\link{addDataFrame}} for writing a \code{data.frame} to a sheet. 91 | #' @examples 92 | #' 93 | #' \dontrun{ 94 | #' 95 | #' file <- paste(tempdir(), "/usarrests.xlsx", sep="") 96 | #' res <- write.xlsx(USArrests, file) 97 | #' 98 | #' # to change the default date format 99 | #' oldOpt <- options() 100 | #' options(xlsx.date.format="dd MMM, yyyy") 101 | #' write.xlsx(x, sheet) # where x is a data.frame with a Date column. 102 | #' options(oldOpt) # revert back to defaults 103 | #' 104 | #' } 105 | #' 106 | #' @export 107 | write.xlsx <- function(x, file, sheetName="Sheet1", 108 | col.names=TRUE, row.names=TRUE, append=FALSE, showNA=TRUE, 109 | password=NULL) 110 | { 111 | if (!is.data.frame(x)) 112 | x <- data.frame(x) # just because the error message is too ugly 113 | 114 | iOffset <- jOffset <- 0 115 | if (col.names) 116 | iOffset <- 1 117 | if (row.names) 118 | jOffset <- 1 119 | 120 | if (append && file.exists(file)){ 121 | wb <- loadWorkbook(file, password=password) 122 | } else { 123 | ext <- gsub(".*\\.(.*)$", "\\1", basename(file)) 124 | wb <- createWorkbook(type=ext) 125 | } 126 | sheet <- createSheet(wb, sheetName) 127 | 128 | noRows <- nrow(x) + iOffset 129 | noCols <- ncol(x) + jOffset 130 | if (col.names){ 131 | rows <- createRow(sheet, 1) # create top row 132 | cells <- createCell(rows, colIndex=1:noCols) # create cells 133 | mapply(setCellValue, cells[1,(1+jOffset):noCols], colnames(x)) 134 | } 135 | if (row.names) # add rownames to data x 136 | x <- cbind(rownames=rownames(x), x) 137 | 138 | colIndex <- seq_len(ncol(x)) 139 | rowIndex <- seq_len(nrow(x)) + iOffset 140 | 141 | .write_block(wb, sheet, x, rowIndex, colIndex, showNA) 142 | saveWorkbook(wb, file, password=password) 143 | 144 | invisible() 145 | } 146 | 147 | 148 | # .jcall("java/lang/System", "V", "gc") # doesn't do anything! 149 | 150 | 151 | -------------------------------------------------------------------------------- /vignettes/excel_report.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Build Excel Reports from R" 3 | author: "Cole Arendt" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | Vignette: > 7 | %\VignetteIndexEntry{Build Excel Reports from R} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | %\VignetteKeywords{spreadsheet, Excel, java, report} 11 | %\VignettePackage{xlsx} 12 | --- 13 | 14 | ```{r setup, echo=FALSE, message=FALSE} 15 | knitr::opts_chunk$set(echo=TRUE, collapse=T, comment='#>') 16 | library(rJava) 17 | library(xlsx) 18 | ``` 19 | 20 | ## Building Excel Reports in R 21 | 22 | Excel has a lot of buy-in. This is generally pretty unfortunate, as there are 23 | much better tools for data analysis (i.e. \R). Excel is also not 24 | platform-agnostic, so there are difficulties generating Excel reports on 25 | non-Windows systems. However, Java is, and the excellent [Apache 26 | POI](https://poi.apache.org/) project provides a nice interface to Excel 27 | documents in a platform-agnostic manner. Further, \R integrates nicely with 28 | this project through the `xlsx` package to provide a suite of tools to be used 29 | in data science and report generation on any operating system. 30 | 31 | # From Scratch 32 | 33 | The first step of any report generation from scratch is data preparation. 34 | Suffice it to say that R has many tools to expedite that process. For instance, 35 | the [`tidyverse`](https://www.tidyverse.org/) provides several packages for getting 36 | data into a nice, _tidy_ format for modeling and visualization. We will presume 37 | that you have your data structured the way that you want and focus on getting 38 | that presentation into Excel. 39 | 40 | ## Functional Cell Styles 41 | 42 | The `CellStyle` class in the `xlsx` package makes possible many of the desirable 43 | traits of a good Excel report - Borders, DataFormats, Alignment, Font, and Fill. 44 | While a bit verbose to type at times, the `+` operator is implemented to make 45 | *building* these styles more natural. For instance, we might define a theme 46 | which has a standard selection of fonts, colors, and formats. 47 | 48 | ```{r theme} 49 | 50 | ## fonts require a workbook 51 | createFonts <- function(wb) { 52 | list( 53 | data = Font(wb, heightInPoints = 11, name='Arial') 54 | , title = Font(wb, heightInPoints = 16, name='Arial', isBold = TRUE) 55 | , subtitle = Font(wb, heightInPoints = 13, name='Arial', isBold = FALSE, isItalic = TRUE) 56 | ) 57 | } 58 | 59 | ## alignment 60 | alignLeft <- Alignment(horizontal='ALIGN_LEFT', vertical='VERTICAL_CENTER', wrapText = TRUE) 61 | alignCenter <- Alignment(horizontal='ALIGN_CENTER', vertical='VERTICAL_CENTER', wrapText=TRUE) 62 | 63 | ## data formats 64 | dataFormatDate <- DataFormat('m/d/yyyy') 65 | dataFormatNumberD <- DataFormat('0.0') 66 | 67 | ## fill 68 | fillPrimary <- Fill('#cc0000','#cc0000','SOLID_FOREGROUND') 69 | fillSecondary <- Fill('#ff6666','#ff6666','SOLID_FOREGROUND') 70 | 71 | ``` 72 | 73 | Once we have defined such standard cell-styles, it is straightforward to use 74 | them with the additive CellStyle framework. 75 | 76 | ```{r prep_for_report, include=FALSE} 77 | ## todo: fix the xlsx jars being available when generating vignette 78 | #.jaddClassPath(rprojroot::is_r_package$find_file('inst/java/rexcel-0.5.1.jar')) 79 | ``` 80 | 81 | ```{r build_report, results='hide'} 82 | ## The dataset 83 | numbercol <- 9 84 | mydata <- as.data.frame(lapply(1:numbercol,function(x){runif(15, 0,200)})) 85 | mydata <- setNames(mydata,paste0('col',1:numbercol)) 86 | 87 | ## Build report 88 | wb <- createWorkbook() 89 | sh <- createSheet(wb, 'Report') 90 | f <- createFonts(wb) 91 | 92 | headerrow <- createRow(sh, 1:2) 93 | headercell <- createCell(headerrow, 1:ncol(mydata)) 94 | 95 | ## title 96 | addMergedRegion(sh,1,1,1,ncol(mydata)) 97 | lapply(headercell[1,],function(cell) { 98 | setCellValue(cell, 'Title of Report') 99 | setCellStyle(cell, CellStyle(wb) + f$title + alignCenter) 100 | }) 101 | 102 | ## subtitle 103 | addMergedRegion(sh, 2,2, 1,ncol(mydata)) 104 | lapply(headercell[2,],function(cell) { 105 | setCellValue(cell, 'A fantastic report about nothing') 106 | setCellStyle(cell, CellStyle(wb) + f$subtitle + alignCenter ) 107 | }) 108 | 109 | ## cell styles for data 110 | cslist <- lapply(1:ncol(mydata), function(x){CellStyle(wb) + f$data + alignCenter + dataFormatNumberD}) 111 | cslist[1:2] <- lapply(cslist[1:2], function(x){x + alignLeft}) ## left align first two columns 112 | 113 | ## add data 114 | workrow <- 4 115 | 116 | addDataFrame(mydata, sh 117 | , col.names=TRUE 118 | , row.names = FALSE 119 | , startRow = workrow 120 | , startColumn = 1 121 | , colStyle = setNames(cslist,1:numbercol) 122 | , colnamesStyle = CellStyle(wb) + f$subtitle + alignCenter + fillPrimary 123 | ) 124 | 125 | workrow <- workrow + nrow(mydata) + 1 ## + 1 for header 126 | 127 | ## add total row... sorta 128 | ## - (just the first row because I am lazy) 129 | addDataFrame(mydata[1,], sh 130 | , col.names=FALSE 131 | , row.names=FALSE 132 | , startRow = workrow 133 | , startColumn = 1 134 | , colStyle = setNames(lapply(cslist,function(x){x + fillSecondary}),1:numbercol) 135 | ) 136 | 137 | saveWorkbook(wb, 'excel_report.xlsx') 138 | 139 | ``` 140 | 141 | Once you get used to some of the verbosity, the elegance of automatically 142 | creating nicely formatted Excel reports on a UNIX platform from R begins to 143 | shine. Further, with a bit of work implementing an R API, we get the benefit of 144 | a robust Java community debugging issues behind the scenes at Apache. If you 145 | would like to contribute on improving the R API and adding functionality, you 146 | can do so [on github](https://github.com/colearendt/xlsx). 147 | 148 | ![Our Beautiful Report](`r rprojroot::is_r_package$find_file('vignettes/excel_report.png')`) 149 | 150 | Bonus: you can even customize print formatting and a whole host of other things! 151 | There is more to come on that. 152 | -------------------------------------------------------------------------------- /man/CellBlock.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/CellBlock.R 3 | \name{CellBlock} 4 | \alias{CellBlock} 5 | \alias{is.CellBlock} 6 | \alias{CellBlock.default} 7 | \alias{CB.setColData} 8 | \alias{CB.setRowData} 9 | \alias{CB.setMatrixData} 10 | \alias{CB.setFill} 11 | \alias{CB.setFont} 12 | \alias{CB.setBorder} 13 | \title{Create and style a block of cells.} 14 | \usage{ 15 | CellBlock(sheet, startRow, startColumn, noRows, noColumns, create = TRUE) 16 | 17 | is.CellBlock(cellBlock) 18 | 19 | \method{CellBlock}{default}(sheet, startRow, startColumn, noRows, noColumns, create = TRUE) 20 | 21 | CB.setColData( 22 | cellBlock, 23 | x, 24 | colIndex, 25 | rowOffset = 0, 26 | showNA = TRUE, 27 | colStyle = NULL 28 | ) 29 | 30 | CB.setRowData( 31 | cellBlock, 32 | x, 33 | rowIndex, 34 | colOffset = 0, 35 | showNA = TRUE, 36 | rowStyle = NULL 37 | ) 38 | 39 | CB.setMatrixData( 40 | cellBlock, 41 | x, 42 | startRow, 43 | startColumn, 44 | showNA = TRUE, 45 | cellStyle = NULL 46 | ) 47 | 48 | CB.setFill(cellBlock, fill, rowIndex, colIndex) 49 | 50 | CB.setFont(cellBlock, font, rowIndex, colIndex) 51 | 52 | CB.setBorder(cellBlock, border, rowIndex, colIndex) 53 | } 54 | \arguments{ 55 | \item{sheet}{a \code{\link{Sheet}} object.} 56 | 57 | \item{startRow}{a numeric value for the starting row.} 58 | 59 | \item{startColumn}{a numeric value for the starting column.} 60 | 61 | \item{noRows}{a numeric value to specify the number of rows for the block.} 62 | 63 | \item{noColumns}{a numeric value to specify the number of columns for the 64 | block.} 65 | 66 | \item{create}{If \code{TRUE} cells will be created if they don't exist, if 67 | \code{FALSE} only existing cells will be used. If cells don't exist (on a 68 | new sheet for example), you have to use \code{TRUE}. On an existing sheet 69 | with data, use \code{TRUE} if you want to blank out an existing cell block. 70 | Use \code{FALSE} if you want to keep the styling of existing cells, but just 71 | modify the value of the cell.} 72 | 73 | \item{cellBlock}{a cell block object as returned by \code{\link{CellBlock}}.} 74 | 75 | \item{x}{the data you want to add to the cell block, a vector or a matrix 76 | depending on the function.} 77 | 78 | \item{colIndex}{a numeric vector specifiying the columns you want relative 79 | to the \code{startColumn}.} 80 | 81 | \item{rowOffset}{a numeric value for the starting row.} 82 | 83 | \item{showNA}{a logical value. If set to \code{FALSE}, NA values will be 84 | left as empty cells.} 85 | 86 | \item{colStyle}{a \code{\link{CellStyle}} object used to style the column.} 87 | 88 | \item{rowIndex}{a numeric vector specifiying the rows you want relative to 89 | the \code{startRow}.} 90 | 91 | \item{colOffset}{a numeric value for the starting column.} 92 | 93 | \item{rowStyle}{a \code{\link{CellStyle}} object used to style the row.} 94 | 95 | \item{cellStyle}{a \code{\link{CellStyle}} object.} 96 | 97 | \item{fill}{a Fill object, as returned by \code{\link{Fill}}.} 98 | 99 | \item{font}{a Font object, as returned by \code{\link{Font}}.} 100 | 101 | \item{border}{a Border object, as returned by \code{\link{Border}}.} 102 | } 103 | \value{ 104 | For \code{CellBlock} a cell block object. 105 | 106 | For \code{CB.setColData}, \code{CB.setRowData}, \code{CB.setMatrixData}, 107 | \code{CB.setFill}, \code{CB.setFont}, \code{CB.setBorder} nothing as he 108 | modification to the workbook is done in place. 109 | } 110 | \description{ 111 | Functions to create and style (not read) a block of cells. Use it to 112 | set/update cell values and cell styles in an efficient manner. 113 | } 114 | \details{ 115 | Introduced in version 0.5.0 of the package, these functions speed up the 116 | creation and styling of cells that are part of a "cell block" (a rectangular 117 | shaped group of cells). Use the functions above if you want to create 118 | efficiently a complex sheet with many styles. A simple by-column styling 119 | can be done by directly using \code{\link{addDataFrame}}. With the 120 | functionality provided here you can efficiently style individual cells, see 121 | the example. 122 | 123 | It is difficult to treat \code{NA}'s consistently between R and Excel via 124 | Java. Most likely, users of Excel will want to see \code{NA}'s as blank 125 | cells. In R character \code{NA}'s are simply characters, which for Excel 126 | means "NA". 127 | 128 | If you try to set more data to the block than you have cells in the block, 129 | only the existing cells will be set. 130 | 131 | Note that when modifying the style of a group of cells, the changes are made 132 | to the pairs defined by \code{(rowIndex, colIndex)}. This implies that the 133 | length of \code{rowIndex} and \code{colIndex} are the same value. An 134 | exception is made when either \code{rowIndex} or \code{colIndex} have length 135 | one, when they will be expanded internally to match the length of the other 136 | index. 137 | 138 | Function \code{CB.setMatrixData} works for numeric or character matrices. 139 | If the matrix \code{x} is not of numeric type it will be converted to a 140 | character matrix. 141 | } 142 | \examples{ 143 | 144 | \donttest{ 145 | wb <- createWorkbook() 146 | sheet <- createSheet(wb, sheetName="CellBlock") 147 | 148 | cb <- CellBlock(sheet, 7, 3, 1000, 60) 149 | CB.setColData(cb, 1:100, 1) # set a column 150 | CB.setRowData(cb, 1:50, 1) # set a row 151 | 152 | # add a matrix, and style it 153 | cs <- CellStyle(wb) + DataFormat("#,##0.00") 154 | x <- matrix(rnorm(900*45), nrow=900) 155 | CB.setMatrixData(cb, x, 10, 4, cellStyle=cs) 156 | 157 | # highlight the negative numbers in red 158 | fill <- Fill(foregroundColor = "red", backgroundColor="red") 159 | ind <- which(x < 0, arr.ind=TRUE) 160 | CB.setFill(cb, fill, ind[,1]+9, ind[,2]+3) # note the indices offset 161 | 162 | # set the border on the top row of the Cell Block 163 | border <- Border(color="blue", position=c("TOP", "BOTTOM"), 164 | pen=c("BORDER_THIN", "BORDER_THICK")) 165 | CB.setBorder(cb, border, 1, 1:1000) 166 | 167 | 168 | # Don't forget to save the workbook ... 169 | # saveWorkbook(wb, file) 170 | } 171 | 172 | } 173 | \author{ 174 | Adrian Dragulescu 175 | } 176 | -------------------------------------------------------------------------------- /R/readColumns.R: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # For CellType: FORMULA, ERROR or blanks, it defaults to "character" 4 | # 5 | # 6 | 7 | #' Read a contiguous set of columns from sheet into an R data.frame 8 | #' 9 | #' Read a contiguous set of columns from sheet into an R data.frame. Uses the 10 | #' \code{RInterface} for speed. 11 | #' 12 | #' 13 | #' Use the \code{readColumns} function when you want to read a rectangular 14 | #' block of data from an Excel worksheet. If you request columns which are 15 | #' blank, these will be read in as empty character "" columns. Internally, the 16 | #' loop over columns is done in R, the loop over rows is done in Java, so this 17 | #' function achieves good performance when number of rows >> number of columns. 18 | #' 19 | #' Excel internally stores dates and datetimes as numeric values, and does not 20 | #' keep track of time zones and DST. When a numeric column is formatted as a 21 | #' datetime, it will be converted into \code{POSIXct} class with a \emph{GMT} 22 | #' timezone. If you need a \code{Date} column, you need to specify explicitly 23 | #' using \code{colClasses} argument. 24 | #' 25 | #' For a numeric column Excels's errors and blank cells will be returned as NaN 26 | #' values. Excel's \code{#N/A} will be returned as NA. Formulas will be 27 | #' evaluated. For a chracter column, blank cells will be returned as "". 28 | #' 29 | #' @param sheet a \code{\link{Worksheet}} object. 30 | #' @param startColumn a numeric value for the starting column. 31 | #' @param endColumn a numeric value for the ending column. 32 | #' @param startRow a numeric value for the starting row. 33 | #' @param endRow a numeric value for the ending row. If \code{NULL} it reads 34 | #' all the rows in the sheet. If you request more than the existing rows in 35 | #' the sheet, the result will be truncated by the actual row number. 36 | #' @param as.data.frame a logical value indicating if the result should be 37 | #' coerced into a \code{data.frame}. If \code{FALSE}, the result is a list 38 | #' with one element for each column. 39 | #' @param header a logical value indicating whether the first row corresponding 40 | #' to the first element of the \code{rowIndex} vector contains the names of the 41 | #' variables. 42 | #' @param colClasses a character vector that represents the class of each 43 | #' column. Recycled as necessary, or if \code{NA} an attempt is made to guess 44 | #' the type of each column by reading the first row of data. Only 45 | #' \code{numeric}, \code{character}, \code{Date}, \code{POSIXct}, column types 46 | #' are accepted. Anything else will be coverted to a \code{character} type. 47 | #' If the length is less than the number of columns requested, replicate it. 48 | #' @param ... other arguments to \code{data.frame}, for example 49 | #' \code{stringsAsFactors} 50 | #' @return A data.frame or a list, depending on the \code{as.data.frame} 51 | #' argument. 52 | #' @author Adrian Dragulescu 53 | #' @seealso \code{\link{read.xlsx2}} for reading entire sheets. See also 54 | #' \code{\link{addDataFrame}} for writing a \code{data.frame} to a sheet. 55 | #' @examples 56 | #' 57 | #' \dontrun{ 58 | #' 59 | #' file <- system.file("tests", "test_import.xlsx", package = "xlsx") 60 | #' 61 | #' wb <- loadWorkbook(file) 62 | #' sheets <- getSheets(wb) 63 | #' 64 | #' sheet <- sheets[["all"]] 65 | #' res <- readColumns(sheet, startColumn=3, endColumn=10, startRow=3, 66 | #' endRow=7) 67 | #' 68 | #' sheet <- sheets[["NAs"]] 69 | #' res <- readColumns(sheet, 1, 6, 1, colClasses=c("Date", "character", 70 | #' "integer", rep("numeric", 2), "POSIXct")) 71 | #' 72 | #' 73 | #' } 74 | #' 75 | #' @export 76 | readColumns <- function(sheet, startColumn, endColumn, startRow, 77 | endRow=NULL, as.data.frame=TRUE, header=TRUE, colClasses=NA, ...) 78 | { 79 | trueEndRow <- sheet$getLastRowNum() + 1 80 | if (is.null(endRow)) # get it from the sheet 81 | endRow <- trueEndRow 82 | 83 | if (endRow > trueEndRow) { 84 | warning(paste("This sheet has only", trueEndRow, "rows")) 85 | endRow <- min(endRow, trueEndRow) 86 | } 87 | 88 | noColumns <- endColumn - startColumn + 1 89 | 90 | Rintf <- .jnew("org/cran/rexcel/RInterface") # create an interface object 91 | 92 | if (header) { 93 | cnames <- try(.jcall(Rintf, "[S", "readRowStrings", 94 | .jcast(sheet, "org/apache/poi/ss/usermodel/Sheet"), 95 | as.integer(startColumn-1), as.integer(endColumn-1), 96 | as.integer(startRow-1))) 97 | if (class(cnames) == "try-error") 98 | stop(paste("Cannot read the header. ", 99 | "The header row doesn't have all requested cells non-blank!")) 100 | startRow <- startRow + 1 101 | } else { 102 | cnames <- as.character(1:noColumns) 103 | } 104 | 105 | # guess or expand colClasses 106 | if (is.na(colClasses)[1]) { 107 | row <- getRows(sheet, rowIndex=startRow) 108 | cells <- getCells(row, colIndex=startColumn:endColumn) 109 | if (length(cells) != noColumns) 110 | warning("Not enough columns in the first row of data to correctly guess colClasses!") 111 | colClasses <- .guess_cell_type(cells) 112 | } 113 | colClasses <- rep(colClasses, length.out=noColumns) # extend colClasses 114 | 115 | res <- vector("list", length=noColumns) 116 | for (i in seq_len(noColumns)) { 117 | if (any(c("numeric", "POSIXct", "Date") %in% colClasses[i])) { 118 | aux <- .jcall(Rintf, "[D", "readColDoubles", 119 | .jcast(sheet, "org/apache/poi/ss/usermodel/Sheet"), 120 | as.integer(startRow-1), as.integer(endRow-1), 121 | as.integer(startColumn-1+i-1)) 122 | if (colClasses[i]=="Date") 123 | aux <- as.Date(aux-25569, origin="1970-01-01") 124 | if (colClasses[i]=="POSIXct") 125 | aux <- as.POSIXct((aux-25569)*86400, tz="GMT", origin="1970-01-01") 126 | } else { 127 | aux <- .jcall(Rintf, "[S", "readColStrings", 128 | .jcast(sheet, "org/apache/poi/ss/usermodel/Sheet"), 129 | as.integer(startRow-1), as.integer(endRow-1), 130 | as.integer(startColumn-1+i-1)) 131 | } 132 | #browser() 133 | if (!is.na(colClasses[i])) 134 | suppressWarnings(class(aux) <- colClasses[i]) # if it gets specified 135 | res[[i]] <- aux 136 | } 137 | 138 | if (as.data.frame) { 139 | cnames[cnames == ""] <- " " # remove some silly c.......... colnames! 140 | names(res) <- cnames 141 | res <- data.frame(res, ...) 142 | } 143 | 144 | res 145 | } 146 | -------------------------------------------------------------------------------- /man/read.xlsx.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/read.xlsx.R, R/read.xlsx2.R 3 | \name{read.xlsx} 4 | \alias{read.xlsx} 5 | \alias{read.xlsx2} 6 | \title{Read the contents of a worksheet into an R \code{data.frame}.} 7 | \usage{ 8 | read.xlsx( 9 | file, 10 | sheetIndex, 11 | sheetName = NULL, 12 | rowIndex = NULL, 13 | startRow = NULL, 14 | endRow = NULL, 15 | colIndex = NULL, 16 | as.data.frame = TRUE, 17 | header = TRUE, 18 | colClasses = NA, 19 | keepFormulas = FALSE, 20 | encoding = "unknown", 21 | password = NULL, 22 | ... 23 | ) 24 | 25 | read.xlsx2( 26 | file, 27 | sheetIndex, 28 | sheetName = NULL, 29 | startRow = 1, 30 | colIndex = NULL, 31 | endRow = NULL, 32 | as.data.frame = TRUE, 33 | header = TRUE, 34 | colClasses = "character", 35 | password = NULL, 36 | ... 37 | ) 38 | } 39 | \arguments{ 40 | \item{file}{the path to the file to read.} 41 | 42 | \item{sheetIndex}{a number representing the sheet index in the workbook.} 43 | 44 | \item{sheetName}{a character string with the sheet name.} 45 | 46 | \item{rowIndex}{a numeric vector indicating the rows you want to extract. 47 | If \code{NULL}, all rows found will be extracted, unless \code{startRow} or 48 | \code{endRow} are specified.} 49 | 50 | \item{startRow}{a number specifying the index of starting row. For 51 | \code{read.xlsx} this argument is active only if \code{rowIndex} is 52 | \code{NULL}.} 53 | 54 | \item{endRow}{a number specifying the index of the last row to pull. If 55 | \code{NULL}, read all the rows in the sheet. For \code{read.xlsx} this 56 | argument is active only if \code{rowIndex} is \code{NULL}.} 57 | 58 | \item{colIndex}{a numeric vector indicating the cols you want to extract. 59 | If \code{NULL}, all columns found will be extracted.} 60 | 61 | \item{as.data.frame}{a logical value indicating if the result should be 62 | coerced into a \code{data.frame}. If \code{FALSE}, the result is a list 63 | with one element for each column.} 64 | 65 | \item{header}{a logical value indicating whether the first row corresponding 66 | to the first element of the \code{rowIndex} vector contains the names of the 67 | variables.} 68 | 69 | \item{colClasses}{For \code{read.xlsx} a character vector that represent the 70 | class of each column. Recycled as necessary, or if the character vector is 71 | named, unspecified values are taken to be \code{NA}. For \code{read.xlsx2} 72 | see \code{\link{readColumns}}.} 73 | 74 | \item{keepFormulas}{a logical value indicating if Excel formulas should be 75 | shown as text in and not evaluated before bringing them in.} 76 | 77 | \item{encoding}{encoding to be assumed for input strings. See 78 | \code{\link[utils]{read.table}}.} 79 | 80 | \item{password}{a String with the password.} 81 | 82 | \item{...}{other arguments to \code{data.frame}, for example 83 | \code{stringsAsFactors}} 84 | } 85 | \value{ 86 | A data.frame or a list, depending on the \code{as.data.frame} 87 | argument. If some of the columns are read as NA's it's an indication that 88 | the \code{colClasses} argument has not been set properly. 89 | 90 | If the sheet is empty, return \code{NULL}. If the sheet does not exist, 91 | return an error. 92 | } 93 | \description{ 94 | The \code{read.xlsx} function provides a high level API for reading data 95 | from an Excel worksheet. It calls several low level functions in the 96 | process. Its goal is to provide the conveniency of 97 | \code{\link[utils]{read.table}} by borrowing from its signature. 98 | } 99 | \details{ 100 | The function pulls the value of each non empty cell in the worksheet into a 101 | vector of type \code{list} by preserving the data type. If 102 | \code{as.data.frame=TRUE}, this vector of lists is then formatted into a 103 | rectangular shape. Special care is needed for worksheets with ragged data. 104 | 105 | An attempt is made to guess the class type of the variable corresponding to 106 | each column in the worksheet from the type of the first non empty cell in 107 | that column. If you need to impose a specific class type on a variable, use 108 | the \code{colClasses} argument. It is recommended to specify the column 109 | classes and not rely on \code{R} to guess them, unless in very simple cases. 110 | 111 | Excel internally stores dates and datetimes as numeric values, and does not 112 | keep track of time zones and DST. When a datetime column is brought into , 113 | it is converted to \code{POSIXct} class with a \emph{GMT} timezone. 114 | Occasional rounding errors may appear and the and Excel string 115 | representation my differ by one second. For \code{read.xlsx2} bring in a 116 | datetime column as a numeric one and then convert to class \code{POSIXct} or 117 | \code{Date}. Also rounding the \code{POSIXct} column in R usually does the 118 | trick too. 119 | 120 | The \code{read.xlsx2} function does more work in Java so it achieves better 121 | performance (an order of magnitude faster on sheets with 100,000 cells or 122 | more). The result of \code{read.xlsx2} will in general be different from 123 | \code{read.xlsx}, because internally \code{read.xlsx2} uses 124 | \code{readColumns} which is tailored for tabular data. 125 | 126 | Reading of password protected workbooks is supported for Excel 2007 OOXML 127 | format only. 128 | } 129 | \examples{ 130 | 131 | \dontrun{ 132 | 133 | file <- system.file("tests", "test_import.xlsx", package = "xlsx") 134 | res <- read.xlsx(file, 1) # read first sheet 135 | head(res) 136 | # NA. Population Income Illiteracy Life.Exp Murder HS.Grad Frost Area 137 | # 1 Alabama 3615 3624 2.1 69.05 15.1 41.3 20 50708 138 | # 2 Alaska 365 6315 1.5 69.31 11.3 66.7 152 566432 139 | # 3 Arizona 2212 4530 1.8 70.55 7.8 58.1 15 113417 140 | # 4 Arkansas 2110 3378 1.9 70.66 10.1 39.9 65 51945 141 | # 5 California 21198 5114 1.1 71.71 10.3 62.6 20 156361 142 | # 6 Colorado 2541 4884 0.7 72.06 6.8 63.9 166 103766 143 | # > 144 | 145 | 146 | # To convert an Excel datetime colum to POSIXct, do something like: 147 | # as.POSIXct((x-25569)*86400, tz="GMT", origin="1970-01-01") 148 | # For Dates, use a conversion like: 149 | # as.Date(x-25569, origin="1970-01-01") 150 | 151 | res2 <- read.xlsx2(file, 1) 152 | 153 | } 154 | 155 | } 156 | \seealso{ 157 | \code{\link{write.xlsx}} for writing \code{xlsx} documents. See 158 | also \code{\link{readColumns}} for reading only a set of columns into R. 159 | } 160 | \author{ 161 | Adrian Dragulescu 162 | } 163 | -------------------------------------------------------------------------------- /R/NamedRanges.R: -------------------------------------------------------------------------------- 1 | # Functions to deal with ranges. 2 | # 3 | # createRange 4 | # getRanges 5 | # readRange 6 | # 7 | 8 | ############################################################################# 9 | # Set an area of a sheet to a contiguous range 10 | # 11 | #' Functions to manipulate (contiguous) named ranges. 12 | #' 13 | #' These functions are provided for convenience only. Use directly the Java 14 | #' API to access additional functionality. 15 | #' 16 | #' @param wb a workbook object as returned by \code{createWorksheet} or 17 | #' \code{loadWorksheet}. 18 | #' @param range a range object as returned by \code{getRanges}. 19 | #' @param sheet a sheet object as returned by \code{getSheets}. 20 | #' @param rangeName a character specifying the name of the name to create. 21 | #' @param colClasses the type of the columns supported. Only \code{numeric} 22 | #' and \code{character} are supported. See \code{\link{read.xlsx2}} for more 23 | #' details. 24 | #' @param firstCell a cell object corresponding to the top left cell in the 25 | #' range. 26 | #' @param lastCell a cell object corresponding to the bottom right cell in the 27 | #' range. 28 | #' @return \code{getRanges} returns the existing ranges as a list. 29 | #' 30 | #' \code{readRange} reads the range into a data.frame. 31 | #' 32 | #' \code{createRange} returns the created range object. 33 | #' @author Adrian Dragulescu 34 | #' @examples 35 | #' 36 | #' 37 | #' file <- system.file("tests", "test_import.xlsx", package = "xlsx") 38 | #' 39 | #' wb <- loadWorkbook(file) 40 | #' sheet <- getSheets(wb)[["deletedFields"]] 41 | #' ranges <- getRanges(wb) 42 | #' 43 | #' # the call below fails on cran tests for MacOS. You should see the 44 | #' # FAQ: https://code.google.com/p/rexcel/wiki/FAQ 45 | #' #res <- readRange(ranges[[1]], sheet, colClasses="numeric") # read it 46 | #' 47 | #' ranges[[1]]$getNameName() # get its name 48 | #' 49 | #' # see all the available java methods that you can call 50 | #' rJava::.jmethods(ranges[[1]]) 51 | #' 52 | #' # create a new named range 53 | #' firstCell <- sheet$getRow(14L)$getCell(4L) 54 | #' lastCell <- sheet$getRow(20L)$getCell(7L) 55 | #' rangeName <- "Test2" 56 | #' # same issue on MacOS 57 | #' #createRange(rangeName, firstCell, lastCell) 58 | #' 59 | #' 60 | #' @export 61 | #' @name NamedRanges 62 | createRange <- function(rangeName, firstCell, lastCell) 63 | { 64 | sheet <- firstCell$getSheet() 65 | sheetName <- sheet$getSheetName() 66 | firstCellRef <- .jnew("org/apache/poi/ss/util/CellReference", 67 | as.integer(firstCell$getRowIndex()), as.integer(firstCell$getColumnIndex())) 68 | lastCellRef <- .jnew("org/apache/poi/ss/util/CellReference", 69 | as.integer(lastCell$getRowIndex()), as.integer(lastCell$getColumnIndex())) 70 | 71 | nameFormula <- paste(sheetName, "!", firstCellRef$formatAsString(), ":", 72 | lastCellRef$formatAsString(), sep="") 73 | 74 | wb <- sheet$getWorkbook() 75 | range <- wb$createName() 76 | range$setNameName(rangeName) 77 | range$setRefersToFormula( nameFormula ) 78 | 79 | range 80 | } 81 | 82 | ############################################################################# 83 | # get info about ranges in the spreadsheet, similar to getSheets 84 | # 85 | #' @export 86 | #' @rdname NamedRanges 87 | getRanges <- function(wb) 88 | { 89 | noRanges <- .jcall(wb, "I", "getNumberOfNames") 90 | if (noRanges == 0){ 91 | cat("Workbook has no ranges!\n") 92 | return() 93 | } 94 | 95 | res <- list() 96 | for (i in 1:noRanges) { 97 | aRange <- .jcall(wb, "Lorg/apache/poi/ss/usermodel/Name;", "getNameAt", 98 | as.integer(i-1)) 99 | if (.jcall(aRange, "Z", "isDeleted")) { 100 | aRangeRef <- "No cell reference" 101 | } else { 102 | aRangeRef <- tryCatch(.jcall(aRange, "S", "getRefersToFormula"), 103 | error = function(e) "Invalid reference") 104 | # one <- list(ref=aRange, name=aRange$getNameName()) 105 | res[[i]] <- aRange 106 | # names(res)[i] <- aRangeRef 107 | } 108 | } 109 | 110 | res 111 | } 112 | 113 | 114 | ############################################################################# 115 | # Read one range. 116 | # range is a Java Object reference as returned by getRanges 117 | # 118 | #' @export 119 | #' @rdname NamedRanges 120 | readRange <- function(range, sheet, colClasses = "character") 121 | { 122 | ## getRefersToFormula throws an error if external reference is broken 123 | aRangeRef <- tryCatch(.jcall(range, "S", "getRefersToFormula"), 124 | error = function(e) stop("Invalid range address", call. = FALSE)) 125 | 126 | ## A broken reference starts with #REF! 127 | if (grepl("#REF!", aRangeRef, fixed=TRUE) > 0) 128 | stop(paste(range, aRangeRef, "is broken"), call. = FALSE) 129 | 130 | ## A linked range looks like '[path\path\file.xls]Sheet'!A1:B1 131 | if (grepl("[", aRangeRef, fixed=TRUE) > 0) 132 | stop(paste(range, aRangeRef, "linked range can't be read"), call. = FALSE) 133 | 134 | areaRef <- .jnew("org/apache/poi/ss/util/AreaReference", aRangeRef) 135 | if (!areaRef$isContiguous(aRangeRef)) 136 | stop(paste(range, "is not contiguous. Not supported yet!"), call. = FALSE) 137 | 138 | firstCell <- areaRef$getFirstCell() 139 | startRow <- firstCell$getRow()+1 140 | startColumn <- firstCell$getCol()+1 141 | 142 | lastCell <- areaRef$getLastCell() 143 | endRow <- lastCell$getRow()+1 144 | endColumn <- lastCell$getCol()+1 145 | 146 | noRows <- endRow - startRow + 1 147 | noColumns <- endColumn - startColumn + 1 148 | 149 | if (length(colClasses) < noColumns) 150 | colClasses <- rep(colClasses, noColumns) 151 | 152 | Rintf <- .jnew("org/cran/rexcel/RInterface") # create an interface object 153 | res <- vector("list", length=noColumns) 154 | for (i in seq_len(noColumns)){ 155 | res[[i]] <- switch(colClasses[i], 156 | numeric = .jcall(Rintf, "[D", "readColDoubles", 157 | .jcast(sheet, "org/apache/poi/ss/usermodel/Sheet"), 158 | as.integer(startRow-1), as.integer(startRow-1+noRows-1), 159 | as.integer(startColumn-1+i-1)), 160 | character = .jcall(Rintf, "[S", "readColStrings", 161 | .jcast(sheet, "org/apache/poi/ss/usermodel/Sheet"), 162 | as.integer(startRow-1), as.integer(startRow-1+noRows-1), 163 | as.integer(startColumn-1+i-1)) 164 | ) 165 | } 166 | 167 | names(res) <- paste("C", startColumn:endColumn, sep="") 168 | data.frame(res) 169 | } 170 | 171 | ## firstCellRef <- .jnew("org/apache/poi/hssf/util/CellReference", firstCell) 172 | ## endCellRef <- .jnew("org/apache/poi/hssf/util/CellReference", endCell) 173 | ## areaRef <- .jnew("org/apache/poi/ss/util/AreaReference", firstCellRef, endCellRef) 174 | ## nameFormula <- areaRef$formatAsString() 175 | -------------------------------------------------------------------------------- /other/src/test/java/org/cran/rexcel/DebugRexcel.java: -------------------------------------------------------------------------------- 1 | package org.cran.rexcel; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.util.Date; 8 | import java.util.Locale; 9 | 10 | import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 11 | import org.apache.poi.ss.usermodel.Cell; 12 | import org.apache.poi.ss.usermodel.CellStyle; 13 | import org.apache.poi.ss.usermodel.CreationHelper; 14 | import org.apache.poi.ss.usermodel.DataFormat; 15 | import org.apache.poi.ss.usermodel.DataFormatter; 16 | import org.apache.poi.ss.usermodel.Row; 17 | import org.apache.poi.ss.usermodel.Sheet; 18 | import org.apache.poi.ss.usermodel.Workbook; 19 | import org.apache.poi.ss.usermodel.WorkbookFactory; 20 | import org.apache.poi.ss.util.DateFormatConverter; 21 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 22 | //import org.apache.poi.xssf.usermodel.XSSFWorkbook; 23 | 24 | public class DebugRexcel { 25 | 26 | /* 27 | * Cannot keep existing formats when using CellBlock. 28 | * Take a file with existing formats and write it back. 29 | */ 30 | public static void issue22() throws InvalidFormatException, IOException { 31 | System.out.println( "Testing issue22 =================================" ); 32 | FileInputStream in = new FileInputStream(new File("../resources/issue22.xlsx") ); 33 | Workbook wb = WorkbookFactory.create(in); 34 | Sheet sheet0 = wb.getSheetAt(0); 35 | Sheet sheet1 = wb.getSheetAt(1); 36 | Sheet sheet2 = wb.getSheetAt(2); 37 | 38 | Cell c00_before = sheet1.getRow(0).getCell(0); 39 | CellStyle cs_before = c00_before.getCellStyle(); 40 | System.out.println("Background color before creation is: " + cs_before.getFillBackgroundColor() ); 41 | System.out.println("Cell style is: " + cs_before.toString() ); 42 | 43 | double[] data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; 44 | System.out.println("On Sheet 1 ...."); 45 | // need to create=true, because sheet is empty! 46 | RCellBlock cb0 = new RCellBlock(sheet0, 0, 0, 3, 3, true); 47 | cb0.setMatrixData(0, 2, 0, 2, data, true, null); 48 | 49 | System.out.println("On Sheet 2 ...."); 50 | RCellBlock cb1 = new RCellBlock(sheet1, 0, 0, 3, 3, false); 51 | Cell c00 = cb1.getCell(0, 0); 52 | CellStyle cs = c00.getCellStyle(); 53 | System.out.println("Background color after creation is: " + cs.getFillBackgroundColor() ); 54 | System.out.println("Cell style is: " + cs.toString() ); 55 | // good news, that the BackgroundColor in the CellBlock is maintained! 56 | cb1.setMatrixData(0, 2, 0, 2, data, true, null); 57 | 58 | System.out.println("On Sheet 3 ...."); 59 | RCellBlock cb2 = new RCellBlock(sheet2, 0, 0, 3, 3, false); 60 | cb2.setMatrixData(0, 2, 0, 2, data, true, null); 61 | 62 | 63 | FileOutputStream out = new FileOutputStream( "/tmp/issue22_out.xlsx" ); 64 | wb.write(out); 65 | out.close(); 66 | System.out.println("Wrote /tmp/issue22_out.xlsx"); 67 | } 68 | 69 | 70 | 71 | /* 72 | * Does not read integers correctly as Strings "12.0" instead of "12" 73 | */ 74 | public static void issue25() throws InvalidFormatException, IOException { 75 | 76 | System.out.println( "Testing issue25 =================================" ); 77 | FileInputStream in = new FileInputStream(new File("../resources/issue25.xlsx") ); 78 | Workbook wb = WorkbookFactory.create(in); 79 | Sheet sheet = wb.getSheetAt(0); 80 | 81 | Row row = sheet.getRow(37); 82 | Cell cell = row.getCell(0); 83 | 84 | System.out.println( cell.getCellType() ); 85 | 86 | System.out.println( cell.getNumericCellValue() ); // returns 8561807.0 !! I want "8561807" 87 | 88 | RInterface R = new RInterface(); 89 | String[] res = R.readColStrings(sheet, 35, 38, 0); 90 | for (int i=0; i