I have problems generating table of contents in the markdown generated by my shinyapp.
I have tried to set in the YAML toc = TRUE but it doesn't work.
the app is something like this, an interface where some data is uploaded and a markdown where some graphics are rendered.
the problem is that when generating the pdf, html or word the table of contents is not generated.
app.R
library(shiny)
library(dplyr)
library(qcc)
library(ggplot2)
library(readxl)
library(kableExtra)
library(knitr)
shinyApp(ui =
fluidPage(fileInput("file", "Cargar Datos", multiple = FALSE),
radioButtons('format', 'Formato del documento', c('PDF', 'HTML', 'Word'),inline = TRUE),
downloadButton('downloadReport')),
server = function(input, output, session){
myData <- reactive({ infile <- input$file
if(is.null(infile)) return(NULL)
data <- read_excel(infile$datapath)
data})
plotData <- function(){plot(myData}
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
))
},
content = function(file) {
src <- normalizePath('report.Rmd')
# temporarily switch to the temp dir, in case you do not have write
# permission to the current working directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd', overwrite = TRUE)
library(rmarkdown)
out <- render('report.Rmd', switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
)
########################################
####
})
report.Rmd
---
title: "title"
subtitle: "subtitle"
output:
toc: true
toc_depth: 4
number_sections: true
author:
- "a1"
- "a2"
date: "`r format(Sys.Date(), '%B %d, %Y')`"
params:
p1: "p1"
p2: "p2"
---
# section1
## section1.1
# section2
```{r}
plotData()
Try passing the options as arguments to the rendering function, e.g.
rmarkdown::render('report.Rmd', rmarkdown::pdf_document(toc = TRUE, toc_depth = 4, number_sections = TRUE))
answered by stefan in a comment on the question.
Related
I am trying to download pdf/docx/html reports based on the inputs provided by user. To do that I created a Shiny app and a qmd file with parameters. qmd file is working fine when i render it separately. But if i render the same document and try to download it from Shiny it is not working. Here is my downloadHandler chunk
output$report <- downloadHandler(
filename = function() {
paste("report", input$report_file_type, sep = ".")
},
content = function(file) {
output <- quarto::quarto_render(
input = 'report_template.qmd',
output_format = input$report_file_type,
execute_params = list(name = input$author_name,
report_title = input$report_title)
)
file.copy(output, file)
}
)
Edit: here is the qmd report template
---
title: "`r params$report_title`"
author: "`r params$name`"
date: "`r format(Sys.time(), '%d %B, %Y')`"
format: html
embed-resources: true
params:
report_title: "report title"
name: "author name"
p_list: list("A", "B")
---
Printing each element of the list...
```{r}
#| echo: true
for(p in eval(parse(text = params$p_list))){
print(p)
}
```
Printing the list...
```{r}
#| echo: true
print(eval(parse(text = params$p_list)))
```
I am not getting any error but at the same nothing is being written to downloads folder. It seems like rendered document is not being assigned to output. Perhaps that's why the coping line is not working. what could be the problem and how to solve it? thanks in advance.
quarto::quarto_render does not return the generated file or anything and so output in your code is NULL and hence you are not getting any output.
Now to get this code working, we need to copy the file generated by quarto::quarto_render to the file parameter of the function passed to content argument of downloadHandler.
shinyApp(
# UI -----------------------------------------------------------
ui = fluidPage(
textInput("author_name", "Author Name", "John Doe"),
textInput("report_title", "Report Title", "Quarto From Shiny"),
radioButtons(
inputId = "report_file_type",
label = "Report Type",
choices = c("HTML" = "html", "PDF" = "pdf")
),
downloadButton("report", "Generate report")
),
# SERVER --------------------------------------------------------
server = function(input, output) {
output$report <- downloadHandler(
filename = function() {
paste("report", input$report_file_type, sep = ".")
},
content = function(file) {
quarto::quarto_render(
input = "report_template.qmd",
output_format = input$report_file_type,
execute_params = list(
name = input$author_name,
report_title = input$report_title
)
)
# copy the quarto generated file to `file` argument.
generated_file_name <- paste("report_template", input$report_file_type,
sep = ".")
file.copy(generated_file_name, file)
}
)
}
)
I am trying to render a table into a pdf using kable in a markdown document generated from a shiny app. It renders OK until I use any functionality from kableExtra (column_spec in the code below) at which point I get the following error:
! LaTeX Error: Illegal character in array
arg.
The problem seems pretty basic and I'm not the first to have this issue, but other solutions (such as this and this) haven't helped. The table renders OK as HTML but it seems that kableExtra doesn't seem to know that it is rendering latex. If I change the knitr.table.format to "pandoc" it renders but still errors of the column_spec line. Any ideas?
UI.R
fluidPage(
title = 'Download a PDF report',
sidebarLayout(
sidebarPanel(
helpText(),
div("Create a Mark Down Document"),
radioButtons('format', 'Document format', c('PDF', 'HTML'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
plotOutput('regPlot')
)
)
)
Server.R
library(rmarkdown)
library(shiny)
library(magrittr)
library(kableExtra)
function(input, output) {
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html'
))
},
content = function(file) {
src <- normalizePath('report.Rmd')
# temporarily switch to the temp dir, in case you do not have write
# permission to the current working directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd', overwrite = TRUE)
out <- render('report.Rmd', switch(
input$format,
PDF = pdf_document(), HTML = html_document()
))
file.rename(out, file)
}
)
}
Report.Rmd
Test kable:
```{r}
auto_set_format <- function() {
if (knitr::is_latex_output()) {
options(knitr.table.format = "latex")
} else {
options(knitr.table.format = "html")
}
}
auto_set_format()
tbl <- knitr::kable(mtcars[1:6, 1:6], caption = 'A subset of mtcars.')
# THIS LINE CAUSES THE PROBEM WHEN WRITING TO PDF. COMMENT OUT AND IT WORKS OK
tbl <- tbl %>% column_spec(3, color = "#62BD19")
tbl
```
For column_spec() you need to give an additional Latex package to knitr, i.e. change your report to
---
title: "Example Table"
header-includes:
- \usepackage{dcolumn}
---
Test kable:
```{r}
auto_set_format <- function() {
if (knitr::is_latex_output()) {
options(knitr.table.format = "latex")
} else {
options(knitr.table.format = "html")
}
}
auto_set_format()
tbl <- knitr::kable(mtcars[1:6, 1:6], caption = 'A subset of mtcars.') %>%
column_spec(3, color = "#62BD19")
tbl
```
and you will be able to produce both reports.
I've created ShinyApp where everything works fine. I'd like to add downloadHandler to generate Markdown report that contains the chosen plot. Firstly, I upload a file into ShinyApp. Nextly, I select variables to be plotted using checkBoxInput. Next step is using dropdown list to select between Lattice/ggplot2 plot and finally I'd like to click download it and get it.
Unfortunately, every time I do try to download it I receive a blank Markdown page. It doesn't really matter what format of report will be generated. I'd like to get an appropiate logic for this task. I tried both solutions I found in a network:
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx')
)
},
content = function(file) {
src <- normalizePath('report.Rmd')
owd <- setwd(getwd())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd', overwrite = TRUE)
out <- render('report.Rmd', switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
})
and
output$report <- downloadHandler(
filename = "report.html",
content = function(file) {
tempReport <- file.path(getwd(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
params <- list(graph = input$graph, colsel = input$colsel)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
So respectively I created report.rmd templates for my app to fullfill it. I tried to put a lot of things inside but none of these works. Do I miss the logic for the template?
---
title: "Untitled"
author: "user"
date: "date"
output: html_document
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r plot, echo=TRUE}
plotdata <- reactive({
d <- dataIn()[, c(req(input$colsel))]
d <- melt(d, id.vars="Numer")
})
plot1 <- reactive({
dotplot(value~Numer, data=plotdata(), auto.key = list(space="right", title="Types"), groups=variable)
})
plot2 <- reactive({
ggplot(plotdata(), aes(x=Numer, y=value, color=variable)) +
geom_point()
})
graphInput <- reactive({
switch(input$graph,
"Lattice" = plot1(),
"ggplot2" = plot2())
})
renderPlot({
graphInput()
})
})
```
Alright, I got it finally! Firstly, we need to run shinyApp using function "Run External". Secondly we don't need that mess I made in the template. Simple:
---
title: "Untitled"
author: "user"
date: "date"
output: html_document
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(shiny)
library(ggplot2)
library(lattice)
library(markdown)
```
```{r plot}
plot1()
plot2()
graphInput()
```
Where plot1(), plot2() and graphinput() represent my:
plot1 <- reactive({
dotplot(value~Numer,data=plotdata(), auto.key = list(space="right", title="WWW"), groups=variable)
})
plot2 <- reactive({
ggplot(plotdata(), aes(x=Numer, y=value, color=variable)) +
geom_point()
})
graphInput <- reactive({
switch(input$graph,
"Lattice" = plot1(),
"ggplot2" = plot2()
)
})
Hello I have this simple shiny app which includes 3 files(ui,server,kable), in which i want to be able to produce a table with kable() after importing a csv file. I can make it work when i produce it in html but it cannot be converted to pdf. Specifically i get this error: Error : pandoc document conversion failed with error 43
#ui.r
library(shiny)
library(rmarkdown)
fluidPage(sidebarLayout(
sidebarPanel(
fileInput("file1", "Input CSV-File"),
downloadButton('downloadReport')
),
mainPanel(tableOutput("table"))
))
#server.r
function(input, output) {
output$downloadReport <- downloadHandler(
filename = "my-report.pdf",
content = function(file) {
src <- normalizePath('kable.Rmd')
# temporarily switch to the temp dir, in case you do not have write
# permission to the current working directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'kable.Rmd', overwrite = TRUE)
out <- render('kable.Rmd', params = list(file = input$file1$datapath))
file.rename(out, file)
}
)
output$table <- renderTable({
inFile <- req(input$file1)
read.csv(inFile$datapath)
})
}
#kable.rmd
---
params:
file: "mtcars.csv"
output: pdf_document
---
```{r echo = FALSE, message = FALSE, include = FALSE}
library(kableExtra)
library(knitr)
```
```{r nice-tab, tidy = FALSE, echo = FALSE, message = FALSE}
csvdata <- read.csv(file = params$file)
kable(csvdata, caption = 'REPORT TABLE',
booktabs = TRUE, longtable = TRUE,format = "latex", escape = FALSE) %>%
kable_styling(full_width = T, font_size = 10 ) %>%
row_spec(row = 0, bold = T, background = "gray")
```
I would like to download Report within Shiny App, which includes Plotly graph.
So far i have not found any answer on stackoverflow.
Till this moment im able to download the screenshot of Plotly but it appears only in my working directory and it is not sent to Rmarkdown.
Example code:
library(shiny)
library(plotly)
library(rsvg)
library(ggplot2)
d <- data.frame(X1=rnorm(50,mean=50,sd=10),X2=rnorm(50,mean=5,sd=1.5),Y=rnorm(50,mean=200,sd=25))
ui <-fluidPage(
title = 'Download report',
sidebarLayout(
sidebarPanel(
helpText(),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport'),
tags$script('
document.getElementById("downloadReport").onclick = function() {
var plotly_svg = Plotly.Snapshot.toSVG(
document.querySelectorAll(".plotly")[0]
);
Shiny.onInputChange("plotly_svg", plotly_svg);
};
')
),
mainPanel(
plotlyOutput('regPlot')
)
)
)
server <- function(input, output, session) {
output$regPlot <- renderPlotly({
p <- plot_ly(d, x = d$X1, y = d$X2,mode = "markers")
p
})
observeEvent(input$plotly_svg, priority = 10, {
png_gadget <- tempfile(fileext = ".png")
png_gadget <- "out.png"
print(png_gadget)
rsvg_png(charToRaw(input$plotly_svg), png_gadget)
})
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
))
},
content = function(file) {
src <- normalizePath('testreport.Rmd')
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'testreport.Rmd')
library(rmarkdown)
out <- render('testreport.Rmd', params = list(region = "Test"), switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
)
}
shinyApp(ui = ui, server = server)
and testreport.Rmd file:
---
title: "test"
output: pdf_document
params:
name: "Test"
region: 'NULL'
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
Any help would be appreciated, because there is not many sources and documentations about R Plotly.
Cheers
If out.png is downloaded to your working directory, you can modify the content function of your downloadHandler to move it to the temporary directory and add it to the report:
content = function(file) {
temp_dir <- tempdir()
tempReport <- file.path(temp_dir, 'testreport.Rmd')
tempImage <- file.path(temp_dir, 'out.png')
file.copy('testreport.Rmd', tempReport, overwrite = TRUE)
file.copy('out.png', tempImage, overwrite = TRUE)
library(rmarkdown)
out <- render(tempReport, params = list(region = "Test"), switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
Your testreport.Rmd could look like (more info here):
---
title: "test"
---
Here's the plot image.
![Plot image](out.png)
You could also pass the arguments of your plotly function in the render of your content function as explained here and use a parametrized Rmarkdown file but this only works for Html reports.
Depending on how deep you want to dive into this, I would suggest creating a .brew file with your shiny code and than you can have your user send the information to the brew file and create the plot. This would give you a static code file which is updated dynamically with new data, each time. The only draw back is that when you make changes to shiny you have to make the same changes to your brew file. The other option is to create a flex dashboard with rmarkdown using the new RStudio 1.0 which becomes a html file.
See (Create parametric R markdown documentation?) for brew example.