How much interest is there to integrate LibreOffice into FreeCAD?

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
Post Reply
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by Kunda1 »

salp wrote: Sun Mar 22, 2020 7:47 pm https://youtu.be/65TIdgF1PeA
Coolness!
BTW, you can put that link in the video bbcode for convenience ;)

Code: Select all

[video][/video]
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
User avatar
salp
Posts: 250
Joined: Thu Nov 21, 2013 11:58 pm
Location: Putnam, NY

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by salp »

will do, thanks for the help.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by Kunda1 »

salp wrote: Sun Mar 22, 2020 10:55 pm
@salp any progress on this?
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
User avatar
salp
Posts: 250
Joined: Thu Nov 21, 2013 11:58 pm
Location: Putnam, NY

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by salp »

No progress so far. MI have been kept busy with work due to the Corona-virus.

I'm hoping to get back on it in a couple of weeks.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by Kunda1 »

salp wrote: Fri May 08, 2020 11:59 pm I'm hoping to get back on it in a couple of weeks.
bump
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
jmaustpc
Veteran
Posts: 11207
Joined: Tue Jul 26, 2011 6:28 am
Location: Australia

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by jmaustpc »

hi all, we had this working many years ago, at least using libre office spreadsheet, this was before Yorik produced the first now obsolete Spreadsheet WB.

Some one else got it to work and posted how to do it so I tried it at the time and it worked.

It was a long time ago and I don't remember the details but I thought we used pyuno, or something else to read data from the spreadsheet. Its all here on the forum somewhere, it was a very long time ago.

Jim
jmaustpc
Veteran
Posts: 11207
Joined: Tue Jul 26, 2011 6:28 am
Location: Australia

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by jmaustpc »

I found what I was thinking about, Kwahoo wrote this tutorial about how to do it...it was 9 years ago. :) It worked back then.


http://freecad-tutorial.blogspot.com/20 ... ffice.html

the summary from the tutorial I linked to above
OOSheet as FreeCAD and LibreOffice bridge
Access to LibreOffice (OpenOffice.org) docs is able from Python. You can do it with PyUNO. When you need Calc spreadsheet, situation is even simpler. In this case OOSheet Python module is useful.

Hope this helps. :)

Jim
User avatar
salp
Posts: 250
Joined: Thu Nov 21, 2013 11:58 pm
Location: Putnam, NY

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by salp »

I finally got time to pick this up again.

I now have the the script able to launch and terminate the soffice application reliably.
I'm able to read named ranges on the spreadsheet and create App:PythonFeature object to store the values.

The code is a mess, but it basically opens a spreadsheet and transfers the values to a FreeCAD object.

To run it:
Install FreeCAD daily build
Install LibreOffice
Change this line to point to your Spreadsheet
document = desktop.loadComponentFromURL("file:///mnt/data1/Python_Prj/LOFC/uno_test_calc.ods" ,"_blank", 0, ())
Chnage where the log file is written
LOG_FILENAME = '/mnt/data1/Python_Prj/LOFC/fc_libre.log'
Change the logging configuration from logging.DEBUG to logging.INFO to turn off logging
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG, format=LOG_FORMAT)
Use the attached spreadsheet to test
uno_test_calc.ods
(7.51 KiB) Downloaded 51 times

Code: Select all

'''
    Application to control LibreOffice Calc from inside FreeCAD enviroment
    Funtions:
    Launch LibreOffice and listen on port 2002
    TODO: use different port if 2002 is being used
    Detect if LibreOffice is currently running
    Shutdown existing instance of LibreOffice
    Open the selected Calc file
    TODO: select file to open before launching LibreOffice
    Create link from FreeCAD to Calc file
    Read data from Calc file (by row,col and also by named range)
    Write data to Calc file (by row,col and also by named range)
    TODO: Create a data structure in Calc
    TODO: duplicate Calc data structre in FreeCAD
    TODO: sync data if it chnages in either location (Calc or FreeCAD)
    TODO: Write properties of selected object to Calc file
    TODO: Make data visible to FreeCAD external variables function 
    >> PHASE II
    TODO: verify path where soffice and freecad are installed (used to import libraries)
    TODO: Allow selection of tab in active sheet
    

'''

import sys
sys.path.append('/usr/lib/libreoffice/program')
sys.path.append('/usr/lib/freecad-daily/lib')

import time
import psutil
import subprocess
import re
import socket
import errno
import logging
from PySide import QtCore, QtGui
import uno
import FreeCAD
import FreeCADGui


