Reputation: 99
I'm attempting to create a download button in my shiny app that downloads out an excel file with multiple tabs, once for each table in my shiny app. I believe I've put the code together correctly but I'm continuing to get the same error. Warning: Error in table9: could not find function "table9" [No stack trace available]
I think it has something to do with the fact that I'm referencing an observe event or even a reactive statement. Any ideas on how to get this working? Code is below:
rm(list=ls())
library(shiny)
library(RODBC)
library(DT)
library(openxlsx)
ui <- bootstrapPage( tags$head(
tags$style(HTML("
body{
background-color: #FBFAFA;
}
h2 {
box-sizing: border-box;
font: Roboto;
font-weight: bold;
font-size: 40px;
border-bottom: 4px solid #b00027;
color: firebrick;
height: 32px;
width: 1140px;
column-rule-color: rgb(51, 51, 51);
perspective-origin: 570px 16px;
transform-origin: 570px 16px;
border: 0px none rgb(51, 51, 51);
margin: 5px 5px 20px;
outline: rgb(51, 51, 51) none 0px;
}
.nav-tabs>li>a {
box-sizing: border-box;
color: darkgray;
float: left;
font-size: 18px;
column-rule-color: rgb(34, 34, 34);
perspective-origin: 569px 51.5px;
background: white;
border-top: 0px none rgb(34, 34, 34);
border-right: 0px none rgb(34, 34, 34);
border-bottom: 1px solid rgb(217, 217, 217);
border-left: 0px none rgb(34, 34, 34);
outline: rgb(34, 34, 34) none 0px;
margin: 5px 3px 3px;
font-weight: bold;
}
table.dataTable thead th, table.dataTable thead td {
padding: 10px 18px;
border-bottom: 1px solid #111;
font-size: medium;
text-align: center;
}
table.dataTable tbody th, table.dataTable tbody td {
padding: 8px 10px;
font-size: medium;
text-align: center;
}
.form-group.shiny-input-container {
display: inline-block;
font-size: 20px;
padding: 1%;
margin: 0px;
}
caption {
padding-top: 8px;
padding-bottom: 8px;
font-weight: bold;
color: firebrick;
margin: 10px 5px 5px;
font-size: 30px;
text-decoration: underline;
text-decoration-color: gray;
}
table.dataTable{
clear: both;
margin-top: 6px !important;
margin-bottom: 6px !important;
max-width: none !important;
border-collapse: separate !important;
border-spacing: 0;
}
.tab-content {
width: 90%;
padding: 2.5%;
background: white;
margin-left: auto;
margin-right: auto;
border-radius: 50px;
}"
))
),
titlePanel("Financial Planning Client Discovery Form"),
tabsetPanel( id = "Main Panel", tabPanel("Client Selection",
textInput(inputId = "First_Name",
label = "First Name",
value = "",
width = NULL,
placeholder = "Enter Client's First Name"),
textInput(inputId = "Last_Name",
label = "Last Name",
value = "",
width = NULL,
placeholder = "Enter Client's Last Name"),
textInput(inputId = "SSN",
label = "Social Security Number",
value = "",
width = NULL,
placeholder = "Enter Client's SSN (XXXXXXXXX)"),
DT::dataTableOutput("MyTable")
), tabPanel("Client Discovery Form Information",downloadButton("downloadData","Download"), DT::dataTableOutput("CDFInfo"),DT::dataTableOutput("WealthSummary"), DT::dataTableOutput("Deposit"),DT::dataTableOutput("Investment"),DT::dataTableOutput("Loan"),
DT::dataTableOutput("Other"))))
server <- function(input, output, session) {
BDW <- odbcConnect("BDW", uid="", pwd="", believeNRows = FALSE)
BOSCDB <- odbcConnect("BOSCDB", uid="", pwd="", believeNRows = FALSE)
table1 <- reactive({sqlQuery(BDW,paste0("
SELECT DISTINCT a.PartyID, FullName as 'Name',TaxID as 'Social Security Number', AddressLine1+' '+City+' '+StateCode+' '+PostalCode as 'Address'
FROM [EnterpriseCustomer].[dbo].[Party]a
LEFT JOIN [EnterpriseCustomer].[dbo].[PartytoAddressRelationship]b ON b.PartyID = a.PartyID
LEFT JOIN [EnterpriseCustomer].[dbo].[Address]c ON c.AddressID = b.AddressID
WHERE FullName like '",input$First_Name,"%'
and FullName like '%",input$Last_Name,"'
and TaxID like '%",input$SSN,"%'
and a.ActiveRecordIndicator = 1
and b.ActiveRecordIndicator = 1
and c.ActiveRecordIndicator = 1"), as.is = TRUE)})
output$MyTable = DT::renderDataTable({table1()}, caption = 'Client Selection',options = list(searching = FALSE, pageLength = 15,list(className = 'dt-left')), selection = 'single', rownames = FALSE)
observeEvent(input$MyTable_rows_selected, {
row <- input$MyTable_rows_selected
table2 <- reactive({sqlQuery(BDW,paste0("SELECT DISTINCT FullName as 'Name',DATEDIFF(hour,DateofBirthorIncorporation,GETDATE())/8766 as 'Age',CONVERT(varchar(10),DateofBirthorIncorporation, 120) as 'Date of Birth',TaxID as 'SSN',GenderCode as 'Gender', OccupationCodeDescription as 'Occupation',DigitalAddress as 'Email', AddressLine1+' '+City+' '+StateCode+' '+PostalCode as 'Address'
FROM [EnterpriseCustomer].[dbo].[Party]a
LEFT JOIN [EnterpriseCustomer].[dbo].[PartytoAddressRelationship]b ON b.PartyID = a.PartyID
LEFT JOIN [EnterpriseCustomer].[dbo].[Address]c ON c.AddressID = b.AddressID
LEFT JOIN [EnterpriseCustomer].[dbo].[PartytoDigitalAddressRelationship]d ON d.PartyID = a.PartyID
LEFT JOIN [EnterpriseCustomer].[dbo].[DigitalAddress]e ON e.DigitalAddressID = d.DigitalAddressID
LEFT JOIN [BDW].[EnterpriseCustomer].[PartyOccupationCodes]g ON a.OccupationCode = g.OccupationCode
WHERE
a.PartyID =",table1()[row,"PartyID"],"
and a.ActiveRecordIndicator = 1 and b.ActiveRecordIndicator = 1"), as.is = TRUE)})
table8 <- reactive({sqlQuery(BOSCDB,paste0("SELECT DISTINCT TaxID, ltrim(rtrim(MinimumAnnualIncomeAmount))+' - '+ltrim(rtrim(MaximumAnnualIncomeAmount)) as 'Annual Income Band',ltrim(rtrim(MinimumNetWorthAmount))+' - '+ltrim(rtrim(MaximumNetWorthAmount)) as 'Net Worth Band',ltrim(rtrim(MinLiquidNetWorthAmt))+' - '+ltrim(rtrim(MaxLiquidNetWorthAmt)) as 'Liquid Net Worth Band'
FROM [ExternalData_Stage].[dbo].[tblPrsCustomerAccount_G]a
LEFT JOIN [ExternalData_Stage].[dbo].[tblPrsCustomerAccount_H]b ON b.AccountNumber = a.AccountNumber
WHERE TaxID = '",table1()[row,"Social Security Number"],"'
and a.DataDate = (SELECT MAX(DataDate) FROM [ExternalData_Stage].[dbo].[tblPrsCustomerAccount_G] WHERE TaxID = '",table1()[row,"Social Security Number"],"')"),as.is = TRUE)})
table9 <- reactive({merge(table2(),table8(), by.x = "SSN", by.y = "TaxID", all.x = TRUE)})
output$CDFInfo <- DT:: renderDataTable({table9()},options = list(dom='t'), caption = 'Client Information', rownames = FALSE)
updateTabsetPanel(session, "Main Panel", selected = "Client Discovery Form Information")
})
observeEvent(input$MyTable_rows_selected, {
row <- input$MyTable_rows_selected
table7 <- reactive({sqlQuery(BDW,paste0("SELECT DISTINCT FullName as 'Name',FORMAT(SUM(CASE WHEN ProductCategory = 'Deposit' THEN Value ELSE 0 END),'C', 'en-US') as 'Total Deposits Balance',FORMAT(SUM(CASE WHEN ProductCategory = 'Loan' THEN Value ELSE 0 END),'C','en-US') as 'Total Loans Balance',FORMAT(SUM(CASE WHEN ProductCategory = 'Investment' THEN Value ELSE 0 END),'C','en-us') as 'Total Investments Balance',FORMAT(SUM(CASE WHEN ProductCategory is null THEN Value ELSE 0 END),'C','en-US') as 'Total Other Balance'
FROM (SELECT DISTINCT PartyID, FinancialAccountID
FROM [EnterpriseCustomer].[dbo].[PartytoFinancialAccountRelationship]
WHERE ActiveRecordIndicator = 1)a
LEFT JOIN (SELECT *
FROM [EnterpriseCustomer].[dbo].[FinancialAccount]
WHERE ActiveRecordIndicator = 1)b ON b.FinancialAccountID = a.FinancialAccountID
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountStatusCodes]c ON b.StatusCode = c.StatusCode
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountProductCodes]d ON b.ProductCode = d.ProductCode AND b.SourceSystemCode = d.SourceSystemCode
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccountValueSnapshot]e ON b.FinancialAccountID = e.FinancialAccountID
LEFT JOIN (SELECT *
FROM [EnterpriseCustomer].[dbo].[Party]
WHERE ActiveRecordIndicator = 1)f ON a.PartyID = f.PartyID
WHERE a.PartyID =",table1()[row,"PartyID"],"GROUP BY FullName"), as.is = TRUE)})
output$WealthSummary <- DT:: renderDataTable({table7()},options = list(dom='t'), caption = 'Client Wealth Management Summary', rownames = FALSE)
updateTabsetPanel(session, "Main Panel", selected = "Client Discovery Form Information")
})
observeEvent(input$MyTable_rows_selected, {
row <- input$MyTable_rows_selected
table3 <- reactive({sqlQuery(BDW,paste0("SELECT DISTINCT FinancialAccountNumber as 'Account Number',FinancialAccountName as 'Account Name',OpenDate as 'Account Open Date', ProductType as 'Account Description', FORMAT(Value,'C','en-US') as 'Account Balance'
FROM [EnterpriseCustomer].[dbo].[PartytoFinancialAccountRelationship]a
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccount]b ON b.FinancialAccountID = a.FinancialAccountID
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountStatusCodes]c ON b.StatusCode = c.StatusCode
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountProductCodes]d ON b.ProductCode = d.ProductCode AND b.SourceSystemCode = d.SourceSystemCode
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccountValueSnapshot]e ON b.FinancialAccountID = e.FinancialAccountID
LEFT JOIN [EnterpriseCustomer].[dbo].[Party]f ON a.PartyID = f.PartyID
WHERE a.PartyID =",table1()[row,"PartyID"],"AND ProductCategory = 'Deposit' AND StatusCategory = 'Open'
AND b.ActiveRecordIndicator = 1"), as.is = TRUE)})
output$Deposit <- DT:: renderDataTable({table3()},options = list(dom='t'), caption = 'Deposit Accounts', rownames = FALSE)
updateTabsetPanel(session, "Main Panel", selected = "Client Discovery Form Information")
})
observeEvent(input$MyTable_rows_selected, {
row <- input$MyTable_rows_selected
table4 <- reactive({sqlQuery(BDW,paste0("SELECT DISTINCT FinancialAccountNumber as 'Account Number',FinancialAccountName as 'Account Name',OpenDate as 'Account Open Date', ProductType as 'Account Description', FORMAT(Value,'C','en-US') as 'Account Balance'
FROM [EnterpriseCustomer].[dbo].[PartytoFinancialAccountRelationship]a
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccount]b ON b.FinancialAccountID = a.FinancialAccountID
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountStatusCodes]c ON b.StatusCode = c.StatusCode
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountProductCodes]d ON b.ProductCode = d.ProductCode AND b.SourceSystemCode = d.SourceSystemCode
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccountValueSnapshot]e ON b.FinancialAccountID = e.FinancialAccountID
LEFT JOIN [EnterpriseCustomer].[dbo].[Party]f ON a.PartyID = f.PartyID
WHERE a.PartyID =",table1()[row,"PartyID"],"AND ProductCategory = 'Investment' AND StatusCategory = 'Open'
AND b.ActiveRecordIndicator = 1"), as.is = TRUE)})
output$Investment <- DT:: renderDataTable({table4()},options = list(dom='t'), caption = 'Investment Accounts', rownames = FALSE)
updateTabsetPanel(session, "Main Panel", selected = "Client Discovery Form Information")
})
observeEvent(input$MyTable_rows_selected, {
row <- input$MyTable_rows_selected
table5 <- reactive({sqlQuery(BDW,paste0("SELECT DISTINCT FinancialAccountNumber as 'Account Number',FinancialAccountName as 'Account Name',OpenDate as 'Account Open Date', ProductType as 'Account Description',ValueType as 'Balance Description', FORMAT(Value,'C','en-US') as 'Account Balance'
FROM [EnterpriseCustomer].[dbo].[PartytoFinancialAccountRelationship]a
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccount]b ON b.FinancialAccountID = a.FinancialAccountID
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountStatusCodes]c ON b.StatusCode = c.StatusCode
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountProductCodes]d ON b.ProductCode = d.ProductCode AND b.SourceSystemCode = d.SourceSystemCode
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccountValueSnapshot]e ON b.FinancialAccountID = e.FinancialAccountID
LEFT JOIN [EnterpriseCustomer].[dbo].[Party]f ON a.PartyID = f.PartyID
WHERE a.PartyID =",table1()[row,"PartyID"],"AND ProductCategory = 'Loan' AND StatusCategory = 'Open'
AND b.ActiveRecordIndicator = 1"), as.is = TRUE)})
output$Loan <- DT:: renderDataTable({table5()},options = list(dom='t'), caption = 'Loan Accounts', rownames = FALSE)
updateTabsetPanel(session, "Main Panel", selected = "Client Discovery Form Information")
})
observeEvent(input$MyTable_rows_selected, {
row <- input$MyTable_rows_selected
table6 <- reactive({sqlQuery(BDW,paste0("SELECT DISTINCT FinancialAccountNumber as 'Account Number',FinancialAccountName as 'Account Name',OpenDate as 'Account Open Date', ProductType as 'Account Description', FORMAT(Value,'C','en-US') as 'Account Balance'
FROM [EnterpriseCustomer].[dbo].[PartytoFinancialAccountRelationship]a
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccount]b ON b.FinancialAccountID = a.FinancialAccountID
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountStatusCodes]c ON b.StatusCode = c.StatusCode
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountProductCodes]d ON b.ProductCode = d.ProductCode AND b.SourceSystemCode = d.SourceSystemCode
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccountValueSnapshot]e ON b.FinancialAccountID = e.FinancialAccountID
LEFT JOIN [EnterpriseCustomer].[dbo].[Party]f ON a.PartyID = f.PartyID
WHERE a.PartyID =",table1()[row,"PartyID"],"AND ProductCategory is NULL AND StatusCategory = 'Open'
AND b.ActiveRecordIndicator = 1"), as.is = TRUE)})
output$Other <- DT:: renderDataTable({table6()},options = list(dom='t'), caption = 'Other Accounts', rownames = FALSE)
updateTabsetPanel(session, "Main Panel", selected = "Client Discovery Form Information")
})
output$downloadData <-
downloadHandler(
filename = function() {
"Financial_Planning_CDF_Data.xlsx"
},
content = function(file) {
write.xlsx(list("Client Information" = table9(),"Wealth Summary" = table7(),"Deposit Accounts" = table3(), "Investment Accounts" = table4(), "Loan Accounts" = table5(),"Other Accounts" = table6()), file, row.names = FALSE)
}
)
}
shinyApp(ui, server)
Upvotes: 0
Views: 408
Reputation: 21287
As suggested by Tom, you can define reactive statements outside the event handlers or use reactiveValues objects as
server <- function(input, output, session) {
rv <- reactiveValues()
observeEvent(input$MyTable_rows_selected, {
row <- input$MyTable_rows_selected
rv$table3 <- reactive({sqlQuery(BDW,...)})
})
output$downloadData <-
downloadHandler(
filename = function() {
"Financial_Planning_CDF_Data.xlsx"
},
content = function(file) {
write.xlsx(list("Deposit Accounts" = rv$table3...), file, row.names = FALSE)
}
)
}
Upvotes: 1
Reputation: 592
It should be enough to restructure your code a bit. So for instance table7
part, you would rewrite it like this to make it available throughout your server function (including the downloadHandler
):
table7 <- reactive({
row <- input$MyTable_rows_selected
sqlQuery(BDW,paste0("SELECT DISTINCT FullName as 'Name',FORMAT(SUM(CASE WHEN ProductCategory = 'Deposit' THEN Value ELSE 0 END),'C', 'en-US') as 'Total Deposits Balance',FORMAT(SUM(CASE WHEN ProductCategory = 'Loan' THEN Value ELSE 0 END),'C','en-US') as 'Total Loans Balance',FORMAT(SUM(CASE WHEN ProductCategory = 'Investment' THEN Value ELSE 0 END),'C','en-us') as 'Total Investments Balance',FORMAT(SUM(CASE WHEN ProductCategory is null THEN Value ELSE 0 END),'C','en-US') as 'Total Other Balance'
FROM (SELECT DISTINCT PartyID, FinancialAccountID
FROM [EnterpriseCustomer].[dbo].[PartytoFinancialAccountRelationship]
WHERE ActiveRecordIndicator = 1)a
LEFT JOIN (SELECT *
FROM [EnterpriseCustomer].[dbo].[FinancialAccount]
WHERE ActiveRecordIndicator = 1)b ON b.FinancialAccountID = a.FinancialAccountID
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountStatusCodes]c ON b.StatusCode = c.StatusCode
LEFT JOIN [BDW].[EnterpriseCustomer].[FinancialAccountProductCodes]d ON b.ProductCode = d.ProductCode AND b.SourceSystemCode = d.SourceSystemCode
LEFT JOIN [EnterpriseCustomer].[dbo].[FinancialAccountValueSnapshot]e ON b.FinancialAccountID = e.FinancialAccountID
LEFT JOIN (SELECT *
FROM [EnterpriseCustomer].[dbo].[Party]
WHERE ActiveRecordIndicator = 1)f ON a.PartyID = f.PartyID
WHERE a.PartyID =",table1()[row,"PartyID"],"GROUP BY FullName"), as.is = TRUE)
})
observeEvent(input$MyTable_rows_selected, {
output$WealthSummary <- DT:: renderDataTable(table7(),options = list(dom='t'), caption = 'Client Wealth Management Summary', rownames = FALSE)
updateTabsetPanel(session, "Main Panel", selected = "Client Discovery Form Information")
})
Upvotes: 1