I have an interactive Rmarkdown document which embeds a few shiny apps that generates graphs based on user inputs.
After I am happy with the graphs generated, I would like to save the report (so that it becomes static).
I have opened the report in my browser (Chrome), and tried printing to pdf. It sort of works, however some figures are cut into two by the page break.
Does anyone know what is the best way to print/save such reports?
I think it's a bit tricky but this is what i use on my app to save html plot on pdf or png format.
Instal wkhtmltopdf
wkhtmltopdf and wkhtmltoimage are open source (LGPLv3) command
line tools to render HTML into PDF and various image formats using the
Qt WebKit rendering engine. These run entirely "headless" and do not
require a display or display service.
Use it in R
This allow you to convert a htmlfile into pdfor img.
In my ShinyApp i use inside a downloadHandler() function somthing like this :
system("wkhtmltopdf --enable-javascript --javascript-delay 2000 plot.html plot.pdf")
I think for your example you could simply convert your html by using :
system("wkhtmltopdf yourFile.html yourFile.pdf")
You can give a download button on the ui.R as:
downloadButton('report', 'Download PDF')
And the corresponding server.R code:
library(knitr)
output$report = downloadHandler(
filename = function() {
paste("Report_", <date/identifier>, ".pdf", sep="")
},
content = function(file) {
rnw <- normalizePath('input.rnw') # assuming you wrote the code to display the graphs etc in this file
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(rnw, 'input.rnw')
out = knit2pdf(rnw, clean=TRUE)
file.rename(out, file)
}
)
Related
I wrote a shiny app that includes generating an rmd file and then rendering it into html report.
As shown in the simple example below, there is a variable created inside the server function of shinyapp, then the created rmd file should have access to this variable while rendering into html.
according to other posts and articles, it seems that we have to copy the rmd file into a temporary folder to work and that's what I tried to do below.
the app is not working.
when I try locally, I get this error:
Quitting from lines 8-9 (x3.Rmd)
Warning: Error in print: object 'xz' not found
so it seems that shiny was able to find the generated rmd, started rendering it but did not have access to the xz variable generated in shiny. I did some reading, and it seems to be related to the render environment (ie it renders in a new session) but I do not know how to fix that. (in the real app I am working on, the render process should have access to a dataframe not just a string variable, but I believe the concept is the same for illustration purpose).
when I tested on shinyapps.io, it says Failed-server problem when I click on the download button. Surprisingly, there is nothing in the application log, it says currently no logs.
when I test the original app I am writing (not this simple example), I get this error in shinyapp.io logs:
2022-04-10T18:01:45.357461+00:00 shinyapps[6055802]: Warning in normalizePath(path, winslash = winslash, mustWork = mustWork) :
2022-04-10T18:01:45.357710+00:00 shinyapps[6055802]: [No stack trace available]
2022-04-10T18:01:45.357627+00:00 shinyapps[6055802]: Warning: Error in abs_path: The file '/tmp/Rtmp27RVU8/x3.Rmd' does not exist.
2022-04-10T18:01:45.357543+00:00 shinyapps[6055802]: path[1]="/tmp/Rtmp27RVU8/x3.Rmd": No such file or directory
My goal is to make this work from shinyapp.io. Any suggestions on where to go from there, I believe there are two issues:
1- make sure the rmd render will have access to the variables generated in shiny
2- save the rmd file in a place that is "convenient" for shiny to find and render.
library(shiny)
ui <- fluidPage(
downloadButton("report", "Download sample report.")
)
server <- function(input, output, session) {
#create content and export it into rmd
observe({
xz= "hello there"
x3 = '---
title: sample
output: html_document
---
``` {r}
print(xz)
```
';write(x3, file="x3.rmd", append = FALSE)
})
#Render the report and pass it to download handler
output$report <- downloadHandler(
filename = "sample.html",
content = function(file) {
tempReport <- file.path(tempdir(), "x3.Rmd")
file.copy("x3.Rmd", tempReport, overwrite = TRUE)
output <- rmarkdown::render(
input = tempReport
)
file.copy(output, file)
})
}
shinyApp(ui, server)
These are the resources I used (but still unable to make it work). All deal with parameterized reports of a user uploaded .rmd, which won't work in my case:
https://shiny.rstudio.com/articles/generating-reports.html
https://community.rstudio.com/t/where-do-i-save-the-rmd-file-i-am-generating-with-a-shiny-r-app/65987/3
https://community.rstudio.com/t/generating-downloadable-reports/39701
https://mastering-shiny.org/action-transfer.html#downloading-reports
I have done this with Shiny App but on a shiny server (in my work place) and can share only the approach here. Currently the access to exact code will take time but this shall give you idea. No idea how it works with shinyapps.io but will try that sometime.
Within UI of shiny provide for a "Generate Report" Button.
In server, with
observeEvent(input$btn_Id,{
#Code to render the html in rmarkdown and then also `downloadHandler()`
})
Please check this also :
Use the downloandHanlder() referring this documentation.
This one gives idea to download data
Solution to passing variables is not special. Just ensure data is already present when you are calling render()
like this:
rmarkdown::render(input = "D:/YourWorkingDirectly/Letters.rmd")
If this doesn't help you , please let me know and will delete the answer.
I'm working on R Sweave to generate a report in PDF in a shiny application on a server. Everything works perfectly in my computer, locally, I can generate my PDF in the application. It also works in the server. But, when I wanted to add an image in a background, a rectangular header, in the R Sweave , it didn't work anymore on the server, it can't be generated.
Here's the code I added in my R Sweave, so my report :
\usepackage{background}
\usepackage{graphicx}
\backgroundsetup{
scale=0.5,
angle=0,
opacity=1,
color=black,
contents={\begin{tikzpicture}[remember picture, overlay]
\node at ([yshift=-.6in] current page.north)
{\includegraphics[width = \paperwidth]{myheader}};
\end{tikzpicture}}
}
Did I forget something ?
Thank you
EDIT : After some researches, I think I probably have a problem with these functions in the script server.R :
output$report <- downloadHandler(
filename = function(){name()},
content = function(file) {
out = knitr::knit2pdf(input="my_report.Rnw",encoding = "UTF-8",clean=TRUE)
file.rename(out, file)
file.copy(file,paste0("export/",Sys.Date(),"_",name()))
},
contentType = 'application/pdf'
)
It seems that I probably forgot an argument in my function out = knitr::knit2pdf(input="my_report.Rnw",encoding = "UTF-8",clean=TRUE). It seems that it can only manage a text on UTF-8 and geometric forms, not an image.
Problem solved! In my R Sweave, I just added \usepackage{tikz} and it works!
Thanks to Dirk Eddelbuettel for his help.
I have a shiny app that allows the user to download an HTML file (knitted from a .Rmd file) that includes the code used to run the analysis based on all the user inputs. I am trying to write the base .Rmd file that gets altered when user inputs vary. I am having trouble including user input variables (e.g. input$button1) into R code chunks. Say the user input for input$button1 = "text1".
```{r}
results <- someFun(input$button1)
```
And I'd like to have it knitted like this:
```{r}
results <- someFun('text1')
```
Every time I download the knitted HTML though, I get input$button1 getting written to file. I would also like to be able to produce an .Rmd file that is formatted with this substitution. It seems like knit_expand() might be the key, but I can't seem to relate available examples to my specific problem. Is the proper way to knit_expand() the whole .Rmd file and specify explicitly all the parameters you want subbed in, or is there a more elegant way within the .Rmd file itself? I would prefer a method similar to this, except that instead of using the asis engine, I could use the r one. Any help would be greatly appreciated. Thanks!
Got it. Solution below. Thanks to Yihui for the guidance. The trick was to knit_expand() the whole .Rmd file, then writeLines() to a new one, then render. With hindsight, the whole process makes sense. With hindsight.
For the example, p1 is a character param 'ice cream' and p2 is an integer param 10. There is a user-defined param in ui.R called input$mdType that is used to decide on the format provided for download.
Rmd file:
Some other text.
```{r}
results <- someFun("{{p1}}", {{p2}})
```
in the downloadHandler() within server.R:
content = function(file) {
src <- normalizePath('userReport.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, 'userReport.Rmd')
exp <- knit_expand('userReport.Rmd', p1=input$p1, p2=input$p2)
writeLines(exp, 'userReport2.Rmd')
out <- rmarkdown::render('userReport2.Rmd', switch(input$mdType,
PDF = pdf_document(), HTML = html_document(), Word = word_document()))
}
file.rename(out, file)
}
Resulting userReport2.Rmd before rendering:
```{r}
results <- someFun("ice cream", 10)
```
I created a shiny app and now i want to plot a chart to pdf. So, is there any way to print a googlevis Chart to pdf in R.
I know its not possible directly, as stated in the help pages. But is there a way to print a static image (similar to a screenshot)? If possible without sweave/knitr?
Thank you in advance
You can do this using wkhtmltopdf, which you need to install and possibly add to your system path. I have got this working for other googlevis objects, where in some cases I did not need the --enable-javascript --javascript-delay option....
output$downloadmap <- downloadHandler("mymap.pdf" ,
content = function(file) {
#print gmap googlevis R object to a html file
print(gmap, file="gmap.html")
#call to wkhtmltopdf installed on server/pc to convert html file to pdf.
#add a delay otherwise (i got an) empty plot
system("wkhtmltopdf --enable-javascript --javascript-delay 2000 gmap.html gmap.pdf")
#copy pdf file to output
file.copy("gmap.pdf", file)
#remove created files from local storage
file.remove("gmap.pdf")
file.remove("gmap.html")
}
)
I am playing around with RShiny recently, and I've built a working web interface that takes two parameters "date" and "location" and gives me back a series of graphs and tables from our database that fit the criteria.
What I would like to do with that, is to have users being able to download all the data and graphs in the form of a RMD report in HTML format.
so I have
1. UI.R with a download button
2. Server.R's downloadHandler starts my RMD script
3. ????
UI.R
downloadButton('downloadData','Download')
Server.R
output$downloadData<- downloadHandler(filename ="myData.html",
content= function(file= NULL){
knit(thread.RMD)
}
Here is the answer I got from the Shiny Google Group : https://groups.google.com/forum/?fromgroups=#!topic/shiny-discuss/XmW9V014EtI
The function that's given as the 'content' argument to downloadHandler takes one option, 'file'. When the download button is clicked, the download handler calls that function, and it uses the file argument to tell it where is should save the output file.
I don't see a way to set the output file name from knit2html(), but you can just rename it after it's created:
output$downloadData <- downloadHandler(
filename ="ShinyData.html",
content = function(file) {
knit2html("myreport.rmd")
file.rename("myreport.html", file)
}
)
(Also, you're missing a closing parenthesis in ui.r.)
-Winston