diff --git a/boxplot_examples.R b/boxplot_examples.R
index b934154e0e0c99456c8fbcb0b9031436c24f294c..1f77431983b2ddd60d818450964306265020acbe 100644
--- a/boxplot_examples.R
+++ b/boxplot_examples.R
@@ -168,16 +168,48 @@ add = "+ggplot2::facet_wrap(facets = 'Categ2', labeller = 'label_both') + ggplot
 
 
 ### Other parameters
-fun_gg_boxplot(data1 = obs1, y = "Time", categ = "Categ1", 
+res <- fun_gg_boxplot(data1 = obs1, y = "Time", categ = "Categ1", 
 return = TRUE, 
 return.ggplot = TRUE,
+return.gtable = FALSE,
 plot = FALSE, 
 warn.print = FALSE, 
 lib.path = NULL
 )
+# plot the result
+fun_open(pdf = FALSE)
+res$ggplot
+
+# display the output (manipulation of res triggers plotting because of the presence of non NULL $ggplot, which is annoying, as explain in the function description)
+fun_open(pdf = FALSE)
+res
+
+# The advantage of $ggplot is that it is easy to update the plot
+
 
+### Notes about the gtable output
+res2 <- fun_gg_boxplot(data1 = obs1, y = "Time", categ = "Categ1", 
+return = TRUE, 
+return.ggplot = FALSE,
+return.gtable = TRUE,
+plot = TRUE, # plot must be TRUE to have a non NULL $gtable output
+warn.print = FALSE, 
+lib.path = NULL
+)
 
+# display the results (does not plot the graph, contrary to $ggplot)
+fun_open(pdf = FALSE)
+res2
 
+# replot
+fun_open(pdf = FALSE)
+gridExtra::grid.arrange(res2$gtable)
+# plot the first grob
+fun_open(pdf = FALSE)
+gridExtra::grid.arrange(res2$gtable[1,1])
+# plot the second grob
+fun_open(pdf = FALSE)
+gridExtra::grid.arrange(res2$gtable[1,2])
 
 
 
diff --git a/cute_little_R_functions.R b/cute_little_R_functions.R
index a644e44824144e24c4e1f47dad2c3b34aab00d5b..41a2eb2ed94f3aef596d5f4a6f443f9bc5b9db3a 100644
--- a/cute_little_R_functions.R
+++ b/cute_little_R_functions.R
@@ -7919,6 +7919,7 @@ article = TRUE,
 grid = FALSE, 
 return = FALSE, 
 return.ggplot = FALSE,
+return.gtable = TRUE,
 plot = TRUE, 
 add = NULL, 
 warn.print = TRUE, 
@@ -7998,6 +7999,7 @@ lib.path = NULL
 # grid: logical. Draw lines in the background to better read the box values? Not considered if article == FALSE (grid systematically present)
 # return: logical. Return the graph parameters?
 # return.ggplot: logical. Return the ggplot object in the output list? Ignored if return argument is FALSE. WARNING: always assign the fun_gg_boxplot() function (e.g., a <- fun_gg_boxplot()) if return.ggplot argument is TRUE, otherwise, double plotting is performed. See $ggplot in the RETURN section below for more details
+# return.gtable: logical. Return the ggplot object as gtable of grobs in the output list? Ignored if plot argument is FALSE. Indeed, the graph must be plotted to get the grobs dispositions. See $gtable in the RETURN section below for more details
 # plot: logical. Plot the graphic? If FALSE and return argument is TRUE, graphical parameters and associated warnings are provided without plotting
 # add: character string allowing to add more ggplot2 features (dots, lines, themes, facet, etc.). Ignored if NULL
 # WARNING: (1) the string must start with "+", (2) the string must finish with ")" and (3) each function must be preceded by "ggplot2::". Example: "+ ggplot2::coord_flip() + ggplot2::theme_bw()"
@@ -8044,6 +8046,7 @@ lib.path = NULL
 # $axes: the x-axis and y-axis info
 # $warn: the warning messages. Use cat() for proper display. NULL if no warning. WARNING: warning messages delivered by the internal ggplot2 functions are not apparent when using the argument plot = FALSE
 # $ggplot: ggplot object that can be used for reprint (use print(...$ggplot) or update (use ...$ggplot + ggplot2::...). NULL if return.ggplot argument is FALSE. Of note, a non-NULL $ggplot in the output list is sometimes annoying as the manipulation of this list prints the plot
+# $gtable: gtable object that can be used for reprint (use gridExtra::grid.arrange(...$ggplot) or with additionnal grobs (use ...$ggplot + ggplot2::...). NULL if return.ggplot argument is FALSE. Contrary to $ggplot, a non-NULL $gtable in the output list is not annoying as the manipulation of this list does not print the plot
 # EXAMPLE
 # DEBUGGING
 # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; set.seed(NULL) ; obs1$Time[1:10] <- NA ; data1 = obs1 ; y = "Time" ; categ = c("Group1") ; categ.class.order = NULL ; box.legend.name = NULL ; categ.color = c("green") ; box.fill = FALSE ; box.width = 0.5 ; box.space = 0.1 ; box.notch = FALSE ; box.line.size = 0.5 ; box.alpha = 0.5 ; box.mean = TRUE ; box.whisker.kind = "std" ; box.whisker.width = 0.5 ; dot.color = "black" ; dot.categ = "Group1"; dot.categ.class.order = c("G", "H") ; dot.legend.name = NULL ; dot.tidy = TRUE ; dot.tidy.bin.nb = 50 ; dot.jitter = 0.25 ; dot.size = 3 ; dot.alpha = 0.5 ; dot.border.size = 0.5 ; dot.border.color = NULL ; y.lim = NULL ; y.log = "no" ; y.tick.nb = NULL ; y.second.tick.nb = NULL ; y.include.zero = FALSE ; y.top.extra.margin = 0.05 ; y.bottom.extra.margin = 0.05 ; stat.disp = NULL ; stat.disp.mean = FALSE ; stat.size = 4 ; stat.dist = 2 ; x.lab = NULL ; y.lab = NULL ; vertical = TRUE ; text.size = 12 ; title = "" ; title.text.size = 8 ; legend.show = TRUE ; legend.width = 0.5 ; text.angle = 0 ; article = FALSE ; grid = FALSE ; return = TRUE ; return.ggplot = FALSE ; plot = TRUE ; add = NULL ; warn.print = FALSE ; lib.path = NULL
@@ -9678,6 +9681,7 @@ warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn
 
 # drawing
 fin.plot <- suppressMessages(suppressWarnings(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + ")))))
+grob.save <- NULL
 if(plot == TRUE){
 # following lines inactivated because of problem in warn.recov and message.recov
 # assign("env_fun_get_message", new.env())
@@ -9689,9 +9693,9 @@ if(plot == TRUE){
 # message.recov <- fun_get_message('print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))', kind = "message", header = FALSE, print.no = FALSE, env = env_fun_get_message) # for recovering messages printed by ggplot() functions
 # if( ! (return == TRUE & return.ggplot == TRUE)){ # because return() plots when return.ggplot is TRUE # finally not used -> see return.ggplot description
 if(is.null(legend.width)){
-suppressMessages(suppressWarnings(print(fin.plot)))
+grob.save <- suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot)))
 }else{
-suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot, legend.final, ncol=2, widths=c(1, legend.width))))
+grob.save <-suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot, legend.final, ncol=2, widths=c(1, legend.width))))
 }
 # }
 # suppressMessages(suppressWarnings(print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))))
