Use Shiny App to Query a SQL Server DB - r

I guess I really don't understand this process like I thought I did. I found the link below, and it seems pretty helpful, but after making only slight modifications, I can't get it to do what I want.
R Shiny SQL Server Query
I just want to launch a webpage and have a user enter a parameter, to be passed into a query.
library(RODBCext)
library(shiny)
ui <- shinyUI(
pageWithSidebar(
headerPanel("Hide Side Bar example"),
sidebarPanel(
textInput("CATEGORY", "Enter CATEGORY below"),
submitButton(text="Submit")
),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tbTable"))
)
)
)
)
browser()
server <- function(input, output, session)
myData <- reactive({
req(input$Id)
#connect to database
dbhandle = odbcDriverConnect('driver={SQL Server};server=my_server;database=data_WH;trusted_connection=true')
browser()
#build query
#query = "SELECT * FROM [my_db].[dbo].[my_table] where [CATEGORY] = '1070'"
query = "SELECT * FROM [my_db].[dbo].[my_table] where [CATEGORY] = ?"
browser()
#store results
res <- sqlExecute(channel = dbhandle,
query = query,
data = list(input$Id),
fetch = TRUE,
stringsAsFactors = FALSE)
#close the connection
odbcClose(dbhandle)
#return results
res
})
output$tbTable <-
renderTable(
myData()
)
shinyApp(ui = ui, server = server)
The SQL string is fine. I entered browser, to try to debug the script, as described in the link below.
https://shiny.rstudio.com/articles/debugging.html
browser()
It didn't pause the code; it didn't help me debug the code. It didn't do anything at all.
Any thoughts anyone?

It looks like your server function is incorrectly defined.
A function defined of the form
fn <- function(arg1, arg2)
expression1
expression2
Is actually going to be evaluated as
fn <- function(arg1, arg2){
expression1
}
expression2
In your server function, because you didn't place your braces, the only expression in the function definition is creating the myData reactive. Your output$tbTable element is completely separate from your function, never gets called in the app, and so your reactive is never processed. You should try this:
library(RODBCext)
library(shiny)
ui <- shinyUI(
pageWithSidebar(
headerPanel("Hide Side Bar example"),
sidebarPanel(
textInput("CATEGORY", "Enter CATEGORY below"),
submitButton(text="Submit")
),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tbTable"))
)
)
)
)
server <- function(input, output, session)
{ # NOTE THE BRACE HERE
myData <- reactive({
req(input$CATEGORY)
#connect to database
dbhandle = odbcDriverConnect('driver={SQL Server};server=my_server;database=data_WH;trusted_connection=true')
#build query
#query = "SELECT * FROM [my_db].[dbo].[my_table] where [CATEGORY] = '1070'"
query = "SELECT * FROM [my_db].[dbo].[my_table] where [CATEGORY] = ?"
#store results
res <- sqlExecute(channel = dbhandle,
query = query,
data = list(input$CATEGORY),
fetch = TRUE,
stringsAsFactors = FALSE)
#close the connection
odbcClose(dbhandle)
#return results
res
})
output$tbTable <-
renderTable(
myData()
)
} # AND NOTE THE CLOSING BRACE HERE
shinyApp(ui = ui, server = server)

Related

R shiny: save data frames from multiple panels

