1069 lines
27 KiB
Python
1069 lines
27 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import datetime
|
|
from decimal import Decimal
|
|
from typing import Any, Union
|
|
|
|
from com.sun.star.sheet import CellFlags
|
|
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
|
|
|
|
from .easymain import (log, DATE_OFFSET,
|
|
BaseObject, Color,
|
|
dict_to_property, run_in_thread, set_properties
|
|
)
|
|
from .easydoc import LODocument
|
|
from .easyevents import EventsRangeSelectionListener, LOEvents
|
|
from .easyshape import LOShapes, LOShape
|
|
from .easydrawpage import LODrawPage
|
|
from .easyforms import LOForms
|
|
|
|
|
|
SECONDS_DAY = 60 * 60 * 24
|
|
ONLY_VALUES = CellFlags.VALUE + CellFlags.DATETIME + CellFlags.STRING
|
|
|
|
|
|
class LOCellStyle():
|
|
|
|
def __init__(self, obj):
|
|
self._obj = obj
|
|
|
|
def __str__(self):
|
|
return f'CellStyle: {self.name}'
|
|
|
|
@property
|
|
def obj(self):
|
|
return self._obj
|
|
|
|
@property
|
|
def name(self):
|
|
return self.obj.Name
|
|
|
|
@property
|
|
def properties(self):
|
|
properties = self.obj.PropertySetInfo.Properties
|
|
data = {p.Name: getattr(self.obj, p.Name) for p in properties}
|
|
return data
|
|
@properties.setter
|
|
def properties(self, values):
|
|
set_properties(self.obj, values)
|
|
|
|
|
|
class LOCellStyles():
|
|
|
|
def __init__(self, obj, doc):
|
|
self._obj = obj
|
|
self._doc = doc
|
|
|
|
def __len__(self):
|
|
return len(self.obj)
|
|
|
|
def __getitem__(self, index):
|
|
return LOCellStyle(self.obj[index])
|
|
|
|
def __setitem__(self, key, value):
|
|
self.obj[key] = value
|
|
|
|
def __delitem__(self, key):
|
|
if not isinstance(key, str):
|
|
key = key.Name
|
|
del self.obj[key]
|
|
|
|
def __contains__(self, item):
|
|
return item in self.obj
|
|
|
|
@property
|
|
def obj(self):
|
|
return self._obj
|
|
|
|
@property
|
|
def names(self):
|
|
return self.obj.ElementNames
|
|
|
|
def new(self, name: str):
|
|
obj = self._doc.create_instance('com.sun.star.style.CellStyle')
|
|
self.obj[name] = obj
|
|
return LOCellStyle(obj)
|
|
|
|
|
|
# ~ IsFiltered,
|
|
# ~ IsManualPageBreak,
|
|
# ~ IsStartOfNewPage
|
|
class LOSheetRows():
|
|
|
|
def __init__(self, sheet, obj):
|
|
self._sheet = sheet
|
|
self._obj = obj
|
|
|
|
def __getitem__(self, index):
|
|
if isinstance(index, int):
|
|
rows = LOSheetRows(self._sheet, self.obj[index])
|
|
else:
|
|
rango = self._sheet[index.start:index.stop,0:]
|
|
rows = LOSheetRows(self._sheet, rango.obj.Rows)
|
|
return rows
|
|
|
|
def __len__(self):
|
|
return self.obj.Count
|
|
|
|
def __str__(self):
|
|
return self.obj.Name
|
|
|
|
@property
|
|
def obj(self):
|
|
return self._obj
|
|
|
|
@property
|
|
def visible(self):
|
|
return self._obj.IsVisible
|
|
@visible.setter
|
|
def visible(self, value):
|
|
self._obj.IsVisible = value
|
|
|
|
@property
|
|
def color(self):
|
|
return self.obj.CellBackColor
|
|
@color.setter
|
|
def color(self, value):
|
|
self.obj.CellBackColor = value
|
|
|
|
@property
|
|
def is_transparent(self):
|
|
return self.obj.IsCellBackgroundTransparent
|
|
@is_transparent.setter
|
|
def is_transparent(self, value):
|
|
self.obj.IsCellBackgroundTransparent = value
|
|
|
|
@property
|
|
def height(self):
|
|
return self.obj.Height
|
|
@height.setter
|
|
def height(self, value):
|
|
self.obj.Height = value
|
|
|
|
def optimal(self):
|
|
self.obj.OptimalHeight = True
|
|
return
|
|
|
|
def insert(self, index, count):
|
|
self.obj.insertByIndex(index, count)
|
|
return
|
|
|
|
def remove(self, index, count):
|
|
self.obj.removeByIndex(index, count)
|
|
return
|
|
|
|
|
|
class LOCalcRanges(object):
|
|
|
|
def __init__(self, obj):
|
|
self._obj = obj
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
pass
|
|
|
|
def __len__(self):
|
|
return self._obj.Count
|
|
|
|
def __iter__(self):
|
|
self._index = 0
|
|
return self
|
|
|
|
def __next__(self):
|
|
try:
|
|
r = self.obj[self._index]
|
|
rango = LOCalcRange(r)
|
|
except IndexError:
|
|
raise StopIteration
|
|
|
|
self._index += 1
|
|
return rango
|
|
|
|
def __contains__(self, item):
|
|
return self._obj.hasByName(item.name)
|
|
|
|
def __getitem__(self, index):
|
|
r = self.obj[index]
|
|
rango = LOCalcRange(r)
|
|
return rango
|
|
|
|
def __str__(self):
|
|
s = f'Ranges: {self.names}'
|
|
return s
|
|
|
|
@property
|
|
def obj(self):
|
|
return self._obj
|
|
|
|
@property
|
|
def names(self):
|
|
return self.obj.ElementNames
|
|
|
|
@property
|
|
def data(self):
|
|
rows = [r.data for r in self]
|
|
return rows
|
|
@data.setter
|
|
def data(self, values):
|
|
for i, data in enumerate(values):
|
|
self[i].data = data
|
|
|
|
@property
|
|
def style(self):
|
|
return ''
|
|
@style.setter
|
|
def style(self, value):
|
|
for r in self:
|
|
r.style = value
|
|
|
|
def add(self, rangos: Any):
|
|
if isinstance(rangos, LOCalcRange):
|
|
rangos = (rangos,)
|
|
for r in rangos:
|
|
self.obj.addRangeAddress(r.range_address, False)
|
|
return
|
|
|
|
def remove(self, rangos: Any):
|
|
if isinstance(rangos, LOCalcRange):
|
|
rangos = (rangos,)
|
|
for r in rangos:
|
|
self.obj.removeRangeAddress(r.range_address)
|
|
return
|
|
|
|
|
|
class LOCalcRange():
|
|
CELL = 'ScCellObj'
|
|
|
|
def __init__(self, obj):
|
|
self._obj = obj
|
|
self._is_cell = obj.ImplementationName == self.CELL
|
|
|
|
def __contains__(self, rango):
|
|
if isinstance(rango, LOCalcRange):
|
|
address = rango.range_address
|
|
else:
|
|
address = rango.RangeAddress
|
|
result = self.cursor.queryIntersection(address)
|
|
return bool(result.Count)
|
|
|
|
def __getitem__(self, index):
|
|
return LOCalcRange(self.obj[index])
|
|
|
|
def __iter__(self):
|
|
self._r = 0
|
|
self._c = 0
|
|
return self
|
|
|
|
def __next__(self):
|
|
try:
|
|
rango = self[self._r, self._c]
|
|
except Exception as e:
|
|
raise StopIteration
|
|
self._c += 1
|
|
if self._c == self.obj.Columns.Count:
|
|
self._c = 0
|
|
self._r +=1
|
|
return rango
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
pass
|
|
|
|
def __len__(self):
|
|
ra = self.range_address
|
|
rows = ra.EndRow - ra.StartRow + 1
|
|
return rows
|
|
|
|
def __str__(self):
|
|
s = f'Range: {self.name}'
|
|
if self.is_cell:
|
|
s = f'Cell: {self.name}'
|
|
return s
|
|
|
|
@property
|
|
def obj(self):
|
|
"""Get original object pyUNO"""
|
|
return self._obj
|
|
|
|
@property
|
|
def len_columns(self):
|
|
"""Get len columns"""
|
|
ra = self.range_address
|
|
cols = ra.EndColumn - ra.StartColumn + 1
|
|
return cols
|
|
|
|
@property
|
|
def is_cell(self):
|
|
"""True if range is cell"""
|
|
return self._is_cell
|
|
|
|
@property
|
|
def is_range(self):
|
|
return not self._is_cell
|
|
|
|
@property
|
|
def name(self):
|
|
"""Return the range address like string"""
|
|
return self.obj.AbsoluteName
|
|
|
|
@property
|
|
def name2(self):
|
|
"""Return the range address like string"""
|
|
return self.name.replace('$', '')
|
|
|
|
@property
|
|
def address(self):
|
|
"""Return com.sun.star.table.CellAddress"""
|
|
return self.obj.CellAddress
|
|
|
|
@property
|
|
def range_address(self):
|
|
"""Return com.sun.star.table.CellRangeAddress"""
|
|
return self.obj.RangeAddress
|
|
|
|
@property
|
|
def sheet(self):
|
|
"""Return sheet parent"""
|
|
return LOCalcSheet(self.obj.Spreadsheet)
|
|
|
|
@property
|
|
def doc(self):
|
|
"""Return doc parent"""
|
|
doc = self.obj.Spreadsheet.DrawPage.Forms.Parent
|
|
return LOCalc(doc)
|
|
|
|
@property
|
|
def style(self):
|
|
"""Get or set cell style"""
|
|
return self.obj.CellStyle
|
|
@style.setter
|
|
def style(self, value):
|
|
self.obj.CellStyle = value
|
|
|
|
@property
|
|
def current_region(self):
|
|
"""Return current region"""
|
|
cursor = self.cursor
|
|
cursor.collapseToCurrentRegion()
|
|
rango = self.obj.Spreadsheet[cursor.AbsoluteName]
|
|
return LOCalcRange(rango)
|
|
|
|
@property
|
|
def back_color(self):
|
|
"""Get or set cell back color"""
|
|
return self._obj.CellBackColor
|
|
@back_color.setter
|
|
def back_color(self, value):
|
|
self._obj.CellBackColor = Color()(value)
|
|
|
|
@property
|
|
def type(self):
|
|
"""Get type of content.
|
|
See https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1table.html#affea688ab9e00781fa35d8a790d10f0e
|
|
"""
|
|
return self.obj.Type
|
|
|
|
@property
|
|
def error(self):
|
|
"""Get number error in formulas"""
|
|
return self.obj.getError()
|
|
|
|
@property
|
|
def string(self):
|
|
"""Get or set content like string"""
|
|
return self.obj.String
|
|
@string.setter
|
|
def string(self, value):
|
|
self.obj.setString(value)
|
|
|
|
@property
|
|
def float(self):
|
|
"""Get or set content like value"""
|
|
return self.obj.Value
|
|
@float.setter
|
|
def float(self, value):
|
|
self.obj.setValue(value)
|
|
|
|
@property
|
|
def formula(self):
|
|
"""Get or set formula"""
|
|
return self.obj.Formula
|
|
@formula.setter
|
|
def formula(self, value):
|
|
self.obj.setFormula(value)
|
|
|
|
@property
|
|
def date(self):
|
|
"""Get or set date"""
|
|
value = int(self.obj.Value)
|
|
date = datetime.date.fromordinal(value + DATE_OFFSET)
|
|
return date
|
|
@date.setter
|
|
def date(self, value):
|
|
d = value.toordinal()
|
|
self.float = d - DATE_OFFSET
|
|
|
|
@property
|
|
def time(self):
|
|
"""Get or set time"""
|
|
seconds = self.obj.Value * SECONDS_DAY
|
|
time_delta = datetime.timedelta(seconds=seconds)
|
|
time = (datetime.datetime.min + time_delta).time()
|
|
return time
|
|
@time.setter
|
|
def time(self, value):
|
|
d = (value.hour * 3600 + value.minute * 60 + value.second) / SECONDS_DAY
|
|
self.float = d
|
|
|
|
@property
|
|
def datetime(self):
|
|
"""Get or set datetime"""
|
|
return datetime.datetime.combine(self.date, self.time)
|
|
@datetime.setter
|
|
def datetime(self, value):
|
|
d = value.toordinal()
|
|
t = (value - datetime.datetime.fromordinal(d)).seconds / SECONDS_DAY
|
|
self.float = d - DATE_OFFSET + t
|
|
|
|
@property
|
|
def value(self):
|
|
"""Get or set value, automatically get type data"""
|
|
v = None
|
|
if self.type == VALUE:
|
|
v = self.float
|
|
elif self.type == TEXT:
|
|
v = self.string
|
|
elif self.type == FORMULA:
|
|
v = self.formula
|
|
return v
|
|
@value.setter
|
|
def value(self, value):
|
|
if isinstance(value, str):
|
|
if value[0] in '=':
|
|
self.formula = value
|
|
else:
|
|
self.string = value
|
|
elif isinstance(value, Decimal):
|
|
self.float = float(value)
|
|
elif isinstance(value, (int, float, bool)):
|
|
self.float = value
|
|
elif isinstance(value, datetime.datetime):
|
|
self.datetime = value
|
|
elif isinstance(value, datetime.date):
|
|
self.date = value
|
|
elif isinstance(value, datetime.time):
|
|
self.time = value
|
|
|
|
@property
|
|
def data_array(self):
|
|
"""Get or set DataArray"""
|
|
return self.obj.DataArray
|
|
@data_array.setter
|
|
def data_array(self, data):
|
|
self.obj.DataArray = data
|
|
|
|
@property
|
|
def formula_array(self):
|
|
"""Get or set FormulaArray"""
|
|
return self.obj.FormulaArray
|
|
@formula_array.setter
|
|
def formula_array(self, data):
|
|
self.obj.FormulaArray = data
|
|
|
|
@property
|
|
def data(self):
|
|
"""Get like data_array, for set, if range is cell, automatically ajust size range.
|
|
"""
|
|
return self.data_array
|
|
@data.setter
|
|
def data(self, values):
|
|
if self.is_cell:
|
|
cols = len(values[0])
|
|
rows = len(values)
|
|
if cols == 1 and rows == 1:
|
|
self.data_array = values
|
|
else:
|
|
self.to_size(cols, rows).data = values
|
|
else:
|
|
self.data_array = values
|
|
|
|
@property
|
|
def dict(self):
|
|
"""Get or set data from to dict"""
|
|
rows = self.data
|
|
k = rows[0]
|
|
data = [dict(zip(k, r)) for r in rows[1:]]
|
|
return data
|
|
@dict.setter
|
|
def dict(self, values):
|
|
data = [tuple(values[0].keys())]
|
|
data += [tuple(d.values()) for d in values]
|
|
self.data = data
|
|
|
|
@property
|
|
def next_free(self):
|
|
"""Get next free cell"""
|
|
ra = self.current_region.range_address
|
|
col = ra.StartColumn
|
|
row = ra.EndRow + 1
|
|
return LOCalcRange(self.sheet[row, col].obj)
|
|
|
|
@property
|
|
def range_data(self):
|
|
"""Get range without headers"""
|
|
rango = self.current_region
|
|
ra = rango.range_address
|
|
row1 = ra.StartRow + 1
|
|
row2 = ra.EndRow + 1
|
|
col1 = ra.StartColumn
|
|
col2 = ra.EndColumn + 1
|
|
return LOCalcRange(self.sheet[row1:row2, col1:col2].obj)
|
|
|
|
@property
|
|
def array_formula(self):
|
|
return self.obj.ArrayFormula
|
|
@array_formula.setter
|
|
def array_formula(self, value):
|
|
self.obj.ArrayFormula = value
|
|
|
|
@property
|
|
def cursor(self):
|
|
cursor = self.obj.Spreadsheet.createCursorByRange(self.obj)
|
|
return cursor
|
|
|
|
# ~ To doc
|
|
@property
|
|
def position(self):
|
|
return self.obj.Position
|
|
|
|
# ~ To doc
|
|
@property
|
|
def size(self):
|
|
return self.obj.Size
|
|
|
|
@property
|
|
def height(self):
|
|
return self.obj.Size.Height
|
|
|
|
@property
|
|
def width(self):
|
|
return self.obj.Size.Width
|
|
|
|
@property
|
|
def x(self):
|
|
return self.obj.Position.X
|
|
|
|
@property
|
|
def y(self):
|
|
return self.obj.Position.Y
|
|
|
|
# ~ To doc
|
|
@property
|
|
def possize(self):
|
|
data = {
|
|
'Width': self.size.Width,
|
|
'Height': self.size.Height,
|
|
'X': self.position.X,
|
|
'Y': self.position.Y,
|
|
}
|
|
return data
|
|
|
|
@property
|
|
def rows(self):
|
|
return LOSheetRows(self.sheet, self.obj.Rows)
|
|
|
|
@property
|
|
def row(self):
|
|
r1 = self.address.Row
|
|
r2 = r1 + 1
|
|
ra = self.current_region.range_address
|
|
c1 = ra.StartColumn
|
|
c2 = ra.EndColumn + 1
|
|
return LOCalcRange(self.sheet[r1:r2, c1:c2].obj)
|
|
|
|
def clear(self, what: int=ONLY_VALUES):
|
|
"""Clear contents"""
|
|
# ~ http://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html
|
|
self.obj.clearContents(what)
|
|
return
|
|
|
|
def offset(self, rows=0, cols=1):
|
|
ra = self.range_address
|
|
col = ra.EndColumn + cols
|
|
row = ra.EndRow + rows
|
|
return LOCalcRange(self.sheet[row, col].obj)
|
|
|
|
def to_size(self, cols: int, rows: int):
|
|
cursor = self.cursor
|
|
cursor.collapseToSize(cols, rows)
|
|
rango = self.obj.Spreadsheet[cursor.AbsoluteName]
|
|
return LOCalcRange(rango)
|
|
|
|
|
|
class LOCalcSheet(BaseObject):
|
|
|
|
def __init__(self, obj):
|
|
super().__init__(obj)
|
|
|
|
def __getitem__(self, index):
|
|
return LOCalcRange(self.obj[index])
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
pass
|
|
|
|
def __str__(self):
|
|
return f'Sheet: {self.name}'
|
|
|
|
@property
|
|
def doc(self):
|
|
return LOCalc(self.obj.DrawPage.Forms.Parent)
|
|
|
|
@property
|
|
def name(self):
|
|
return self._obj.Name
|
|
@name.setter
|
|
def name(self, value):
|
|
self._obj.Name = value
|
|
|
|
@property
|
|
def code_name(self):
|
|
return self._obj.CodeName
|
|
@code_name.setter
|
|
def code_name(self, value):
|
|
self._obj.CodeName = value
|
|
|
|
@property
|
|
def visible(self):
|
|
return self._obj.IsVisible
|
|
@visible.setter
|
|
def visible(self, value):
|
|
self._obj.IsVisible = value
|
|
|
|
@property
|
|
def color(self):
|
|
return self._obj.TabColor
|
|
@color.setter
|
|
def color(self, value):
|
|
self._obj.TabColor = Color()(value)
|
|
|
|
@property
|
|
def used_area(self):
|
|
cursor = self.create_cursor()
|
|
cursor.gotoEndOfUsedArea(True)
|
|
return self[cursor.AbsoluteName]
|
|
|
|
@property
|
|
def is_protected(self):
|
|
return self._obj.isProtected()
|
|
|
|
@property
|
|
def password(self):
|
|
return ''
|
|
@password.setter
|
|
def password(self, value):
|
|
self.obj.protect(value)
|
|
|
|
@property
|
|
def draw_page(self):
|
|
return LODrawPage(self.obj.DrawPage)
|
|
@property
|
|
def dp(self):
|
|
return self.draw_page
|
|
@property
|
|
def shapes(self):
|
|
return self.draw_page
|
|
|
|
@property
|
|
def forms(self):
|
|
return LOForms(self.obj.DrawPage)
|
|
|
|
@property
|
|
def events(self):
|
|
return LOEvents(self.obj.Events)
|
|
|
|
@property
|
|
def height(self):
|
|
return self.obj.Size.Height
|
|
|
|
@property
|
|
def width(self):
|
|
return self.obj.Size.Width
|
|
|
|
def protect(self, value):
|
|
self.obj.protect(value)
|
|
return
|
|
|
|
def unprotect(self, value):
|
|
try:
|
|
self.obj.unprotect(value)
|
|
return True
|
|
except:
|
|
pass
|
|
return False
|
|
|
|
def move(self, pos: int=-1):
|
|
index = pos
|
|
if pos < 0:
|
|
index = len(self.doc)
|
|
self.doc.move(self.name, index)
|
|
return
|
|
|
|
def remove(self):
|
|
self.doc.remove(self.name)
|
|
return
|
|
|
|
def copy(self, new_name: str='', pos: int=-1):
|
|
index = pos
|
|
if pos < 0:
|
|
index = len(self.doc)
|
|
new_sheet = self.doc.copy_sheet(self.name, new_name, index)
|
|
return new_sheet
|
|
|
|
def copy_to(self, doc: Any, target: str='', pos: int=-1):
|
|
"""Copy sheet to other document.
|
|
"""
|
|
index = pos
|
|
if pos < 0:
|
|
index = len(doc)
|
|
|
|
new_name = target or self.name
|
|
sheet = doc.copy_from(self.doc, self.name, new_name, index)
|
|
return sheet
|
|
|
|
def activate(self):
|
|
"""Activate sheet"""
|
|
self.doc.activate(self.obj)
|
|
return
|
|
|
|
def create_cursor(self, rango: Any=None):
|
|
if rango is None:
|
|
cursor = self.obj.createCursor()
|
|
else:
|
|
obj = rango
|
|
if hasattr(rango, 'obj'):
|
|
obj = rango.obj
|
|
cursor = self.obj.createCursorByRange(obj)
|
|
return cursor
|
|
|
|
|
|
class LOCalcSheetsCodeName(BaseObject):
|
|
"""Access by code name sheet"""
|
|
|
|
def __init__(self, obj):
|
|
super().__init__(obj)
|
|
self._sheets = obj.Sheets
|
|
|
|
def __getitem__(self, index):
|
|
"""Index access"""
|
|
for sheet in self._sheets:
|
|
if sheet.CodeName == index:
|
|
return LOCalcSheet(sheet)
|
|
raise IndexError
|
|
|
|
def __iter__(self):
|
|
self._i = 0
|
|
return self
|
|
|
|
def __next__(self):
|
|
"""Interation sheets"""
|
|
try:
|
|
sheet = LOCalcSheet(self._sheets[self._i])
|
|
except Exception as e:
|
|
raise StopIteration
|
|
self._i += 1
|
|
return sheet
|
|
|
|
def __contains__(self, item):
|
|
"""Contains"""
|
|
for sheet in self._sheets:
|
|
if sheet.CodeName == item:
|
|
return True
|
|
return False
|
|
|
|
|
|
class LOCalc(LODocument):
|
|
"""Classe for Calc module"""
|
|
TYPE_RANGES = ('ScCellObj', 'ScCellRangeObj')
|
|
RANGES = 'ScCellRangesObj'
|
|
SHAPE = 'com.sun.star.drawing.SvxShapeCollection'
|
|
_type = 'calc'
|
|
|
|
def __init__(self, obj):
|
|
super().__init__(obj)
|
|
self._sheets = obj.Sheets
|
|
self._listener_range_selection = None
|
|
|
|
def __getitem__(self, index):
|
|
"""Index access"""
|
|
return LOCalcSheet(self._sheets[index])
|
|
|
|
def __setitem__(self, key: str, value: Any):
|
|
"""Insert new sheet"""
|
|
self._sheets[key] = value
|
|
|
|
def __len__(self):
|
|
"""Count sheets"""
|
|
return self._sheets.Count
|
|
|
|
def __contains__(self, item):
|
|
"""Contains"""
|
|
return item in self._sheets
|
|
|
|
def __iter__(self):
|
|
self._i = 0
|
|
return self
|
|
|
|
def __next__(self):
|
|
"""Interation sheets"""
|
|
try:
|
|
sheet = LOCalcSheet(self._sheets[self._i])
|
|
except Exception as e:
|
|
raise StopIteration
|
|
self._i += 1
|
|
return sheet
|
|
|
|
def __str__(self):
|
|
return f'Calc: {self.title}'
|
|
|
|
@property
|
|
def sheets(self):
|
|
"""Acces by code name sheet"""
|
|
return LOCalcSheetsCodeName(self.obj)
|
|
|
|
@property
|
|
def headers(self):
|
|
"""Get true if is visible columns/rows headers"""
|
|
return self._cc.ColumnRowHeaders
|
|
@headers.setter
|
|
def headers(self, value):
|
|
"""Set visible columns/rows headers"""
|
|
self._cc.ColumnRowHeaders = value
|
|
|
|
@property
|
|
def tabs(self):
|
|
"""Get true if is visible tab sheets"""
|
|
return self._cc.SheetTabs
|
|
@tabs.setter
|
|
def tabs(self, value):
|
|
"""Set visible tab sheets"""
|
|
self._cc.SheetTabs = value
|
|
|
|
@property
|
|
def selection(self):
|
|
"""Get current seleccion"""
|
|
sel = None
|
|
selection = self.obj.CurrentSelection
|
|
type_obj = selection.ImplementationName
|
|
|
|
if type_obj in self.TYPE_RANGES:
|
|
sel = LOCalcRange(selection)
|
|
elif type_obj == self.RANGES:
|
|
sel = LOCalcRanges(selection)
|
|
elif type_obj == self.SHAPE:
|
|
if len(selection) == 1:
|
|
sel = LOShape(selection[0])
|
|
else:
|
|
sel = LOShapes(selection)
|
|
else:
|
|
log.debug(type_obj)
|
|
return sel
|
|
|
|
@property
|
|
def active(self):
|
|
"""Get active sheet"""
|
|
return LOCalcSheet(self._cc.ActiveSheet)
|
|
|
|
@property
|
|
def names(self):
|
|
"""Get all sheet names"""
|
|
names = self.obj.Sheets.ElementNames
|
|
return names
|
|
|
|
@property
|
|
def events(self):
|
|
"""Get class events"""
|
|
return LOEvents(self.obj.Events)
|
|
|
|
def ranges(self):
|
|
"""Create ranges container"""
|
|
obj = self._create_instance('com.sun.star.sheet.SheetCellRanges')
|
|
return LOCalcRanges(obj)
|
|
|
|
def new_sheet(self):
|
|
"""Create new instance sheet"""
|
|
s = self._create_instance('com.sun.star.sheet.Spreadsheet')
|
|
return s
|
|
|
|
def select(self, rango: Any):
|
|
"""Select range"""
|
|
obj = rango
|
|
if hasattr(rango, 'obj'):
|
|
obj = rango.obj
|
|
self._cc.select(obj)
|
|
return
|
|
|
|
@run_in_thread
|
|
def start_range_selection(self, controllers: Any, args: dict={}):
|
|
"""Start select range selection by user
|
|
|
|
`See Api RangeSelectionArguments <https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1sheet_1_1RangeSelectionArguments.html>`_
|
|
"""
|
|
if args:
|
|
args['CloseOnMouseRelease'] = args.get('CloseOnMouseRelease', True)
|
|
else:
|
|
args = dict(
|
|
Title = 'Please select a range',
|
|
CloseOnMouseRelease = True)
|
|
properties = dict_to_property(args)
|
|
|
|
self._listener_range_selection = EventsRangeSelectionListener(controllers(self))
|
|
self._cc.addRangeSelectionListener(self._listener_range_selection)
|
|
self._cc.startRangeSelection(properties)
|
|
return
|
|
|
|
def remove_range_selection_listener(self):
|
|
"""Remove range listener"""
|
|
if not self._listener_range_selection is None:
|
|
self._cc.removeRangeSelectionListener(self._listener_range_selection)
|
|
return
|
|
|
|
def activate(self, sheet: Union[str, LOCalcSheet]):
|
|
"""Activate sheet
|
|
|
|
:param sheet: Sheet to activate
|
|
:type sheet: str, pyUno or LOCalcSheet
|
|
"""
|
|
obj = sheet
|
|
if isinstance(sheet, LOCalcSheet):
|
|
obj = sheet.obj
|
|
elif isinstance(sheet, str):
|
|
obj = self._sheets[sheet]
|
|
self._cc.setActiveSheet(obj)
|
|
return
|
|
|
|
def insert(self, name: Union[str, list, tuple]):
|
|
"""Insert new sheet
|
|
|
|
:param name: Name new sheet, or iterable with names.
|
|
:type name: str, list or tuple
|
|
:return: New last instance sheet.
|
|
:rtype: LOCalcSheet
|
|
"""
|
|
names = name
|
|
if isinstance(name, str):
|
|
names = (name,)
|
|
for n in names:
|
|
self._sheets[n] = self._create_instance('com.sun.star.sheet.Spreadsheet')
|
|
return LOCalcSheet(self._sheets[n])
|
|
|
|
def move(self, sheet: Union[str, LOCalcSheet], pos: int=-1):
|
|
"""Move sheet name to position
|
|
|
|
:param sheet: Instance or Name sheet to move
|
|
:type sheet: LOCalcSheet or str
|
|
:param pos: New position, if pos=-1 move to end
|
|
:type pos: int
|
|
"""
|
|
name = sheet
|
|
index = pos
|
|
if pos < 0:
|
|
index = len(self)
|
|
if isinstance(sheet, LOCalcSheet):
|
|
name = sheet.name
|
|
self._sheets.moveByName(name, index)
|
|
return
|
|
|
|
def remove(self, sheet: Union[str, LOCalcSheet]):
|
|
"""Remove sheet by name
|
|
|
|
:param sheet: Instance or Name sheet to move
|
|
:type sheet: LOCalcSheet or str
|
|
"""
|
|
name = sheet
|
|
if isinstance(sheet, LOCalcSheet):
|
|
name = sheet.name
|
|
self._sheets.removeByName(name)
|
|
return
|
|
|
|
def _get_new_name_sheet(self, name):
|
|
i = 1
|
|
new_name = f'{name}_{i}'
|
|
while new_name in self:
|
|
i += 1
|
|
new_name = f'{name}_{i}'
|
|
return new_name
|
|
|
|
def copy_sheet(self, sheet: Union[str, LOCalcSheet], new_name: str='', pos: int=-1):
|
|
"""Copy sheet
|
|
"""
|
|
name = sheet
|
|
if isinstance(sheet, LOCalcSheet):
|
|
name = sheet.name
|
|
index = pos
|
|
if pos < 0:
|
|
index = len(self)
|
|
if not new_name:
|
|
new_name = self._get_new_name_sheet(name)
|
|
self._sheets.copyByName(name, new_name, index)
|
|
return LOCalcSheet(self._sheets[new_name])
|
|
|
|
def copy_from(self, doc: Any, source: Any=None, target: Any=None, pos: int=-1):
|
|
"""Copy sheet from document
|
|
"""
|
|
index = pos
|
|
if pos < 0:
|
|
index = len(self)
|
|
|
|
names = source
|
|
if not source:
|
|
names = doc.names
|
|
elif isinstance(source, str):
|
|
names = (source,)
|
|
elif isinstance(source, LOCalcSheet):
|
|
names = (source.name,)
|
|
|
|
new_names = target
|
|
if not target:
|
|
new_names = names
|
|
elif isinstance(target, str):
|
|
new_names = (target,)
|
|
|
|
for i, name in enumerate(names):
|
|
self._sheets.importSheet(doc.obj, name, index + i)
|
|
self[index + i].name = new_names[i]
|
|
|
|
return LOCalcSheet(self._sheets[index])
|
|
|
|
def sort(self, reverse=False):
|
|
"""Sort sheets by name
|
|
|
|
:param reverse: For order in reverse
|
|
:type reverse: bool
|
|
"""
|
|
names = sorted(self.names, reverse=reverse)
|
|
for i, n in enumerate(names):
|
|
self.move(n, i)
|
|
return
|
|
|
|
def get_ranges(self, address: str):
|
|
"""Get the same range address in each sheet.
|
|
"""
|
|
ranges = self.ranges()
|
|
ranges.add([sheet[address] for sheet in self])
|
|
return ranges
|
|
|
|
@property
|
|
def cs(self):
|
|
return self.cell_styles
|
|
@property
|
|
def cell_styles(self):
|
|
obj = self.obj.StyleFamilies['CellStyles']
|
|
return LOCellStyles(obj, self)
|