* Added option to hide file headers
* Changed output to be a positional argument (required) * Added blank cell coloring to HTML output
This commit is contained in:
parent
13ad8dbd3c
commit
159f54347c
|
|
@ -36,10 +36,11 @@ def WriteCSV(filename, groups, net, headings, prefs):
|
||||||
|
|
||||||
writer = csv.writer(f, delimiter=delimiter, lineterminator="\n")
|
writer = csv.writer(f, delimiter=delimiter, lineterminator="\n")
|
||||||
|
|
||||||
if prefs.numberRows:
|
if not prefs.hideHeaders:
|
||||||
writer.writerow(["Component"] + headings)
|
if prefs.numberRows:
|
||||||
else:
|
writer.writerow(["Component"] + headings)
|
||||||
writer.writerow(headings)
|
else:
|
||||||
|
writer.writerow(headings)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
rowCount = 1
|
rowCount = 1
|
||||||
|
|
@ -63,19 +64,20 @@ def WriteCSV(filename, groups, net, headings, prefs):
|
||||||
|
|
||||||
rowCount += 1
|
rowCount += 1
|
||||||
|
|
||||||
#blank rows
|
if not prefs.hideHeaders:
|
||||||
for i in range(5):
|
#blank rows
|
||||||
writer.writerow([])
|
for i in range(5):
|
||||||
|
writer.writerow([])
|
||||||
writer.writerow(["Component Groups:",nGroups])
|
|
||||||
writer.writerow(["Component Count:",nTotal])
|
writer.writerow(["Component Groups:",nGroups])
|
||||||
writer.writerow(["Fitted Components:", nFitted])
|
writer.writerow(["Component Count:",nTotal])
|
||||||
writer.writerow(["Number of PCBs:",prefs.boards])
|
writer.writerow(["Fitted Components:", nFitted])
|
||||||
writer.writerow(["Total components:", nBuild])
|
writer.writerow(["Number of PCBs:",prefs.boards])
|
||||||
writer.writerow(["Schematic Version:",net.getVersion()])
|
writer.writerow(["Total components:", nBuild])
|
||||||
writer.writerow(["Schematic Date:",net.getSheetDate()])
|
writer.writerow(["Schematic Version:",net.getVersion()])
|
||||||
writer.writerow(["BoM Date:",net.getDate()])
|
writer.writerow(["Schematic Date:",net.getSheetDate()])
|
||||||
writer.writerow(["Schematic Source:",net.getSource()])
|
writer.writerow(["BoM Date:",net.getDate()])
|
||||||
writer.writerow(["KiCad Version:",net.getTool()])
|
writer.writerow(["Schematic Source:",net.getSource()])
|
||||||
|
writer.writerow(["KiCad Version:",net.getTool()])
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
@ -6,6 +6,7 @@ import os
|
||||||
BG_GEN = "#E6FFEE"
|
BG_GEN = "#E6FFEE"
|
||||||
BG_KICAD = "#FFE6B3"
|
BG_KICAD = "#FFE6B3"
|
||||||
BG_USER = "#E6F9FF"
|
BG_USER = "#E6F9FF"
|
||||||
|
BG_EMPTY = "#FF8080"
|
||||||
|
|
||||||
#return a background color for a given column title
|
#return a background color for a given column title
|
||||||
def bgColor(col):
|
def bgColor(col):
|
||||||
|
|
@ -58,24 +59,26 @@ def WriteHTML(filename, groups, net, headings, prefs):
|
||||||
|
|
||||||
|
|
||||||
#PCB info
|
#PCB info
|
||||||
html.write("<h2>KiBoM PCB Bill of Materials</h2>\n")
|
if not prefs.hideHeaders:
|
||||||
html.write('<table border="1">\n')
|
html.write("<h2>KiBoM PCB Bill of Materials</h2>\n")
|
||||||
html.write("<tr><td>Source File</td><td>{source}</td></tr>\n".format(source=net.getSource()))
|
html.write('<table border="1">\n')
|
||||||
html.write("<tr><td>BoM Date</td><td>{date}</td></tr>\n".format(date=net.getDate()))
|
html.write("<tr><td>Source File</td><td>{source}</td></tr>\n".format(source=net.getSource()))
|
||||||
html.write("<tr><td>Schematic Version</td><td>{version}</td></tr>\n".format(version=net.getVersion()))
|
html.write("<tr><td>BoM Date</td><td>{date}</td></tr>\n".format(date=net.getDate()))
|
||||||
html.write("<tr><td>Schematic Date</td><td>{date}</td></tr>\n".format(date=net.getSheetDate()))
|
html.write("<tr><td>Schematic Version</td><td>{version}</td></tr>\n".format(version=net.getVersion()))
|
||||||
html.write("<tr><td>KiCad Version</td><td>{version}</td></tr>\n".format(version=net.getTool()))
|
html.write("<tr><td>Schematic Date</td><td>{date}</td></tr>\n".format(date=net.getSheetDate()))
|
||||||
html.write("<tr><td>Component Groups</td><td>{n}</td></tr>\n".format(n=nGroups))
|
html.write("<tr><td>KiCad Version</td><td>{version}</td></tr>\n".format(version=net.getTool()))
|
||||||
html.write("<tr><td>Component Count (per PCB)</td><td>{n}</td></tr>\n".format(n=nTotal))
|
html.write("<tr><td>Component Groups</td><td>{n}</td></tr>\n".format(n=nGroups))
|
||||||
html.write("<tr><td>Fitted Components (per PCB)</td><td>{n}</td></tr>\n".format(n=nFitted))
|
html.write("<tr><td>Component Count (per PCB)</td><td>{n}</td></tr>\n".format(n=nTotal))
|
||||||
html.write("<tr><td>Number of PCBs</td><td>{n}</td></tr>\n".format(n=prefs.boards))
|
html.write("<tr><td>Fitted Components (per PCB)</td><td>{n}</td></tr>\n".format(n=nFitted))
|
||||||
html.write("<tr><td>Total Component Count<br>(for {n} PCBs)</td><td>{t}</td></tr>\n".format(n=prefs.boards, t=nBuild))
|
html.write("<tr><td>Number of PCBs</td><td>{n}</td></tr>\n".format(n=prefs.boards))
|
||||||
html.write("</table>\n")
|
html.write("<tr><td>Total Component Count<br>(for {n} PCBs)</td><td>{t}</td></tr>\n".format(n=prefs.boards, t=nBuild))
|
||||||
html.write("<br>\n")
|
html.write("</table>\n")
|
||||||
html.write("<h2>Component Groups</h2>\n")
|
html.write("<br>\n")
|
||||||
html.write('<p style="background-color: {bg}">Kicad Fields (default)</p>\n'.format(bg=BG_KICAD))
|
html.write("<h2>Component Groups</h2>\n")
|
||||||
html.write('<p style="background-color: {bg}">Generated Fields</p>\n'.format(bg=BG_GEN))
|
html.write('<p style="background-color: {bg}">Kicad Fields (default)</p>\n'.format(bg=BG_KICAD))
|
||||||
html.write('<p style="background-color: {bg}">User Fields</p>\n'.format(bg=BG_USER))
|
html.write('<p style="background-color: {bg}">Generated Fields</p>\n'.format(bg=BG_GEN))
|
||||||
|
html.write('<p style="background-color: {bg}">User Fields</p>\n'.format(bg=BG_USER))
|
||||||
|
html.write('<p style="background-color: {bg}">Empty Fields</p>\n'.format(bg=BG_EMPTY))
|
||||||
|
|
||||||
#component groups
|
#component groups
|
||||||
html.write('<table border="1">\n')
|
html.write('<table border="1">\n')
|
||||||
|
|
@ -109,7 +112,11 @@ def WriteHTML(filename, groups, net, headings, prefs):
|
||||||
html.write('\t<td align="center">{n}</td>\n'.format(n=rowCount))
|
html.write('\t<td align="center">{n}</td>\n'.format(n=rowCount))
|
||||||
|
|
||||||
for n, r in enumerate(row):
|
for n, r in enumerate(row):
|
||||||
bg = bgColor(headings[n])
|
|
||||||
|
if len(r) == 0:
|
||||||
|
bg = BG_EMPTY
|
||||||
|
else:
|
||||||
|
bg = bgColor(headings[n])
|
||||||
|
|
||||||
html.write('\t<td align="center"{bg}>{val}</td>\n'.format(bg=' bgcolor={c}'.format(c=bg) if bg else '', val=link(r)))
|
html.write('\t<td align="center"{bg}>{val}</td>\n'.format(bg=' bgcolor={c}'.format(c=bg) if bg else '', val=link(r)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ class BomPref:
|
||||||
self.useRegex = True #Test various columns with regex
|
self.useRegex = True #Test various columns with regex
|
||||||
self.compareFootprints = True #test footprints when comparing components
|
self.compareFootprints = True #test footprints when comparing components
|
||||||
self.boards = 1
|
self.boards = 1
|
||||||
|
self.hideHeaders = False
|
||||||
self.verbose = False #by default, is not verbose
|
self.verbose = False #by default, is not verbose
|
||||||
self.configurations = [] #list of various configurations
|
self.configurations = [] #list of various configurations
|
||||||
|
|
||||||
|
|
|
||||||
56
KiBOM_CLI.py
56
KiBOM_CLI.py
|
|
@ -31,9 +31,10 @@ def say(*arg):
|
||||||
parser = argparse.ArgumentParser(description="KiBOM Bill of Materials generator script")
|
parser = argparse.ArgumentParser(description="KiBOM Bill of Materials generator script")
|
||||||
|
|
||||||
parser.add_argument("netlist", help='xml netlist file. Use "%%I" when running from within KiCad')
|
parser.add_argument("netlist", help='xml netlist file. Use "%%I" when running from within KiCad')
|
||||||
parser.add_argument("--output", "-o", help='BoM output file name.\nUse "%%O" when running from within KiCad to use the default output name (csv file).\nFor e.g. HTML output, use "%%O.html"\r\nIf output file is unspecified, default output filename (csv format) will be used', default=None)
|
parser.add_argument("output", default="", help='BoM output file name.\nUse "%%O" when running from within KiCad to use the default output name (csv file).\nFor e.g. HTML output, use "%%O.html"')
|
||||||
parser.add_argument("--boards", "-b", help="Number of boards to build (default = 1)", type=int, default=1)
|
parser.add_argument("-b", "--boards", help="Number of boards to build (default = 1)", type=int, default=1)
|
||||||
parser.add_argument("-v", "--verbose", help="Enable verbose output", action='count')
|
parser.add_argument("-v", "--verbose", help="Enable verbose output", action='count')
|
||||||
|
parser.add_argument("-n", "--noheader", help="Do not generate file headers; data only.", action='count')
|
||||||
parser.add_argument("--cfg", help="BoM config file (script will try to use 'bom.ini' if not specified here)")
|
parser.add_argument("--cfg", help="BoM config file (script will try to use 'bom.ini' if not specified here)")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
@ -48,25 +49,6 @@ verbose = args.verbose is not None
|
||||||
input_file = os.path.abspath(input_file)
|
input_file = os.path.abspath(input_file)
|
||||||
|
|
||||||
say("Input:",input_file)
|
say("Input:",input_file)
|
||||||
|
|
||||||
output_file = args.output
|
|
||||||
|
|
||||||
if output_file is None:
|
|
||||||
output_file = input_file.replace(".xml","_bom.csv")
|
|
||||||
|
|
||||||
#enfore a proper extension
|
|
||||||
valid = False
|
|
||||||
extensions = [".xml",".csv",".txt",".tsv",".html"]
|
|
||||||
for e in extensions:
|
|
||||||
if output_file.endswith(e):
|
|
||||||
valid = True
|
|
||||||
break
|
|
||||||
if not valid:
|
|
||||||
close("Extension must be one of",extensions)
|
|
||||||
|
|
||||||
output_file = os.path.abspath(output_file)
|
|
||||||
|
|
||||||
say("Output:",output_file)
|
|
||||||
|
|
||||||
#look for a config file!
|
#look for a config file!
|
||||||
#bom.ini by default
|
#bom.ini by default
|
||||||
|
|
@ -83,6 +65,8 @@ pref = BomPref()
|
||||||
#pass various command-line options through
|
#pass various command-line options through
|
||||||
pref.verbose = verbose
|
pref.verbose = verbose
|
||||||
pref.boards = args.boards
|
pref.boards = args.boards
|
||||||
|
if args.noheader:
|
||||||
|
pref.hideHeaders = True
|
||||||
|
|
||||||
if os.path.exists(config_file):
|
if os.path.exists(config_file):
|
||||||
pref.Read(config_file)
|
pref.Read(config_file)
|
||||||
|
|
@ -115,14 +99,42 @@ for g in groups:
|
||||||
for f in g.fields:
|
for f in g.fields:
|
||||||
columns.AddColumn(f)
|
columns.AddColumn(f)
|
||||||
|
|
||||||
|
#don't add 'boards' column if only one board is specified
|
||||||
if pref.boards <= 1:
|
if pref.boards <= 1:
|
||||||
columns.RemoveColumn(ColumnList.COL_GRP_BUILD_QUANTITY)
|
columns.RemoveColumn(ColumnList.COL_GRP_BUILD_QUANTITY)
|
||||||
say("Removing:",ColumnList.COL_GRP_BUILD_QUANTITY)
|
say("Removing:",ColumnList.COL_GRP_BUILD_QUANTITY)
|
||||||
|
|
||||||
|
#todo
|
||||||
|
write_to_bom = True
|
||||||
|
result = True
|
||||||
|
|
||||||
#Finally, write the BoM out to file
|
#Finally, write the BoM out to file
|
||||||
result = WriteBoM(output_file, groups, net, columns.columns, pref)
|
if write_to_bom:
|
||||||
|
|
||||||
|
output_file = args.output
|
||||||
|
|
||||||
|
if output_file is None:
|
||||||
|
output_file = input_file.replace(".xml","_bom.csv")
|
||||||
|
|
||||||
|
#enfore a proper extension
|
||||||
|
valid = False
|
||||||
|
extensions = [".xml",".csv",".txt",".tsv",".html"]
|
||||||
|
for e in extensions:
|
||||||
|
if output_file.endswith(e):
|
||||||
|
valid = True
|
||||||
|
break
|
||||||
|
if not valid:
|
||||||
|
close("Extension must be one of",extensions)
|
||||||
|
|
||||||
|
output_file = os.path.abspath(output_file)
|
||||||
|
|
||||||
|
say("Output:",output_file)
|
||||||
|
|
||||||
|
result = WriteBoM(output_file, groups, net, columns.columns, pref)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue