8

I create a flextable based on a csv file, I put some style on it, change some cells. Then I would like to remove a specific columns of this flextable before add it to a doc. Is-there a way to create a copy of a flextable and specifying col_keys?

mydf <- GetData(....)
cols <- names(mydf)
myft <- flextable(mydf, col_keys = cols)
# Adding style to ft...
# ....

# Here I want to remove one column to the ft (and only here, not when first creating the ft)
# something as:
# ft <- CreateCopyOfFlextable(ft,cols[-which(cols=='COLB')])
#
my_doc <- read_docx()
my_doc <- my_doc %>%  body_add_par("")   %>%
  body_add_flextable(value = ft) 

print(my_doc, target = 'c:/temp/doc.docx')
Po78
  • 143
  • 1
  • 7
  • 1
    Why don't you exclude the variable you don't need in `col_keys`? – David Gohel May 15 '19 at 11:52
  • 1
    Sorry I don't understand. I can't exclude the COLB when creating the flextable() as I need this column to apply styles, this is why I need to remove it just before the body_add_flextable – Po78 May 15 '19 at 12:40
  • sorry. you style the column but then you don't want to display it? – David Gohel May 15 '19 at 12:41
  • Here an example df <- data.frame(COLA=c('a','b','c'),COLB=c('','changevalue',''),COLC=c(10,12,13)) ft<-flextable(df) ft <- ft %>% style(i=which(ft$body$dataset$COLB=='changevalue'),pr_t=fp_text(color="black", font.size=11, bold=TRUE, italic=FALSE, underline=FALSE, font.family="Times New Roman"),part="body") ft<-compose(ft, i=2,j=3, value = as_paragraph(as_chunk('100')),part = 'body') # now I want to remove the COLB columns as I don't need it anymore – Po78 May 15 '19 at 12:43

3 Answers3

10

I just had the same problem and had a devil of a time Googling for a solution. @David-Gohel truly has the answer here, but I feel the need to provide a similar solution with additional explanation.

My problem and the OPs is that we wanted to use the data from columns that wouldn't be displayed to influence the formatting of columns that will be displayed. The concept that was not initially obvious is that you can send a data frame to flextable with more columns than you intend to display (instead of displaying all and deleting them you've used them). Then, by using the col_keys argument, you can select only those columns that you want to display while keeping the remaining ones around for additional processing (e.g., for using compose(), paragraph(), or add_chunk()).

If I understand correctly, COLB is supposed to be a flag to indicate that certain rows of COLC should be modified. If so, then my solution looks like this:

library(flextable)
library(magrittr)
library(officer)

df <- data.frame(COLA=c('a', 'b', 'c'),
                 COLB=c('', 'changevalue', ''),
                 COLC=c(10, 12, 13))

ft <- flextable(df, col_keys = c("COLA", "COLC")) %>% # Retain but don't display COLB
  compose(i = ~ COLB =='changevalue', # Use COLB for conditional modifications
          j = "COLC", 
          value = as_paragraph(as_chunk('100')), 
          part = 'body')  %>% 
  style(i = ~ COLB =='changevalue', # Use COLB for conditional formatting on COLC
        j = "COLC",
        pr_t = fp_text(color = "black", 
                       font.size = 11, 
                       bold = TRUE,
                       italic = FALSE,
                       underline = FALSE,
                       font.family = "Times New Roman"),
        part = "body")

ft

And here's what the above code produces (e.g., the "changevalue" column is the trigger for conditionally inserting 100 in COLC and also for changing the formatting):

Example Flextable

D. Woods
  • 3,004
  • 3
  • 29
  • 37
4
library(flextable)
library(magrittr)
library(officer)

df <- data.frame(COLA=c('a','b','c'),
                 COLB=c('','changevalue',''),
                 COLC=c(10,12,13))
ft<-flextable(df, col_keys = c("COLA", "COLB"))
ft <- ft %>% 
  style(i= ~ COLB=='changevalue',
        pr_t=fp_text(color="black", font.size=11, bold=TRUE,  italic=FALSE, underline=FALSE, font.family="Times New Roman"),part="body")
ft<-compose(ft, i=2, j="COLB", value = as_paragraph(as_chunk('100')),part = 'body')
ft

David Gohel
  • 9,180
  • 2
  • 16
  • 34
  • col_keys are the displayed variables, not a subset – David Gohel May 15 '19 at 12:51
  • Thanks David, but in your code, I'm loosing 10 and 13 values – Po78 May 15 '19 at 12:55
  • This is your code, not mine :) I have no idea what your are trying to achieve. Was just trying to help ;) ++ – David Gohel May 15 '19 at 13:02
  • Thanks for your help David, I understand. I have to rethink how to use flextable, I'm not sure your solution can be easaly integrated in my code (there are othe columns right to COLC, and other treatment. Thanks again for your help. – Po78 May 15 '19 at 13:06
  • Dear David, I have a related question about your `flextable` package [**HERE**](https://stackoverflow.com/questions/59399901/displaying-multiple-tables-using-package-officer-and-flextable) would you please take a look when find time? –  Dec 18 '19 at 21:01
0

I'm styling another column based on COLB. Here an example:

df <- data.frame(COLA=c('a','b','c'),COLB=c('','changevalue',''),COLC=c(10,12,13))
ft<-flextable(df)
ft <- ft %>% style(i=which(ft$body$dataset$COLB=='changevalue'),pr_t=fp_text(color="black",   font.size=11, bold=TRUE,  italic=FALSE, underline=FALSE, font.family="Times New Roman"),part="body")
ft<-compose(ft, i=2,j=3, value = as_paragraph(as_chunk('100')),part = 'body')
# now I want to remove the COLB columns as I don't need it anymore
# ???????
my_doc <- read_docx()
my_doc <- my_doc %>%  body_add_par("")   %>%  body_add_flextable(value = ft) 

print(my_doc, target = 'c:/temp/orliange_p/sample.docx') %>% invisible()
Po78
  • 143
  • 1
  • 7
  • 2
    I already told you to not use `x$body$dataset$...`, this are internal structure and may change someday. Use only documented and exported functions. – David Gohel May 15 '19 at 12:50