Word renderer#
The WordRenderer turns a calculation into a Word document (.docx) whose equations
are native Word equations, the kind Word’s own equation editor makes. Click into any
value or symbol in Word to edit it. Fonts and sizes come from the document’s styles, so
every equation matches the text around it.
Installing#
The renderer builds documents with python-docx, an optional dependency:
$ pip install "handcalcs[word]"
Usage#
from handcalcs import HandCalcs
from handcalcs.renderers import WordRenderer
source = '''
## Roots of a quadratic
from math import sqrt
a = 2; b = -7; c_0 = 3
x_1 = (-b + sqrt(b**2 - 4*a*c_0)) / (2*a) # larger root
'''
HandCalcs(WordRenderer())(source, destination="quadratic.docx")
With destination=, the document is saved there and its Path is returned. Without it,
the renderer returns a python-docx
Document: call
document.save(path) yourself, or keep adding to it with python-docx first. The
renderer’s filepath= option saves every render it makes, wherever it is called from.
This works from a plain .py script or any Python program, with no Jupyter or export
step. Pass a pathlib.Path to render a whole file:
HandCalcs(WordRenderer())(Path("calc.py"), destination="calc.docx").
Layout#
handcalcs |
Word |
|---|---|
a run of calc lines |
one equation, flush left, its rows aligned on the first |
a params line ( |
a borderless table, one equation per cell, so the grid keeps its columns |
|
a paragraph in the |
comment lines |
a text paragraph |
an import |
the import’s source in the |
|
a text paragraph with the condition as an inline equation: “Since (a > 1) → (2 > 1) is True:” |
a nested block |
indented 0.5” per level |
an inline comment |
normal text after the equation; on its own row when the line shows substitutions |
a |
extra rows in the same aligned equation |
Names follow the shared naming rules:
subscripts, Greek letters, accents and the symbols option look the same as in the other
renderers. A single letter is italic, as in print; a word (max, Rd) is upright and
stays one run, so you can edit it as one word in Word.
Choosing a layout for Google Docs and LibreOffice#
Word aligns the rows of a calc on their = signs with an equation array. Google Docs
and LibreOffice don’t show equation arrays properly: Google Docs runs the rows together
on one line, and LibreOffice draws the alignment marks as stray symbols. For a document
headed there, use the "lines" layout. Each row becomes an equation of its own (no =
alignment), and rows that continue the one above are indented a little:
WordRenderer(filepath="calc.docx", layout="lines")
|
Looks right in |
Rows |
|---|---|---|
|
Word |
one equation per run of calcs, aligned on |
|
Word, Google Docs, LibreOffice |
one equation per row, not aligned |
A comment command changes the layout for the calcs that follow it:
# hc: layout = "lines"
Templates and reports#
A company template. template= starts each document from a .docx. Its styles, page
setup, headers and footers and any content already in it (a title block, say) are kept,
and the calculation is added after that content:
WordRenderer(template="company.docx", filepath="beam.docx")
Several calcs in one report. document= appends to a python-docx Document you
already have, so one report can hold many calculations with your own text between them:
import docx
from handcalcs import HandCalcs
from handcalcs.renderers import WordRenderer
report = docx.Document("company.docx")
report.add_heading("Beam design", level=1)
calc = HandCalcs(renderer=WordRenderer(document=report))
calc(beam_source)
report.add_paragraph("The column carries the beam reaction.")
calc(column_source)
report.save("report.docx")
Give template= or document=, not both.
Styles#
The renderer uses the document’s Normal and Heading 1-Heading 9 styles, and adds
two of its own when the document doesn’t define them:
Style |
Kind |
Used for |
Default |
|---|---|---|---|
|
paragraph, based on |
paragraphs holding equations |
6 pt before and after a group, none between its rows |
|
character |
imports |
Consolas |
To restyle them, define styles with these names in your template. Equations take their
paragraph’s font size, so a larger HC Math gives larger equations. If a template has
no Heading N style, that heading becomes a bold paragraph and handcalcs warns you.
Options#
WordRenderer(
filepath=None, # also save every render here
layout="aligned", # or "lines"
template=None, # a .docx to start each document from
document=None, # a python-docx Document to append to
)
An unknown layout or a missing template raises an error when the renderer is created.
Units#
pint and
forallpeople values show their number as
math and their unit as text: 2.8125 kN·m. The number takes the format code. A pint unit
is written in the registry’s format, so set ureg.formatter.default_format = "~P" for
short unit symbols (mm² rather than millimeter ** 2).
In Jupyter#
%%render has no Word display, so the Word renderer isn’t a jupyter_renderer. To make
a document from a notebook, put the calculation in a Python cell:
document = HandCalcs(renderer=WordRenderer(filepath="calc.docx"))(source)
To convert rendered Markdown instead, pandoc turns the Markdown renderer’s output into Word equations too:
$ pandoc calc.md -o calc.docx
pandoc centres every equation, splits upright words into single letters and flattens params grids into one row, so the Word renderer gives a closer match to handcalcs’ layout.
Notes#
A list or tuple longer than 10 items shows its first and last 3 items around “…”, as in every renderer (the
max_itemsandedge_itemssettings). An equation row can’t break across lines, so use a line continuation (\) to break a long equation yourself.HandCalcs(renderer=WordRenderer()).demo()renders the general handcalcs demo as a document.
Source#
src/handcalcs/renderers/word/renderer.py: the renderer, its options and the tree walk
src/handcalcs/renderers/word/handlers.py: node handlers that return OMML fragments
src/handcalcs/renderers/word/omml.py: builders for Office Math Markup (OMML)
src/handcalcs/renderers/word/document.py: writing paragraphs, equations and tables
The Word renderer’s handlers return OMML strings, Word’s math markup, the way the
LaTeX renderer’s return LaTeX, so the base renderer’s line machinery works on them
unchanged. Only complete() builds the document. See
Example: a non-text renderer.
Comment commands#
command
effect in Word
-f CODEformats calculated values, as in every renderer
-mputs the symbolic, numeric and result columns on rows of their own
-binserts an empty paragraph
-ileaves the line out
-h,;a params table
layout = "lines"one equation per row for the calcs that follow