You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R Shiny点击actionButton向现有Excel文件新增工作表失败求解

问题根源

你目前代码的核心错误有4个:

  • Shiny上传的文件会存放在系统临时目录下的随机路径,你自行替换文件名后缀、修改工作目录的逻辑完全不符合Shiny文件上传的规则,导致找不到目标文件
  • 同时加载xlsx和openxlsx两个包存在函数命名冲突,且xlsx依赖Java环境,运行稳定性差
  • write.xlsx第一个参数传入了字符串'new_data',不是实际要写入的数据集对象
  • 未判断上传文件格式,CSV文件本身不支持多工作表,追加操作本身就无法执行,需要加格式判断

修正后可运行的完整代码

这里替换为纯openxlsx实现,不需要Java环境,逻辑更稳定:

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", ".csv")),
      actionButton(inputId = "Run", label = "Write Data to Table")
    ),
    mainPanel(DT::dataTableOutput(outputId = "table1"))
  )
)

server <- function(input, output) {
  # 存储上传的数据
  datasetInput <- reactive({
    infile <- input$file
    if (is.null(infile)) return(NULL)    
    # 读取文件
    if(grepl(".xlsx$", infile$name)){
      data <- read_excel(infile$datapath)
    } else if(grepl(".csv$", infile$name)){
      data <- read.csv(infile$datapath)
    }
    # 列名替换空格为下划线
    names(data) <- gsub(pattern = " ", replacement = "_", x = names(data))
    return(data) 
  })
  
  output$table1 <- DT::renderDataTable({    
    datasetInput()
  })
  
  observeEvent(input$Run,{    
    # 先判断有没有上传文件
    req(input$file, datasetInput())
    infile <- input$file
    # 仅对xlsx文件执行追加操作
    if(!grepl(".xlsx$", infile$name)){
      showNotification("仅支持向xlsx文件追加工作表", type = "error")
      return()
    }
    # 读取已上传的Excel文件全内容
    wb <- loadWorkbook(infile$datapath)
    # 检查工作表名是否重复,重复则加后缀避免报错
    sheet_name <- "New_Sheet3"
    if(sheet_name %in% names(wb)){
      sheet_name <- paste0(sheet_name, "_", format(Sys.time(), "%H%M%S"))
    }
    # 这里如果要写入自己的数据集就替换datasetInput()为你自己的data frame
    addWorksheet(wb, sheetName = sheet_name)
    writeData(wb, sheet = sheet_name, x = datasetInput())
    # 保存修改后的文件,这里可以修改为你要保存的本地路径
    saveWorkbook(wb, file.path(getwd(), infile$name), overwrite = TRUE)
    showNotification(paste0("已成功追加工作表:", sheet_name), type = "message")
  })
}

shinyApp(ui = ui, server = server)

补充说明

  • 代码默认将修改后的Excel保存到当前Shiny运行的工作目录下,文件名和你上传的文件名一致
  • 如果要写入的不是你上传的预览数据,而是你自定义的new_data数据集,直接把writeData里的datasetInput()替换为你的数据集对象即可
  • 加了工作表名重复校验,避免同名工作表导致写入失败
  • 加了CSV文件的异常提示,CSV本身不支持多工作表结构,无法执行追加操作

内容的提问来源于stack exchange,提问作者Raghavan vmvs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 20:15:03