Titles and Footnotes

A specific thing that {clinify} helps users with is the application of titles and footnotes to a document. In clinical tables, it’s common that you need to use the header and the footer of the word document to apply titles and footnotes. There are several functions available within {clinify} to help you here.

Titles and Footnotes

Let’s look at an example:

library(clinify)

clintable(mtcars) |>
  clin_add_titles(
    list(
      c("Left", "Page {PAGE} of {NUMPAGES}"),
      c("Just the middle")
    )
  ) |>
  clin_add_footnotes(
    list(
      c(
        "Here's a footnote.",
        format(Sys.time(), "%H:%M %A, %B %d, %Y")
      )
    )
  )

Left

Page of

Just the middle

mpg

cyl

disp

hp

drat

wt

qsec

vs

am

gear

carb

21.0

6

160.0

110

3.90

2.620

16.46

0

1

4

4

21.0

6

160.0

110

3.90

2.875

17.02

0

1

4

4

22.8

4

108.0

93

3.85

2.320

18.61

1

1

4

1

21.4

6

258.0

110

3.08

3.215

19.44

1

0

3

1

18.7

8

360.0

175

3.15

3.440

17.02

0

0

3

2

18.1

6

225.0

105

2.76

3.460

20.22

1

0

3

1

14.3

8

360.0

245

3.21

3.570

15.84

0

0

3

4

24.4

4

146.7

62

3.69

3.190

20.00

1

0

4

2

22.8

4

140.8

95

3.92

3.150

22.90

1

0

4

2

19.2

6

167.6

123

3.92

3.440

18.30

1

0

4

4

17.8

6

167.6

123

3.92

3.440

18.90

1

0

4

4

16.4

8

275.8

180

3.07

4.070

17.40

0

0

3

3

17.3

8

275.8

180

3.07

3.730

17.60

0

0

3

3

15.2

8

275.8

180

3.07

3.780

18.00

0

0

3

3

10.4

8

472.0

205

2.93

5.250

17.98

0

0

3

4

Here's a footnote.

11:05 Saturday, August 01, 2026

Both clin_add_titles() and clin_add_footnotes() take a list of character vectors. Each element of the list will be applied as a row of the title or footnote. The number of elements of the list determines how those elements are aligned:

Note the text field "Page {PAGE} of {NUMPAGES}". {clinify} has a special helper function clin_replace_pagenums() that will find cells within a flextable containing {PAGE} or {NUMPAGES} and replace them with the word auto field for current and total pages respectively. By default within {clinify} this actual takes places during the default styling functions (see vignette("defaults")). Note that when you print to HTML, the {PAGE} and {NUMPAGES} portions of the string will appear blank.

Another option for setting titles and footnotes is to create your own flextable object.

clintable(mtcars) |>
  clin_add_titles(ft = flextable::flextable(head(iris, 2)))

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.1

3.5

1.4

0.2

setosa

4.9

3.0

1.4

0.2

setosa

mpg

cyl

disp

hp

drat

wt

qsec

vs

am

gear

carb

21.0

6

160.0

110

3.90

2.620

16.46

0

1

4

4

21.0

6

160.0

110

3.90

2.875

17.02

0

1

4

4

22.8

4

108.0

93

3.85

2.320

18.61

1

1

4

1

21.4

6

258.0

110

3.08

3.215

19.44

1

0

3

1

18.7

8

360.0

175

3.15

3.440

17.02

0

0

3

2

18.1

6

225.0

105

2.76

3.460

20.22

1

0

3

1

14.3

8

360.0

245

3.21

3.570

15.84

0

0

3

4

24.4

4

146.7

62

3.69

3.190

20.00

1

0

4

2

22.8

4

140.8

95

3.92

3.150

22.90

1

0

4

2

19.2

6

167.6

123

3.92

3.440

18.30

1

0

4

4

17.8

6

167.6

123

3.92

3.440

18.90

1

0

4

4

16.4

8

275.8

180

3.07

4.070

17.40

0

0

3

3

17.3

8

275.8

180

3.07

3.730

17.60

0

0

3

3

15.2

8

275.8

180

3.07

3.780

18.00

0

0

3

3

10.4

8

472.0

205

2.93

5.250

17.98

0

0

3

4

While this particular example is obscure, this opens up the possibility to specifically craft your own title or footnote.

Titles and footnotes from a spec

Projects usually keep the titles and footnotes for every table in one place - a spreadsheet, a CSV, a database table - rather than writing them into each program. Instead of a list, ls accepts a data frame holding every line for a table, and each function takes the rows that belong to it:

spec <- data.frame(
  type = c("title", "title", "footnote", "footnote_page"),
  text1 = c(
    "Protocol: CDISCPILOT01",
    "Table 14-2.01",
    "Source: {FILE}",
    "Kept off the table pages"
  ),
  text2 = c("Page {PAGE} of {NUMPAGES}", NA, NA, NA),
  align = c("split", "center", "left", "left")
)

clintable(head(iris, 3)) |>
  clin_add_titles(spec, tokens = list(FILE = "programs/t14-2-01.R")) |>
  clin_add_footnotes(spec, tokens = list(FILE = "programs/t14-2-01.R")) |>
  clin_add_footnote_page(spec)

Protocol: CDISCPILOT01

Page of

Table 14-2.01

Kept off the table pages

Source: programs/t14-2-01.R

Only type and text1 are required; text2 holds the right hand side of a split line and align places each line. A surface with no rows in the spec is left alone, which is what lets the same object be handed to all three functions - above, clin_add_footnotes() ignores the title and footnote page rows.

Reading the spec in is deliberately left to you. It is an ordinary data frame, so where it comes from is your choice, and clinify does not need to know about spreadsheets to accept one.

tokens fills in {NAME} placeholders, which is how a program path or a run date reaches text that was written elsewhere. Note that {PAGE} and {NUMPAGES} are left alone - those become real Word page number fields when the table renders, so they should not be passed as tokens.

Footnote Pages

Another circumstance that {clinify} allows for is the creation of a specific footnote pages. This can be used in circumstances where there are too many required footnotes for the table, and rather than putting in the footer you can place them into their own specific preceding page of the table itself. Also, note in this example that if you want to add a single left aligned title, you can provide duplicate text, which keeps the left alignment and merges the duplicate values.

clintable(mtcars) |>
  clin_add_titles(
    list(
      c("Left", "Left"),
      c("Just the middle")
    )
  ) |>
  clin_add_footnotes(
    list(
      c(
        "Here's a footnote.",
        format(Sys.time(), "%H:%M %A, %B %d, %Y")
      )
    )
  ) |>
  clin_add_footnote_page(
    list(
      c("One very long footnote full of text"),
      c("Two very long footnote full of text"),
      c("Three very long footnote full of text"),
      c("Four very long footnote full of text"),
      c("Five very long footnote full of text")
    )
  )

Left

Just the middle

One very long footnote full of text

Two very long footnote full of text

Three very long footnote full of text

Four very long footnote full of text

Five very long footnote full of text

Here's a footnote.

11:05 Saturday, August 01, 2026

The interface to clin_add_footnote_page() is identical to clin_add_titles() and clin_add_footnotes(), so the same capabilities exist for this function as well.