Skip to content

Instantly share code, notes, and snippets.

@arturo182
Last active March 22, 2024 14:29
Show Gist options
  • Save arturo182/a8c4a4b96907cfccf616a1edb59d0389 to your computer and use it in GitHub Desktop.
Save arturo182/a8c4a4b96907cfccf616a1edb59d0389 to your computer and use it in GitHub Desktop.
A KiCad BOM script for generating JLCPCB PCBA-compatible files!
<!--XSL style sheet to convert EESCHEMA XML Partlist Format to grouped CSV BOM Format
Copyright (C) 2014, Wolf Walter.
Copyright (C) 2013, Stefan Helmert.
Copyright (C) 2018, Kicad developers.
Copyright (C) 2019, arturo182.
GPL v2.
Functionality:
Generation of JLCPCB PCBA 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/bom2grouped_csv_jlcpcb.xsl" "%I"
-->
<!--
@package
Generates a JLCPCB PCBA service compatible BOM
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
Comment,Designator,Footprint,LCSC
The command line is
xsltproc -o "%O.csv" "full_path/bom2grouped_csv_jlcpcb.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"/>
<xsl:variable name="digits" select="'1234567890'" />
<!-- for matching 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>Comment,Designator,Footprint,LCSC</xsl:text>
<!-- 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>
<xsl:text>"</xsl:text><xsl:value-of select="value"/><xsl:text>","</xsl:text>
<!-- list of all references -->
<xsl:for-each select="key('partTypeByValueAndFootprint', concat(footprint, '-', value))">
<!-- strip non-digits from reference and sort based on remaining number -->
<xsl:sort select="translate(@ref, translate(@ref, $digits, ''), '')" data-type="number" />
<xsl:value-of select="@ref"/>
<xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
</xsl:for-each>
<xsl:text>","</xsl:text>
<xsl:value-of select="footprint"/><xsl:text>","</xsl:text>
<xsl:value-of select="fields/field[@name='LCSC']"/><xsl:text>"</xsl:text>
</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: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:text>"</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
@amazed-2022
Copy link

If you install this, it should work fine. The full package for JLCPCB is created without any issue and in a subdir called "Production"

Thank you very much for the hint!

@JosephLL753
Copy link

I am still lost with this.

I have installed the Fabrication Toolkit, and created the .py file with the name bom2grouped_csv_jlcpcb.py, but I am still receiving the error code:
tree = ET.parse(xml_path)
^
IndentationError: expected an indented block

@amazed-2022
Copy link

amazed-2022 commented Mar 29, 2023

I am still lost with this.

You don't need the bom2grouped_csv_jlcpcb stuff at all!

Just use the "Fabrication Toolkit" button in the PCB Editor.

kép

@GadgetNutt
Copy link

I am still lost with this.

I have installed the Fabrication Toolkit, and created the .py file with the name bom2grouped_csv_jlcpcb.py, but I am still receiving the error code: tree = ET.parse(xml_path) ^ IndentationError: expected an indented block

Did you install Python and the lxml library?

@tormyvancool
Copy link

I am still lost with this.

You don't need the bom2grouped_csv_jlcpcb stuff at all!

Just use the "Fabrication Toolkit" button in the PCB Editor.

kép

Indeed I also posted how to get it (see a couple of replies above your one) ... but it seems ppl is not reading instructions

@GadgetNutt
Copy link

I'm currently using the other method. I'll probably switch soon. In the meantime I responded because someone asked.

@ep201
Copy link

ep201 commented Apr 7, 2023

How do you add this script to kicad? instructions are not clear


Found out how to add it, there is a Bill of Materials button on the top toolbar in schematic editor in KiCad 6, next to the board view button.
image

Now, I'm getting this error, same as outlined in this forum post: https://forum.kicad.info/t/command-error-return-code-11-to-generate-bom/5447/12
can we get a fix for this?
image
It may be an issue with directories with spaces. The directory after C:/Users/ in the paths in this screenshot are formatted "[Firstname] [Lastname]" , with a space between first and last, and I encounter the same issue.


edit 2: fixed issue by replacing %O in the command line with a file name, e.g. "bom.csv" instead of "%O.csv"
edit 3: actually, no matter which project I run, now any bom file is only exported to the original folder, not the destination project folder, no matter how I name the file destination.

@tormyvancool
Copy link

tormyvancool commented Apr 8, 2023

How do you add this script to kicad? instructions are not clear

Drop thi s script. it's now overtaken by the one I mentioned above.
And you install it via the plugin manager

image

@Mk-arc
Copy link

Mk-arc commented Apr 13, 2023

