I am trying to make a powerpoint file with officer that includes tables with hyperlinks in their cells, but I can't find a way how to do it.
E.g. a row in a 2 column table on a slide could include 'Ensembl' in the 1st column, the 2nd column would say 'ENSG00000165025' and clicking on it would open up the browser at 'uswest.ensembl.org/Homo_sapiens/Gene/Summary?g=ENSG00000165025'. Some values in the 2nd column could be just plain text.
Is this possible to achieve?
With the new version on github, you will be able to include hyperlinks as demo below:
library(flextable)
dat <- data.frame(
col = "CRAN website", href = "https://cran.r-project.org",
stringsAsFactors = FALSE)
ft <- flextable(dat)
ft <- display(
ft, col_key = "col", pattern = "# {{mylink}}",
formatters = list(mylink ~ hyperlinked_text(href, col) )
)
ft
`
dat <- data.frame(
col = "entrez",
href = "https://www.ncbi.nlm.nih.gov/gene?cmd=Retrieve&dopt=full_report&list_uids=6850",
stringsAsFactors = FALSE)
ft <- flextable(dat)
ft <- display(
ft, col_key = "col", pattern = "# {{mylink}}",
formatters = list(mylink ~ hyperlink_text(href, col) )
)
ft # works fine
doc <- read_pptx() %>%
add_slide(layout = 'Title and Content', 'Office Theme') %>%
ph_with_flextable(ft) # error
Error in doc_parse_raw(x, encoding = encoding, base_url = base_url,
as_html = as_html, : EntityRef: expecting ';' [23]
repeat with:
dat <- data.frame(
col = "entrez", href = URLencode("https://www.ncbi.nlm.nih.gov/gene?cmd=Retrieve&dopt=full_report&list_uids=6850", reserved = TRUE),
stringsAsFactors = FALSE)
ft <- flextable(dat)
ft <- display(
ft, col_key = "col", pattern = "# {{mylink}}",
formatters = list(mylink ~ hyperlink_text(href, col) )
)
ft # clicking the link in rstudio fails
doc <- read_pptx() %>%
add_slide(layout = 'Title and Content', 'Office Theme') %>%
ph_with_flextable(ft) # fine, no error message, but error message when opening pp file
Related
I have seen that there is already a question about that known limitation for pptx.
But is there a workaround like converting it first into an image and import that to pptx or something similar?
I don‘t care that the table can‘t be edited afterwards, that would actually be an advantage.
Edit:
Here as wished a minimal example where the Graphs are not included in the pptx.
library(flextable)
library(data.table)
library(officer)
library(dplyr)
z <- as.data.table(ggplot2::diamonds)
z <- z[, list(
price = mean(price, na.rm = TRUE),
list_col = list(.SD$x)
), by = "cut"]
z
ft <- flextable(data = z) %>%
compose(j = "list_col", value = as_paragraph(
plot_chunk(value = list_col, type = "dens", col = "pink",
width = 1.5, height = .4, free_scale = TRUE)
)) %>%
colformat_double(big.mark = " ", suffix = " $") %>%
set_header_labels(list_col = "density") %>%
autofit()
ft
print(ft, preview = "pptx")
You can use the new grid output feature for that—the following code demo some of its features (see ?gen_grob for more informations):
library(flextable)
library(data.table)
library(officer)
library(dplyr)
z <- as.data.table(ggplot2::diamonds)
z <- z[, list(
price = mean(price, na.rm = TRUE),
list_col = list(.SD$x)
), by = "cut"]
z
ft <- flextable(data = z) %>%
mk_par(j = "list_col", value = as_paragraph(
plot_chunk(value = list_col, type = "dens", col = "pink",
width = 1.5, height = .4, free_scale = TRUE)
)) %>%
colformat_double(big.mark = " ", suffix = " $") %>%
set_header_labels(list_col = "density") %>%
autofit()
ft
# create powerpoint
ppt <- read_pptx() %>%
add_slide() %>%
ph_with(value = plot_instr(code = plot(ft, fit = FALSE, scaling = "fixed")),
location = ph_location_type()) %>%
add_slide() %>%
ph_with(value = plot_instr(code = plot(ft)),
location = ph_location_fullsize()) %>%
add_slide() %>%
ph_with(value = plot_instr(code = plot(ft, fit = "width", scaling = "min")),
location = ph_location_fullsize())
# save powerpoint
print(ppt, preview = "pptx", target = 'output.pptx')
You could save your table as an image using save_as_image from officer package. After that you can add the image using ph_with where you add a value using the external_img function to add your image. Here is a reproducible example:
library(flextable)
library(data.table)
library(officer)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:data.table':
#>
#> between, first, last
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
z <- as.data.table(ggplot2::diamonds)
z <- z[, list(
price = mean(price, na.rm = TRUE),
list_col = list(.SD$x)
), by = "cut"]
z
#> cut price list_col
#> 1: Ideal 3457.542 3.95,3.93,4.35,4.31,4.49,4.49,...
#> 2: Premium 4584.258 3.89,4.20,3.88,3.79,4.38,3.97,...
#> 3: Good 3928.864 4.05,4.34,4.25,4.23,4.23,4.26,...
#> 4: Very Good 3981.760 3.94,3.95,4.07,4.00,4.21,3.85,...
#> 5: Fair 4358.758 3.87,6.45,6.27,5.57,5.63,6.11,...
ft <- flextable(data = z) %>%
compose(j = "list_col", value = as_paragraph(
plot_chunk(value = list_col, type = "dens", col = "pink",
width = 1.5, height = .4, free_scale = TRUE)
)) %>%
colformat_double(big.mark = " ", suffix = " $") %>%
set_header_labels(list_col = "density") %>%
autofit()
# image
image <- save_as_image(ft, path = '~/Downloads/table.png')
# create powerpoint
ppt <- read_pptx() %>% add_slide()
slide <- ppt %>% ph_with(value = external_img(image), location = ph_location(left = 0, top = 0))
# save powerpoint
print(ppt, preview = "pptx", target = 'output.pptx')
Created on 2022-09-23 with reprex v2.0.2
flextable can naturally be placed into powerpoint pptx with Officer https://ardata-fr.github.io/officeverse/officer-for-powerpoint.html
a simple example
library(flextable)
library(officer)
myflex <- flextable(head(iris))
my_pres <- read_pptx()
my_pres <- add_slide(my_pres, layout = "Title and Content", master = "Office Theme")
my_pres <- ph_with(my_pres, value =myflex,
location = ph_location_type(type = "body"))
print(my_pres, target = "example.pptx")
I earlier incorrectly called out htmltools_value() as being relevant, but this would only be so if you wanted to put a flextable (myflex) into a shiny renderUI - which is something I did a lot recently...
I'm using flextable and officer to write a table with hyperlinked cells to a powerpoint slide, but I can't figure out how to remove the underline in the URL. Here's my code:
library(officer)
library(flextable)
library(magrittr)
# Make the table
no_ul <- fp_text(underlined = FALSE)
ft <- data.frame(x = "Hello", link = "www.google.com") %>%
flextable(col_keys = "x") %>%
compose(j = 1,
value = as_paragraph(hyperlink_text(x = x, url = link, props = no_ul))
)
# Add to a slide
my_pres <- read_pptx() %>%
add_slide() %>%
ph_with(value = ft, location = ph_location_type(type = "body"))
print(my_pres, "~/Desktop/flex_example.pptx")
When I open up "flex_example.pptx" this is the table:
How do I remove the underline of the hyperlink???? I was hoping underlined = FALSE would do it, but no luck!
THANK YOU IN ADVANCE!!!!
I want to create on the same word landscape document both a table and text formatted in column.
The problem is that whenever I add body_end_section_columns_landscape() it creates a new page.
Example of working code in portrait format:
library(officer)
library(flextable)
ft <- qflextable(head(iris))
read_docx() %>%
body_add_flextable(value = ft ) %>%
body_end_section_continuous() %>%
body_add_par(value = paste(rep(letters,50), collapse = ' ')) %>%
body_end_section_columns() %>%
print(target = "test.docx")
If I try to create similar in landscape
ft <- qflextable(head(iris))
read_docx() %>%
body_add_flextable(value = ft ) %>%
body_end_section_landscape() %>%
body_add_par(value = paste(rep(letters,50), collapse = ' ')) %>%
body_end_section_columns_landscape() %>%
print(target = "test.docx")
It adds a second page for the text.
Is there a possibility to have both on same page as landscape same as in the portrait one?
Thank you
Yes, functions body_end_section_* are adding a break page between sections. You need to add specific section settings (type = "continuous") and use body_end_block_section() to achieve what you want to do:
library(officer)
library(magrittr)
library(flextable)
landscape_one_column <- block_section(
prop_section(
page_size = page_size(orient = "landscape"), type = "continuous"
)
)
landscape_two_columns <- block_section(
prop_section(
page_size = page_size(orient = "landscape"), type = "continuous",
section_columns = section_columns(widths = c(4, 4))
)
)
ft <- qflextable(head(iris))
read_docx() %>%
# there starts section with landscape_one_column
body_add_flextable(value = ft) %>%
body_end_block_section(value = landscape_one_column) %>% # there stops section with landscape_one_column
# there starts section with landscape_two_columns
body_add_par(value = paste(rep(letters, 50), collapse = " ")) %>%
body_end_block_section(value = landscape_two_columns) %>% # there stops section with landscape_two_columns
print(target = "test.docx")
So I am working on creating an automated powerpoint report in R using the officer package. I want to create a bulleted list with numerous levels but I need to be able to have specific text formatting for each line (i.e. I want the first two words to be green while the rest of the line is black). I tried using unordered_list() but this command doesn't allow the specific text formatting I need. I've tried the code below which colors/bolds the text that I want, but ph_add_par(level = ) does not indent the bullet points.
Is there a way that I can format the text how I want while also being able to manipulate the bullet point levels? I want it to look something like this:
enter image description here
library(officer)
report <- read_pptx()
sprint_1 <- sprintf("%s total crimes in %s %s",
tc20, params$month, params$year)
report%>%
add_slide(layout = 'Title and Content', master = 'Office Theme')%>%
ph_with(value = "Academy: Summary Notes", location = ph_location_type(type = "title"))%>%
ph_empty(location = ph_location_type("body")) %>%
ph_add_par(level = 1L)%>%
ph_add_text(str = sprint_1, style = fp_text(color = "black", font.size = 28, bold = TRUE, underlined = TRUE))%>%
ph_add_par(level = 2L)%>%
ph_add_text(str = paste("compared to this time in ", params$pastyear, " (", tc_ytd19, " total crimes)", sep = ""),
style = fp_text(color = 'black', font.size = 24)) %>%
ph_add_text(str = paste(pct_chg_mth, "change", sep = " "),
style = fp_text(color = "green", font.size = 24)) -> report
I am not able to run your code but the following code should help. Use block_list and in ph_with call set level_list=c(1L, 2L, 1L)
library(officer)
fpt_blue_bold <- fp_text(color = "#006699", bold = TRUE)
fpt_red_italic <- fp_text(color = "#C32900", italic = TRUE)
value <- block_list(
fpar(ftext("hello world", fpt_blue_bold)),
fpar(ftext("hello", fpt_blue_bold), " ",
ftext("world", fpt_red_italic)),
fpar(
ftext("blah blah blah", fpt_red_italic)))
value
doc <- read_pptx()
doc <- add_slide(doc)
doc <- ph_with(doc, value, location = ph_location_type(type = "body"),
level_list = c(1L, 2L, 1L))
print(doc, target = "test.pptx")
I have a zip file which has multiple images of 2 types.1 -FrequencyRose images 2- EnergyRose images. I have created a flextable and then replacing the even rows with images and odd rows with the image titles using for loop . The loop is correctly displaying the titles but its only printing the last read image of each type mulitple times instead of actually printing all the images as per loop count.
img.file <- unzip("D:\\Mast_Image Files.zip")
fr_files <- img.file[grepl(paste("FrequencyRose", collapse = "|"), img.file)]
er_files <- img.file[grepl(paste("EnergyRose", collapse = "|"), img.file)]
fr_files has 3 image file paths and same with er_files
click
num_masts = length(img.file)
c1 = rep("Freq_rose",num_masts)
c2 = rep("Energy_Rose",num_masts)
df = data.frame(c1,c2)
dfft = flextable(df)
sso=seq(1,num_masts,2)
sse=seq(2,num_masts,2)
for (g in 1:(num_masts/2)){
ff.img = fr_files[g]
ef.img = er_files[g]
dfft2 = dfft %>%
display(
i = sse[g], col_key = "c1", pattern = "{{img}}",
formatters = list( img ~ as_image(c1,
src = ff.img, width = 3, height = 3))) %>%
display(
i = sse[g], col_key = "c2", pattern = "{{img}}",
formatters = list( img ~ as_image(c2,
src = ef.img, width = 3, height = 3))) %>%
display(
i = sso[g], col_key = "c1", pattern = paste("Freq_Rose","mast",g)) %>%
display(
i = sso[g], col_key = "c2", pattern = paste("Energy Rose","mast",g))
}
this loop is able to produce titles correctly but the only the fr_files[3], er_files[3] is looping over all the even rows of corresponding columns. output is as :final results . could not find the issue.
I can't reproduce your example (I don't have the images).
library(ggplot2)
library(tidyverse)
library(flextable)
# a data example ----
zz <- iris %>%
group_by(Species) %>%
summarise( n = n(), avg = mean(Petal.Length),
img_path = paste0( unique(as.character(Species)), ".png"),
gg = list(ggplot(tibble(Sepal.Length, Petal.Width), aes(Sepal.Length, Petal.Width)) + geom_point() + theme_minimal())
)
zz
# create the png ----
walk2(zz$gg, zz$img_path, function(gg, path){
png(filename = path, width = 300, height = 300)
print(gg)
dev.off()
})
From there you have everything you need and the flextable commands could be:
# create the flextable -----
flextable(zz, col_keys = c("Species", "n", "avg", "plot")) %>%
# here, i is selecting only odd rows
compose(i = ~ seq_along(Species) %% 2 > 0, j = "plot", value = as_paragraph(as_image(img_path, width = 300/72, height = 300/72))) %>%
theme_box() %>%
autofit()