Reporting is implemented using the onbrand
package which is a templated interface to the officer
package. Officer provides a lot of control over the generation of both Word and PowerPoint documents. If you feel comfortable programming in R, you may wan to use that package directly. However the templated workflow in onbrand
facilitates switching between organizational templates. Currently ubiquity
has support for generating both PowerPoint and Word reports, and this vignette will go over example scripts for both types of reports.
onbrand
in ubiquity
One objective of reporting in ubiquity
is to allow the management of several reports simultaneously. This is done by creating wrapper functions for functions in onbrand
. Where the onbrand
functions take in an onbrand
object, the wrapper functions take in a ubiquity
system object and an optional report name (rptname
). The other inputs to the ubiquty
wrapper functions are passed through directly to the wrapped onbrand
function. At the bottom of this vignette, the ubiquity
function name is listed along with the onbrand
name it wraps around.
To make a copy of the example scripts in the current working directory run the following:
library(ubiquity)
workshop_fetch(section="Reporting", overwrite=TRUE) fr =
This should create the following scripts
make_report_PowerPoint.R
Generates a PowerPoint presentation from an R scriptmake_report_Word.R
Generates a Word document from an R scriptThen general process for creating a report is:
system_rpt_read_template()
.system_rpt_add_slide()
for PowerPoint and system_rpt_add_doc_content()
for Word), or append analysis results using integrated workflow reporting (e.g. system_rpt_estimation()
to add the results of parameter estimation).system_rpt_save_report()
.The examples below are intended to work with a ubiquity
system object. So at the top of any script you will need to build the system. If you don’t have a system file, this command will create an empty template in the current directory:
build_system("system.txt") cfg =
make_report_PowerPoint.R
)Before we get started we’ll create some content for the presentation. Since we’re wrapping around onbrand
functions, the content is expected in a format consistent with those functions. For details on the format of different content types, see the help for onbrand::add_pptx_ph_content()
.
First we’ll create some figures. First a ggplot object (p
) and an image file (imgfile
).
library(ggplot2)
ggplot() + annotate("text", x=0, y=0, label = "picture example")
p = tempfile(pattern="image", fileext=".png")
imgfile =ggsave(filename=imgfile, plot=p, height=5.15, width=9, units="in")
Next we’ll create tabular data (tdata
):
data.frame(Parameters = c("Vp", "Cl", "Q", "Vt"),
tdata =Values = 1:4,
Units = c("L", "L/hr", "L/hr", "L") )
Tables can be displayed in three different ways: as an Office table, an onbrand
abstraction of a flextable
, or a user defined flextable
object. These are lists with specific elements. You should see the content specifications found in onbrand::add_pptx_ph_content()
for details on how these lists should be formatted. The examples below should be able to get you started.
Office table
list(table = tdata,
tco =header = TRUE,
first_row = FALSE)
flextable
using onbrand
abstraction
list(table = tdata, # This element contains the table data
tcf =header_top = list( # Defining the table headers
Parameters = "Name",
Values = "Value",
Units = "Units"),
cwidth = 0.8, # Column width
table_autofit = TRUE, # Making the tables automatically fit
table_theme = "theme_zebra", # Selecting the table theme
first_row = FALSE)
User-defined flextable
object
flextable::flextable(tdata)
tfo = flextable::autofit(tfo) tfo =
Lastly list content is specified in a paired vector. The first element indicates the indention level, and the second indicates the content. Note: This will only work for placeholders that contain list content.
c(1, "First major item",
lcontent =2, "first sub bullet",
2, "second sub bullet",
3, "sub sub bullet",
1, "Second major item",
2, "first sub bullet",
2, "second sub bullet")
First we initialize a new report. If the template option is set to "PowerPoint"
it will create an empty presentation using the internal ubiquity
template. Below we discuss creating custom templates for your organization.
system_rpt_read_template(cfg, "PowerPoint") cfg =
Slides are added using ubiquity::system_rpt_add_slide()
with the slide template to be used and the elements identifying the placeholders and the placeholder content. Here we’re adding slides for a title ("title_slide"
) and a section ("section_side"
).
system_rpt_add_slide(cfg,
cfg =template = "title_slide",
elements = list(
title=list(content = "Reporting in ubiquity",
type = "text")))
system_rpt_add_slide(cfg,
cfg =template = "section_slide",
elements = list(
title=list(content = "Content Types",
type = "text")))
For each element there is a list element (e.g. title
) that contains content and content type. The type specifies whether the content is a figure, table, etc. In this example we’re using text. There are two types of text content. One is plain text and the other is lists. This is determined by the placeholder type in PowerPoint. We’ll go through examples below for different types of content and available templates. For details on the format of the template
and elements
inputs see the documentation for onbrand::report_add_slide()
. To show the available templates, placeholder element names in each template, and the type of text they can hold you can do the following:
system_rpt_template_details(cfg) fr =
This will produce output in the console like the following:
## Mapping: /Library/Frameworks/R.framework/Versions/4.0/Resources/library/ubiquity/ubinc/templates/report.yaml
## Report Type: PowerPoint
## title_slide (master/template)
## > title (text)
## > sub_title (text)
## section_slide (master/template)
## > title (text)
## > sub_title (text)
## title_only (master/template)
## > title (text)
## content_text (master/template)
## > title (text)
## > sub_title (text)
## > content_body (text)
## content_list (master/template)
## > title (text)
## > sub_title (text)
## > content_body (list)
In the previous example we added text content, here we will add the list content we created above (lcontent
). Notice that we simply specify the content type is "list"
. Note: You can only do this if the content type is list in the slide master.
system_rpt_add_slide(cfg,
cfg =template = "content_list",
elements = list(
title=
list(content = "Lists",
type = "text"),
sub_title=
list(content = "For placholders that contain lists.",
type = "text"),
content_body=
list(content = lcontent,
type = "list")))
If you specify the content type is "ggplot"
, then you can just provide the ggplot object (p
).
system_rpt_add_slide(cfg,
cfg =template = "content_text",
elements = list(
title=
list(content = "Figures: ggplot object",
type = "text"),
sub_title=
list(content = "Using ggplot objects directly",
type = "text"),
content_body=
list(content = p,
type = "ggplot")))
If you have an image in a file you want to insert you can use the "imagefile"
content type. One was created above and the location is stored in the imgfile
object.
system_rpt_add_slide(cfg,
cfg =template = "content_text",
elements = list(
title=
list(content = "Figures: image file",
type = "text"),
sub_title=
list(content = "Inserting figures from files",
type = "text"),
content_body=
list(content = imgfile,
type = "imagefile")))
First we’re going to add a table using the built in Office tables. The content is stored in tco
and can be added to any placeholder as long as we specify the type as "table"
.
system_rpt_add_slide(cfg,
cfg =template = "content_text",
elements = list(
title=
list(content = "Tables: Office",
type = "text"),
sub_title=
list(content = "Table in native Office format",
type = "text"),
content_body=
list(content = tco,
type = "table")))
Similarly, you can add a flextable
using the onbrand
abstraction by specifying the type as "flextable"
and supply the correctly formatted content created above (tcf
).
system_rpt_add_slide(cfg,
cfg =template = "content_text",
elements = list(
title=
list(content = "Tables: flextable",
type = "text"),
sub_title=
list(content = "Flextables using onbrand abstraction",
type = "text"),
content_body=
list(content = tcf,
type = "flextable")))
Lastly, you can create a flextable
directly. This gives you a lot of control with regards to formatting. You simply need to specify the type as "flextable_object"
and provide an object created with flextable
(tfo
).
system_rpt_add_slide(cfg,
cfg =template = "content_text",
elements = list(
title=
list(content = "Tables: flextable object",
type = "text"),
sub_title=
list(content = "Flextables using a user-created flextable object",
type = "text"),
content_body=
list(content = tfo,
type = "flextable_object")))
The rest of the reporting script (make_report_PowerPoint.R
) simply provides examples of the other available slide templates. You can look through those to see if they are suitable for your needs. If they are not and you need other templates or wish to create a template for your school or organization, jump down to the section on custom organizational templates.
Once you’re done you can then save the presentation to a file:
system_rpt_save_report(cfg, output_file = "example.pptx")
make_report_Word.R
)Just like the PowerPoint example above, we need to create some content for Word reporting. We’re using wrappers here for onbrand
functions so document content needs to be provided in a specific format documented in the help for onbrand::report_add_doc_content()
Text formatting can be plain text, formatted as Markdown, or formatted using the officer::fpar()
command.
paste(rep("The quick brown fox jumped over the lazy dog.", 70), collapse= " ")
plain_text_content = paste(rep("The *quick* <color:brown>brown</color> fox **jumped** over the ~lazy dog~.", 70), collapse=" ")
md_text_content = officer::fpar(
fpar_text_content =::ftext("The quick ", prop=NULL),
officer::ftext("brown", prop=officer::fp_text(color="brown")),
officer::ftext(" fox jumped over the lazy dog.", prop=NULL)) officer
For figures we can use two formats a ggplot object (p
) or an image file (imgfile
) these are packed into content lists gpc
and ifc
, respectively.
library(ggplot2)
ggplot() + annotate("text", x=0, y=0, label = "picture example")
p = tempfile(pattern="image", fileext=".png")
imgfile =ggsave(filename=imgfile, plot=p, height=5.15, width=9, units="in")
list(image = p,
gpc =caption = "This is an example of an image from a ggplot object.")
list(image = imgfile,
ifc =caption = "This is an example of an image from a file.")
The same tabular data from before is used here as well:
data.frame(Parameters = c("Vp", "Cl", "Q", "Vt"),
tdata =Values = 1:4,
Units = c("L", "L/hr", "L/hr", "L") )
Office table
The content for tables in Office format is similar but it has other elements as well such as a figure caption:
list(table = tdata, # This element contains the table data
tco =header = TRUE, # These two lines control the header
first_row = FALSE,
caption = "This creates a table using an Office theme/format.")
flextable
using onbrand
abstraction
Similarly we can create a flextable
using the onbrand
abstraction. In this case we’re supplying a caption and specifying the format of the caption is Markdown ("md"
).
list(table = tdata, # This element contains the table data
tcf =caption_format = "md",
caption = "This creates a <ff:courier>flextable</ff> using the <ff:courier>onbrand</ff> abstraction",
header_top = list( # Defining the table headers
Parameters = "Name",
Values = "Value",
Units = "Units"),
cwidth = 0.8, # Column width
table_autofit = TRUE, # Making the tables automatically fit
table_theme = "theme_zebra", # Making the tables automatically fit
first_row = FALSE)
User-defined flextable
object
flextable::flextable(tdata)
tfo = flextable::autofit(tfo)
tfo =
list(ft = tfo,
tcfo =caption = "This inserts a flextable object created by the user")
We create a new Word report by defining the template option as "Word"
.
system_rpt_read_template(cfg, "Word") cfg =
Content is added using ubiquity::system_rpt_add_doc_content()
with the content and type of content specified. This wraps around the onbrand::report_add_doc_content()
function. See the help for that function for allowed types and the expected format of the content. Below we will cover some examples of common content to be added.
Text content contains a style
element where you can specify the onbrand
style.
system_rpt_add_doc_content(cfg,
cfg =type="text",
content = list(
style = "Heading_1",
text = "Formatting Text"))
To get a list of available styles for a given template you can use system_rpt_template_details()
:
system_rpt_template_details(cfg) fr =
This will produce output in the console like the following:
## Mapping: /Library/Frameworks/R.framework/Versions/4.0/Resources/library/ubiquity/ubinc/templates/report.yaml
## Report Type: Word
## onbrand style (word style, style type)
## --------------------------------------
## Code (Code, paragraph)
## Figure_Caption (graphic title, paragraph)
## Heading_1 (heading 1, paragraph)
## Heading_2 (heading 2, paragraph)
## Heading_3 (heading 3, paragraph)
## Normal (Normal, paragraph)
## Table_Caption (table title, paragraph)
## TOC (toc 1, paragraph)
## Table (Table Grid, table)
Text can be added in three different formats: plain text, as Markdown, and using the officer::fpar()
command from the officer
package.
Plain text
If no style
is specified a template default style will be used.
system_rpt_add_doc_content(cfg,
cfg =type="text",
content = list(
text = plain_text_content))
Markdown
To add text content other than plain text you need to add a format
element. For example you can supply text in Markdown format and then define the format
as "md"
. For details on Markdown supported see the help for the onbrand::md_to_officer()
function.
system_rpt_add_doc_content(cfg,
cfg =type="text",
content = list(
style = "Normal",
format = "md",
text = md_text_content))
Using officer::fpar()
Officer formats text using the officer::fpar()
command. If you have an fpar
object you can use that as the text
element for the content. You just need to specify the format
as "fpar"
.
system_rpt_add_doc_content(cfg,
cfg =type="text",
content = list(
style = "Normal",
format = "fpar",
text = fpar_text_content))
To add figures you can specify the type as either an "imagefile"
or "ggplot"
:
system_rpt_add_doc_content(cfg,
cfg =type = "imagefile",
content = ifc)
system_rpt_add_doc_content(cfg,
cfg =type = "ggplot",
content = gpc)
Tables can be added in Office table, onbrand
abstraction of flextables, and as flextable objects. This is done by using the type "table"
, "flextable"
, and "flextable_object"
respectively:
system_rpt_add_doc_content(cfg,
cfg =type = "table",
content = tco)
system_rpt_add_doc_content(cfg,
cfg =type = "flextable",
content = tcf)
system_rpt_add_doc_content(cfg,
cfg =type = "flextable_object",
content = tcfo)
For information on adding other content (such as using placeholder text within a document) and formatting (number of columns, page orientation, etc) see the function onbrand::report_add_doc_content()
for a list of allowed type
values and the expected content
format.
Once you’re done you can then save the document to a file:
system_rpt_save_report(cfg, output_file = "example.docx")
Internally ubiquity
uses the onbrand
package for customizable templates. To create a template for your organization you should use the onbrand
vignette for Custom Templates. This will instruct you to create a yaml mapping file for your templates. You can use the built in organizational template as a starting point for that:
system_fetch_template(cfg, template="myOrg") tr =
In order to use the ubiquity
workflows, you will need to have specific placeholders for PowerPoint and styles for Word. You can have others, but you will at least need those listed below. These should already be defined in the organizational template. You simply need to ensure that the placeholder names and content types from PowerPoint are correct and that the style names in Word you create are also assigned to the correct onbrand
styles.
In PowerPoint you will need to have a document template with the following slide masters/templates. You will need to name the slide Master the name shown in the table below. For each slide master you will need to create placeholders for the specified content. Make sure the content type matches that shown below. When you create the onbrand
mapping file you will need to use the placeholder names shown below.
Master/Template | onbrand | Content |
Name | Placeholder | Type |
title_slide | title | text |
sub_title | text | |
section_slide | title | text |
sub_title | text | |
title_only | title | text |
content_text | title | text |
sub_title | text | |
content_body | text | |
content_list | title | text |
sub_title | text | |
content_body | list | |
two_content_header_list | title | text |
sub_title | text | |
content_left_header | text | |
content_left | list | |
content_right_header | text | |
content_right | list | |
two_content_header_text | title | text |
sub_title | text | |
content_left_header | text | |
content_left | text | |
content_right_header | text | |
content_right | text | |
two_content_list | title | text |
sub_title | text | |
content_left | list | |
content_right | list | |
two_content_text | title | text |
sub_title | text | |
content_left | text | |
content_right | text |
For Word reporting you will need to have a Word template with the following styles defined. When you create the onbrand
mapping file you will need to use the onbrand Style name listed.
onbrand | Word | Style |
Style | Style | Type |
Code | Code | paragraph |
Figure_Caption | graphic title | paragraph |
Heading_1 | heading 1 | paragraph |
Heading_2 | heading 2 | paragraph |
Heading_3 | heading 3 | paragraph |
Normal | Normal | paragraph |
Table_Caption | table title | paragraph |
TOC | toc 1 | paragraph |
Table | Table Grid | table |
To use the custom templates you would use system_rpt_read_template()
and specify the mapping file and the Office document containing your template. For example if you wanted to load a PowerPoint template called myOrg.pptx
and your yaml mapping file was called myOrg.yaml
you would use the following:
system_rpt_read_template(cfg,
cfg =mapping = "myOrg.yaml",
template = "myOrg.pptx")
After that you can just use all the normal reporting functions to add content to the report.
ubiquity
workflowsAfter performing a parameter estimation and archiving the estimation with a specified analysis name, that analysis name can be used to retrieve the results and append them to an open report using system_rpt_estimation()
. This function supports both PowerPoint and Word reports.
system_rpt_estimation(cfg=cfg, analysis_name="analysis_name") cfg =
The results of NCA can be appended to a report using the system_rpt_nca()
function and supplying the NCA analysis name. This function supports both PowerPoint and Word reports.
system_rpt_nca(cfg=cfg, analysis_name="analysis_name") cfg =
officer
Sometimes the functions provided above are not sufficient to get what you want done. It may be more convenient to directly use the officer
functions to add content or modify your report. If you have report initialized, you can pull that report out of the ubiquity system object using system_fetch_rpt_officer_object()
:
system_fetch_rpt_officer_object(cfg) rpt =
Now rpt
is an officer
object. If it contains a PowerPoint presentation you can use all of the officer
functions for PowerPoint to modify that object. If it’s a Word document you can use the Word functions from officer
to modify/add content. Once you’re done making changes you can put the object back using system_set_rpt_officer_object()
:
system_set_rpt_officer_object(cfg, rpt) cfg =
Then you can continue using the ubiquity functions above or save the document.
ubiquity
and onbrand
functionsubiquity |
onbrand |
---|---|
system_rpt_read_template() |
onbrand::read_template() |
system_rpt_read_template() |
onbrand::read_template() |
system_rpt_add_slide() |
onbrand::report_add_slide() |
system_rpt_add_doc_content() |
onbrand::report_add_doc_content() |
system_rpt_save_report() |
onbrand::save_report() |
system_rpt_template_details() |
onbrand::template_details() |
system_fetch_rpt_officer_object() |
onbrand::fetch_officer_object() |
system_set_rpt_officer_object() |
onbrand::set_officer_object() |