2018-08-04 03:28:27 +01:00
|
|
|
# Bullets and Numbering
|
|
|
|
|
|
|
|
`docx` is quite flexible in its bullets and numbering system, allowing
|
|
|
|
the user great freedom in how bullets and numbers are to be styled and
|
|
|
|
displayed. E.g., numbers can be shown using Arabic numerals, roman
|
|
|
|
numerals, or even ordinal words ("one", "two", "three", ...). The
|
|
|
|
format also supports re-using bullets/numbering styles throughout the
|
|
|
|
document, so that different lists using the same style need not
|
|
|
|
redefine them.
|
|
|
|
|
|
|
|
Because of this flexibility, bullets and numbering in DOCX involves a
|
|
|
|
couple of moving pieces:
|
|
|
|
|
|
|
|
1. Document-level bullets/numbering definitions (abstract)
|
|
|
|
2. Document-level bullets/numbering definitions (concrete)
|
|
|
|
3. Paragraph-level bullets/numbering selection
|
|
|
|
|
|
|
|
## Document-level bullets/numbering definitions (abstract)
|
|
|
|
|
|
|
|
Every document contains a set of abstract bullets/numbering
|
|
|
|
definitions which define the formatting and layout of paragraphs using
|
|
|
|
those bullets/numbering. An abstract numbering system defines how
|
|
|
|
bullets/numbers are to be shown for lists, including any sublists that
|
|
|
|
may be used. Thus each abstract definition includes a series of
|
|
|
|
_levels_ which form a sequence starting at 0 indicating the top-level
|
2021-03-25 19:21:27 +03:00
|
|
|
list look and increasing from there to describe the sublists, then
|
2018-08-04 03:28:27 +01:00
|
|
|
sub-sublists, etc. Each level includes the following properties:
|
|
|
|
|
2019-03-07 15:32:16 +11:00
|
|
|
* **level**: This is its 0-based index in the definition stack
|
2018-08-04 03:28:27 +01:00
|
|
|
* **numberFormat**: This indicates how the bullet or number should be
|
|
|
|
generated. Options include `bullet` (meaning don't count), `decimal`
|
|
|
|
(arabic numerals), `upperRoman`, `lowerRoman`, `hex`, and many
|
|
|
|
more.
|
|
|
|
* **levelText**: This is a format string using the output of the
|
|
|
|
`numberFormat` function and generating a string to insert before
|
|
|
|
every item in the list. You may use `%1`, `%2`, ... to reference the
|
|
|
|
numbers from each numbering level before this one. Thus a level
|
|
|
|
text of `%d)` with a number format of `lowerLetter` would result in
|
|
|
|
the sequence "a)", "b)", ...
|
|
|
|
* and a few others, which you can see in the OXML spec section 17.9.6
|
|
|
|
|
2021-03-25 19:21:27 +03:00
|
|
|
## Document-level bullets/numbering definitions (concrete)
|
2018-08-04 03:28:27 +01:00
|
|
|
|
|
|
|
Concrete definitions are sort of like concrete subclasses of the
|
2021-03-25 19:21:27 +03:00
|
|
|
abstract definitions. They indicate their parent and are allowed to
|
2018-08-04 03:28:27 +01:00
|
|
|
override certain level definitions. Thus two lists that differ only in
|
|
|
|
how sub-sub-lists are to be displayed can share the same abstract
|
|
|
|
numbering definition and have slightly different concrete definitions.
|
|
|
|
|
|
|
|
## Paragraph-level bullets/numbering selection
|
|
|
|
|
|
|
|
In order to use a bullets/numbering definition (which must be
|
|
|
|
concrete), paragraphs need to select it, similar to applying a CSS
|
|
|
|
class to an element, using both the concrete numbering definition ID
|
|
|
|
and the level number that the paragraph should be at. Additionally, MS
|
|
|
|
Word and LibreOffice typically apply a "ListParagraph" style to
|
|
|
|
paragraphs that are being numbered.
|
|
|
|
|
|
|
|
## Using bullets/numbering in `docx`
|
|
|
|
|
|
|
|
`docx` includes a pre-defined bullet style which you can add to your
|
|
|
|
paragraphs using `para.bullets()`. If you require different bullet
|
|
|
|
styles or numbering of any kind, you'll have to use the
|
|
|
|
`docx.Numbering` class.
|
|
|
|
|
|
|
|
First you need to create a new numbering container class and use it to
|
2019-03-07 15:33:32 +11:00
|
|
|
create your abstract numbering style, define your levels, and create
|
|
|
|
your concrete numbering style:
|
2018-08-04 03:28:27 +01:00
|
|
|
|
2019-08-06 17:51:13 +01:00
|
|
|
```ts
|
2018-08-04 03:28:27 +01:00
|
|
|
const numbering = new docx.Numbering();
|
|
|
|
|
|
|
|
const abstractNum = numbering.createAbstractNumbering();
|
|
|
|
abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent(720, 260));
|
|
|
|
abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent(1440, 980));
|
|
|
|
abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent(2160, 1700));
|
|
|
|
|
2018-11-08 11:09:09 +01:00
|
|
|
const concrete = numbering.createConcreteNumbering(abstractNum);
|
2018-08-04 03:28:27 +01:00
|
|
|
```
|
|
|
|
|
2019-03-07 15:36:06 +11:00
|
|
|
You can then apply your concrete style to paragraphs using the
|
|
|
|
`setNumbering` method:
|
2018-08-04 03:28:27 +01:00
|
|
|
|
2019-08-06 17:51:13 +01:00
|
|
|
```ts
|
2018-08-04 03:28:27 +01:00
|
|
|
topLevelP.setNumbering(concrete, 0);
|
|
|
|
subP.setNumbering(concrete, 1);
|
|
|
|
subSubP.setNumbering(concrete, 2);
|
|
|
|
```
|