The toolkit is great. But please not that it first deletes the complete content of the production folder without warning :( caused some data loss for me.

@ramonimbao
Copy link

For anyone who wants the .py file by @GadgetNutt to work, it's missing indentations.

Here's how the source file should look:

import lxml.etree as ET
import csv
import sys

# Get the command line arguments
xml_path = sys.argv[1]
csv_path = sys.argv[2]

def generate_bom(xml_path, csv_path):
	# Load the EESCHEMA XML Partlist Format file
	tree = ET.parse(xml_path)
	root = tree.getroot()

	# Define the namespace for the XML file
	ns = {"xsl": "http://www.w3.org/1999/XSL/Transform"}

	# Load the XSL stylesheet to transform the XML file to CSV
	xslt_tree = ET.parse("C:/Program Files/KiCad/bin/scripting/plugins/bom2grouped_csv_jlcpcb.xsl")
	transform = ET.XSLT(xslt_tree)

	# Apply the transformation to the XML file
	csv_data = transform(root)

	# Convert the XSLTResultTree object to a string and split into lines
	csv_data_str = str(csv_data)
	csv_lines = csv_data_str.splitlines()

	# Write the transformed CSV data to file
	with open(csv_path, "w", newline="") as csvfile:
		writer = csv.writer(csvfile, delimiter=",", quotechar="'", quoting=csv.QUOTE_NONE)
		for line in csv_lines:
			writer.writerow(line.split(","))

# Example usage
generate_bom(xml_path, csv_path)

The location of the bom2group_csv_jlcpcb.xsl might be different for you so be sure to change that as necessary.

I also had to open a KiCAD Command Prompt and run python install lxml before it worked since it was missing the module.

Tested working on a fresh install of KiCAD 7.0.2.

@tormyvancool
Copy link

The toolkit is great. But please not that it first deletes the complete content of the production folder without warning :( caused some data loss for me.

+1 for that. On top of this it will be nice to have the PROJECT_NAME into the file names ... if it puts Date and Hours to keep kind of versioning, it will be nice

@rtek1000
Copy link

rtek1000 commented Jul 4, 2023

Hi.` The xsltproc appears to have been removed from KiCAD 7. Here is a solution:
Keep the instructions currently, but one slight change. Create a new .py file with the same name and put it in the same folder as bom2grouped_csv_jlcpcb.xsl and create the file.
and set the commandline to: python "\KiCad\6.0\plugins\bom2grouped_csv_jlcpcb.py" "%I" "%O.csv"

Hello, thanks for the update, unfortunately it is not working for me. :( I get the following error:

    tree = ET.parse(xml_path)
    ^
IndentationError: expected an indented block

How could I make it work?

If you install this, it should work fine. The full package for JLCPCB is created without any issue and in a subdir called "Production" image

Thanks!

@rtek1000
Copy link

rtek1000 commented Jul 4, 2023

Hi.` The xsltproc appears to have been removed from KiCAD 7. Here is a solution:
Keep the instructions currently, but one slight change. Create a new .py file with the same name and put it in the same folder as bom2grouped_csv_jlcpcb.xsl and create the file.
and set the commandline to: python "\KiCad\6.0\plugins\bom2grouped_csv_jlcpcb.py" "%I" "%O.csv"

Hello, thanks for the update, unfortunately it is not working for me. :( I get the following error:

    tree = ET.parse(xml_path)
    ^
IndentationError: expected an indented block

How could I make it work?

If you install this, it should work fine. The full package for JLCPCB is created without any issue and in a subdir called "Production" image

Thanks!

Ref.:
[YouTube: How to Place a PCB Assembly Order at JLCPCB]

Note: Generating Pick and Place files (CPL file (.pos), already included in the package "Production"):

The CPL file has to be generated from the PCB editor, click on "File" -> "Fabrication output" -> "Footprint position (.pos) file" and export the file with the following settings. Source.

Note: "2. Notes on DFM - 1.The design of the PCB footprints must comply with "medium density" or "low density" standards listed in IPC-7351B. High density is not supported." (Terms and Conditions of JLCPCB Assembly Service)

Ref.:

Manufacturing defects caused by PCB Design

@hasenradball
Copy link

Hi Arthur,

with the KICAD 7.0 I got an error, and I am not clear about the root cause here.
Can You probably give an Hint?

grafik

@UnforeseenOcean
Copy link

UnforeseenOcean commented Sep 6, 2023

Hi Arthur,

with the KICAD 7.0 I got an error, and I am not clear about the root cause here. Can You probably give an Hint?

grafik

This is due to the xsltproc executable being omitted from the installation. I had to transplant it from QMK (the executable) and Git (DLL files) on Windows to get it working. (Not sure on Ubuntu which you seem to be using, please consult your system files)

You need both the library and executable on Windows. Copy over all files named xsltproc.exe and msys-*.dll from Git and QMK into KiCad/7.0/bin/ folder to get it working. It's quite annoying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment