Skip to content

Commit d19a6fe

Browse files
authored
Merge pull request #283 from Merck/277-possible-to-add-auto-table-numbering-across-multi-page-tables
2 parents b478e07 + ed35425 commit d19a6fe

9 files changed

Lines changed: 2634 additions & 4 deletions

R/conversion.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ convert <- function(text,
8585
"\n" = "\\line ",
8686
"\\pagenumber" = "\\chpgn ",
8787
"\\totalpage" = "\\totalpage",
88-
"\\pagefield" = "{\\field{\\*\\fldinst NUMPAGES }} "
88+
"\\pagefield" = "{\\field{\\*\\fldinst NUMPAGES }} ",
89+
"\\pagenumber_hardcoding" = "\\pgnhardcoding"
8990
)
9091

9192
# Define Pattern for latex code

R/rtf_encode_table.R

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,13 @@ rtf_encode_table <- function(tbl, verbose = FALSE) {
151151
sep = "\n"
152152
)
153153

154-
rtf_feature <- paste(unlist(rtf_feature), collapse = "\n")
154+
## Post Processing for page numbers (per page basis)
155+
for (i in seq_len(n_page)) {
156+
rtf_feature[i] <- gsub("\\pgnhardcoding", i, rtf_feature[i], fixed = TRUE)
157+
rtf_feature[i] <- gsub("\\totalpage", n_page, rtf_feature[i], fixed = TRUE)
158+
}
155159

156-
## Post Processing for total page number
157-
rtf_feature <- gsub("\\totalpage", n_page, rtf_feature, fixed = TRUE) # total page number
160+
rtf_feature <- paste(unlist(rtf_feature), collapse = "\n") # total page number
158161

159162
end <- as_rtf_end()
160163
if (verbose) {

tests/testthat/_snaps/independent-testing-rtf_encode_table.md

Lines changed: 12 additions & 0 deletions
Large diffs are not rendered by default.

tests/testthat/test-independent-testing-rtf_encode_table.R

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,76 @@ test_that("Test case when using subline_by, page_by, group_by simultaneously wit
345345
)
346346
expect_true(tmp[[length(tmp)]])
347347
})
348+
349+
test_that("Test pagenumber_hardcoding with multi-page table", {
350+
tbl <- iris[1:100, ] |>
351+
rtf_title("Table: Iris Data (\\pagenumber_hardcoding/\\totalpage)") |>
352+
rtf_colheader("Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species") |>
353+
rtf_body(col_rel_width = rep(1, 5))
354+
355+
encoded <- rtf_encode_table(tbl)
356+
357+
expect_snapshot_output(encoded)
358+
})
359+
360+
test_that("Test pagenumber_hardcoding replaces correctly per page", {
361+
tbl <- iris[1:100, ] |>
362+
rtf_title("Table (\\pagenumber_hardcoding/\\totalpage)") |>
363+
rtf_body(col_rel_width = rep(1, 5))
364+
365+
encoded <- rtf_encode_table(tbl)
366+
367+
pages <- strsplit(encoded$body, "\\\\page")[[1]]
368+
n_pages <- length(pages)
369+
370+
for (i in seq_len(n_pages)) {
371+
expect_true(grepl(as.character(i), pages[i], fixed = TRUE))
372+
expect_true(grepl(as.character(n_pages), pages[i], fixed = TRUE))
373+
}
374+
})
375+
376+
test_that("Test pagenumber_hardcoding in page header", {
377+
tbl <- iris[1:100, ] |>
378+
rtf_page() |>
379+
rtf_body() |>
380+
rtf_page_header(text = "Page \\pagenumber_hardcoding of \\totalpage")
381+
382+
encoded <- rtf_encode_table(tbl)
383+
384+
pages <- strsplit(encoded$body, "\\\\page")[[1]]
385+
n_pages <- length(pages)
386+
387+
for (i in seq_len(min(3, n_pages))) {
388+
expect_true(grepl(paste0("Page ", i), pages[i]))
389+
expect_true(grepl(paste0("of ", n_pages), pages[i]))
390+
}
391+
})
392+
393+
test_that("Test pagenumber_hardcoding with totalpage in footnote", {
394+
tbl <- iris[1:100, ] |>
395+
rtf_body(col_rel_width = rep(1, 5)) |>
396+
rtf_footnote("Page \\pagenumber_hardcoding of \\totalpage")
397+
398+
attr(tbl, "page")$page_footnote <- "all"
399+
400+
encoded <- rtf_encode_table(tbl)
401+
402+
pages <- strsplit(encoded$body, "\\\\page")[[1]]
403+
n_pages <- length(pages)
404+
405+
for (i in seq_len(min(3, n_pages))) {
406+
expect_true(grepl(as.character(i), pages[i]))
407+
expect_true(grepl(as.character(n_pages), pages[i]))
408+
}
409+
})
410+
411+
test_that("Test pagenumber_hardcoding survives without extra spaces", {
412+
tbl <- iris[1:50, ] |>
413+
rtf_title("Test (\\pagenumber_hardcoding/\\totalpage)") |>
414+
rtf_body()
415+
416+
encoded <- rtf_encode_table(tbl)
417+
418+
expect_false(grepl("\\\\totalpage ", encoded$body, fixed = TRUE))
419+
expect_false(grepl("\\\\pgnhardcoding", encoded$body, fixed = TRUE))
420+
})
28.6 KB
Binary file not shown.
28.8 KB
Binary file not shown.

