04. Styling

In This Vignette

  • Quick Styling
  • Styles and Themes
  • Styles and CSS
  • XL Styles
  • Included Themes
  • Simple Themes
  • Styling with the quick table functions
  • Styling Rows/Columns/Cells
  • Changing styling/formatting after table creation using tbl$setStyling()
  • Formatting cell borders for specific cells
  • Changing styling/formatting using pt$mapStyling()
  • Creating a New Theme
  • Summary of Styling Rules
  • Styling Output
  • Further Reading

Quick Styling

This ‘Quick Start’ describes one easy method of styling table cells. A fuller explanation is given in the other sections of this vignette.

Cells in a table are styled using CSS. The quickest way to apply styles to individual cells in a table is using:

tbl$setStyling(rFrom, cFrom, rTo, cTo, rowNumbers, columnNumbers, cells, cellType, visible, baseStyleName, style, declarations)

To apply styles to a single cell, e.g. at row 1, column 2:

tbl$setStyling(1, 2, declarations=list("font-weight"="bold", "text-align"="center")

To apply styles to a range of cells, e.g. rows 2 to 3 and columns 1 to 5:

tbl$setStyling(2, 1, 3, 5, declarations=list("font-weight"="bold", "text-align"="center") or equivalently: tbl$setStyling(rowNumbers=2:3, columnNumbers=1:5, declarations=list("font-weight"="bold", "text-align"="center")

The above sets CSS style attributes on the individual cells. This is quick and easy, though very verbose. Named styles are more efficient for large tables (hundreds/thousands of cells) and are described in the following sections.

Styles and Themes

basictabler can render tables to a few different formats. The focus of this vignette is styling when rendering to HTML.

When rendered to HTML, the appearance of basictabler tables can be changed using styles and themes:

  • A style defines the appearance of a cell in the table.
    • A cell here is a general term that covers row/column headings, values in the body of the table and totals.
  • A style has a name and a set of style settings.
  • Each table has a collection of styles.
  • For each cell in the table, a style name can be set.
  • A theme is a collection of styles that can easily be applied to a table.

The basictabler package is supplied with some basic themes. Additional themes can be defined.

In addition, for each cell in the table, a set of style overrides can be set. These are style declarations that apply to individual cells.

Styles and CSS

A style is a collection of name-value pairs. The name-value pairs used to specify styles are simply Cascading Style Sheet properties and values. A full introduction and reference for CSS can be found on the w3schools website.

An example of defining a basictabler style is:

tableStyles$addStyle(styleName="ColumnHeader", list(
    "font-family"="arial",
    "font-size"="0.75em",
    padding="2px",
    border="1px solid blue",
    "vertical-align"="middle",
    "text-align"="center",
    "font-weight"="bold",
    color="blue",
    "background-color"="#FFFFFF",
    "xl-wrap-text"="wrap"
  ))

When viewing tables in an IDE such as R Studio, then typically only one table is viewed at a time.

If multiple tables are being output together (e.g. into a single HTML page) then specifying a styleNamePrefix in the tbl$renderTable() call is needed. The CSS declarations generated by the basictabler package for each table will then not overlap with each other. This can be seen in all of the examples in this vignette.

XL Styles

The basictabler package also supports outputting to Excel files. The Excel output can use CSS styling and/or Excel specific styling. The Excel specific styles are defined alongside the CSS styles and start with “xl-”, e.g. see the example above. The Excel specific styles are ignored by the HTML output. For more details about the Excel export, see the Excel Export vignette.

Included Themes

The basictabler package includes three basic themes:

Default Theme

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- "default"  # this theme is already the default, so this line isn't really needed
tbl$renderTable(styleNamePrefix="t0")

Compact Theme

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- "compact"
tbl$renderTable(styleNamePrefix="t1")

Large Plain Theme

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- "largeplain"
tbl$renderTable(styleNamePrefix="t2")

Simple Themes

Simple themes can be defined using a list. Several examples are shown below.

# define the font and colours
simpleBlueTheme <- list(
  fontName="Verdana, Arial",
  fontSize="0.75em",
  headerBackgroundColor = "rgb(68, 114, 196)",
  headerColor = "rgb(255, 255, 255)",
  cellBackgroundColor = "rgb(255, 255, 255)",
  cellColor = "rgb(0, 0, 0)",
  totalBackgroundColor = "rgb(186, 202, 233)",
  totalColor = "rgb(0, 0, 0)",
  borderColor = "rgb(48, 84, 150)"
)

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- simpleBlueTheme
tbl$renderTable(styleNamePrefix="t3")
# define the colours
simpleGrayTheme <- list(
  fontName="Courier New, Courier",
  fontSize="0.75em",
  headerBackgroundColor = "rgb(128, 128, 128)",
  headerColor = "rgb(255, 255, 255)",
  cellBackgroundColor = "rgb(255, 255, 255)",
  cellColor = "rgb(0, 0, 0)",
  totalBackgroundColor = "rgb(192, 192, 192)",
  totalColor = "rgb(0, 0, 0)",
  borderColor = "rgb(64, 64, 64)"
)

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- simpleGrayTheme
tbl$renderTable(styleNamePrefix="t4")
# define the colours
simpleGreenTheme <- list(
  fontName="Helvetica, arial",
  fontSize="0.75em",
  headerBackgroundColor = "rgb(112, 173, 71)",
  headerColor = "rgb(255, 255, 255)",
  cellBackgroundColor="rgb(255, 255, 255)",
  cellColor="rgb(0, 0, 0)",
  totalBackgroundColor = "rgb(182, 216, 158)",
  totalColor="rgb(0, 0, 0)",
  borderColor = "rgb(84, 130, 53)"
)

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=FALSE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- simpleGreenTheme
tbl$renderTable(styleNamePrefix="t6")

Styling with the quick table functions

The following example defines a simple theme and supplies this to the quick table function to specify styling:

# aggregate the sample data to make a small data frame
library(basictabler)
library(dplyr)
tocsummary <- bhmsummary %>%
  group_by(TOC) %>%
  summarise(OnTimeArrivals=sum(OnTimeArrivals),
            OnTimeDepartures=sum(OnTimeDepartures),
            TotalTrains=sum(TrainCount)) %>%
  ungroup() %>%
  mutate(OnTimeArrivalPercent=OnTimeArrivals/TotalTrains*100,
         OnTimeDeparturePercent=OnTimeDepartures/TotalTrains*100) %>%
  arrange(TOC)

# column formats
columnFormats=list(NULL, list(big.mark=","), 
                   list(big.mark=","), list(big.mark=","), "%.1f", "%.1f")

# simple theme
simpleBlueTheme <- list(
  fontName="Verdana, Arial",
  fontSize="0.75em",
  headerBackgroundColor = "rgb(68, 114, 196)",
  headerColor = "rgb(255, 255, 255)",
  cellBackgroundColor = "rgb(255, 255, 255)",
  cellColor = "rgb(0, 0, 0)",
  totalBackgroundColor = "rgb(186, 202, 233)",
  totalColor = "rgb(0, 0, 0)",
  borderColor = "rgb(48, 84, 150)"
)

# headings in red text, cells in light gray
tbl <- qtbl(tocsummary, firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("TOC", "On-Time Arrivals", 
                                    "On-Time Departures", "Total Trains", 
                                    "On-Time Arrival %", "On-Time Departure %"),
            columnFormats=columnFormats, theme=simpleBlueTheme)

# render table
tbl$renderTable(styleNamePrefix="t9")

The next example demonstrates specifying more granular style settings when using a quick table function:

# aggregate the sample data to make a small data frame
library(basictabler)
library(dplyr)
tocsummary <- bhmsummary %>%
  group_by(TOC) %>%
  summarise(OnTimeArrivals=sum(OnTimeArrivals),
            OnTimeDepartures=sum(OnTimeDepartures),
            TotalTrains=sum(TrainCount)) %>%
  ungroup() %>%
  mutate(OnTimeArrivalPercent=OnTimeArrivals/TotalTrains*100,
         OnTimeDeparturePercent=OnTimeDepartures/TotalTrains*100) %>%
  arrange(TOC)

# column formats
columnFormats=list(NULL, list(big.mark=","), 
                   list(big.mark=","), list(big.mark=","), "%.1f", "%.1f")

# create the table
tbl <- qtbl(tocsummary, firstColumnAsRowHeaders=FALSE,
            explicitColumnHeaders=c("TOC", "On-Time Arrivals", 
                                    "On-Time Departures", "Total Trains", 
                                    "On-Time Arrival %", "On-Time Departure %"),
            columnFormats=columnFormats, 
            tableStyle=list("border-color"="maroon"),
            headingStyle=list("color"="cornsilk", "background-color"="maroon", 
                              "font-style"="italic", "border-color"="maroon"), 
            cellStyle=list("color"="maroon", "background-color"="cornsilk", 
                           "border-color"="maroon"))

# set column alignment of first column
tbl$setStyling(2, 1, 5, 1, declarations=list("text-align"="left"))

# render table
tbl$renderTable(styleNamePrefix="t10")

The quick table functions specify the same styling/formatting for all headers and all cells. To specify different styling/formatting for specific headings and/or specific rows/columns, use the more verbose syntax for creating the table as shown in the examples below.

Styling Rows/Columns/Cells

Specifying cell appearance while creating a table from a data frame

The following example defines a new style and uses this for one of the columns in the table, with the other columns using the normal cell style.

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)
df <- data.frame(saleIds, items, quantities, prices)
colNames <- c("Sale ID", "Item", "Quantity", "Price")
colFormats <- list(NULL, NULL, NULL, "%.2f")

# construct the table
library(basictabler)
tbl <- BasicTable$new()

# define a new style
tbl$addStyle(styleName="AltCell", list(
  "font-family"="Arial",
  "font-size"="0.8em",
  "font-weight"="bold",
  padding="2px 2px 2px 8px",
  "border-bottom"="1px solid #9C0006",
  "text-align"="right",
  color="#9C0006",
  "background-color"="#FFC7CE"
))
colStyleNames <- c("Cell", "Cell", "AltCell", "Cell")

# populate the table
tbl$addData(df, explicitColumnHeaders=colNames, 
            columnFormats=colFormats, baseStyleNames=colStyleNames)
tbl$renderTable(styleNamePrefix="t11")

Specifying cell appearance while creating a table column-by-column

It is also possible to define a new style for an entire column when creating a table column-by-column. In the example below a new style is created and this is used as the base style for the third column.

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()

# define a new style
tbl$addStyle(styleName="AltColumn", list(
  "font-family"="Arial",
  "font-size"="0.8em",
  "font-weight"="bold",
  padding="2px 2px 2px 8px",
  "border-bottom"="1px solid #9C0006",
  "text-align"="right",
  color="#9C0006",
  "background-color"="#FFC7CE"
))
tbl$cells$setCell(1, 1, cellType="root", rawValue="Sale ID")
tbl$cells$setCell(1, 2, cellType="columnHeader", rawValue="Item")
tbl$cells$setCell(1, 3, cellType="columnHeader", rawValue="Quantity")
tbl$cells$setCell(1, 4, cellType="columnHeader", rawValue="Price")
tbl$cells$setColumn(1, cellTypes="rowHeader", rawValues=saleIds)
tbl$cells$setColumn(2, cellTypes="cell", rawValues=items)
tbl$cells$setColumn(3, cellTypes="cell", rawValues=quantities, baseStyleName="AltColumn")
tbl$cells$setColumn(4, cellTypes="cell", rawValues=prices,
                    formats=list("%.2f"))
tbl$renderTable(styleNamePrefix="t13")

Specifying cell appearance while creating a table row-by-row

Similarly, it is possible to define a new style for an entire row when creating a table row-by-row. In the example below a new style is created and this is used as the base style for the……

# cell types for the cells in each row
cellTypes <- c("rowHeader", "cell", "cell", "cell")

# formats for the values in each row
# (only the value in the fourth column needs formatting)
formats <- list(NULL, NULL, NULL, "%.2f")

# construct the table
library(basictabler)
tbl <- BasicTable$new()

# define a new style
tbl$addStyle(styleName="AltRow", list(
  "font-family"="Arial",
  "font-size"="0.8em",
  "font-weight"="bold",
  padding="2px 2px 2px 8px",
  "border-bottom"="1px solid #9C0006",
  "text-align"="right",
  color="#9C0006",
  "background-color"="#FFC7CE"
))
tbl$cells$setCell(1, 1, cellType="root", rawValue="Sale ID")
tbl$cells$setCell(1, 2, cellType="columnHeader", rawValue="Item")
tbl$cells$setCell(1, 3, cellType="columnHeader", rawValue="Quantity")
tbl$cells$setCell(1, 4, cellType="columnHeader", rawValue="Price")
tbl$cells$setRow(2, cellTypes=cellTypes, formats=formats,
                 rawValues=list(5334, "Apple", 5, 0.34452354))
tbl$cells$setRow(3, cellTypes=cellTypes, formats=formats,
                 rawValues=list(5336, "Orange", 8, 0.4732543), baseStyleNames="AltRow")
tbl$cells$setRow(4, cellTypes=cellTypes, formats=formats,
                 rawValues=list(5338, "Banana", 6, 1.3443243))
tbl$renderTable(styleNamePrefix="t14")

When creating tables column-by-column and row-by-row, it is possible to specify a vector for baseStyleNames of the same length as rawValues, to be able to specify different styles for each cell in the column/row:

# cell types for the cells in each row
cellTypes <- c("rowHeader", "cell", "cell", "cell")

# formats for the values in each row
# (only the value in the fourth column needs formatting)
formats <- list(NULL, NULL, NULL, "%.2f")

# construct the table
library(basictabler)
tbl <- BasicTable$new()

# define a new style
tbl$addStyle(styleName="AltRowLeftAlign", list(
  "font-family"="Arial",
  "font-size"="0.8em",
  "font-weight"="bold",
  padding="2px 2px 2px 2px",
  "border-bottom"="1px solid #9C0006",
  "text-align"="left",
  color="#9C0006",
  "background-color"="#FFC7CE"
))
tbl$addStyle(styleName="AltRowRightAlign", list(
  "font-family"="Arial",
  "font-size"="0.8em",
  "font-weight"="bold",
  padding="2px 2px 2px 8px",
  "border-bottom"="1px solid #9C0006",
  "text-align"="right",
  color="#9C0006",
  "background-color"="#FFC7CE"
))
styleNames <- c("AltRowLeftAlign", "AltRowRightAlign", 
                    "AltRowRightAlign", "AltRowRightAlign")
tbl$cells$setCell(1, 1, cellType="root", rawValue="Sale ID")
tbl$cells$setCell(1, 2, cellType="columnHeader", rawValue="Item")
tbl$cells$setCell(1, 3, cellType="columnHeader", rawValue="Quantity")
tbl$cells$setCell(1, 4, cellType="columnHeader", rawValue="Price")
tbl$cells$setRow(2, cellTypes=cellTypes, formats=formats,
                 rawValues=list(5334, "Apple", 5, 0.34452354))
tbl$cells$setRow(3, cellTypes=cellTypes, formats=formats,
                 rawValues=list(5336, "Orange", 8, 0.4732543), baseStyleNames=styleNames)
tbl$cells$setRow(4, cellTypes=cellTypes, formats=formats,
                 rawValues=list(5338, "Banana", 6, 1.3443243))
tbl$renderTable(styleNamePrefix="t15")

Specifying cell appearance while creating a table cell-by-cell

The following example shows two different ways of specifying cell styling whilst creating a table cell-by-cell. The first method defines an entirely new cell style (i.e. that is not part of the standard theming). This cell style is then used when styling one of the cells. The second method specifies one additional style declaration that is applied on top of the standard theming.

library(basictabler)
tbl <- BasicTable$new()

# specify a new cell style
tbl$addStyle(styleName="AltCell", list(
  "font-family"="Arial",
  "font-size"="0.8em",
  "font-weight"="bold",
  padding="2px 2px 2px 8px",
  "border"="2px solid #9C0006",
  "text-align"="right",
  color="#9C0006",
  "background-color"="#FFC7CE"
))

# build the table
tbl$cells$setCell(1, 1, cellType="root", rawValue="Sale ID")
tbl$cells$setCell(1, 2, cellType="columnHeader", rawValue="Item")
tbl$cells$setCell(1, 3, cellType="columnHeader", rawValue="Quantity")
tbl$cells$setCell(2, 1, cellType="rowHeader", rawValue=5334)
tbl$cells$setCell(2, 2, cellType="cell", rawValue="Apple")
tbl$cells$setCell(3, 1, cellType="rowHeader", rawValue=5336)
tbl$cells$setCell(3, 2, cellType="cell", rawValue="Orange")

# use the new style for the following cell (used instead of the theme styling)
tbl$cells$setCell(2, 3, cellType="cell", rawValue=5, baseStyleName="AltCell")

# specify an additional style declaration for the following cell (used on 
# top of the theme styling)
tbl$cells$setCell(3, 3, cellType="cell", rawValue=8, 
                  styleDeclarations=list("background-color"="#FFFF00"))

# render the table
tbl$renderTable(styleNamePrefix="t12")

Changing styling/formatting after table creation using tbl$setStyling()

The individual cells in the table can have their appearance changed by retrieving the cell then applying a style to the cell. The example below shows two different ways of applying cells to an individual cell. These styles apply in addition to the styles coming from the underlying theme, e.g. highlighting a cell:

# define the colours
orangeTheme <- list(
  fontName="Garamond, arial",
  fontSize="0.75em",
  headerBackgroundColor = "rgb(237, 125, 49)",
  headerColor = "rgb(255, 255, 255)",
  cellBackgroundColor = "rgb(255, 255, 255)",
  cellColor = "rgb(0, 0, 0)",
  totalBackgroundColor = "rgb(248, 198, 165)",
  totalColor = "rgb(0, 0, 0)",
  borderColor = "rgb(198, 89, 17)"
)

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- orangeTheme

# apply an additional highlight to one cell (3rd row, 2nd column)
tbl$setStyling(3, 2, declarations=list("background-color"="#FFFF00"))

# apply an additional highlight to one cell (3rd row, 3rd column)
cellHighlight <- tbl$createInlineStyle(declarations=list("background-color"="#00FFFF"))
cell <- tbl$cells$getCell(3, 3)
cell$style <- cellHighlight

# render the table
tbl$renderTable(styleNamePrefix="t16")

In the example above, the default cell style from the theme is still applied. The highlight is applied in addition to the default styling. To stop the base styling being applied, create a new named style and set the baseStyleName property on the cell to the name of the new style.

The tbl$setStyling() function is used in the example above. This function has the following arguments:

  • rFrom and cFrom are the coordinates of the cell where the styling is to be applied. If the styling is being applied to multiple cells, this is the top-left cell in the rectangular cell range where the styling is to be applied.
  • rTo and cTo are the coordinates of the bottom right cell when styling is being applied to a rectangular range of cells. If styling is only being applied to a single cell, these arguments are not needed.
  • rowNumbers and columnNumbers are integer vectors of row and/or column numbers specifying where the styling is to be applied. If both rowNumbers and columnNumbers are specified, then the cells at the intersection of the specified row numbers and column numbers are styled.
  • cells is a list of cells to apply styling to. Either rFrom/cFrom or cells is typically specified - not both.
  • cellType is one of the following values that specifies the cell type to be applied to the specified cells: root, rowHeader, columnHeader, cell, total. The cellType controls the default styling that is applied to the cell.
  • visible The cell visibility (TRUE or FALSE) to apply to the specified cells.
  • baseStyleName is the name of a style in the table theme to apply to the specified cells. Set this explicitly to NULL to revert to the default style specified in the table theme.
  • style is a TableStyle override object to apply to the specified cells. This is created by calling tbl$createInlineStyle() as shown in the example above.
  • declarations is a list of style override declarations to apply to the specified cells.
  • applyBorderToAdjacentCells is a logical value - specify TRUE to override the border in neighbouring cells, e.g. the left border of the current cell becomes the right border of the cell to the left.

The tbl$createInlineStyle() function is also used in the example above. This function creates a new unnamed style (that is not part of the table theme) and takes two arguments: baseStyleName specifies the name of the style that the new style will be based on (i.e. will have it’s style properties copied from) and declarations which specifies new/overriding style properties for the new style.

The lapply() function can be used to set the style for multiple cells to a new inline style:

# apply inline style to multiple cells
highlight <- tbl$createInlineStyle(declarations=list("background-color"="#FFCC66"))
cells <- tbl$getCells(specifyCellsAsList=TRUE, rowNumbers=c(1, 3))
lst <- lapply(cells, function(cell) {cell$style <- highlight})

For many more examples of styling parts of a table, see the Finding and Formatting vignette.

Formatting cell borders for specific cells

CSS rendering rules mean that the first encountered border setting is used. When table cells have no separation, this means the left/top borders of a cell are actually defined by the right/bottom borders of the previous cells (i.e. to the left and above). This means attempting to set the border of a specific cell often doesn’t produce the desired effect, e.g. attempting to change the border of a specific cell to red:

x <- data.frame(a=c(1,2,3),b=c(4,5,6),c=c(7,8,9))
tbl <- BasicTable$new()
tbl$addData(x)
tbl$setStyling(rowNumbers=3, columnNumbers=2, 
               declarations=list("border"="1px solid red"))
tbl$renderTable()

This can be resolved by specifying applyBorderToAdjacentCells=TRUE:

x <- data.frame(a=c(1,2,3),b=c(4,5,6),c=c(7,8,9))
tbl <- BasicTable$new()
tbl$addData(x)
tbl$setStyling(rowNumbers=3, columnNumbers=2, 
               declarations=list("border"="1px solid red"),
               applyBorderToAdjacentCells=TRUE)
tbl$renderTable()

Changing styling/formatting using pt$mapStyling()

Sometimes it is desirable to set the styling more dynamically, i.e. the styling of each cell should vary according to the value of the each cell, e.g. increasingly large numbers have an increasingly intense red cell background colour. This can be done with the mapStyling() method, which has the following arguments:

  • styleProperty - the name of the style property to set e.g. “background-color”.
  • cells - a list specifying the PivotCell objects to be styled.
  • valueType - the type of style value to be set - one of the following values: text/character, number/numeric, or color/colour
  • mapType - the type of mapping to be performed - the following mapping types are supported:
    • value - a 1:1 mapping which maps each specified “from” value to the corresponding “to” value, e.g. 100 -> “green”.
    • logic - each from value is logical criteria - see more details below.
    • range - values between each pair of “from” values are mapped to the corresponding “to” value, e.g. values in the range 80-100 -> “green”.
    • continuous - rescales values between each pair of “from” values into the range of the corresponding pair of “to” values, e.g. if the “from” range is 80-100 and the corresponding “to” range is 0.8-1, then 90 -> 0.9.
  • mappings - the mappings to be applied, specified in one of the following three forms:
    • a list containing pairs of values, e.g. list(0, "red", 0.4, "yellow", 0.8, "green")
    • a list containing “from” and “to” vectors/lists, e.g. list(from=c(0, 0.4, 0.8), to=c("red", "yellow", "green"))
    • a custom mapping function that will be invoked once per cell, e.g. function(v, cell) { if(isTRUE(v>0.8)) return("green") }.
  • styleLowerValues - a logical value, default FALSE, that specifies whether values less than the lowest specified “from” value should be styled using the style specified for the lowest “from” value.
  • styleHigherValues - a logical value, default TRUE, that specifies whether values greater than the highest specified “from” value should be styled using the style specified for the highest “from” value.

mapType=“logical” is a generic way of specifying mapping rules, which can be of any of the following forms:

  • a specific value, e.g. 12.
  • a specific value equality condition, e.g. "v==12", where v represents the cell value.
  • a value range expression using the following abbreviated form: “value1<=v<value2”, e.g. "10<=v<15".
    • Only “<” or “<=” can be used in these abbreviated value range expressions.
  • a standard R logical expression, e.g. "10<=v && v<15".
    • Basic R functions that test the value can also be used, e.g. "is.na(v)".

Further Notes:

  • mapType=“continuous” cannot be used with valueType=“text”/“character”.
  • A range specified as list(0, "red", 1000) is equivalent to “0<=v<1000”, i.e. the upper value is excluded from the range.
  • styleLowerValues and styleHigherValues only apply when valueType is “range” or “continuous”.
  • Mappings must be supplied in ascending order when valueType is “range” or “continuous”.

Examples

Several examples are given below. All of these examples use the following data:

library(basictabler)
library(dplyr)
tocsummary <- bhmsummary %>%
  group_by(TOC) %>%
  summarise(OnTimeArrivals=sum(OnTimeArrivals),
            OnTimeDepartures=sum(OnTimeDepartures),
            TotalTrains=sum(TrainCount)) %>%
  ungroup() %>%
  mutate(OnTimeArrivalPercent=OnTimeArrivals/TotalTrains*100,
         OnTimeDeparturePercent=OnTimeDepartures/TotalTrains*100) %>%
  arrange(TOC)

# formatting values (explained in the introduction vignette)
columnFormats=list(NULL, list(big.mark=","), list(big.mark=","), 
                   list(big.mark=","), "%.1f", "%.1f")

Style mapping example with mapType="logic"

The example pivot table below maps cell colours from cell values using conditional/logical expressions:

tbl <- BasicTable$new()
tbl$addData(tocsummary, firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("TOC", "On-Time Arrivals", 
                                    "On-Time Departures", "Total Trains", 
                                    "On-Time Arrival %", "On-Time Departure %"),
            columnFormats=columnFormats)
cells <- tbl$getCells(rowNumbers=2:5, columnNumbers=2:4, matchMode="combinations")
tbl$mapStyling(cells=cells, styleProperty="background-color", valueType="color", 
               mapType="logic",
               mappings=list("v==2348", "pink", "v<3000", "red", "3000<=v<15000", 
                             "yellow", "v>15000", "green"))
tbl$mapStyling(cells=cells, styleProperty="background-color", valueType="text", 
               mapType="logic", mappings=list("v==1404", "red"))
tbl$renderTable()

Style mapping example with mapType="range"

The example pivot table below maps cell colours from cell values using ranges, i.e. 0-1000 -> “red” and 1000-15000 -> “orange”:

tbl <- BasicTable$new()
tbl$addData(tocsummary, firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("TOC", "On-Time Arrivals", 
                                    "On-Time Departures", "Total Trains", 
                                    "On-Time Arrival %", "On-Time Departure %"),
            columnFormats=columnFormats)
cells <- tbl$getCells(rowNumbers=2:5, columnNumbers=2:4, matchMode="combinations")
tbl$mapStyling(cells=cells, styleProperty="background-color", valueType="color", 
               mapType="range",
               mappings=list(0, "red", 3000, "orange", 5000, 
                             "yellow", 15000, "green"))
tbl$renderTable()

Style mapping example with mapType="continuous"

An example of styling using the “continuous” map type can be found in the Finding and Formatting vignette.

Style mapping example with mapType="function"

The example pivot table below maps cell colours using a custom function. The cell argument passed to the function is the current cell being styled, e.g. to format based on the column number:

tbl <- BasicTable$new()
tbl$addData(tocsummary, firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("TOC", "On-Time Arrivals", 
                                    "On-Time Departures", "Total Trains", 
                                    "On-Time Arrival %", "On-Time Departure %"),
            columnFormats=columnFormats)
cells <- tbl$getCells(rowNumbers=2:5, columnNumbers=2:4, matchMode="combinations")
redclr <- function(x, cell) {
  clr <- 255-floor(140*cell$columnNumber/3)
  return(paste0("#",
                format(as.hexmode(255), width=2),
                format(as.hexmode(clr), width=2),
                format(as.hexmode(clr), width=2)))
}
tbl$mapStyling(cells=cells, styleProperty="background-color", mappings=redclr)
tbl$renderTable()

Creating a New Theme

Since a theme is a collection of styles, creating themes is relatively straightforward. The names of the styles are then assigned to the different types of cells within a table:

  • tableStyle - the name of the style applied to the table (i.e. the HTML <table> element).
  • rootStyle - the name of the style applied to the empty cell at the top left of the table.
  • rowHeaderStyle - the name of the style applied to the row header cells.
  • colHeaderStyle - the name of the style applied to the column header cells.
  • cellStyle - the name of the style applied to the cells in the body of the table.
  • totalStyle - the name of the style applied to the total cells in the table.

E.g. creating a custom theme that displays a mixture of bright colours (a rather ugly bubble-gum theme):

library(basictabler)
# define the theme and styles
createCustomTheme <- function(parentTable=NULL, themeName="myCustomTheme") {
  tableStyles <- TableStyles$new(parentTable=parentTable, themeName=themeName)
  # borders in purple
  tableStyles$addStyle(styleName="Table", list(
      "display"="table",
      "border-collapse"="collapse",
      "border"="2px solid #B28DFF"
    ))
  # column headings in pink
  tableStyles$addStyle(styleName="ColumnHeader", list(
      "font-family"="\"Courier New\", Courier, monospace",
      "font-size"="0.75em",
      "font-weight"="bold",
      padding="2px",
      "border"="2px solid #B28DFF",
      "vertical-align"="middle",
      "text-align"="center",
      "font-weight"="bold",
      color="#DB49AC",
      "background-color"="#FFCCF9",
      "xl-wrap-text"="wrap"
    ))
  # row headings in blue
  tableStyles$addStyle(styleName="RowHeader", list(
      "font-family"="\"Courier New\", Courier, monospace",
      "font-size"="0.75em",
      "font-weight"="bold",
      padding="2px 8px 2px 2px",
      "border"="1px solid #B28DFF",
      "vertical-align"="middle",
      "text-align"="left",
      "font-weight"="bold",
      color="#438EC8",
      "background-color"="#ACE7FF",
      "xl-wrap-text"="wrap"
    ))
  # cells in yellow
  tableStyles$addStyle(styleName="Cell", list(
      "font-family"="\"Courier New\", Courier, monospace",
      "font-size"="0.75em",
      padding="2px 2px 2px 8px",
      "border"="1px solid #B28DFF",
      "text-align"="right",
      color="#FF800D",
      "background-color"="#FFFFD1"
    ))
  # totals in orange
  tableStyles$addStyle(styleName="Total", list(
      "font-family"="\"Courier New\", Courier, monospace",
      "font-size"="0.75em",
      "font-weight"="bold",
      padding="2px 2px 2px 8px",
      "border"="1px solid rgb(84, 130, 53)",
      "text-align"="right",
      color="#3BC6B6",
      "background-color"="#BFFCC6"
    ))
  tableStyles$tableStyle <- "Table"
  tableStyles$rootStyle <- "ColumnHeader"
  tableStyles$rowHeaderStyle <- "RowHeader"
  tableStyles$colHeaderStyle <- "ColumnHeader"
  tableStyles$cellStyle <- "Cell"
  tableStyles$totalStyle <- "Total"
  return(invisible(tableStyles))
}

# data for the table
saleIds <- c(5334, 5336, 5338)
items <- c("Apple", "Orange", "Banana")
quantities <- c(5, 8, 6)
prices <- c(0.34452354, 0.4732543, 1.3443243)

# construct the table
library(basictabler)
tbl <- BasicTable$new()
tbl$addData(data.frame(saleIds, items, quantities, prices), 
            firstColumnAsRowHeaders=TRUE,
            explicitColumnHeaders=c("Sale ID", "Item", "Quantity", "Price"),
            columnFormats=list(NULL, NULL, NULL, "%.2f"))

# theme the table and render
tbl$theme <- createCustomTheme(tbl)
tbl$renderTable(styleNamePrefix="t8")

Summary of Styling Rules

basictabler styles cells using the following rules:

  • Each cell in a table has an associated cell type (root / rowHeader / columnHeader / cell / total). This controls the default styling applied to a cell.
    • Specify cell type of a new cell: tbl$cells$setCell(1, 2, cellType="columnHeader", rawValue="Item")
    • Change cell type of an existing cell: tbl$cells$getCell(3, 2)$cellType <- "columnHeader"
  • The styling theme applied to a table defines a set of styles and the default style for each cell type.
    • Create a new simple theme using a list and assigning this to the tbl$theme field.
    • Create a new custom theme by writing a function createCustomTheme().
    • Assign a theme to the table theme property: tbl$theme <- createCustomTheme(tbl)
  • Each individual cell can also have a different style, specified by settings the baseStyleName for the cell.
    • Single cell example: tbl$cells$getCell(3, 2)$baseStyleName <- "AltCellStyle".
    • Alternative single cell example: tbl$setStyling(3, 2, baseStyleName="AltCellStyle").
    • Cell range example: tbl$setStyling(3, 2, 3, 6, baseStyleName="AltCellStyle").
  • It is also possible to declare individual style overrides (e.g. a different text colour). These override specific style settings from the named styles.
    • Single cell example: tbl$setStyling(3, 2, declarations=list("text-align"="left", "background-color"="yellow")).
    • Cell range example: tbl$setStyling(3, 2, 3, 6, declarations=list("text-align"="left", "background-color"="yellow")).
  • It is possible to specify a new base style and overrides together. The declarations override the settings in the base style.
    • Single cell example: tbl$setStyling(3, 2, baseStyleName="AltCellStyle", declarations=list("text-align"="left", "background-color"="yellow")).
    • Cell range example: tbl$setStyling(3, 2, 3, 6, baseStyleName="AltCellStyle", declarations=list("text-align"="left", "background-color"="yellow")).
  • Instead of specifying the declarations as a list, an inline style can be declared. This is an unnamed style object that is used for one or multiple cells and is not part of the table theme.
    • See the “Changing cell appearance after cells have been created” section in this vignette for an example.
    • See the “Finding and Formatting” vignette for more examples.

Styling Output

When rendering to HTML, two styles settings are written by basictabler in the HTML for each table cell:

HTML class attribute

Example: < td class=“StyleName” >

  • The cell$baseStyleName is used as the HTML class name.
  • If no cell$baseStyleName has been explicitly set for a cell, then the base style name (for the relevant cell type) specified in the table theme is used.
  • The class names can be prefixed if required - useful when using several tables on the same HTML page.
  • It is also possible to generate class names that refer to styles not defined in the table - useful when the styles are defined in an external CSS file.

HTML style attribute

Example: < td style=“text-align:left;background-color:yellow;” >

The cell style override declarations (= the declarations of the inline style) are used as the value of the HTML style attribute for each cell.