我正在开发一个Shiny应用程序,它采用Excel文档,更改其结构和格式,并返回一个包含10个唯一工作表(基于美国地区)的新Excel文档。我写的代码在更改数据方面很好,但它不会返回Excel文件。相反,它只返回一个空白文件。如果有人知道如何回答这个问题,那就太棒了。这是我的代码,仅删除了一些数据操作(因此更容易理解)。
让我知道这是否有意义!
GDrive上的Excel文档链接:https://drive.google.com/file/d/1OHaYh0OcMDTbU5BhrL81EO7d5pgwfJju/view?usp=sharing
UI:
library(shiny)
library(xlsx)
library(dplyr)library(shinythemes)
shinyUI(fluidPage(theme = shinytheme("spacelab"),
titlePanel("Dataset Manipulation Example"),
tags$caption("Edited by S. Gouyet 2.21.2018"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Insert File',
accept = c(".xlsx")
),
downloadButton("downloadData", "Download updated Excel document")
)
,
mainPanel(
)
)
)
)
服务器:
shinyServer(function(input, output) {
reacdata<-reactive({
inFile1 <- input$file1
if(is.null(inFile1))
return(NULL)
df <- read_excel(inFile1$datapath)
df <- df %>% select(`SALES REGION`, `Price`)
Northeast1 <- df %>% filter(`SALES REGION` == "Northeast 1")
Northeast2 <- df %>% filter(`SALES REGION` == "Northeast 2")
CapMetro <- df %>% filter(`SALES REGION` == "Cap-Metro")
Southern <- df %>% filter(`SALES REGION` == "Southern")
Eastern <- df %>% filter(`SALES REGION` == "Eastern")
GreatLakes <- df %>% filter(`SALES REGION` == "Great Lakes")
Western <- df %>% filter(`SALES REGION` == "Western")
Pacific <- df %>% filter(`SALES REGION` == "Pacific")
wb <- createWorkbook()
sheet <- createSheet(wb, sheetName="addDataFrame1")
addDataFrame(df, sheet)
sheet <- createSheet(wb, sheetName="Northeast1")
addDataFrame(Northeast1, sheet)
sheet <- createSheet(wb, sheetName = "Northeast 2")
addDataFrame(Northeast2, sheet)
sheet <- createSheet(wb, sheetName = "Cap-Metro")
addDataFrame(Northeast2, sheet)
sheet <- createSheet(wb, sheetName = "Southern")
addDataFrame(Southern, sheet)
sheet <- createSheet(wb, sheetName = "Eastern")
addDataFrame(Southern, sheet)
sheet <- createSheet(wb, sheetName = "Great Lakes")
addDataFrame(GreatLakes, sheet)
sheet <- createSheet(wb, sheetName = "Western")
addDataFrame(Western, sheet)
sheet <- createSheet(wb, sheetName = "Pacific")
addDataFrame(Pacific, sheet)
})
output$downloadData <- downloadHandler(
filename ="test.xlsx",
content = function(file) {
saveWorkbook(wb, file)
}
)
})
答案 0 :(得分:1)
当我运行您的应用并尝试下载Excel工作表时,我收到此错误:
错误:对象&#39; wb&#39;找不到
这意味着R无法找到wb
,因此saveWorkbook
没有要写入Excel工作表的对象。
您在reactive expression内创建了wb
,用于将数据存储在reacdata
中。这意味着我们需要在reacdata()
中致电saveWorkbook
。请注意括号。
output$downloadData <- downloadHandler(
filename ="test.xlsx",
content = function(file) {
saveWorkbook(reacdata(), file)
}
)
我们重新运行该应用并尝试下载Excel表格。但是,现在我们收到了这个错误:
错误:尝试应用非功能性
然后我们可以在控制台中查看堆栈跟踪:
Warning: Error in saveWorkbook: attempt to apply non-function
Stack trace (innermost first):
54: saveWorkbook
53: download$func [#67]
4: <Anonymous>
3: do.call
2: print.shiny.appobj
1: <Promise>
Error : attempt to apply non-function
我们在saveWorkbook
看到错误。
我们在反应式表达式中返回的最后一个对象将存储在reacdata()
中。 reacdata
中的最后一行是addDataFrame(Pacific, sheet)
。但是,我们希望reacdata()
包含工作簿对象。所以,我们再向reacdata
添加一行,如下所示:
reacdata<-reactive({
# data manipulation etc...
wb
})
如果您使用这些更改运行应用程序,它将起作用。但我们也可以做一些改进。
使用split
列出每个地区的数据框列表。为了保持上传数据框中未包含的区域,我们将SALES REGION
设为一个因素。
df$`SALES REGION` <- factor(df$`SALES REGION`, levels = c("Northeast 1",
"Northeast 2",
"Cap-Metro",
"Southern",
"Eastern",
"Great Lakes",
"Western",
"Pacific"))
df_list <- split(df, df$`SALES REGION`, drop = FALSE)
编写一个函数来添加命名工作表。
## wb: workbook
## data_frame: data.frame to add to the new sheet
## sheet_name: name of the new sheet
add_sheet <- function(wb, data_frame, sheet_name) {
sheet <- createSheet(wb, sheetName = sheet_name)
addDataFrame(data_frame, sheet)
}
创建工作簿对象,然后添加工作表
## create workbook
wb <- createWorkbook()
## add sheets
add_sheet(wb, df, "addDataFrame1")
for(i in names(df_list)) {
add_sheet(wb, df_list[[i]], i)
}
## write out data
example <- data.frame(structure(list(ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26), `SALES REGION` = c("Northeast 1",
"Northeast 2", "Western", "Southern", "Pacific", "Northeast 1",
"Northeast 2", "Western", "Southern", "Pacific", "Northeast 1",
"Northeast 2", "Western", "Southern", "Pacific", "Northeast 1",
"Northeast 2", "Western", "Southern", "Pacific", "Northeast 1",
"Northeast 2", "Western", "Southern", "Pacific", "Great Lakes"
), Price = c(100, 106, 3201, 4236.66666666667, 5787.16666666667,
7337.66666666667, 8888.16666666667, 10438.6666666667, 11989.1666666667,
13539.6666666667, 15090.1666666667, 16640.6666666667, 18191.1666666667,
19741.6666666667, 21292.1666666667, 22842.6666666667, 24393.1666666667,
25943.6666666667, 27494.1666666667, 29044.6666666667, 30595.1666666667,
32145.6666666667, 33696.1666666667, 35246.6666666667, 36797.1666666667,
1031), Jobs = c(10, 900, 30, 321, 331, 337.3, 343.6, 349.9, 356.2,
362.5, 368.8, 375.1, 381.4, 387.7, 394, 400.3, 406.6, 412.9,
419.2, 425.499999999999, 431.799999999999, 438.099999999999,
444.399999999999, 450.699999999999, 456.999999999999, 9312)), .Names = c("ID",
"SALES REGION", "Price", "Jobs"), row.names = c(NA, -26L), class = c("tbl_df",
"tbl", "data.frame")))
write.xlsx(example, "Example.xlsx")
## ui
library(shiny)
library(xlsx)
library(dplyr)
library(shinythemes)
ui <- fluidPage(theme = shinytheme("spacelab"),
titlePanel("Dataset Manipulation Example"),
tags$caption("Edited by S. Gouyet 2.21.2018"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Insert File',
accept = c(".xlsx")
),
downloadButton("downloadData", "Download updated Excel document")
)
,
mainPanel(
)
)
)
## server
server <- function(input, output) {
reacdata<-reactive({
inFile1 <- input$file1
if(is.null(inFile1))
return(NULL)
df <- read_excel(inFile1$datapath)
df <- df %>% select(`SALES REGION`, `Price`)
# create list with one dataframe per region
df$`SALES REGION` <- factor(df$`SALES REGION`, levels = c("Northeast 1",
"Northeast 2",
"Cap-Metro",
"Southern",
"Eastern",
"Great Lakes",
"Western",
"Pacific"))
df_list <- split(df, df$`SALES REGION`, drop = FALSE)
# write function to add named sheets
## wb: workbook
## data_frame: data.frame to add to the new sheet
## sheet_name: name of the new sheet
add_sheet <- function(wb, data_frame, sheet_name) {
sheet <- createSheet(wb, sheetName = sheet_name)
addDataFrame(data_frame, sheet)
}
# make the workbook and add the first dataframe
wb <- createWorkbook()
add_sheet(wb, df, "addDataFrame1")
# use a loop to add sheets
for(i in names(df_list)) {
add_sheet(wb, df_list[[i]], i)
}
# return the workbook object
wb
})
output$downloadData <- downloadHandler(
filename ="test.xlsx",
content = function(file) {
saveWorkbook(reacdata(), file)
}
)
}
shinyApp(ui = ui, server = server)