In the following app, I would like to add a global button, to save the tables in the 2 panels at the same time.
Ideally, they should be saved to an xlsx file, in tabs named after the corresponding tabs.
Please note that the tabs were created using a module.
Many thanks!!
library(shiny)
library(DT)
modDtUi <- function(id){ # UI module
ns = NS(id)
DT::dataTableOutput(ns('x1'))
}
modDt <- function(input, output, session, data, globalSession){ # Server module
x <- data
output$x1 <- DT::renderDataTable(x, selection = 'none', editable = TRUE)
proxy <- dataTableProxy('x1', session = globalSession)
}
ui <- fluidPage(
mainPanel(
tabsetPanel(
tabPanel("Table1", modDtUi("editable")),
tabPanel("Table2", modDtUi("editable2"))
)
)
)
server <- function(input, output, session) {
callModule(modDt,"editable", data = head(iris,10), globalSession = session)
callModule(modDt,"editable2", data = tail(iris,5), globalSession = session)
}
shinyApp(ui = ui, server = server)
I believe this demo works.
I used reactiveValues v$data to store the data inside the module. The module will return v$data so it can be retrieved when you want to save the data in the shiny server.
I also added an observeEvent to detect changes in the data, and update the data table with replaceData.
The excel file is created using the writexl library, but you could substitute with others of course.
Let me know if this works for you. I imagine there are some elements of this answer that can be improved upon - and if we can identify them, would like to edit further.
library(shiny)
library(DT)
library(writexl)
modDtUi <- function(id){ # UI module
ns = NS(id)
DT::dataTableOutput(ns(id))
}
modDt <- function(input, output, session, data, id, globalSession){ # Server module
v <- reactiveValues(data = data)
output[[id]] <- DT::renderDataTable(v$data, selection = 'none', editable = TRUE)
proxy <- dataTableProxy(id, session = globalSession)
id_input = paste(id, "cell_edit", sep = "_")
# Could add observeEvent here to detect edit event
observeEvent(input[[id_input]], {
info = input[[id_input]]
if (!is.null(info)) {
v$data[info$row, info$col] <<- DT::coerceValue(info$value, v$data[info$row, info$col])
}
replaceData(proxy, v$data, resetPaging = FALSE)
})
return(data = reactive({v$data}))
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
width = 2,
actionButton("btn", "Save Both")
),
mainPanel(
tabsetPanel(
tabPanel("Table1", modDtUi("editable1")),
tabPanel("Table2", modDtUi("editable2"))
)
)
)
)
server <- function(input, output, session) {
e1 <- callModule(modDt, "editable1", data = head(iris,10), id = "editable1", globalSession = session)
e2 <- callModule(modDt, "editable2", data = tail(iris,5), id = "editable2", globalSession = session)
observeEvent(input$btn, {
print("Saving...")
sheets <- list("e1" = e1(), "e2" = e2())
write_xlsx(sheets, "test.xlsx")
})
}
shinyApp(ui = ui, server = server)

R Shiny App to Edit MongoDB

I have a Shiny Application that uses a MongoDB (using mongolite). The application loads and saves to the database with no issues but I am trying to find a way to edit the MongoDB through a datatable(using DT) where when the user edits or deletes a row that they can press an actionbutton to update the mongoDB. When I try to run it currently I am getting
"Warning: Error in : argument must be bson or json."
Is there a way for me to edit from DT, convert it to the JSON Mongo is expecting from the Shiny app? Below is the code.
library(shiny)
library(DT)
library(mongolite)
ui <- fluidPage(
# Application title
titlePanel("MongoTest"),
# Sidebar
sidebarLayout(
sidebarPanel(
actionButton("submit", "Submit"),
actionButton("load","Load"),
actionButton("update","update"),
actionButton("deleteRows", "Delete Rows")
),
#Main UI
mainPanel(
fluidPage(
fluidRow(h2("Interactive Table", align="center")),
tags$hr(),
fluidRow(
DT::dataTableOutput("Interactive_Table")
)
)
)
)
)
server = function(input, output, session){
#Function that loads the information from the mongoDB
loadData <- function() {
# Connect to the database
db = mongo(collection = "collectionhere",db ="SET", url = "mongodb://localhost:27017")
# Read all the entries
data <- db$find()
return(data)
}
READ_IN_DATA=loadData()
values <- reactiveValues(dfWorking = READ_IN_DATA)
#Function that saves data to DB
saveData <- function(data) {
# Connect to the database
db = mongo(collection = "collectionhere",db ="SET", url = "mongodb://localhost:27017")
data <- as.data.frame(t(data))
db$insert(data)
}
updateData = function(data){
# Connect to the database
db = mongo(collection = "collectionhere",db ="SET", url = "mongodb://localhost:27017")
data <- as.data.frame(t(data))
#subjects$update('{}', '{"$set":{"has_age": false}}', multiple = TRUE)
db$update(data)
}
#Loading In the Data
observeEvent(input$load, {
loadData()
})
#Update the DB based off changes to the table
observeEvent(input$update, {
updated_df=as.data.frame(values$dfWorking)
updateData(t(updated_df))
})
#Deleting Rows
observeEvent(input$deleteRows,{
if (!is.null(input$Interactive_Table_rows_selected)) {
values$dfWorking <- values$dfWorking[-as.numeric(input$Interactive_Table_rows_selected),]
}
})
#DT Table
output$Interactive_Table = renderDataTable({
datatable(values$dfWorking,editable=TRUE
)
})
}
# Run the application
shinyApp(ui = ui, server = server)

