Shiny DT не может добавить кнопки для загрузки в формате csv/excel

Возникли проблемы с добавлением кнопок «загрузить как csv/excel» в раздел DataTable моего приложения Shiny. Кажется, что, поскольку мои «данные» запрашиваются из красного смещения, они не распознают их как фрейм данных.

Ошибка: «данные» должны быть двумерными (например, фрейм данных или матрица)

Из этого документа кажется, что он возвращает его как фрейм данных, который противоречит сообщению об ошибке. Любая идея, как я могу исправить это и заставить кнопки работать?

server <- function(input, output) {
  
  observeEvent(input$executeSQL, {
    if (input$selection == "CL7D") {
      output$mytable = DT::renderDataTable({ 
        dbGetQuery(conn, "select * from dummy")
        extensions = "Buttons" 
        options = list(paging = TRUE,
                       scrollX=TRUE, 
                       searching = TRUE,
                       ordering = TRUE,
                       dom = 'Bfrtip',
                       buttons = c('copy', 'csv', 'excel', 'pdf'),
                       pageLength=5, 
                       lengthMenu=c(3,5,10) )
      })
    }
    
  })
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
28
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш первый аргумент renderDataTable действительно является выражением, как и должно быть, но... ваше выражение мало что делает.

  1. Сначала он извлекает какие-то данные из dbGetQuery, но так как они нигде не хранятся, то тут же теряются.
  2. Затем он создает локальную переменную с именем extensions и присваивает ей значение "Buttons".
  3. Наконец, он создает локальную переменную с именем options, то есть list(..).

Поскольку поведение по умолчанию в R для выражения с { ... } заключается в том, что оно «возвращает» последнее выражение внутри него, это означает, что оно не возвращает значение из dbGetQuery, оно не возвращает extensions, вместо этого оно возвращает значение options, который не является двумерным.

Возможно, вы имели в виду:

  observeEvent(input$executeSQL, {
    if (input$selection == "CL7D") {
      output$mytable = DT::renderDataTable(        # remove the '{'
        dbGetQuery(conn, "select * from dummy"),   # add a ','
        extensions = "Buttons",                   # add a ','
        options = list(paging = TRUE,
                       scrollX=TRUE, 
                       searching = TRUE,
                       ordering = TRUE,
                       dom = 'Bfrtip',
                       buttons = c('copy', 'csv', 'excel', 'pdf'),
                       pageLength=5, 
                       lengthMenu=c(3,5,10) )
      )                                            # remove the '}'
    }
    
  })

Боковые примечания:

  1. Я предпочитаю, чтобы действия по созданию/запросу данных были простыми reactive компонентами, которые затем можно было бы использовать в других местах. Например, допустим, вы хотите, чтобы баннер в верхней части вашего блестящего приложения отображал количество возвращенных строк. С вашим текущим кодом вам нужно будет запустить dbGetQueryдважды.

    Вместо этого сделайте его реактивным, а затем используйте позже; таким образом, если вам нужно использовать данные для любого другого компонента в вашем блестящем приложении, они будут доступны вам отдельно.

      mydata <- eventReactive(input$executeSQL, {
        dbGetQuery(conn, "select * from dummy")
      })
      observeEvent(mydata(), {
        if (input$selection == "CL7D") {
          output$mytable = DT::renderDataTable(
            mydata(),
            extensions = "Buttons",
            options = list(paging = TRUE,
                           scrollX=TRUE, 
                           searching = TRUE,
                           ordering = TRUE,
                           dom = 'Bfrtip',
                           buttons = c('copy', 'csv', 'excel', 'pdf'),
                           pageLength=5, 
                           lengthMenu=c(3,5,10) )
          )
        }
    
      })
    
  2. Я еще не видел ни одного рабочего примера shiny, где реактивный компонент, вложенный в другой, имеет смысл. Я не тестировал ваш код здесь (отсутствуют данные, пользовательский интерфейс и т. д.), но я подозреваю, что ваш код будет работать лучше, чище, чем

      mydata <- eventReactive(input$executeSQL, {
        dbGetQuery(conn, "select * from dummy")
      })
      output$mytable <- DT::renderDataTable(
        if (input$selection == "CL7D") mydata(),
        extensions = "Buttons",
        options = list(paging = TRUE,
                           scrollX=TRUE, 
                           searching = TRUE,
                           ordering = TRUE,
                           dom = 'Bfrtip',
                           buttons = c('copy', 'csv', 'excel', 'pdf'),
                           pageLength=5, 
                           lengthMenu=c(3,5,10) )
          )
    

    Если это не сработает, уберите условное выражение if,

      mydata <- eventReactive(input$executeSQL, {
        dbGetQuery(conn, "select * from dummy")
      })
      data_CL7D <- reactive({
        if (input$selection == "CL7D") mydata()
      })
      output$mytable <- DT::renderDataTable(
        data_CL7D(),
        extensions = "Buttons",
        options = list(paging = TRUE,
                           scrollX=TRUE, 
                           searching = TRUE,
                           ordering = TRUE,
                           dom = 'Bfrtip',
                           buttons = c('copy', 'csv', 'excel', 'pdf'),
                           pageLength=5, 
                           lengthMenu=c(3,5,10) )
          )
    

Другие вопросы по теме