Использовать downloadHandler для редактирования существующего файла Excel на основе загруженных данных? - PullRequest
0 голосов
/ 16 октября 2018

Я работаю над блестящим приложением, в котором пользователь будет загружать файл Excel, данные будут обрабатываться, а затем экспортируется новый файл Excel с этими данными для проверки пользователем.У меня проблемы с функцией downloadHandler.Я использовал для создания совершенно нового файла Excel каждый раз на основе загруженных данных, как это:

output$export <- downloadHandler(
filename = "answers.xlsx",
content = function(file){
  write.xlsx(exportdata(), file)
     })
  })

Это работает отлично.

Теперь я хотел бы отредактировать файл Excel, который я включу при публикации приложения, и разрешить пользователю загружать эту отредактированную версию следующим образом:

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)
})

Однако это приводит кошибка Warning: Error in write_file: Expecting a single string value: [type=character; extent=0]. [No stack trace available].Я не уверен, что происходит не так, как, когда я запускаю раздел контента за пределами блестящего приложения, он работает просто отлично.Кажется, проблема в команде saveWorkbook.

Причина, по которой я хотел бы редактировать существующий файл Excel, а не создавать новый, заключается в том, что файл шаблона, который я включаю в приложение, уже имеет диаграммыСделано, что должно измениться, когда новые данные записываются в файл.Пользователи хотели бы иметь возможность редактировать эти диаграммы самостоятельно, а не просто видеть изображение графика.Если у кого-то есть более простой способ сделать это, это было бы здорово!Заранее благодарим за помощь!

Воспроизводимый пример с использованием этого файла Excel:

    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)

1 Ответ

0 голосов
/ 17 октября 2018

Функция saveWorkbook не любит работать как функция записи для функции content.Заблуждение да, но мы все еще можем использовать его в функции содержимого, но не в качестве последнего шага.Мы должны использовать классическую функцию записи, такую ​​как write.xlsx, чтобы удовлетворить функцию содержимого, которая ожидает файл и путь к файлу для записи.

Чтобы обойти это, мы создаем временный файл в папке Data (эта папка будет находиться в директории с сервером и пользовательским интерфейсом и будет опубликована).Программа читает файл шаблона (см. Специальную функцию ниже), изменяет его, а затем записывает / перезаписывает файл temp .Этот временный файл затем читается и присваивается read.xlsx, а затем записывается write.xlsx.Это удовлетворяет функции содержимого и позволяет нам использовать шаблон для экспорта.

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)
    }) 
  }

Чтобы читать на всех листах, мы не можем просто использовать read.xlsx, так как он не просматривает все листы.Используя функцию, созданную Джеромом Англимом здесь , мы можем прочитать все листы из Excel.Это функция read_excel_allsheets.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...