Skip to content

Commit

Permalink
commit Brian's BOM generation scripts so they don't get lost
Browse files Browse the repository at this point in the history
  • Loading branch information
liftoff-sr committed Oct 20, 2011
1 parent 15f0147 commit 4c06357
Show file tree
Hide file tree
Showing 9 changed files with 867 additions and 2 deletions.
7 changes: 5 additions & 2 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ Common
* Push file open semantics down to one of the base frame classes ( likely candidate is
WinEDA_BasicFrame ) so that file open behavior is consistent across all applications.

* Look over Brian's python BOM generation scripts, which are now in
scripts/python/ky and sort them out, and get something into the installation as well.
Code came from Brian in this posting's attachment, which is ky2.zip:
https://lists.launchpad.net/kicad-developers/msg06763.html
but is now in scripts/python/ky temporarily.


CvPCB
Expand Down Expand Up @@ -48,6 +53,4 @@ E6) Start initial work for changing component library file format to use Dick's
PCBNew
------

Dick:

* Use BOARD_ITEM::MenuIcon() in the onrightclick.cpp
38 changes: 38 additions & 0 deletions scripts/bom-in-python/ky/bom_example1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Tab delimited list (The same as std output) Ungrouped
#

# Import the KiCad python helper module and the csv formatter
import ky
import csv
import sys

# Generate an instance of a generic netlist, and load the netlist tree from
# the command line option. If the file doesn't exist, execution will stop
net = ky.netlist(sys.argv[1])

# Open a file to write to, if the file cannot be opened output to stdout
# instead
try:
f = open(sys.argv[2], 'w')
except IOError:
print >> sys.stderr, __file__, ":", e
f = stdout

# Create a new csv writer object to use as the output formatter, although we
# are created a tab delimited list instead!
out = csv.writer(f, delimiter='\t', quoting=csv.QUOTE_NONE)

# Output a field delimited header line
out.writerow(['Source:', net.getSource()])
out.writerow(['Date:', net.getDate()])
out.writerow(['Tool:', net.getTool()])
out.writerow(['Component Count:', len(net.components)])
out.writerow(['Ref', 'Value', 'Part', 'Documentation', 'Description', 'Vendor'])

# Output all of the component information
for c in net.components:
out.writerow([c.getRef(), c.getValue(), c.getLib() + "/" + c.getPart(),
c.getDatasheet(), c.getDescription(), c.getField("Vendor")])
38 changes: 38 additions & 0 deletions scripts/bom-in-python/ky/bom_example2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Ungrouped (One component per row) CSV output
#

# Import the KiCad python helper module
import ky
import csv
import sys

# Generate an instance of a generic netlist, and load the netlist tree from
# the command line option. If the file doesn't exist, execution will stop
net = ky.netlist(sys.argv[1])

# Open a file to write to, if the file cannot be opened output to stdout
# instead
try:
f = open(sys.argv[2], 'w')
except IOError:
print >> sys.stderr, __file__, ":", e
f = stdout

# Create a new csv writer object to use as the output formatter
out = csv.writer(f, delimiter=',', quotechar="\"", quoting=csv.QUOTE_ALL)

# Output a field delimited header line
out.writerow(['Source:', net.getSource()])
out.writerow(['Date:', net.getDate()])
out.writerow(['Tool:', net.getTool()])
out.writerow(['Component Count:', len(net.components)])
out.writerow(['Ref', 'Value', 'Footprint', 'Datasheet', 'Manufacturer', 'Vendor'])

# Output all of the component information (One component per row)
for c in net.components:
out.writerow([c.getRef(), c.getValue(), c.getFootprint(), c.getDatasheet(),
c.getField("Manufacturer"), c.getField("Vendor")])

51 changes: 51 additions & 0 deletions scripts/bom-in-python/ky/bom_example3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Sorted and Grouped CSV BOM
#

# Import the KiCad python helper module and the csv formatter
import ky
import csv
import sys

# Generate an instance of a generic netlist, and load the netlist tree from
# the command line option. If the file doesn't exist, execution will stop
net = ky.netlist(sys.argv[1])

# Open a file to write to, if the file cannot be opened output to stdout
# instead
try:
f = open(sys.argv[2], 'w')
except IOError:
print >> sys.stderr, __file__, ":", e
f = stdout

# Create a new csv writer object to use as the output formatter
out = csv.writer(f, delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL)

# Output a set of rows for a header providing general information
out.writerow(['Source:', net.getSource()])
out.writerow(['Date:', net.getDate()])
out.writerow(['Tool:', net.getTool()])
out.writerow(['Component Count:', len(net.components)])
out.writerow(['Ref', 'Qnty', 'Value', 'Part', 'Datasheet', 'Description', 'Vendor'])

# Get all of the components in groups of matching parts + values (see ky.py)
grouped = net.groupComponents()

# Output all of the component information
for group in grouped:
refs = ""

# Add the reference of every component in the group and keep a reference
# to the component so that the other data can be filled in once per group
for component in group:
refs += component.getRef() + ", "
c = component

# Fill in the component groups common data
out.writerow([refs, len(group), c.getValue(), c.getLib() + "/" + c.getPart(), c.getDatasheet(),
c.getDescription(), c.getField("Vendor")])


78 changes: 78 additions & 0 deletions scripts/bom-in-python/ky/bom_example4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Sorted and Grouped HTML BOM
#

