I have an existing workbook with some data and charts.
I'm using openxlsx to add recent data and would like to edit an existing named range to reflect this (the charts use this named region).
I tried using writeData and createNamedRegion to do that, but I receive the error message "Error in (...): Named region with name 'named_region' already exists!"
library(openxlsx)
filename <- 'test.xlsx'
wb <- createWorkbook()
addWorksheet(wb, sheetName = 'test')
writeData(wb, sheet='test', x=data.frame(a=1:3,b=2:4), startCol=1, startRow=1,
colNames=T, rowNames=F, name='named_region')
saveWorkbook(wb, file=filename, overwrite=TRUE)
wb <- loadWorkbook(file = filename)
writeData(wb, sheet='test', x = data.frame(a=4:5,b=5:6),
startRow=5, colNames=F, rowNames=FALSE, keepNA=FALSE) # ok
# not ok
# writeData(wb, sheet='test', x = data.frame(a=4:5,b=5:6),
# startRow=5, colNames=F, rowNames=FALSE, keepNA=FALSE, name='named_region')
# createNamedRegion(wb, sheet='test', cols=1, rows=2:6, name='named_region')
saveWorkbook(wb, file=filename, overwrite=TRUE)
Related
I am working on a shiny app where the user will upload an excel file, the data will be manipulated, and then a new excel file with this data is exported for the user to examine. I am having issues with the downloadHandler function. I used to create an entirely new excel file every time based on the uploaded data like this:
output$export <- downloadHandler(
filename = "answers.xlsx",
content = function(file){
write.xlsx(exportdata(), file)
})
})
This works fine.
Now I would like to edit an excel file that I will include when I publish the app and allow the user to download this edited version like this:
output$export <- downloadHandler(
filename = "answers.xlsx",
content = function(file){
wb <- loadWorkbook("6rep-charts.xlsx")
writeData(wb, sheet = "Species Match Results", correlInput())
writeData(wb, sheet = "BS1 Data", bs1Input())
writeData(wb, sheet = "BS2 Data", bs2Input())
saveWorkbook(wb, file)
})
However, this results in the error Warning: Error in write_file: Expecting a single string value: [type=character; extent=0]. [No stack trace available]. I am not sure what is going wrong as when I run the content section outside of the shiny app, it works just fine. The problem seems to be in the saveWorkbook command.
The reason I would like to edit an existing excel file rather than create a new one is that the template file I'm including in the app has charts already made that should change when the new data is written into the file. The users would like to be able to edit these charts themselves, rather than just see a picture of a graph. If anyone has a simpler way to accomplish this, that would be great! Thank you in advance for your help!
Reproducible example using this excel file:
library(shiny); library(readxl); library(xlsx)
ui <- shinyUI(fluidPage(
titlePanel("Old Faithful Geyser Data"),
fluidRow(
column(3,
downloadButton(outputId = "export",
label = "Export Results to Excel")
),
column(6,
dataTableOutput("data")
))))
server <- function(input, output) {
adata <- faithful[1:20,]
bdata <- faithful[21:50,]
cdata <- faithful[51:200,]
read_excel_allsheets <- function(filename, tibble = FALSE) {
sheets <- readxl::excel_sheets(filename)
x <- lapply(sheets, function(Y) {readxl::read_excel(filename, sheet = Y)})
if(!tibble) x <- lapply(x, as.data.frame)
names(x) <- sheets
x
}
output$data <- renderDataTable({
adata })
output$export <- downloadHandler(
filename = "answers.xlsx",
content = function(file){
wb <- loadWorkbook("./Data/template.xlsx")
writeData(wb, sheet = "Alpha", adata)
writeData(wb, sheet = "Beta", bdata)
writeData(wb, sheet = "Gamma", cdata)
saveWorkbook(wb, file="./Data/temp.xlsx", overwrite = T)
print("done")
Fin_WB<- read_excel_allsheets("./Data/temp.xlsx")
write.xlsx(Fin_WB, file)
} ) }
shinyApp(ui = ui, server = server)
Simpler solution (I am unable to leave comments due to too low reputation):
output$export <- downloadHandler(
filename = "answers.xlsx",
content = function(file){
wb <- loadWorkbook("./Data/template.xlsx")
writeData(wb, sheet = "Alpha", adata)
writeData(wb, sheet = "Beta", bdata)
writeData(wb, sheet = "Gamma", cdata)
saveWorkbook(wb, file="./Data/temp.xlsx", overwrite = T)
file.copy(from = "./Data/temp.xlsx", to = file)
})
No need for the function read_excel_allsheets.
The saveWorkbook function does not like to operate as a write function for the content function. Confusing yes, but we can still use it within the content function, just not as the final step. We have to use a classic write function such as write.xlsx to satisfy the content function which is expecting the file and file path to write to.
To get around this we create a temp file in the Data folder (this folder will be in the dir with server and ui, and will be published). The program reads in the template file (see special function below), modifies it, and then writes/overwrites the temp file. This temp file is then read in and assigned by read.xlsx and then written to by write.xlsx. This satisfies the content function and allows us to use a template for export.
read_excel_allsheets <- function(filename, tibble = FALSE) {
sheets <- readxl::excel_sheets(filename)
x <- lapply(sheets, function(X) readxl::read_excel(filename, sheet = X))
if(!tibble) x <- lapply(x, as.data.frame)
names(x) <- sheets
x
}
output$export <- downloadHandler(
filename = "answers.xlsx",
content = function(file){
wb <- loadWorkbook("./Data/template.xlsx")
writeData(wb, sheet = "Alpha", adata)
writeData(wb, sheet = "Beta", bdata)
writeData(wb, sheet = "Gamma", cdata)
saveWorkbook(wb, file="./Data/temp.xlsx", overwrite = T)
print("done")
Fin_WB<- read_excel_allsheets("./Data/temp.xlsx")
write.xlsx(Fin_WB, file)
})
}
In order to read in all the sheets, we cannot simply use read.xlsx as it wont look at all the sheets. Using a function created here by Jeromy Anglim, we can read in all the sheets from excel. This is the read_excel_allsheets function.
In my script, I need to create an excel workbook with many sheets, where the first 2 sheets are by default, read from another workbook and incorporated into the exported excel.
Im using the xlsx package to format the export excel. However, I could not find any function in the xlsx package, that could read a sheet from an excel, and add it to another one.
Here is my code to read the first excel:
template_wb <- loadWorkbook(file = 'template.xlsx')
sheets <- getSheets(wb)
sheet1 <- sheets[[1]]
sheet2 <- sheets[[2]]
In the second part of the code, i create another workbook, which contains multiple sheets, from which, sheet1 and sheet2, should be one of.
wb<-createWorkbook(type="xlsx")
as_sheet <- createSheet(wb, sheetName = "AS")
dc_sheet <- createSheet(wb, sheetName = "DC")
ro_sheet <- createSheet(wb, sheetName = "RO")
### add content to worksheets
# the suggested code should go there
### save workbook
saveWorkbook(wb, 'out.xlsx')
I would like to add the content of sheet1 to dc_sheet and the content of sheet2 to ro_sheet before adding more data into as_sheet and then saving the workbook.
How can I do this?
I'm pretty sure a simple assignment statement will do the trick:
template_wb <- loadWorkbook(file = 'template.xlsx')
sheets <- getSheets(template_wb)
sheet1 <- sheets[[1]]
sheet2 <- sheets[[2]]
wb<-createWorkbook(type="xlsx")
as_sheet <- createSheet(wb, sheetName = "AS")
dc_sheet <- createSheet(wb, sheetName = "DC")
ro_sheet <- createSheet(wb, sheetName = "RO")
dc_sheet<-sheet1
ro_sheet<-sheet2
# Your code here
saveWorkbook(wb, 'out.xlsx')
I tried it out and it worked fine
You can work with a copy, and save it as a new file.
wb <- loadWorkbook(file)
# Rename the sheets
wb$setSheetName(0L, "AS")
wb$setSheetName(1L, "DC")
# Delete the aditional sheets
sheets <- getSheets(wb)
lapply(names(sheets)[-(1:2)], function(x) removeSheet(wb, sheetName = x))
# Assign the sheets to the objects of R
sheets <- getSheets(wb)
as_sheet <- sheets[[1]]
dc_sheet <- sheets[[2]]
# Create the new sheet
ro_sheet <- createSheet(wb, sheetName = "RO")
# save workbook
saveWorkbook(wb, 'out.xlsx')
I have sales data in an Excel file in that I have to open in sheet3. I tried below code but am unable to give hyperlinks to sheet3.
library(xlsx)
wb <- createWorkbook()
sheet1 <- createSheet(wb, "Sheet1")
rows <- createRow(sheet1)
cells <- createCell(rows)
links <- c("[D://r datasets/sales data.xlsx]sheet3!")
names(links) <- c("link1")
for (row in 1:length(links)) {
setCellValue(cells[[row,1]], names(links)[row])
addHyperlink(cells[[row,1]], links[row])
}
saveWorkbook(wb, "hyperlinks to file.xlsx")
shell.exec("hyperlinks to file.xlsx")
Can anyone help in this regard?
You can do
library(xlsx)
wb1 <- createWorkbook()
createSheet(wb1, "Sheet1")
createSheet(wb1, "Sheet2")
createSheet(wb1, "Sheet3")
saveWorkbook(wb1, tf1 <- tempfile(fileext = ".xlsx"))
wb2 <- createWorkbook()
sheet2 <- createSheet(wb2, "Sheet2")
rows <- createRow(sheet2)
cells <- createCell(rows)
setCellValue(cells[[1,1]], "To Other File")
addHyperlink(cells[[1,1]],sprintf("file:///%s#%s!%s", normalizePath(tf1, "/"), names(getSheets(wb1))[2], "B2"), "FILE")
saveWorkbook(wb2, tf2 <- tempfile(fileext = ".xlsx"))
shell.exec(tf2)
When running Shiny, I get the message that "java.lang.OutOfMemoryError: Java heap space" when the download function is called. It works when the data file is smaller; but all of the tables combined should be less than 5,000 rows and 15 columns for the instance I'm looking at. Can someone help me make my downloadHandler functional with this kind of file size?
*# server.R*
library(XLConnect)
shinyServer(function(input, output, session) {
... (filtering operation on a data frame to create multiple sub tables)
output$downloadData <- downloadHandler(
filename = function() {paste(input$category,"_raw_token_data.xlsx")},
content = function(file){
fname <- paste(file,"xlsx",sep=".")
wb <- loadWorkbook(fname, create = TRUE)
createSheet(wb, name = "-terms")
createSheet(wb, name = "+terms")
createSheet(wb, name = "-tokens")
createSheet(wb, name = "+tokens")
createSheet(wb, name = "test_stats")
writeWorksheet(wb, raw()$filter_neg, sheet = "-terms")
writeWorksheet(wb, raw()$filter_kw, sheet = "+terms")
writeWorksheet(wb, df()$neg_raw, sheet = "-tokens")
writeWorksheet(wb, df()$rel_raw, sheet = "+tokens")
writeWorksheet(wb, df()$test_raw, sheet = "test_stats")
saveWorkbook(wb)
file.rename(fname,file)
}
) # closing for downloadHandler
}) # closing for shinyServer
Solution:
options(java.parameters = "-Xmx1g") # increase heap size to 1gb
library(RWeka)
I created a program that breaks a database in several other banks. But in this program I save this several banks in txt so now I'd like save in xls, but I don't know how.
I tried for (nm in Nms) write.table(Res[[nm]], paste(nm, 'xls', sep='.'), sep="\t",dec=",",col.names=TRUE, row.names=FALSE, quote=TRUE, na="NA")
but it did not work
decup <- function(dados,var){
require(gdata)
dados <- read.xls("dados.xls")
attach(dados)
Res = split(dados, var)
for (nm in Nms) write.table(Res[[nm]], file=paste(nm, 'txt', sep='.'))
for (nm in Nms) zip(paste(nm,'zip',sep='.'),paste(nm,'xls',sep='.'), zip = Sys.getenv("R_ZIPCMD", "zip"))
}
You can use library XLConnect to read/write .xlsx files and
writeWorksheet let's you save the your data.frames:
library(XLConnect)
## open workbook or create it if doesn't exist
wb <- loadWorkbook("writeWorksheet.xlsx", create = TRUE)
## for each data.frame create a sheet with its data
lapply(seq_along(Res), function(x)
createSheet(wb, name = paste0("sheet",x))
writeWorksheet(wb, Res[[x]], sheet = paste0("sheet",x), startRow = 4, startCol = 2)
}
# Save workbook (this actually writes the file to disk)
saveWorkbook(wb)
EDIT to save a data.frame by workbook you do this :
lapply(seq_along(Res), function(x){
wb <- loadWorkbook(paste0("database",x), create = TRUE)
createSheet(wb, name ='sheet1' )
writeWorksheet(wb, Res[[x]], sheet = 'sheet1', startRow = 4, startCol = 2)
saveWorkbook(wb)
})