Eeschema bom scripts: move python scripts to eeschema/plugins/python_scripts and xsl scripts to subdir xsl_scripts.

Python scripts are now installed (previously: were ignored by the make install command)
Better comments in python scripts.
This commit is contained in:
jean-pierre charras 2017-05-15 16:40:21 +02:00
parent a374f46b5e
commit 58f90b3adb
21 changed files with 158 additions and 209 deletions

View File

@ -3,17 +3,28 @@
# See chapter 14 of eeschema.pdf
set( xsl_lst
bom2csv.xsl
bom_cvs.xsl
netlist_form_cadstar-RINF.xsl
netlist_form_cadstar.xsl
netlist_form_OrcadPcb2.xsl
netlist_form_pads-pcb.xsl
bom_with_title_block_2_csv.xsl
set( XSL_SCRIPTS_LIST
xsl_scripts/bom_with_title_block_2_csv.xsl
xsl_scripts/bom2csv.xsl
xsl_scripts/bom2grouped_csv.xsl
xsl_scripts/netlist_form_cadstar-RINF.xsl
xsl_scripts/netlist_form_cadstar.xsl
xsl_scripts/netlist_form_OrcadPcb2.xsl
xsl_scripts/netlist_form_pads-pcb.xsl
)
install( FILES ${xsl_lst}
set( PYTHON_SCRIPTS_LIST
python_scripts/README-bom.txt
python_scripts/kicad_netlist_reader.py
python_scripts/bom_csv_grouped_by_value.py
python_scripts/bom_csv_grouped_by_value_with_fp.py
python_scripts/bom_csv_sorted_by_ref.py
python_scripts/bom_html_grouped_by_value.py
python_scripts/bom_html_with_advanced_grouping.py
python_scripts/bom_sorted_by_ref.py
)
install( FILES ${XSL_SCRIPTS_LIST} ${PYTHON_SCRIPTS_LIST}
DESTINATION ${KICAD_PLUGINS}
COMPONENT binary
)

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--XSL style sheet that takes EESCHEMA's Generic Netlist Format as input and
outputs a simple BOM in CSV format. Feel free to enhance this and submit
patches.
How to use:
Eeschema.pdf: chapter 14
-->
<!--
@package
Generate a comma separated value BOM list (csv file type).
Components are sorted by value
One component per line
Fields are
Quantity, 'Part name', Description, lib
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF -->
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<!-- for each component -->
<xsl:template match="libpart">
<!-- -->
<xsl:value-of select="count(//comp/libsource/@part[@part])"/><xsl:text>,"</xsl:text>
<xsl:value-of select="@part"/><xsl:text>","</xsl:text>
<xsl:value-of select="description"/><xsl:text>","</xsl:text>
<xsl:value-of select="@lib"/>
<xsl:text>"&nl;</xsl:text>
</xsl:template>
<xsl:template match="/export">
<xsl:text>Qty,partname,description,lib&nl;</xsl:text>
<xsl:apply-templates select="libparts/libpart"/>
</xsl:template>
</xsl:stylesheet>

View File

@ -9,6 +9,9 @@
Components are sorted by ref and grouped by value
Fields are (if exist)
Item, Qty, Reference(s), Value, LibPart, Footprint, Datasheet
Command line:
python "pathToFile/bom_csv_grouped_by_value.py" "%I" "%O.csv"
"""
from __future__ import print_function
@ -25,7 +28,6 @@ def myEqu(self, other):
In this example of a custom equivalency operator we compare the
value, the part name and the footprint.
"""
result = True
if self.getValue() != other.getValue():
@ -76,7 +78,7 @@ columnset = compfields | partfields # union
columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset))
# Create a new csv writer object to use as the output formatter
out = csv.writer( f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL )
out = csv.writer( f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL )
# override csv.writer's writerow() to support encoding conversion (initial encoding is utf8):
def writerow( acsvwriter, columns ):

View File

@ -10,6 +10,9 @@
Components are sorted by ref and grouped by value with same footprint
Fields are (if exist)
'Ref', 'Qnty', 'Value', 'Cmp name', 'Footprint', 'Description', 'Vendor'
Command line:
python "pathToFile/bom_csv_grouped_by_value_with_fp.py" "%I" "%O.csv"
"""
# Import the KiCad python helper module and the csv formatter

View File

@ -11,6 +11,9 @@
One component per line
Fields are (if exist)
Ref, value, Part, footprint, Datasheet, Manufacturer, Vendor
Command line:
python "pathToFile/bom_csv_sorted_by_ref.py" "%I" "%O.csv"
"""
from __future__ import print_function

