Source code for equipment.spreadsheet

#!/usr/bin/python3
# -*- coding: utf-8 -*-

'''Pychemqt, Chemical Engineering Process simulator
Copyright (C) 2009-2025, Juan José Gómez Romera <jjgomera@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.'''


###############################################################################
# library for spreadsheet equipment integration
###############################################################################


import os
import string

try:
    import ezodf
    import openpyxl
except:
    pass

from tools.qt import translate

from .parents import equipment


[docs] class Spreadsheet(equipment): """Clase que define un la interaccion con un hoja de calculo de libreoffice/openoffice Parámetros: project: instancia project input: entity de entrada output: entity de salida filename: Path del archivo ods datamap: Array con la estructura de datos a traspasar, cada elemento es un dicciontario con los datos de conversion de valores entity: corriente o equipo del que exportar el valor variable: nombre del valor de la variable de la corriente unidad: unidad del valor a pasar en el caso de magitudes hoja: Nombre de la hoja celda: Celda en la que colocar el dato """ title = translate("equipment", "Spreadsheet") help = "" kwargs = { "project": None, "input": "", "output": "", "filename": "", "datamap": []} kwargs_forbidden = ["project", ] @property def isCalculable(self): self.msg = "" self.status = 1 if not self.kwargs["filename"] or \ not os.path.isfile(self.kwargs["filename"]): self.msg = translate("equipment", "undefined spreadsheet filename") self.status = 0 return if not self.kwargs["datamap"]: self.msg = translate("equipment", "undefined spreadsheet data map") self.status = 3 return True
[docs] def cleanOldValues(self, **kwargs): """Si se cambia la ruta de la hoja de cálculo se reinicia el datamap""" if kwargs.get("filename", "") and \ kwargs.get("filename", "") != self.kwargs["filename"]: self.kwargs["datamap"] = [] self.kwargs.update(kwargs)
[docs] def calculo(self): ext = self.kwargs["filename"].split(".")[-1] if ext == "ods": self._dependence = "ezodf" spreadsheet = ezodf.opendoc(self.kwargs["filename"]) self.sheets = [name for name in spreadsheet.sheets.names()] if self.kwargs["datamap"]: for data in self.kwargs["datamap"]: entity = self.kwargs["project"].getObject(data["entity"]) sheet = spreadsheet.sheets[data["sheet"]] indProp = entity.propertiesTitle().index(data["property"]) if entity.propertiesUnit()[indProp] == str: value = entity.__getattribute__( entity.propertiesAttribute()[indProp]) else: indUnit = entity.propertiesUnit()[indProp].__text__.index(data["unit"]) units = entity.propertiesUnit()[indProp].__units__ value = entity.__getattribute__(entity.propertiesAttribute()[indProp]).__getattribute__(units[indUnit]) # Chequear celda = list(data["cell"]) column = [] while celda[0] in string.ascii_uppercase: column.append(celda.pop(0)) base = len(string.ascii_uppercase) exponente = 0 columna = 0 while column: ordinal = ord(column.pop())-64 columna += ordinal*base**exponente exponente += 1 fila = int("".join(celda)) if fila > sheet.nrows(): sheet.append_rows(fila-sheet.nrows()) if columna > sheet.ncols(): sheet.append_columns(columna-sheet.ncols()) sheet[data["cell"]].set_value(value) spreadsheet.save() elif ext == "xlsx": self._dependence = "openpyxl" spreadsheet = openpyxl.load_workbook(self.kwargs["filename"]) self.sheets = spreadsheet.get_sheet_names() if self.kwargs["datamap"]: for data in self.kwargs["datamap"]: entity = self.kwargs["project"].getObject(data["entity"]) sheet = spreadsheet[data["sheet"]] indProp = entity.propertiesTitle().index(data["property"]) if entity.propertiesUnit()[indProp] == str: value = entity.__getattribute__(entity.propertiesAttribute()[indProp]) else: indUnit = entity.propertiesUnit()[indProp].__text__.index(data["unit"]) units = entity.propertiesUnit()[indProp].__units__ value = entity.__getattribute__(entity.propertiesAttribute()[indProp]).__getattribute__(units[indUnit]) sheet[data["cell"]] = value comentario = openpyxl.comments.Comment("{0[entity]}.{0[property]}.{0[unit]} ---> {0[sheet]}.{0[cell]}".format(data), 'pychemqt') sheet[data["cell"]].comment = comentario spreadsheet.save(".".join(self.kwargs["filename"].split(".")[:-1])+"-bak"+".xlsx") elif ext == "xls": # TODO: Implement old office support pass self.salida = []
[docs] def writeListtoJSON(self, kwarg, key, value): """Personalizar en el caso de equipos con listas complejas""" kwarg_list = {} if key == "datamap": for i, data in enumerate(value): kwarg_list[i] = data kwarg[key] = kwarg_list
[docs] def readListFromJSON(self, data, key): """Read list from file, customize in entities with complex list""" kwarg = [] if key == "datamap": for i, data in data[key].items(): kwarg.append(data) return kwarg
[docs] def propTxt(self): txt = "#---------------" txt += translate("equipment", "Data map") txt += "-----------------#" + os.linesep txt += self.propertiesToText(0) if self.kwargs["datamap"]: for data in self.kwargs["datamap"]: txt += "{0[entity]}.{0[property]}.{0[unit]} ---> {0[sheet]}.{0[cell]}".format(data)+os.linesep else: txt += translate("equipment", "Undefined")+os.linesep return txt
[docs] @classmethod def propertiesEquipment(cls): l = [(translate("equipment", "Spreadsheet path"), "filename", str), (translate("equipment", "Data map"), "datamap", None)] return l
[docs] def propertiesListTitle(self, index): lista = [] for data in self.kwargs["datamap"]: lista.append("{0[entity]}.{0[property]}.{0[unit]} ---> {0[sheet]}.{0[cell]}".format(data)) return lista
[docs] def writeStatetoJSON(self, state): """Write instance parameter to file""" state["sheets"] = self.sheets
[docs] def readStatefromJSON(self, state): """Load instance parameter from saved file""" self.sheets = state["sheets"] self.salida = [None]
if __name__ == '__main__': spreadsheet=Spreadsheet(filename="/media/datos/ejemplo.ods") # spreadsheet = ezodf.opendoc("/media/datos/ejemplo.ods") # hoja=spreadsheet.sheets["Prueba"] # hoja["B6"].set_value(5.) # hoja["B7"].set_value(4.) # spreadsheet.save() # print hoja["D6"].value # spreadsheet=Spreadsheet(filename="/media/datos/ejemplo.xlsx") # ws=wb["Calculos"] # ws['I4']=32 # wb.save('/media/datos/ejemplo2.xlsx') # import xlrd # # book = xlrd.open_workbook("/media/datos/ejemplo.xls") # # for sheet_name in book.sheet_names(): # sheet = book.sheet_by_name(sheet_name) ## print sheet.row_values(0)[0] # print sheet_name # print dir(book) # book.save()