@@ -9747,7 +9751,8 @@ y.labels = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{tempo$y$s
 y.positions = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{unlist(attributes(tempo$y$breaks))}
 ), 
 warn = paste0("\n", warn, "\n\n"), 
-ggplot = if(return.ggplot == TRUE){fin.plot}else{NULL} # fin.plot plots the graph if return == TRUE
+ggplot = if(return.ggplot == TRUE){fin.plot}else{NULL}, # fin.plot plots the graph if return == TRUE
+gtable = if(return.gtable == TRUE){grob.save}else{NULL} # fin.plot plots the graph if return == TRUE
 )
 return(output) # this plots the graph if return.ggplot is TRUE and if no assignment
 }
@@ -9760,8 +9765,6 @@ return(output) # this plots the graph if return.ggplot is TRUE and if no assignm
 
 
 
-
-
 fun_gg_scatter <- function(
 data1, 
 x, 
@@ -11889,3 +11892,5 @@ return(output) # this plots the graph if return.ggplot is TRUE and if no assignm
 
 
 
+
+
diff --git a/fun_gg_boxplot.docx b/fun_gg_boxplot.docx
index d41aacaba64cbbd85dd46da5b4e6e0055d1c1c41..b6cd214e2070127516bd701599cd4ab7c1474f5e 100644
Binary files a/fun_gg_boxplot.docx and b/fun_gg_boxplot.docx differ