View File

@ -9,6 +9,9 @@
Components are sorted by ref and grouped by value
Fields are (if exist)
Ref, Quantity, Value, Part, Datasheet, Description, Vendor
Command line:
python "pathToFile/bom_html_grouped_by_value.py" "%I" "%O.html"
"""
from __future__ import print_function

View File

@ -10,6 +10,9 @@
Components are sorted and grouped by value
Fields are (if exist)
Ref, Quantity, Value, Part, Footprint, Description, Vendor
Command line:
python "pathToFile/bom_with_advanced_grouping.py" "%I" "%O.html"
"""

View File

@ -3,12 +3,15 @@
#
"""
@package
Generate a BOM list file.
Generate a BOM list file (a simple text).
Components are sorted by ref
One component per line
Fields are (if exist)
Ref, Quantity, value, Part, footprint, Description, Vendor
Fields are separated by tabs
Command line:
python "pathToFile/bom_sorted_by_ref.py" "%I" "%O.txt"
"""
from __future__ import print_function

View File

@ -25,6 +25,9 @@
One component per line
Fields are
Ref,Value, Footprint, Datasheet, Field5, Field4, price
Command line
xsltproc -o "%O.csv" "pathToFile/bom2csv.xsl" "%I"
-->
<!DOCTYPE xsl:stylesheet [

View File

@ -0,0 +1,104 @@
<!--XSL style sheet to convert EESCHEMA XML Partlist Format to grouped CSV BOM Format
Copyright (C) 2014, Wolf Walter.
Copyright (C) 2013, Stefan Helmert.
GPL v2.
Functionality:
Generation of Digi-Key ordering system compatible BOM
How to use this is explained in eeschema.pdf chapter 14. You enter a command line into the
netlist exporter using a new (custom) tab in the netlist export dialog.
The command line is
xsltproc -o "%O.csv" "FullPathToFile/bom2groupedCsv.xsl" "%I"
-->
<!--
@package
Functionality:
* Generate a comma separated value BOM list (csv file type).
* Components are sorted by ref and grouped by same value+footprint
One value per line
Fields are
Reference, Quantity, Value, Footprint, Datasheet
The command line is
xsltproc -o "%O.csv" "FullPathToFile/bom2groupedCsv.xsl" "%I"
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF, or LF, your choice -->
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<!-- for Muenchian grouping of footprint and value combination -->
<xsl:key name="partTypeByValueAndFootprint" match="comp" use="concat(footprint, '-', value)" />
<!-- for table head and empty table fields-->
<xsl:key name="headentr" match="field" use="@name"/>
<!-- main part -->
<xsl:template match="/export">
<xsl:text>Reference, Quantity, Value, Footprint, Datasheet</xsl:text>
<!-- find all existing table head entries and list each one once -->
<xsl:for-each select="components/comp/fields/field[generate-id(.) = generate-id(key('headentr',@name)[1])]">
<xsl:text>, </xsl:text>
<xsl:value-of select="@name"/>
</xsl:for-each>
<!-- all table entries -->
<xsl:apply-templates select="components"/>
</xsl:template>
<xsl:template match="components">
<!-- for Muenchian grouping of footprint and value combination -->
<xsl:for-each select="comp[count(. | key('partTypeByValueAndFootprint', concat(footprint, '-', value))[1]) = 1]">
<xsl:sort select="@ref" />
<xsl:text>&nl;</xsl:text>
<!-- list of all references -->
<xsl:for-each select="key('partTypeByValueAndFootprint', concat(footprint, '-', value))">
<xsl:sort select="@ref" />
<xsl:value-of select="@ref"/><xsl:text> </xsl:text>
</xsl:for-each><xsl:text>,</xsl:text>
<!-- quantity of parts with same footprint and value -->
<xsl:value-of select="count(key('partTypeByValueAndFootprint', concat(footprint, '-', value)))"/><xsl:text>,</xsl:text>
<xsl:text>"</xsl:text>
<xsl:value-of select="value"/><xsl:text>","</xsl:text>
<xsl:value-of select="footprint"/><xsl:text>","</xsl:text>
<xsl:value-of select="datasheet"/><xsl:text>"</xsl:text>
<xsl:apply-templates select="fields"/>
</xsl:for-each>
</xsl:template>
<!-- table entries with dynamic table head -->
<xsl:template match="fields">
<!-- remember current fields section -->
<xsl:variable name="fieldvar" select="field"/>
<!-- for all existing head entries -->
<xsl:for-each select="/export/components/comp/fields/field[generate-id(.) = generate-id(key('headentr',@name)[1])]">
<xsl:variable name="allnames" select="@name"/>
<xsl:text>,"</xsl:text>
<!-- for all field entries in the remembered fields section -->
<xsl:for-each select="$fieldvar">
<!-- only if this field entry exists in this fields section -->
<xsl:if test="@name=$allnames">
<!-- content of the field -->
<xsl:value-of select="."/>
<xsl:text>"</xsl:text>
</xsl:if>
<!--
If it does not exist, use an empty cell in output for this row.
Every non-blank entry is assigned to its proper column.
-->
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,26 +1,19 @@
<!--
@package
EESCHEMA BOM plugin. Creates BOM CSV files from the project net file.
Based on Stefan Helmert bom2csv.xsl
Note:
The project infomation (i.e title, company and revision) is taken from and the root sheet.
The project infomation (i.e title, company and revision) is taken from the root sheet.
Arthur:
Ronald Sousa HashDefineElectronics.com
Usage:
on Windows:
xsltproc -o "%O.csv" "C:\Program Files (x86)\KiCad\bin\plugins\bom2csv.xsl" "%I"
on Linux:
xsltproc -o "%O.csv" /usr/local/lib/kicad/plugins/bom2csv.xsl "%I"
Ouput Example:
Source,
Kicad Rev, working director and file source
Generated Date, date this file was generated
Title, the project's tile
Title, the project's title
Company, the project's company
Rev, the project's revision
Date Source, project's issue date
@ -28,9 +21,15 @@
Comment, This is comment 2
Comment, This is comment 3
Comment, This is comment 4
-->
<!--
@package
Output format
Reference, Value, Fields[n], Library, Library Ref
U1, PIC32MX, Fields[n], KicadLib, PIC
Command line:
xsltproc -o "%O.csv" "pathToFile/bom2csv.xsl" "%I"
-->
<!DOCTYPE xsl:stylesheet [

View File

@ -1385,8 +1385,8 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName, double aMMt
export_vrml_module( model3d, pcb, module, output_file, wrml_3D_models_scaling_factor,
aExport3DFiles, aUseRelativePaths, a3D_Subdir );
// write out the board and all layers
write_layers( model3d, output_file, pcb );
// write out the board and all layers
write_layers( model3d, output_file, pcb );
// Close the outer 'transform' node
output_file << "]\n}\n";

View File

@ -1,140 +0,0 @@
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Sorted and Grouped HTML BOM with more advanced grouping
#
"""
@package
Generate a HTML BOM list.
Components are sorted and grouped by ref
Fields are (if exist)
Ref, Quantity, Value, Symbol, footprint, Description, Vendor
"""
from __future__ import print_function
# Import the KiCad python helper module and the csv formatter
import kicad_netlist_reader
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 grouped by value and footprint </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.getLibName() != other.getLibName():
result = False
elif self.getPartName() != other.getPartName():
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.
kicad_netlist_reader.comp.__equ__ = myEqu
# Generate an instance of a generic netlist, and load the netlist tree from
# video.xml. If the file doesn't exist, execution will stop
net = kicad_netlist_reader.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:
e = "Can't open output file for writing: " + sys.argv[2]
print( __file__, ":", e, sys.stderr )
f = sys.stdout
components = net.getInterestingComponents()
# 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(components)))
row = "<tr><th style='width:640px'>Ref</th>" + "<th>Qnty</th>"
row += "<th>Value</th>"
row += "<th>Symbol</th>"
row += "<th>Footprint</th>"
row += "<th>Description</th>"
row += "<th>PartNumber</th>"
row += "<th>Vendor</th></tr>"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
# Get all of the components in groups of matching parts + values
# (see kicad_netlist_reader.py)
grouped = net.groupComponents(components)
# 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:
if len(refs) > 0:
refs += ", "
refs += component.getRef()
c = component
row = "<tr>"
row += "<td>" + refs +"</td>"
row += "<td align=center>" + str(len(group)) + "</td>"
row += "<td align=center>" + c.getValue() + "</td>"
# row += "<td align=center>" + c.getLibName() + ":" + c.getPartName() + "</td>"
row += "<td align=center>" + c.getPartName() + "</td>"
row += "<td align=center>" + c.getFootprint() + "</td>"
row += "<td align=center>" + c.getDescription() + "</td>"
row += "<td align=center>" + c.getField("PartNumber") + "</td>"
row += "<td align=center>" + c.getField("Vendor") + "</td>"
row += "</tr>"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
# Print the formatted html to output file
print(html, file=f)