Skip to content

Commit

Permalink
Add a mechanism to rename columns
Browse files Browse the repository at this point in the history
- **Pull-request**: [#82](#82)
- **Opened**: 2020-03-18
- **Status**: Open
- **Branch**: column_rename

-## Description

Column names displayed in the table head are the names of the KiCad fields or the internal names used by KiBoM.
Sometimes the names aren't pretty. As an example is common to use `manf#` for the part name used by the component manufacturer.
Using long names for KiCad fields is a bad idea.

This patch allows to rename the columns names so you can use pretty names in the headings.

You must define a `COLUMN_RENAME` section in the configuration file.
Then add entries with the name of the original field and the name you want, separated by a tab (ASCII 9).
Here is an example:

```
[COLUMN_RENAME]
manf#	Manufacturer part number
```

Note that you must use a tab as separator. Using a space won't work because *Manufacturer part number* also has spaces.

-## Limitations

The separator must be a tab.

-## Additional notes

- This patch also makes the `prefs.ignore` list lowercase.
  This is to avoid converting it to lower case all the time.
- `prefs.colRename` is a hash. I saw that various preference options should also be a *dict* instead of a *list*.
  • Loading branch information
set-soft committed Jul 18, 2020
1 parent 02407b9 commit 562bc40
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 25 deletions.
12 changes: 7 additions & 5 deletions kibom/bom_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ def WriteBoM(filename, groups, net, headings=columns.ColumnList._COLUMNS_DEFAULT
prefs = BomPref()

# Remove any headings that appear in the ignore[] list
headings = [h for h in headings if not h.lower() in [i.lower() for i in prefs.ignore]]
headings = [h for h in headings if not h.lower() in prefs.ignore]
# Allow renaming the columns
head_names = [h if h.lower() not in prefs.colRename else prefs.colRename[h.lower()] for h in headings]

# If no extension is given, assume .csv (and append!)
if len(filename.split('.')) < 2:
Expand All @@ -54,28 +56,28 @@ def WriteBoM(filename, groups, net, headings=columns.ColumnList._COLUMNS_DEFAULT

# CSV file writing
if ext in ["csv", "tsv", "txt"]:
if WriteCSV(filename, groups, net, headings, prefs):
if WriteCSV(filename, groups, net, headings, head_names, prefs):
debug.info("CSV Output -> {fn}".format(fn=filename))
result = True
else:
debug.error("Error writing CSV output")

elif ext in ["htm", "html"]:
if WriteHTML(filename, groups, net, headings, prefs):
if WriteHTML(filename, groups, net, headings, head_names, prefs):
debug.info("HTML Output -> {fn}".format(fn=filename))
result = True
else:
debug.error("Error writing HTML output")

elif ext in ["xml"]:
if WriteXML(filename, groups, net, headings, prefs):
if WriteXML(filename, groups, net, headings, head_names, prefs):
debug.info("XML Output -> {fn}".format(fn=filename))
result = True
else:
debug.error("Error writing XML output")

elif ext in ["xlsx"]:
if WriteXLSX(filename, groups, net, headings, prefs):
if WriteXLSX(filename, groups, net, headings, head_names, prefs):
debug.info("XLSX Output -> {fn}".format(fn=filename))
result = True
else:
Expand Down
12 changes: 8 additions & 4 deletions kibom/csv_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
import sys


def WriteCSV(filename, groups, net, headings, prefs):
def WriteCSV(filename, groups, net, headings, head_names, prefs):
"""
Write BoM out to a CSV file
filename = path to output file (must be a .csv, .txt or .tsv file)
groups = [list of ComponentGroup groups]
net = netlist object
headings = [list of headings to display in the BoM file]
headings = [list of headings to search for data in the BoM file]
head_names = [list of headings to display in the BoM file]
prefs = BomPref object
"""

Expand Down Expand Up @@ -43,9 +44,12 @@ def WriteCSV(filename, groups, net, headings, prefs):

if not prefs.hideHeaders:
if prefs.numberRows:
writer.writerow(["Component"] + headings)
comp = "Component"
if comp.lower() in prefs.colRename:
comp = prefs.colRename[comp.lower()]
writer.writerow([comp] + head_names)
else:
writer.writerow(headings)
writer.writerow(head_names)

count = 0
rowCount = 1
Expand Down
13 changes: 7 additions & 6 deletions kibom/html_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ def link(text):
return text


def WriteHTML(filename, groups, net, headings, prefs):
def WriteHTML(filename, groups, net, headings, head_names, prefs):
"""
Write BoM out to a HTML file
filename = path to output file (must be a .htm or .html file)
groups = [list of ComponentGroup groups]
net = netlist object
headings = [list of headings to display in the BoM file]
headings = [list of headings to search for data in the BoM file]
head_names = [list of headings to display in the BoM file]
prefs = BomPref object
"""

Expand Down Expand Up @@ -99,9 +100,9 @@ def WriteHTML(filename, groups, net, headings, prefs):
if prefs.numberRows:
html.write("\t<th></th>\n")

for i, h in enumerate(headings):
for i, h in enumerate(head_names):
# Cell background color
bg = bgColor(h)
bg = bgColor(headings[i])
html.write('\t<th align="center"{bg}>{h}</th>\n'.format(
h=h,
bg=' bgcolor="{c}"'.format(c=bg) if bg else '')
Expand Down Expand Up @@ -151,9 +152,9 @@ def WriteHTML(filename, groups, net, headings, prefs):
html.write("<tr>\n")
if prefs.numberRows:
html.write("\t<th></th>\n")
for i, h in enumerate(headings):
for i, h in enumerate(head_names):
# Cell background color
bg = bgColor(h)
bg = bgColor(headings[i])
html.write('\t<th align="center"{bg}>{h}</th>\n'.format(h=h, bg=' bgcolor="{c}"'.format(c=bg) if bg else ''))
html.write("</tr>\n")

Expand Down
23 changes: 20 additions & 3 deletions kibom/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class BomPref:
SECTION_REGEXCLUDES = "REGEX_EXCLUDE"
SECTION_REGINCLUDES = "REGEX_INCLUDE"
SECTION_JOIN = "JOIN" # (#81)
SECTION_COLUMN_RENAME = "COLUMN_RENAME"

OPT_DIGIKEY_LINK = "digikey_link"
OPT_PCB_CONFIG = "pcb_configuration"
Expand All @@ -47,8 +48,8 @@ class BomPref:
def __init__(self):
# List of headings to ignore in BoM generation
self.ignore = [
ColumnList.COL_PART_LIB,
ColumnList.COL_FP_LIB,
ColumnList.COL_PART_LIB.lower(),
ColumnList.COL_FP_LIB.lower(),
]

self.corder = ColumnList._COLUMNS_DEFAULT
Expand Down Expand Up @@ -83,6 +84,8 @@ def __init__(self):
# User can add custom grouping columns in bom.ini
]

self.colRename = {} # None by default

self.regIncludes = [] # None by default

self.regExcludes = [
Expand Down Expand Up @@ -177,7 +180,7 @@ def Read(self, file, verbose=False):

# Read out ignored-rows
if self.SECTION_IGNORE in cf.sections():
self.ignore = [i for i in cf.options(self.SECTION_IGNORE)]
self.ignore = [i.lower() for i in cf.options(self.SECTION_IGNORE)]

# Read out column order
if self.SECTION_COLUMN_ORDER in cf.sections():
Expand All @@ -203,6 +206,13 @@ def Read(self, file, verbose=False):
if len(re.split('[ \t]+', pair)) == 2:
self.regIncludes.append(re.split('[ \t]+', pair))

if self.SECTION_COLUMN_RENAME in cf.sections():
self.colRename = {}
for pair in cf.options(self.SECTION_COLUMN_RENAME):
pair = re.split('\t', pair)
if len(pair) == 2:
self.colRename[pair[0].lower()] = pair[1]

# Add an option to the SECTION_GENRAL group
def addOption(self, parser, opt, value, comment=None):
if comment:
Expand Down Expand Up @@ -309,6 +319,13 @@ def Write(self, file):
continue
cf.set(self.SECTION_REGINCLUDES, i[0] + "\t" + i[1])

cf.add_section(self.SECTION_COLUMN_RENAME)
cf.set(self.SECTION_COLUMN_RENAME, '; A list of columns to be renamed')
cf.set(self.SECTION_COLUMN_RENAME, '; Format is: "[ColumName] [NewName]" (white-space separated)')

for k, v in self.colRename.items():
cf.set(self.SECTION_COLUMN_RENAME, k + "\t" + v)

cf.add_section(self.SECTION_REGEXCLUDES)
cf.set(self.SECTION_REGEXCLUDES, '; A series of regular expressions used to exclude parts from the BoM')
cf.set(self.SECTION_REGEXCLUDES, '; If a component matches ANY of these, it will be excluded from the BoM')
Expand Down
14 changes: 9 additions & 5 deletions kibom/xlsx_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
try:
import xlsxwriter
except:
def WriteXLSX(filename, groups, net, headings, prefs):
def WriteXLSX(filename, groups, net, headings, head_names, prefs):
return False
else:
import os
Expand All @@ -13,11 +13,12 @@ def WriteXLSX(filename, groups, net, headings, prefs):
filename = path to output file (must be a .xlsx file)
groups = [list of ComponentGroup groups]
net = netlist object
headings = [list of headings to display in the BoM file]
headings = [list of headings to search for data in the BoM file]
head_names = [list of headings to display in the BoM file]
prefs = BomPref object
"""

def WriteXLSX(filename, groups, net, headings, prefs):
def WriteXLSX(filename, groups, net, headings, head_names, prefs):

filename = os.path.abspath(filename)

Expand All @@ -33,9 +34,12 @@ def WriteXLSX(filename, groups, net, headings, prefs):
worksheet = workbook.add_worksheet()

if prefs.numberRows:
row_headings = ["Component"] + headings
comp = "Component"
if comp.lower() in prefs.colRename:
comp = prefs.colRename[comp.lower()]
row_headings = [comp] + head_names
else:
row_headings = headings
row_headings = head_names

cellformats = {}
column_widths = {}
Expand Down
4 changes: 2 additions & 2 deletions kibom/xml_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from xml.dom import minidom


def WriteXML(filename, groups, net, headings, prefs):
def WriteXML(filename, groups, net, headings, head_names, prefs):

if not filename.endswith(".xml"):
return False
Expand Down Expand Up @@ -49,7 +49,7 @@ def WriteXML(filename, groups, net, headings, prefs):

attrib = {}

for i, h in enumerate(headings):
for i, h in enumerate(head_names):
h = h.replace(' ', '_') # Replace spaces, xml no likey
h = h.replace('"', '')
h = h.replace("'", '')
Expand Down

0 comments on commit 562bc40

Please sign in to comment.