title: how to update Spreadsheet values using FreeCAD python module
body: <p>Let's say I have a FreeCAD model that defines a certain geometry with dimensions height, width, and length that are defined in cells of the model's spreadsheet.
  I want to build an automation pipeline in a stand-alone Python script using the FreeCAD module that
   - reads that model
   - sets the spreadsheet cells to values provided by the client
   - recomputes the model accordingly
   - generates geometry by tessellating the model's parts for further processing outside of FreeCAD (irrelevant with regard to this question)</p>
  
  <p>The script is working except that it fails to change the parameter values that are used to compute the model. The resulting geometry always reflects the original values that were saved with the model.</p>
  
  <p>I've added an assert command (line 44). <code>geometry[0][0][2]</code> is a Vector whose <code>x</code> coordinate happens to equal the value of the <code>width</code> parameter in spreadsheet cell A5.</p>
  
  <p>If one invokes the script as</p>
  
  <pre><code>python so.py so_example.FCStd 10 5 3 6
  </code></pre>
  
  <p>the assert fails because the geometry gets generated based on the spreadsheet's original values (<code>width=2</code>) and not the overwritten ones (<code>width=3</code>).</p>
  
  <p>How can I effectively overwrite those spreadsheet cell values?</p>
  
  <p>Script so.py:</p>
  
  <pre><code>FREECADPATH = '/usr/lib/freecad/lib'
  import sys
  sys.path.append(FREECADPATH)
  from collections import defaultdict
  
  def convert_model(filename, arclen, radius, width, height):
      try:
          import FreeCAD
          from FreeCAD import Vector
      except ValueError:
          print ('import error\n')
      else:
          FreeCAD.open(filename)
  
          doc = App.ActiveDocument
  
          sheet = doc.Spreadsheet
          print("mode = "+str(sheet.getEditorMode("A5")))
          sheet.setEditorMode("A5", 0)
          print("mode' = "+str(sheet.getEditorMode("A5")))
          print("arclen = "+str(sheet.arclen))
          print("radius = "+str(sheet.radius))
          print("angle = "+str(sheet.angle))
          print("width = "+str(sheet.width))
          print("height = "+str(sheet.height))
          sheet.set("arclen", str(arclen))
          sheet.set("radius", str(radius))
          sheet.set("width", str(width))
          sheet.set("height", str(height))
          sheet.recompute()
          # verify that the radius and also the dependent angle have changed after the recomputer
          print("arclen' = "+str(sheet.arclen))
          print("radius' = "+str(sheet.radius))
          print("angle' = "+str(sheet.angle))
          print("width' = "+str(sheet.width))
          print("height' = "+str(sheet.height))
  
          # recompute the model
          doc.recompute()
  
          geometry = generate_geometry(doc)
          print("generated geometry: "+str(geometry[0][0]))
  
          assert geometry[0][0][2] == Vector(width, 0, 0)
  
  def generate_geometry(doc):
      objects = doc.Objects
      return [tessellate_shape(shaped) for shaped in objects if shaped.TypeId == 'PartDesign::Body']
  
  def tessellate_shape(shaped):
      return shaped.Shape.tessellate(0.1)
  
  def main():
      filename=sys.argv[1]
      arclen=float(sys.argv[2])
      radius=float(sys.argv[3])
      width=float(sys.argv[4])
      height=float(sys.argv[5])
      convert_model(filename, arclen, radius, width, height)
  
  if __name__=='__main__':
     main()
  </code></pre>
  
  <p><a href="https://drive.google.com/open?id=1rKddgHQnW5iBZ2FrPmZIGD-BdEpJGmF6" rel="nofollow noreferrer">FreeCAD example model</a></p>