R Shiny中DT扩展按钮如何下载保留原格式并追加工作表的Excel文件
问题描述
我开发了一款搭载两类下载功能的R Shiny应用:
- 第一种是基于Shiny原生
downloadHandler实现的下载方案 - 第二种是基于R DT包的数据表(datatable)按钮扩展实现的内置下载方案
应用完整代码如下:
library(shiny) library(openxlsx) library(readxl) library(DT) ui <- fluidPage( titlePanel("Writer App"), sidebarLayout(sidebarPanel(fileInput(inputId = "file", label = "Read File Here", accept = c(".xlsx")), downloadLink("downloadData", "Download")), mainPanel(DTOutput(outputId = "table1")))) server <- function(input, output) { datasetInput <- reactive({ infile<- input$file if (is.null(infile)) return(NULL) #READ .XLSX AND .CSV FILES if(grepl(infile$datapath, pattern = ".xlsx" )){data=read_excel(infile$datapath)} else if(grepl(infile$datapath , pattern = ".csv" )){data=read.csv(infile$datapath )} #RENAME DATAFRAME WITH UNDERSCORES names(data)<-gsub(pattern = " ", replacement = "_", x = names(data)) return(data) }) output$table1 <- renderDT({ datasetInput<-datasetInput() datatable(datasetInput,extensions = c('Buttons', 'Scroller'), options = list( dom = 'tB', deferRender = TRUE, scrollY = 400, scroller = TRUE, buttons = list(list(extend = 'excel'))) ) }) output$downloadData <- downloadHandler( filename = function() { paste("data-", Sys.Date(), ".xlsx", sep="")}, content = function(file) { tf<-tempdir() Files=list.files(path=tf, pattern=".xlsx", recursive = TRUE)[1] file.copy(from =paste0(tf, "/",Files ), to= "temp_1.xlsx") wb2 <- loadWorkbook(file = "temp_1.xlsx") df_1<-data.frame("DF"= c(1:3)) addWorksheet(wb = wb2,sheetName = "Parameters1") writeData(wb2, "Parameters1", df_1, startCol = 1, startRow = 2, rowNames = TRUE) saveWorkbook(wb2, file) })} shinyApp(ui = ui, server = server)
当前应用加载Excel文件时,downloadHandler下载方式可以完整保留原Excel工作表的格式,在工作簿中追加新工作表后即可下载包含新内容的完整Excel工作簿。咨询是否可以通过数据表下方的DT扩展下载按钮实现同等效果:即保留原Excel的全部格式、追加自定义新工作表后完成文件下载,目前暂未找到可行实现方案。
解答
结论:DT默认的内置Excel导出按钮无法实现该需求。
DT自带的Excel导出按钮是纯前端JavaScript实现的,核心逻辑是直接抓取当前页面上DT表格渲染出的纯数据内容,调用前端SheetJS库生成全新的Excel文件,全程不会和服务端存储的原始上传文件产生交互:
- 它无法读取原Excel文件的单元格格式、其他工作表、隐藏内容等信息,仅能导出当前页面表格展示的纯文本、数值数据
- 它没有权限调用R端的
openxlsx等工具包操作服务端存储的原始工作簿,自然不可能实现保留原格式、追加自定义工作表的效果。
如果需要把下载按钮放在DT的按钮栏中,和DT原生按钮保持一致的展示位置,不需要单独在侧边栏放置下载链接,可以直接在DT的按钮配置中新增自定义按钮,绑定你已经编写完成的R端文件处理逻辑即可,修改成本极低,核心修改代码如下:
# 修改renderDT内的buttons配置 output$table1 <- renderDT({ datasetInput<-datasetInput() datatable(datasetInput,extensions = c('Buttons', 'Scroller'), options = list( dom = 'tB', deferRender = TRUE, scrollY = 400, scroller = TRUE, buttons = list( # 替换原来的默认excel按钮为自定义下载按钮 list( text = '导出完整带格式Excel', action = DT::JS("function() { // 触发R端已有的下载逻辑 document.querySelector('#downloadData').click() }") ) ) ) ) })
这种实现方式下按钮完全嵌入DT的按钮栏,用户使用体验和DT原生导出按钮无差异,同时可以100%复用你已经验证通过的R端Excel处理逻辑,稳定实现保留原格式、追加自定义工作表的导出需求。
内容的提问来源于stack exchange,提问作者Raghavan vmvs
相关产品推荐
相关产品推荐

