Created
February 7, 2017 16:05
-
-
Save pwuertz/a8af404a975638371cd1165dec1c3872 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
import re | |
import csv | |
import collections | |
import xml.etree.ElementTree | |
def natural_sort(l): | |
""" | |
Natural sort for strings containing numbers | |
""" | |
convert = lambda text: int(text) if text.isdigit() else text.lower() | |
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] | |
return sorted(l, key=alphanum_key) | |
def generate_bom_table(fname): | |
""" | |
Generate BOM from KiCad XML file. | |
""" | |
xml_root = xml.etree.ElementTree.parse(fname).getroot() | |
# xml_root = xml.etree.ElementTree.fromstring(s) | |
# first pass, get field names | |
field_names = set() | |
for field in xml_root.findall("./components/comp/fields/field"): | |
field_names.add(field.get("name")) | |
field_names = list(field_names) | |
# second pass, group parts with identical (value, footprint, fields...) | |
part_groups = collections.OrderedDict() | |
for comp in xml_root.findall("./components/comp"): | |
# build attribute list for comp | |
fields = dict([(f.get("name"), f.text) for f in comp.findall("fields/field")]) | |
fields_ordered = [fields.get(n, "") for n in field_names] | |
attr = tuple([comp.findtext("value"), comp.findtext("footprint")] + fields_ordered) | |
# store to part groups and refs | |
reference = comp.get("ref") | |
group_refs = part_groups.get(attr, []) | |
group_refs.append(reference) | |
part_groups[attr] = group_refs | |
bom_header = ["Qty", "Value", "Footprint", "Refs"] + field_names | |
bom_table = [] | |
for attr, refs in part_groups.items(): | |
value, footprint = attr[:2] | |
fields = list(attr[2:]) | |
refs_str = ", ".join(natural_sort(refs)) | |
line = tuple([len(refs), value, footprint, refs_str] + fields) | |
bom_table.append(line) | |
return bom_table, bom_header | |
if __name__ == "__main__": | |
import argparse | |
parser = argparse.ArgumentParser(description='KiCad BOM export') | |
parser.add_argument('file', type=str, help="KiCad BOM XML") | |
args = parser.parse_args() | |
# generate BOM table | |
bom_table, bom_header = generate_bom_table(args.file) | |
# write BOM table to CSV | |
csv_writer = csv.writer(sys.stdout) | |
csv_writer.writerow(bom_header) | |
for row in bom_table: | |
csv_writer.writerow(row) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment