#!/usr/bin/env python from csv import DictReader import re input_file = "schematics_r2.0_breakdown.csv" output_file = "partial_bom_r2.0_modelb.txt" # read in the data we need from the CSV file bom = dict() for datarow in DictReader(open(input_file, 'r')): if datarow['Type'] == "component" and datarow['A/B/NF'] in ("", "B"): # just components for 'Model B' part_type = datarow['ComponentType'] if part_type not in bom: bom[part_type] = dict() # every component has at least a Value or PartNumber (some have both) if datarow['Value']: part_index = datarow['Value'] elif datarow['PartNumber']: part_index = datarow['PartNumber'] if part_index not in bom[part_type]: bom[part_type][part_index] = {'Value': datarow['Value'], 'PartNumber': datarow['PartNumber'], 'Quantity': 0} bom[part_type][part_index]['Quantity'] += 1 def sortvalue(strvalue): # 'flatten' values to decimal units so they can be numerically compared m = re.match("^(\d+)(u|p|n|uF|M|v|K|R)(\d+)?$", strvalue) if m: value = int(m.group(1)) if m.group(3): value += int(m.group(3)) / 10.0 if m.group(2) == 'M': value *= 10**6 elif m.group(2) == 'K': value *= 10**3 elif m.group(2) in ('u', 'uF'): value /= 10.0**6 elif m.group(2) == 'p': value /= 10.0**9 elif m.group(2) == 'n': value /= 10.0**12 return value else: return strvalue # output the calculated data in a wiki-format table display_fields = ('PartNumber', 'Value', 'Quantity') bomfile = open(output_file, 'w') bomfile.write("{| border=1\n! ComponentType") for field in display_fields: bomfile.write(" !! %s" % field) bomfile.write("\n") total = 0 for type in sorted(bom): section = '' subtotal = 0 for component in sorted(bom[type], key=sortvalue): section += "|-\n| %s" % type for field in display_fields: section += " || %s" % str(bom[type][component][field]) section += "\n" subtotal += bom[type][component]['Quantity'] bomfile.write("|-\n! colspan=3 align=left | %s !! %d\n" % (type, subtotal)) bomfile.write(section) total += subtotal bomfile.write("|-\n! colspan=3 align=left | %s !! %d\n" % ('Total', total)) bomfile.write("|}\n") bomfile.close()