vignettes/rtf-text.Rmd

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,94 @@ r2rtf:::write_rtf_para(res, "rtf/text-combine3.rtf")
237237
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
238238
knitr::include_graphics("pdf/text-combine3.pdf")
239239
```
240+
241+
## RTF Control Words for Page Numbering
242+
243+
The r2rtf package supports several control words for page numbering in tables. These control words can be used in titles, headers, footnotes, and other text elements.
244+
245+
### Available Control Words
246+
247+
| Control Word | Description | Use Case |
248+
|--------------|-------------|----------|
249+
| `\pagenumber` | Dynamic RTF page field (document-level) | When you need the actual document page number |
250+
| `\pagenumber_hardcoding` | Hardcoded table-specific page number | For multi-page tables with table-relative page numbering (e.g., "Page 1 of 3") |
251+
| `\totalpage` | Total number of pages in the table | Works with `\pagenumber_hardcoding` to show "X of Y" format |
252+
| `\pagefield` | RTF NUMPAGES field code | For total document pages |
253+
254+
### Example 1: Using `\pagenumber` (Document-Level Page Number)
255+
256+
This example uses `\pagenumber` which shows the document-level page number. When multiple tables are combined, it shows the absolute page position in the document.
257+
258+
```{r}
259+
tbl1_file <- tempfile(fileext = ".rtf")
260+
tbl2_file <- tempfile(fileext = ".rtf")
261+
262+
iris[1:30, ] |>
263+
rtf_title("Table 1: Iris Data (Page \\pagenumber)") |>
264+
rtf_colheader("Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species") |>
265+
rtf_body(col_rel_width = rep(1, 5)) |>
266+
rtf_encode() |>
267+
write_rtf(tbl1_file)
268+
269+
iris[31:60, ] |>
270+
rtf_title("Table 2: Iris Data (Page \\pagenumber)") |>
271+
rtf_colheader("Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species") |>
272+
rtf_body(col_rel_width = rep(1, 5)) |>
273+
rtf_encode() |>
274+
write_rtf(tbl2_file)
275+
276+
assemble_rtf(
277+
input = c(tbl1_file, tbl2_file),
278+
output = "rtf/page-number-dynamic.rtf"
279+
)
280+
```
281+
282+
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
283+
knitr::include_graphics("pdf/page-number-dynamic.pdf")
284+
```
285+
286+
### Example 2: Using `\pagenumber_hardcoding` (Table-Specific Page Number)
287+
288+
This example uses `\pagenumber_hardcoding` which shows the table-specific page number. When multiple tables are combined, each table maintains its own independent page numbering (1/N, 2/N, etc.). Note that Table 1 spans multiple pages to demonstrate how the page counter works within a single table.
289+
290+
```{r}
291+
tbl3_file <- tempfile(fileext = ".rtf")
292+
tbl4_file <- tempfile(fileext = ".rtf")
293+
294+
# Create a multi-page table to demonstrate page numbering within a single table
295+
iris[1:100, ] |>
296+
rtf_title("Table 1: Iris Data (\\pagenumber_hardcoding/\\totalpage)") |>
297+
rtf_colheader("Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species") |>
298+
rtf_body(col_rel_width = rep(1, 5)) |>
299+
rtf_encode() |>
300+
write_rtf(tbl3_file)
301+
302+
# Single page table to show independent numbering
303+
iris[101:130, ] |>
304+
rtf_title("Table 2: Iris Data (\\pagenumber_hardcoding/\\totalpage)") |>
305+
rtf_colheader("Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species") |>
306+
rtf_body(col_rel_width = rep(1, 5)) |>
307+
rtf_encode() |>
308+
write_rtf(tbl4_file)
309+
310+
assemble_rtf(
311+
input = c(tbl3_file, tbl4_file),
312+
output = "rtf/page-number-hardcoding.rtf"
313+
)
314+
```
315+
316+
```{r, out.width = "100%", out.height = "400px", echo = FALSE, fig.align = "center"}
317+
knitr::include_graphics("pdf/page-number-hardcoding.pdf")
318+
```
319+
320+
### Key Differences
321+
322+
**`\pagenumber` (Dynamic Field):**
323+
- Shows: 1, 2, 3, 4, 5, ... (continuous across document)
324+
- Use when: You need absolute document page numbers
325+
- Behavior: When combining tables with `assemble_rtf()`, pages continue numbering across all tables
326+
327+
**`\pagenumber_hardcoding` (Hardcoded Table Pages):**
328+
- Shows: Table 1 displays "1/3, 2/3, 3/3", Table 2 displays "1/1" (each restarts)
329+
- Use when: You need table-relative page numbering where each table has its own counter
330+
- Behavior: Each table's pages are numbered independently starting from 1. This is especially useful for multi-page tables that need internal page tracking.

0 commit comments

Comments
 (0)