davidgohel / flextable

table farming
https://ardata-fr.github.io/flextable-book/
554 stars 79 forks source link

Specifying positions of tabulation marks (decimal, left, right) in a table cell. An XML work... #549

Closed Generalized closed 6 months ago

Generalized commented 1 year ago

Hello @davidgohel !

I'm looking for a way to specify the positions of tabulation marks in table cell. This helps to organize the content, especially in clinical tables and align numbers properly.

It can be easily done by using decimal and ordinary tabulation marks: obraz

The sequence, that adds the tab specification is as follows:

<w:pPr>
              <w:tabs>
                <w:tab w:val="decimal" w:pos="564"/>
                <w:tab w:val="decimal" w:pos="1260"/>
              </w:tabs>
</w:pPr>

But then the code makes my head aching. It seems that Word splits the decimal numbers into parts by using the dot (or culture-specific?) separator and puts the numbers separately. The XML from the ZIPped DOCx (content.xml) is horribly long to paste it here, so let me just paste the document itself:

tab_examples.docx

I was able to add the tab specification into the main document using the body_add_xml():

x <- officer::body_add_xml(x, '<w:pPr>  
  <w:tabs>  
    <w:tab w:val="left" w:pos="2160" />   
    <w:tab w:val="left" w:pos="5040" />   
  </w:tabs>  
</w:pPr>', pos="before")

It threw a warning, but worked well:

Warning messages:
1: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w on pPr is not defined [201]
2: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w on tabs is not defined [201]
3: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w for val on tab is not defined [201]
4: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w for pos on tab is not defined [201]
5: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w on tab is not defined [201]
6: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w for val on tab is not defined [201]
7: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w for pos on tab is not defined [201]
8: In read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html,  :
  Namespace prefix w on tab is not defined [201]

I thought something similar could be done on the level of table cells, the same we can specify the other cell-level properties, like margins. For example through a list: list(c(tab_type = "left", position=xxx), c(tab_type = "decimal", position = xxxx)) or list (tab_type = c("left", "decimal", "decimal", "right"), position = c(22.2,333.3,444.4,555)).

This would facilitate creating clinical tables a lot, as we very often combine descriptive statistics together to save space in lengthy tables (sometimes spanning multiple pages!) and to make the numbers easier to read.

davidgohel commented 1 year ago

hello, this is related or a duplicate of #278

The problem is not how to do it but what is the API that should be implemented. Probably a new function as_tab().

It will take times as I can't dedicate time on it for now

davidgohel commented 7 months ago

Hello @Generalized

You can try the new dev version of flextable

# remotes::install_github("davidgohel/officer")
# remotes::install_github("davidgohel/flextable")

z <- data.frame(col1 = c(9999.099, 99.999, 9.0, 0.9))
set_flextable_defaults(big.mark = "")
ts <- fp_tabs(
  fp_tab(pos = .4, style = "decimal"),
  fp_tab(pos = 1.2, style = "decimal")
)

zz <- flextable(z) |>
  align(align = "center", part = "all") |> 
  width(width = 3) |>
  prepend_chunks(j = 1, as_chunk("\t")) |> 
  tab_settings(j = 1, value = ts)

print(zz, preview = "docx")
Capture d’écran 2024-02-23 à 19 00 23
davidgohel commented 6 months ago

I am closing the issue, let me know if it needs to be reopened

github-actions[bot] commented 3 weeks ago

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue and link to this old issue if necessary.