我正在尝试制作一个闪亮的应用程序,可以通过该应用程序顺序上传excel文件。每次我上传文件时,它都会添加到先前加载的文件中(假设它们具有相同的格式)。
我所做的是将df_all
定义为一个空数据框。每次我单击“上传”并选择一个文件时,我都会执行bind_rows(df_all, df)
。但这没有用。
有人可以帮我弄清楚我做错了什么吗?我花了几个小时尝试所有不同的东西,但没有成功。
# set working directory
setwd(my_working_directory)
ipak <- function(pkg){
new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
if (length(new.pkg))
install.packages(new.pkg, dependencies = TRUE)
sapply(pkg, require, character.only = TRUE)
}
packages <- c('devtools', 'readxl',
'shiny', 'DT')
ipak(packages)
## ui
##---------------------------------------------------------------
ui <- fluidPage(
fluidRow(
column(9, h2('Import Excel'), align='center')
),
sidebarLayout(
sidebarPanel(
#----------------------Upload Files-----------------
conditionalPanel(
condition= " input.tabs == 'Upload_Files' ",
fileInput('file', 'Choose Excel file',
accept = c(".xlsx")
)
)
),
#------------------------------Main Panel------------------------
mainPanel(
tabsetPanel(
id = 'tabs',
tabPanel('Upload_Files',
fluidRow (
column(12, DT::dataTableOutput('data.table1') )
)
)
)
)
)
)
##--------------------server-----------------------
server <- function(input, output, session) {
df_all = data.frame()
output$data.table1 <- DT::renderDataTable({
# input$file will be NULL initially.
req(input$file)
inFile <- input$file
if(is.null(inFile)) {
return(NULL)
}
df=read_excel(inFile$datapath)
df_all = bind_rows(df_all, df)
return(df_all)
})
}
runApp(shinyApp(ui=ui, server=server))
答案 0 :(得分:0)
您对df_all
的更新存在缺陷,原因有两个:
df_all
时,它将采用外部引用(在反应性块外部),然后将其分配给块内的df_all
,而从不更新外部。在某些情况下,这建议使用<<-
,尽管我不鼓励使用这种思维方式,因为它会导致程序设计出现问题(如果不必要,应该避免产生副作用)。还有... df_all
保持反应状态。相反,尝试
server <- function(input, output, session) {
df_all <- reactiveVal(NULL)
output$data.table1 <- DT::renderDataTable({
req(input$file)
olddf <- isolate(df_all())
if(is.null(input$file)) return(NULL)
df <- readr::read_excel(input$file$datapath)
df <- dplyr::bind_rows(olddf, df)
isolate(df_all(df))
return(df)
})
}
这应该在所有表的结构相似的情况下起作用。您可能希望通过一些预检查等方式(在一个名称中确认名称,在另一个中确认名称,等等)在行绑定时更加谨慎。
顺便说一句:我使用isolate(...)
,以便重新呈现表不会两次触发DT:renderDataTable
。这并不是说渲染不能响应 else 对df_all
所做的更改,但不能对自身施加(循环)反应。