Scott
Scott

Reputation: 161

Modify the format of a portion of a flextable cell

I want to modify the format of a portion of a cell, while leaving the remaining text unmodified for inclusion in a .docx report:
e.g., Brill (Scophthalmus rhombus) in subdivisions 22-32 (Baltic Sea)

My data is set up with HTML tags, which I have been trying to modify using the display() function. My example (somewhat obviously) modifies the entire cell. I expect that the pattern argument can be modified with {{moustaches}} to make the nested formatting possible, but I haven't had any luck.

library(flextable)
library(officer)
library(dplyr)

data <- structure(list(Description = c("Brill (<em>Scophthalmus rhombus</em>) in subdivisions 22-32 (Baltic Sea)", 
                                       "Cod (<em>Gadus morhua</em>) in subdivisions 22-24, western Baltic stock (western Baltic Sea)", 
                                       "Cod (<em>Gadus morhua</em>) in subdivisions 25-32, eastern Baltic stock (eastern Baltic Sea)", 
                                       "Dab (<em>Limanda limanda</em>) in subdivisions 22-32 (Baltic Sea)", 
                                       "Flounder (<em>Platichthys flesus</em>) in subdivisions 22 and 23 (Belt Seas and the Sound)", 
                                       "Flounder (<em>Platichthys flesus</em>) in subdivisions 24 and 25 (west of Bornholm and southwestern central Baltic)"),
                       SpeciesScientificName = c("Scophthalmus rhombus", "Gadus morhua", "Gadus morhua", "Limanda limanda", "Platichthys flesus", "Platichthys flesus")),
                  .Names = c("Description", "SpeciesScientificName"), 
                  row.names = c(NA, 6L), class = "data.frame")

data %>% 
  mutate(Description = gsub("<em>.*?</em>", "%s", Description)) %>%
  flextable() %>% 
  display(col_key = "Description", pattern = "{{sp_italics}}",
          formatters = list(sp_italics ~ sprintf(Description, SpeciesScientificName)),
          fprops = list(sp_italics = fp_text(italic = TRUE)))

Upvotes: 4

Views: 1845

Answers (3)

MargaretS
MargaretS

Reputation: 21

Here is an update to the answer based on the new functions in flextable (I tried this solution and display() is deprecated).

I also used set_table_properties(layout = "autofit") instead of autofit(), as autofit() gave me a table that extended outside the margins in the .docx (SO explanation here).

data <- structure(
  list(id = c(
    "Brill", "Cod", "Cod", "Dab", "Flounder", "Flounder"
  ), SpeciesScientificName = c(
    "Scophthalmus rhombus",
    "Gadus morhua", "Gadus morhua", "Limanda limanda", "Platichthys flesus",
    "Platichthys flesus"
  ), subdivision = c(
    "22-32", "22-24, western Baltic stock",
    "25-32, eastern Baltic stock", "22-32", "22 and 23", "24 and 25"
  ), location = c(
    "Baltic Sea", "western Baltic Sea", "eastern Baltic Sea",
    "Baltic Sea", "Belt Seas and the Sound", "west of Bornholm and southwestern central Baltic"
  )),
  class = "data.frame", .Names = c("id", "SpeciesScientificName", "subdivision", "location"),
  row.names = c(NA, -6L)
)

ft <- data %>%
  flextable(col_keys = c("dummy_col", "SpeciesScientificName")) %>%
  flextable::mk_par(
    j = "dummy_col",
    value = as_paragraph(
      id,
      " (", as_i(SpeciesScientificName), ") in ",
      location,
      " (",
      as_chunk(location, props = fp_text_default(color = "red")), ")"
    )
  ) %>%
  set_header_labels(
    dummy_col = "whatever",
    SpeciesScientificName = "SpeciesScientificName"
  ) %>%
  set_table_properties(layout = "autofit")


print(ft, preview = "docx")

Screenshot of result

Upvotes: 2

Benbob
Benbob

Reputation: 378

There may be an easier solution. Using ftExtra and colformat_md() will let you do markdown formatting (though it doesn't seem to allow plain HTML)

https://ardata-fr.github.io/flextable-book/extensions.html#ftextra

library(ftExtra)
data.frame(x = c("**bold**", "*italic*"),
           y = c("^superscript^", "~subscript~"),
           z = c("***^ft^~Extra~** is*", "*Cool*")) %>% 
flextable() %>% 
colformat_md()

Upvotes: 3

David Gohel
David Gohel

Reputation: 10675

The display function is defining displayed values. It does not allow to format only a portion a of text in a cell, it defines the paragraph content and its formatting. I would start from a tidy data.frame.

data <- structure(list(id = c("Brill", "Cod", "Cod", "Dab", "Flounder", 
"Flounder"), SpeciesScientificName = c("Scophthalmus rhombus", 
"Gadus morhua", "Gadus morhua", "Limanda limanda", "Platichthys flesus", 
"Platichthys flesus"), subdivision = c("22-32", "22-24, western Baltic stock", 
"25-32, eastern Baltic stock", "22-32", "22 and 23", "24 and 25"
), location = c("Baltic Sea", "western Baltic Sea", "eastern Baltic Sea", 
"Baltic Sea", "Belt Seas and the Sound", "west of Bornholm and southwestern central Baltic"
)), class = "data.frame", .Names = c("id", "SpeciesScientificName",  "subdivision", "location"), 
row.names = c(NA, -6L))

> data
        id SpeciesScientificName                 subdivision
1    Brill  Scophthalmus rhombus                       22-32
2      Cod          Gadus morhua 22-24, western Baltic stock
3      Cod          Gadus morhua 25-32, eastern Baltic stock
4      Dab       Limanda limanda                       22-32
5 Flounder    Platichthys flesus                   22 and 23
6 Flounder    Platichthys flesus                   24 and 25
                                          location
1                                       Baltic Sea
2                               western Baltic Sea
3                               eastern Baltic Sea
4                                       Baltic Sea
5                          Belt Seas and the Sound
6 west of Bornholm and southwestern central Baltic

Your example is concatenating 4 informations in one paragraph, the argument formatters will require 4 arguments...

ft <- data %>% 
  flextable(col_keys = c("dummy_col", "SpeciesScientificName")) %>% 
  display(col_key = "dummy_col", pattern = "{{id_}} ({{sciname_}}) in {{subdivision_}} ({{location_}})",
          formatters = list(id_ ~ id, sciname_ ~ SpeciesScientificName, subdivision_ ~ subdivision, location_ ~ location ),
          fprops = list(sciname_ = fp_text(italic = TRUE), location_ = fp_text(color="red") )) %>% 
  set_header_labels(dummy_col="whatever") %>% 
  theme_booktabs() %>% autofit()

read_docx() %>% body_add_flextable(ft) %>% print("test.docx")

enter image description here

Upvotes: 6

Related Questions