Import Data from SQL Server To shiny app

i worked on data from SQL Server in R using RODBC and after getting my result i created ShinyApp to deploy my result But i want to get my data from my SQL query directly without exporting my result to Excel and then import it to shiny,How can i do that?
Test <- odbcDriverConnect("driver={SQL Server};server=localhost;database=Fakahany;trusted_connection=true")
Orders<- sqlQuery(Test,"
SELECT
WHWorkOrderHeaderId
, OtherLangDescription
FROM Warehouse.WHWorkOrderDetails
INNER JOIN Warehouse.WHWorkOrderHeader AS WHH
ON Warehouse.WHWorkOrderDetails.WHWorkOrderHeaderId = WHH.ID
INNER JOIN Warehouse.StockItems
ON Warehouse.WHWorkOrderDetails.StockItemId = Warehouse.StockItems.Id
WHERE Type = 'IO'
ORDER BY OtherLangDescription ASC")
#Creating the correlations
Orders$OtherLangDescription <- as.factor(Orders$OtherLangDescription)
orderList <- unique(Orders$OtherLangDescription)
ListId <- lapply(orderList, function(x) subset(Orders, OtherLangDescription == x)$WHWorkOrderHeaderId)
Initial_Tab <- lapply(ListId, function(x) subset(Orders, WHWorkOrderHeaderId %in% x)$OtherLangDescription)
Correlation_Tab <- mapply(function(Product, ID) table(Product)/length(ID),
Initial_Tab, ListId)
colnames(Correlation_Tab) <- orderList
cor_per<- round(Correlation_Tab*100,2)
DF<-data.frame(row=rownames(cor_per)[row(cor_per)], col=colnames(cor_per)[col(cor_per)], corr=c(cor_per))
and this is my app code:
#loading Packages
library(RODBC)
library(shiny)
library(rsconnect)
ui <- fluidPage(
titlePanel("Item Correlation"),
sidebarPanel(
selectInput("Item2","Select Item",choices= DF$FirstItem),
h6("Powerd By:"),
img(src='edrak.png',height='50px',width='110px')
# ,selectInput("Item","SelectItem",choices= DF$col)
),
mainPanel(
tableOutput("Itemcorr")
)
)
server <- function(input,output){
output$Itemcorr <- renderTable({
subset(DF, DF$FirstItem == input$Item2)
})
}
shinyApp(ui, server)
This should do what you want.
library(RODBCext)
library(shiny)
ui <- shinyUI(
pageWithSidebar(
headerPanel("Hide Side Bar example"),
sidebarPanel(
textInput("CATEGORY", "Enter CATEGORY below"),
submitButton(text="Submit")
),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tbTable"))
)
)
)
)
server <- function(input, output, session)
{ # NOTE THE BRACE HERE
myData <- reactive({
req(input$CATEGORY)
#connect to database
dbhandle = odbcDriverConnect('driver={SQL Server};server=Server_Name;database=Database_Name;trusted_connection=true')
#build query
query = "SELECT * FROM [Your_Table] where [CATEGORY] = ?"
#store results
res <- sqlExecute(channel = dbhandle,
query = query,
data = list(input$CATEGORY),
fetch = TRUE,
stringsAsFactors = FALSE)
#close the connection
odbcClose(dbhandle)
#return results
res
})
output$tbTable <-
renderTable(myData())
} # AND NOTE THE CLOSING BRACE HERE
shinyApp(ui = ui, server = server)
You may want to consider this as well.
library(shiny)
library(RODBCext)
shinyApp(
ui =
shinyUI(
fluidPage(
uiOutput("select_category"),
tableOutput("display_data")
# plotOutput("plot_data")
)
),
# server needs the function; looks ok
server = shinyServer(function(input, output, session)
{
# A reactive object to get the query. This lets you use
# the data in multiple locations (plots, tables, etc) without
# having to perform the query in each output slot.
QueriedData <- reactive({
req(input$showDrop)
ch <- odbcDriverConnect("driver={SQL Server};server=Server_Name;database=DATABASE_NAME;trusted_connection=true")
showList <- sqlExecute(ch, "SELECT * FROM [Your_Table] WHERE Category = ?",
data = list(Category = input$showDrop),
fetch = TRUE,
stringsAsFactors = FALSE)
odbcClose(ch)
showList
})
# The select input control. These can be managed dynamically
# from the server, and then the control send back to the UI
# using `renderUI`
output$select_category <- renderUI({
ch <- odbcDriverConnect("driver={SQL Server};server=Server_Name;database=DATABASE_NAME;trusted_connection=true")
showList <- sqlExecute(ch, "Select Distinct Category From [Your_Table] Order by Category",
fetch = TRUE,
stringsAsFactors = FALSE)
odbcClose(ch)
selectInput(inputId = "showDrop",
label = "Select Asset",
showList$Category)
})
# Display the data in a table
output$display_data <- renderTable({
QueriedData()
})
# Display a plot
# output$plot_data <-
# renderPlot({
# plot(QueriedData()) # fill in the plot code you want to use.
# })
})
)

