---
title: "Tables That Work for HTML and Word"
date: last-modified
format:
  docx: default
  html:
    embed-resources: true
execute: 
    warning: false
    message: false
---

Packages such as `gt` and `flextable` produce highly flexible and beautiful HTML tables, but using features such as math in them will not result in a properly rendered Word `.docx` file.  Using R functions that render HTML that is simple but flexible results in well-rendered Word and HTML.  Here is an example using the `Hmisc` package `summaryM` function and its `print` method, which uses the [`htmlTable` package](https://cran.r-project.org/web/packages/htmlTable) by Max Gordon, which you can use in this context to produce a wide variety of nice tables.

`Quarto` allows you to include Markdown inside the html as described [here](https://quarto.org/docs/authoring/tables.html#html-tables).  I define a little function `mk` to facitate that.

```{r results='asis'}
require(Hmisc)
options(prType='html')
mk <- function(x) paste0('<span data-qmd="', x, '"></span>')

getHdata(support)
d <- support
label(d$age) <- mk('Age _in years_ $\\alpha_{3}$')
s <- summaryM(age + sex + crea + sod ~ dzclass, test=TRUE, data=d)
print(s, npct='both', digits=3, middle.bold=TRUE, prmsd=TRUE)
```

The HTML file is perfect.  `pandoc` (used by `Quarto`) rendered the `.docx` table quite well, just not respecting font size changes and the `middle.bold` argument to put the median in a larger, bold, font.

The math rendered from `summaryM` output uses HTML Greek characters, subscripts, superscripts, and font size changes.  Better output would have been achieved by using the `mk()` approach except for font size.

Here's an example from an `htmlTable` package [vignette](https://cran.r-project.org/web/packages/htmlTable/vignettes/complex_tables.html).

```{r}
require(htmlTable)
output <-
  matrix(paste("Content", LETTERS[1:16]),
         ncol = 4, byrow = TRUE)

output |>
  htmlTable(header =  paste(c("1st", "2nd", "3rd", "4th"), "header"),
            rnames = paste(c("1st", "2nd", "3rd", "4th"), "row"),
            rgroup = c("Group A", "Group B"),
            n.rgroup = c(2, 2),
            cgroup = c("Cgroup 1", "Cgroup 2&dagger;"),
            n.cgroup = c(2, 2),
            caption = "Basic table with both column spanners (groups) and row groups",
            tfoot = "&dagger; A table footer commment")
```

Here's a more advanced one from [here](https://cran.r-project.org/web/packages/htmlTable/vignettes/general.html).

```{r}
mx <- matrix(ncol = 6, nrow = 8)
rownames(mx) <- paste(c("1st", "2nd",
                        "3rd",
                        paste0(4:8, "th")),
                      "row")
colnames(mx) <- paste(c("1st", "2nd",
                        "3rd", 
                        paste0(4:6, "th")),
                      "hdr")

for (nr in 1:nrow(mx)) {
  for (nc in 1:ncol(mx)) {
    mx[nr, nc] <-
      paste0(nr, ":", nc)
  }
}
rgroup <- c(paste("Group", LETTERS[1:2]), "")
attr(rgroup, "add") <- list(`2` = "More")
mx |>
  addHtmlTableStyle(align = "rr|r",
                    align.header = "cc|c",
                    spacer.celltype = "double_cell",
                    col.columns = c(rep("none", 2),
                                    rep("#F5FBFF", 4)),
                    col.rgroup = c("none", "#F7F7F7"),
                    css.cell = "padding-left: .5em; padding-right: .2em;",
                    css.header = "font-weight: normal") |> 
  htmlTable(rgroup = rgroup,
            n.rgroup = c(2,4),
            tspanner = paste("Spanner", LETTERS[1:2]),
            n.tspanner = c(1),
            cgroup = list(c("", "Column spanners"),
                          c("", "Cgroup 1", "Cgroup 2&dagger;")),
            n.cgroup = list(c(1,5),
                            c(2,2,2)),
            caption = "A table with column spanners, row groups, and zebra striping",
            tfoot = "&dagger; A table footer commment",
            cspan.rgroup = 2)
```

The Word result isn't perfect, but not bad.

## Other R Packages for Table Making

The `kableExtra` package will not work for `docx` output.  Try `gt` using an example from [here](https://gt.rstudio.com/articles/gt.html). [Sometimes adding `prefer-html: true` in the `yaml` header will make simple html tables render properly in Word.]{.aside}

```{r}
require(gt)
d <- airquality[1:10,]
d$Year <- 1973

gt(d) |>
  tab_header(
    title = "New York Air Quality Measurements",
    subtitle = "Daily measurements in New York City (May 1-10, 1973)"
  ) |>
  tab_spanner(
    label = "Time",
    columns = c(Year, Month, Day)
  ) |>
  tab_spanner(
    label = "Measurement",
    columns = c(Ozone, Solar.R, Wind, Temp)
  ) |>
  cols_move_to_start(
    columns = c(Year, Month, Day)
  ) |>
  cols_label(
    Ozone   = md("Ozone,<br>_ppbV_"),
    Solar.R = md("Solar R.,<br>$$\\text{cal}/m^2$$"),
    Wind    = md("Wind,<br>mph"),
    Temp    = md("Temp,<br>$$^{\\circ}F$$")
  )
```

Math expressions rendered fine in HTML but not in Word.

## `rms` Package Model Output Example

Here I fit an ordinal regression model on a continuous response variable using the `orm` function in `rms`, the use the `orm` print method.  With `options(prTYpe='html')` in effect the results are rendered in HTML.

```{r}
require(rms)
set.seed(1)
x <- runif(20)
y <- runif(20)
f <- orm(y ~ x)
f
```

The Word result is excellent except for loss of the long overbar over $|\Pr(Y \geq \text{median}) - \frac{1}{2}|$ and the coefficient table header being repeated.

