Introduction
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.
Implenting 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.
Reporting workshop files
To make a copy of the example scripts in the current working directory run the following:
library(ubiquity)
fr = workshop_fetch(section="Reporting", overwrite=TRUE)
This should create the following scripts
-
make_report_PowerPoint.R
Generates a PowerPoint presentation from an R script -
make_report_Word.R
Generates a Word document from an R script
Then general process for creating a report is:
- Initialize a report using the function
system_rpt_read_template()
. - Use the functions that add content to reports
(
system_rpt_add_slide()
for PowerPoint andsystem_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). - Lastly, save the output using
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:
cfg = build_system("system.txt")
PowerPoint reports (make_report_PowerPoint.R
)
Creating some content
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)
p = ggplot() + annotate("text", x=0, y=0, label = "picture example")
imgfile = tempfile(pattern="image", fileext=".png")
ggsave(filename=imgfile, plot=p, height=5.15, width=9, units="in")
Next we’ll create tabular data (tdata
):
tdata = data.frame(Parameters = c("Vp", "Cl", "Q", "Vt"),
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
tco = list(table = tdata,
header = TRUE,
first_row = FALSE)
flextable
using onbrand
abstraction
tcf = list(table = tdata, # This element contains the table data
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
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.
lcontent = c(1, "First major item",
2, "first sub bullet",
2, "second sub bullet",
3, "sub sub bullet",
1, "Second major item",
2, "first sub bullet",
2, "second sub bullet")
Creating a new report
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.
cfg = system_rpt_read_template(cfg, "PowerPoint")
Adding slides to a report
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"
).
cfg = system_rpt_add_slide(cfg,
template = "title_slide",
elements = list(
title=list(content = "Reporting in ubiquity",
type = "text")))
cfg = system_rpt_add_slide(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:
fr = system_rpt_template_details(cfg)
This will produce output in the console like the following:
## Mapping: /private/var/folders/l9/6pm7xq5j1hn6l00zrs22j6mc0000gn/T/Rtmp66QvU7/temp_libpath1e7429f774c3/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)
Adding lists
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.
cfg = system_rpt_add_slide(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")))
Adding figures
If you specify the content type is "ggplot"
, then you
can just provide the ggplot object (p
).
cfg = system_rpt_add_slide(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.
cfg = system_rpt_add_slide(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")))
Adding tables
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"
.
cfg = system_rpt_add_slide(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
).
cfg = system_rpt_add_slide(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
).
cfg = system_rpt_add_slide(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.
Saving the report
Once you’re done you can then save the presentation to a file:
system_rpt_save_report(cfg, output_file = "example.pptx")
Word reports (make_report_Word.R
)
Creating some content
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.
plain_text_content = paste(rep("The quick brown fox jumped over the lazy dog.", 70), collapse= " ")
md_text_content = paste(rep("The *quick* <color:brown>brown</color> fox **jumped** over the ~lazy dog~.", 70), collapse=" ")
fpar_text_content = officer::fpar(
officer::ftext("The quick ", prop=NULL),
officer::ftext("brown", prop=officer::fp_text(color="brown")),
officer::ftext(" fox jumped over the lazy dog.", prop=NULL))
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)
p = ggplot() + annotate("text", x=0, y=0, label = "picture example")
imgfile = tempfile(pattern="image", fileext=".png")
ggsave(filename=imgfile, plot=p, height=5.15, width=9, units="in")
gpc = list(image = p,
caption = "This is an example of an image from a ggplot object.")
ifc = list(image = imgfile,
caption = "This is an example of an image from a file.")
The same tabular data from before is used here as well:
tdata = data.frame(Parameters = c("Vp", "Cl", "Q", "Vt"),
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:
tco = list(table = tdata, # This element contains the table data
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"
).
tcf = list(table = tdata, # This element contains the table data
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
Creating a new report
We create a new Word report by defining the template option as
"Word"
.
cfg = system_rpt_read_template(cfg, "Word")
Adding content to the report
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.
Adding text
Text content contains a style
element where you can
specify the onbrand
style.
cfg = system_rpt_add_doc_content(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()
:
fr = system_rpt_template_details(cfg)
This will produce output in the console like the following:
## Mapping: /private/var/folders/l9/6pm7xq5j1hn6l00zrs22j6mc0000gn/T/Rtmp66QvU7/temp_libpath1e7429f774c3/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)
## Notes (Notes, paragraph)
## TOC (toc 1, paragraph)
## Table_Caption (table title, 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.
cfg = system_rpt_add_doc_content(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.
cfg = system_rpt_add_doc_content(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"
.
cfg = system_rpt_add_doc_content(cfg,
type="text",
content = list(
style = "Normal",
format = "fpar",
text = fpar_text_content))
Adding figures
To add figures you can specify the type as either an
"imagefile"
or "ggplot"
:
cfg = system_rpt_add_doc_content(cfg,
type = "imagefile",
content = ifc)
cfg = system_rpt_add_doc_content(cfg,
type = "ggplot",
content = gpc)
Adding tables
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:
cfg = system_rpt_add_doc_content(cfg,
type = "table",
content = tco)
cfg = system_rpt_add_doc_content(cfg,
type = "flextable",
content = tcf)
cfg = system_rpt_add_doc_content(cfg,
type = "flextable_object",
content = tcfo)
Other content and formatting
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.
Saving the report
Once you’re done you can then save the document to a file:
system_rpt_save_report(cfg, output_file = "example.docx")
Using custom organizational templates
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:
tr = system_fetch_template(cfg, template="myOrg")
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.
PowerPoint
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 |
Word
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 |
Notes |
Notes |
paragraph |
TOC |
toc 1 |
paragraph |
Table_Caption |
table title |
paragraph |
Table |
Table Grid |
table |
Using the custom templates
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:
cfg = system_rpt_read_template(cfg,
mapping = "myOrg.yaml",
template = "myOrg.pptx")
After that you can just use all the normal reporting functions to add content to the report.
Integration with ubiquity
workflows
Parameter estimation
After 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.
cfg = system_rpt_estimation(cfg=cfg, analysis_name="analysis_name")
Non-compartmental analysis (NCA)
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.
cfg = system_rpt_nca(cfg=cfg, analysis_name="analysis_name")
Modifying reports directly with 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()
:
rpt = system_fetch_rpt_officer_object(cfg)
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()
:
cfg = system_set_rpt_officer_object(cfg, rpt)
Then you can continue using the ubiquity functions above or save the document.