# Import the KiCad python helper module and the csv formatter
import ky
import sys

# Start with a basic html template
html = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<h1><!--SOURCE--></h1>
<p><!--DATE--></p>
<p><!--TOOL--></p>
<p><!--COMPCOUNT--></p>
<table>
<!--TABLEROW-->
</table>
</body>
</html>
"""

# Generate an instance of a generic netlist, and load the netlist tree from
# the command line option. If the file doesn't exist, execution will stop
net = ky.netlist(sys.argv[1])

# Open a file to write to, if the file cannot be opened output to stdout
# instead
try:
f = open(sys.argv[2], 'w')
except IOError:
print >> sys.stderr, __file__, ":", e
f = stdout

# Output a set of rows for a header providing general information
html = html.replace('<!--SOURCE-->', net.getSource())
html = html.replace('<!--DATE-->', net.getDate())
html = html.replace('<!--TOOL-->', net.getTool())
html = html.replace('<!--COMPCOUNT-->', "<b>Component Count:</b>" + \
str(len(net.components)))

row = "<tr><th style='width:640px'>Ref</th>" + "<th>Qnty</th>"
row += "<th>Value</th>" + "<th>Part</th>" + "<th>Datasheet</th>"
row += "<th>Description</th>" + "<th>Vendor</th></tr>"

html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")

# Get all of the components in groups of matching parts + values (see ky.py)
grouped = net.groupComponents()

# Output all of the component information
for group in grouped:
refs = ""

# Add the reference of every component in the group and keep a reference
# to the component so that the other data can be filled in once per group
for component in group:
refs += component.getRef() + ", "
c = component

row = "<tr><td>" + refs +"</td><td>" + str(len(group))
row += "</td><td>" + c.getValue() + "</td><td>" + c.getLib() + "/"
row += c.getPart() + "</td><td>" + c.getDatasheet() + "</td><td>"
row += c.getDescription() + "</td><td>" + c.getField("Vendor")
row += "</td></tr>"

html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")

# Print the formatted html to the file
print >> f, html
113 changes: 113 additions & 0 deletions scripts/bom-in-python/ky/bom_example5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Sorted and Grouped HTML BOM with more advanced grouping
#

# Import the KiCad python helper module and the csv formatter
import ky
import sys

# Start with a basic html template
html = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>KiCad BOM Example 5</title>
</head>
<body>
<h1><!--SOURCE--></h1>
<p><!--DATE--></p>
<p><!--TOOL--></p>
<p><!--COMPCOUNT--></p>
<table>
<!--TABLEROW-->
</table>
</body>
</html>
"""

def myEqu(self, other):
"""myEqu is a more advanced equivalence function for components which is
used by component grouping. Normal operation is to group components based
on their Value, Library source, and Library part.
In this example of a more advanced equivalency operator we also compare the
custom fields Voltage, Tolerance and Manufacturer as well as the assigned
footprint. If these fields are not used in some parts they will simply be
ignored (they will match as both will be empty strings).
"""
result = True
if self.getValue() != other.getValue():
result = False
elif self.getLib() != other.getLib():
result = False
elif self.getPart() != other.getPart():
result = False
elif self.getFootprint() != other.getFootprint():
result = False
elif self.getField("Tolerance") != other.getField("Tolerance"):
result = False
elif self.getField("Manufacturer") != other.getField("Manufacturer"):
result = False
elif self.getField("Voltage") != other.getField("Voltage"):
result = False

return result

# Override the component equivalence operator - it is important to do this
# before loading the netlist, otherwise all components will have the original
# equivalency operator.
ky.component.__equ__ = myEqu

# Generate an instance of a generic netlist, and load the netlist tree from
# video.tmp. If the file doesn't exist, execution will stop
net = ky.netlist(sys.argv[1])

# Open a file to write too, if the file cannot be opened output to stdout
# instead
try:
f = open(sys.argv[2], 'w')
except IOError:
print >> sys.stderr, __file__, ":", e
f = stdout

# Output a set of rows for a header providing general information
html = html.replace('<!--SOURCE-->', net.getSource())
html = html.replace('<!--DATE-->', net.getDate())
html = html.replace('<!--TOOL-->', net.getTool())
html = html.replace('<!--COMPCOUNT-->', "<b>Component Count:</b>" + \
str(len(net.components)))

row = "<tr><th style='width:640px'>Ref</th>" + "<th>Qnty</th>"
row += "<th>Value</th>" + "<th>Part</th>" + "<th>Datasheet</th>"
row += "<th>Description</th>" + "<th>Vendor</th></tr>"

html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")

# Get all of the components in groups of matching parts + values (see ky.py)
grouped = net.groupComponents()

# Output all of the component information
for group in grouped:
refs = ""

# Add the reference of every component in the group and keep a reference
# to the component so that the other data can be filled in once per group
for component in group:
refs += component.getRef() + ", "
c = component

row = "<tr><td>" + refs +"</td><td>" + str(len(group))
row += "</td><td>" + c.getValue() + "</td><td>" + c.getLib() + "/"
row += c.getPart() + "</td><td>" + c.getDatasheet() + "</td><td>"
row += c.getDescription() + "</td><td>" + c.getField("Vendor")
row += "</td></tr>"

html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")

# Print the formatted html to output file
print >> f, html
Loading

0 comments on commit 4c06357

Please sign in to comment.