shiny R can't display a text from vector

How can I display value only on the browser?
Below is my code.
ui <- shinyUI(bootstrapPage(
absolutePanel(
textOutput("renderText1")
)
)
)
server <- function(input,output,session)
{
observeEvent(input$dropdown, {
query <- sprintf("select ....",input$dropdown)
cabinet_info <- dbGetQuery(con,query)
output$renderText1 <- renderText({
paste(cabinet_info)
})
})
}
Below are the outputs:
c('a','w','r','t')
While Geovany's answer may work, it is not a good practice to use observeEvent with the global assignment operator (<<-).
If you would like to execute a side effect (e.g. writing a file, plotting, printing), then you can use observe or observeEvent, but if you want to use a return value, use eventReactive instead.
ui <- shinyUI(bootstrapPage(
absolutePanel(
selectInput("dropdown", label = 'SelectInput', choices = c('A', 'B')),
textOutput("renderText1")
)
)
)
server <- function(input,output,session)
{
cab <- eventReactive(input$dropdown, {
query <- sprintf("select ....",input$dropdown)
#cabinet_info <- dbGetQuery(con,query) #Replaced by a constant
cabinet_info <- paste(c(input$dropdown, 'a','w','r','t'), sep=",")
})
output$renderText1 <- renderText({
cab()
})
}
shinyApp(ui, server)
Call eventReactive from the server side just like a function: cab()
This could help you
runApp(list(
ui = shinyUI(bootstrapPage(
absolutePanel(
actionButton("dropdown", "dropdown"),
textOutput("renderText1")
)
)
),
server = shinyServer(function(input, output) {
cabinet_info <- NULL
observeEvent(input$dropdown, {
cabinet_info <<- c('a','w','r','t')
})
output$renderText1 <- renderText({
input$dropdown
paste(cabinet_info, collapse = ',')
})
})
))

R shiny shinysky autocomplete using database query

I am trying to do this autocomplete using a list which would be populated dynamically from a database everytime the applications loads. Unfortunately the following approach isn't working.
rm(list = ls())
library(shinysky)
library(shiny)
library(RMySQL)
loadData <- function(publisherId) {
# Connect to the database
mydb = dbConnect(MySQL(), user='root', password='root',host='localhost',dbname="tq")
# Construct the fetching query
query <- sprintf("select * from tq.publisher_dim where publisher_id = %s",publisherId) # Submit the fetch query and disconnect
data <- dbGetQuery(mydb, query)
dbDisconnect(mydb)
data
}
loadPubIds <- function() {
# Connect to the database
mydb = dbConnect(MySQL(), user='root', password='root', host='localhost', dbname="tq")
# Construct the fetching query
query <- sprintf("select distinct publisher_id from tq.publisher_dim" )
# Submit the fetch query and disconnect
data <- dbGetQuery(mydb, query)
dbDisconnect(mydb)
data
}
my_autocomplete_list <- c(loadPubIds())
ui <- fluidPage(
select2Input("txt","",choices = NULL,selected = NULL),
textInput(inputId ="publisherId", label="choose publisherId", value = "", width = NULL, placeholder = NULL),
actionButton("goButton", "Go!"),
dataTableOutput('mytable')
#textOutput('myquery')
)
server <- function(input, output,session) {
test <- reactive({
pubs <- loadPubIds()
})
observe({
pubs <- loadPubIds()
updateSelect2Input(session, 'txt', choices = as.list(pubs), label = "")
})
output$mytable <- renderDataTable({
if (input$goButton == 0)
return()
isolate({ loadData(input$publisherId) })
})
}
shinyApp(ui = ui, server = server)
Any help would be great.

Resources