def port_in_use(port):
    testSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    location = ("localhost", port)
    #location = ("127.0.0.1", 16793)
    #socket_status = testSocket.connect_ex(location)
    try:
        testSocket.bind(location)
    except socket.error as e:
        if e.errno == errno.EADDRINUSE:
            logging.debug(f'func port_in_use: {location} status:{e}')
            return 1
        else:
            logging.debug(f'func port_in_use: {location} status: {e}')
            return 0


def app_exist(app_name):
    from shutil import which
    return which(app_name) is not None


def check_process(name, value):
    #if process is running and if arguments include 'value' then return the PID #
    logging.debug(str(name))
    for proc in psutil.process_iter():
        try:
            # Search process name & return process PID
            processName = proc.name()
            if processName == name:
                processCmd = proc.cmdline()  # list of arguments
                for i in processCmd:
                    found = re.search('(?<=port.)\d+', i)
                    if  found:
                        logging.debug(proc.pid)
                        return proc.pid
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass
    return 0


def sofficeStart(value):
    run_soffice = [
                'soffice',
                '--accept=socket,host=localhost,port=' + str(value) +';urp;StarOffice.Service',
                '--nologo',
                '--norestore',
                '--minimized',
                '--invisible', 
            ]
    subprocess.Popen(run_soffice)
    logging.debug(f'start soffice with arg: {run_soffice}')
    time.sleep(1)


#setup_logging
LOG_FILENAME = '/mnt/data1/Python_Prj/LOFC/fc_libre.log'
LOG_FORMAT = "%(asctime)s : %(funcName)s : %(levelname)s : %(lineno)i : %(message)s"
LOG_LEVEL = ''
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG, format=LOG_FORMAT) 
logging.debug('--  New session  --')



#Test if soffice is running and listening on port
port = 2002
procID = check_process('soffice.bin', port)
if procID > 1:
    logging.debug(f'soffice.bin listening on port {procID}')
    portStatus = port_in_use(port)
    if portStatus > 0:
        logging.debug(f'Kill soffice, PID: {procID}')
        p = psutil.Process(procID)
        p.terminate()
        time.sleep(1)

logging.debug(f'start sofficel, listen on port {port}')
sofficeStart(port)
procID = check_process('soffice.bin', port)
logging.debug(f'soiffice.bin process ID: {procID}')

# common code to connect to running Calc spreadsheet
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
document = desktop.loadComponentFromURL("file:///mnt/data1/Python_Prj/LOFC/uno_test_calc.ods" ,"_blank", 0, ())
#TODO  create function to select Calc file
logging.debug("document opened ?")

#Link to active spreadsheet
active_sheet = document.CurrentController.ActiveSheet

# edit cell content
cell1 = active_sheet.getCellRangeByName("C2")
cell1.String = "Hey , I'm working ?"
logging.debug(active_sheet.getCellRangeByName("C2").String)

rangeName = active_sheet.getCellRangeByName("name_of_range")
rangeName.String = "Write to named range"
logging.debug(active_sheet.getCellRangeByName("name_of_range").String)

oRanges = document.NamedRanges.getElementNames()
for oName in oRanges:
    cell_range = document.NamedRanges.getByName(oName).ReferredCells
    row_index = cell_range.getCellByPosition(0, 0).getCellAddress().Row
    col_index = cell_range.getCellByPosition(0, 0).getCellAddress().Column
    logging.debug("NamedRange: " + oName)
    logging.debug("     Value:" + active_sheet.getCellRangeByName(oName).String)
    logging.debug("       Row: " + str(row_index + 1))
    logging.debug("    Column: " + chr(col_index + 65))
    logging.debug("----------------------------")
    
# Create App::FeaturePython object & add properties

ref_obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "fc_libre")
ref_obj.Label = "uno_test_calc.ods"
for oName in oRanges:
    value = active_sheet.getCellRangeByName(oName).String
    logging.debug(f'set property name = {oName}  |  value = {value}')
    ref_obj.addProperty("App::PropertyFloat", oName)
    setattr(ref_obj, oName, float(value))


User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by Kunda1 »

@salp Nice! Would you be interested in sharing this on github/gitlab with all the relevant test files for easier download and perhaps helpful Pull Requests from the community ?
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
User avatar
salp
Posts: 250
Joined: Thu Nov 21, 2013 11:58 pm
Location: Putnam, NY

Re: How much interest is there to integrate LibreOffice into FreeCAD?

Post by salp »

I will put this up on github
Post Reply