Blame view

BOm/bom_html_with_advanced_grouping.py 4.63 KB
f8ffc2c5   mahmoudrabia   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  #
  # Example python script to generate a BOM from a KiCad generic netlist
  # The KiCad generic xml netlist is expected to be encoded UTF-8
  #
  # Example: Sorted and Grouped HTML BOM with advanced grouping
  #
  
  """
      @package
      Output: HTML
      Grouped By: Value, Part, Footprint, Tolerance, Manufacturer, Voltage, DNP
      Sorted By: Ref
      Fields: Ref, Qnty, Value, Part, Footprint, Description, Vendor, DNP
  
      Command line:
      python "pathToFile/bom_with_advanced_grouping.py" "%I" "%O.html"
  """
  
  from __future__ import print_function
  
  # Import the KiCad python helper module and the csv formatter
  import kicad_netlist_reader
  import kicad_utils
  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 and Footprint.
  
      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.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
      elif self.getDNP() != other.getDNP():
          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.__eq__ = myEqu
  
  # Generate an instance of a generic netlist, and load the netlist tree from
  # <file>.tmp. If the file doesn't exist, execution will stop
  net = kicad_netlist_reader.netlist(sys.argv[1])
  
  # Open a file to write to, if the file cannot be opened output to stdout
  # instead
  try:
      f = kicad_utils.open_file_write(sys.argv[2], 'wb')
  except IOError:
      e = "Can't open output file for writing: " + sys.argv[2]
      print(__file__, ":", e, file=sys.stderr)
      f = sys.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>Footprint</th>"
  row += "<th>Description</th>" + "<th>Vendor</th>" + "<th>DNP</th></tr>"
  
  html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
  
  components = net.getInterestingComponents( excludeBOM=True )
  
  # 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 = "\n    "
      row += "<tr><td>" + refs +"</td><td>" + str(len(group))
      row += "</td><td>" + c.getValue() + "</td><td>" + c.getLibName() + ":"
      row += c.getPartName() + "</td><td>" + c.getFootprint() + "</td><td>"
      row += c.getDescription() + "</td><td>" + c.getField("Vendor") + "</td><td>"
      row += c.getDNPString()
      row += "</td></tr>"
  
      html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
  
  # Write the formatted html to the file
  if sys.version_info[0] < 3:
      f.write(html)
  else:
      f.write(html.encode('utf-8'))
  f.close