# pcb-rnd - user manual

## 7.3 Export plugins

### 7.3.3 export_bom

Export_bom is a configurable template based export plugin that prints the BoM (Bill of Materials) list in a text file. The plugin classifies subcircuits by a templatable ID and count how many instances of each ID has on the board. The output contains an optional file header, then an optional block (typically a single line) for each unique ID and an optional file footer.

In pseudo-code:

    print header_template
    foreach subc in subcircuits {
    	id = template_render(subc, sort_id_template)
    	items[id]++
    }
    sort(items[] by id)
    foreach i in items[] {
    	print item_template_for_i
    }
    print footer_template

#### 7.3.3.1 Template configuration

Each bom export format has an user assigned NAME (which is the short name of the format). There is a list of strings in the config tree under plugins/export_xy/templates; each item is named as NAME.something where something is:

- NAME.name: the long name of the format (as shown on the UI); mandatory
- NAME.header: header template, printed once when the output file is opened; optional
- NAME.footer: footer template, printed once when the output file is finished; optional
- NAME.sort_id: used to render the "ID" string for each subcircuit; two subcircuits with matched ID are taken as the same type of component and is counted as a repetion (one item group); at the end items are alphabetically sorted by this ID
- NAME.item: renders an output block (typically a single line) for an item group
- NAME.footer: terminal template, printed once for each terminal within each subcircuit; optional
- NAME.needs_escape: list all characters (as a string) that require escaping when printed with the "escape." prefix (see below)
- NAME.escape: if specified, the first character of this string is used as the escape character; if not specified, offending characters are not escaped but replaced with an underscore
- NAME.skip_if_empty: if specified, for each item to be added the template is rendered and if the result is empty, the item is ignored
- NAME.skip_if_nonempty: if specified, for each item to be added the template is rendered and if the result is not empty, the item is ignored

Templates are text strings; they are printed as is, keeping all newlines and whitespace. Portions in between % signs are substituted, depending on the context.

#### 7.3.3.2. Substitution keywords

keyword | description
--- | ---
%UTC% | current date and time in UTC
%author% | board author
%title% | board title
%count% | integer value, number of subcircuits in the current item group
%subc.a.KEY% | take a subcircuit (randomly) from the current item group and print its attribute value of the attribute whose name matches KEY; print empty string for non-existing attributes (but this can be controlled by the | suffix operator)
%subc.prefix% | print the sequence of left side alhpanumeric characters of subc.a.refdes; e.g. "R" for "R14" and "CONN" for "CONN1"; typically sort_id starts with this so that the output us sorted by "component type" (as deduced from refdes prefix) first

Any of these may get an escape. prefix, , e.g. %escape.author% will print the author with characters escaped. That means the resulting string is checked for needs_escape character and are escaped using the escape character. For example if the template contains:

    value="%subc.a.value%"

and needs_escape contains the double quote character and escape is a backslash and the subc's value attribute is 1/4" bolt, the following string is printed:

    value="1/4\" bolt"

Or if escape is not specified:

    value="1/4_ bolt"

Any substitution (e.g. "%foo%") may get an optional suffix operator:

%foo|unk% | same as %foo% but print "unk" if foo evaluated to empty
%foo?yes% | same as %foo% but print "yes" if the value of foo represents true, "n/a" otherwise
%foo?yes:nope% | same as %foo% but print "yes" if the value of foo represents true, "nope" otherwise

For example %subc.a.hand_solder?hand solder:reflow% will look at the valueof the subcircuit's hand_solder attribute; if it's true, yes, on or 1, "hand solder" is printed, else "reflow" is printed.

#### 7.3.3.3. Notes on sort_id

When subcircuits are first iterated, they are sorted into item groups by their sort_id template. For each item group, only one subcircuit is remembered, and only one block of info is printed.

In practice this means:

- sort_id affects which subcircuits are counted as one group
- sort_id determines the order of output
- sort_id shall contain every subcircuit attribute the item template is going to print

The last is a requirement because if there is an attribute, e.g. foo, and there are two subcircuits with different foo values and sort_id does not contain %subc.a.foo%, the two subcircuits may end up in the same item group. Then if item contains %subc.a.foo%, it can print only one value, so it will choose one of the two randomly.

However if %subc.a.foo% is on the sort_id template, the two subcircuits will yield different ID which means they never end up in the same item group. This also means any item group will have only one value for subc.a.foo in this case, so printing %subc.a.foo% from item will be deterministic.