Source code for diaGrabber.source.libreOfficeCalc
# -*- coding: utf-8 *-*
#bla
#
#
import sys
import ooolib
# open/libre-office support
# see old: http://sourceforge.net/projects/ooolib/
# see new: https://code.google.com/p/odslib-python/
from _dimension import _dimension
from _source import _source
[docs]class libreOfficeCalc(_source):
'''allow to read values from a libre/open-office-calc document'''
##########mmist
def __init__(self, ODS_file_name, sheet_name_or_number,
data_type="unknown", print_error_when_cell_is_empty = False):
'''prepare for reading values from an libreOffice-calc-document
needs:
* ODS_file_name = "name of the file" e.g. "myfile.ods"
* sheet_name_or_number ="name" OR number of the sheet e.g. "sheet1" OR 4
'''
super(libreOfficeCalc,self).__init__(data_type)
self.file_name = ODS_file_name
self.doc = ooolib.Calc()
self.doc.load(self.file_name)
self.empty_cell_list = []
self.finished_building_empty_cell_list = False
self.print_error_when_cell_is_empty = print_error_when_cell_is_empty
self.sheet_name_or_number = sheet_name_or_number
self._readout_every_n_line = 1
self._index_counter = 0 #helps to indices the dimensions
self.file_dim = []
self.coord_list = []
[docs] def setReadoutEveryNLine(self, readout_every_n_line):
self._readout_every_n_line = int(readout_every_n_line)
[docs] def dimension(self, name, cell_range):
'''
needs:
* cell_range = "START:STOP" e.g. "C2:C1000"
* it's also possible to scan multiple collums... just type e.g. "A1:E10"
'''
return self._ODSdimension(self, name, cell_range)
######PRIVATE############
class _ODSdimension(_dimension):
'''special dimension-class with extra functionality from libreOffice-processes
which uses some atributes from its parent class
and inherit from the general _dimension'''
def __init__(self, parent, name, cell_range):
index = parent._index_counter
parent._index_counter += 1
super(libreOfficeCalc.dimension, self).__init__(name, index)
self._getCoordRange(cell_range)
parent.file_dim.append("")#better genrate now than later
parent.coord_list.append([0,0])
def _getCoordRange(self, cell_range):
'''in: cell_range e.g. "A1:A100"
out: coord_range = [X_start, X_stop, Y_start, Y_stop] e.q. [0,10,2,2]'''
cell_range = cell_range.split(":")
start = cell_range[0]
if len(cell_range) > 1:
stop = cell_range[1]
else:
stop = start
for i in range(len(start)):
if start[i].isdigit():
break
self.X_start = self._transformLetters2Coordinates(start[:i])
self.Y_start = int(start[i:])
self.X_step = self.X_start
self.Y_step = self.Y_start
for i in range(len(stop)):
if stop[i].isdigit():
break
self.X_stop = self._transformLetters2Coordinates(stop[:i])
self.Y_stop = int(stop[i:])
def _transformLetters2Coordinates(self, i):
'''
in: letter e.g. "A" or "E"
out: number related to letter e.g. 1 or 5
'''
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def letters2numbers(x, d = dict((letr,n%26+1) for n,
letr in enumerate(letters[0:52]))):
return d[x]
coordinate_list = map(letters2numbers, i)
coordinateX = 0
n = 0
m = len(coordinate_list) - 1
for n in range(len(coordinate_list)):
coordinateX += coordinate_list[n] * 26 ** m
m -= 1
return coordinateX
def _getMinMax(self,dims):
sys.exit(NotImplemented)
def _prepareReadOut(self, matrixClass):
self._prepareStandard(matrixClass)
if type(self.sheet_name_or_number) == int:
self.doc.set_sheet_index(self.sheet_name_or_number - 1)
elif type(self.sheet_name_or_number) == str:
found_sheet = False
for i in range(self.doc.get_sheet_count()):
self.doc.set_sheet_index(i)
if self.doc.get_sheet_name() == self.sheet_name_or_number:
found_sheet = True
break
if not found_sheet:
sys.exit("ERROR: sheet-name '%s' doesn't exist in your ods-file"
% self.sheet_name_or_number)
else:
sys.exit("""ERROR: sheet_name_or_number must be a integer (e.g. 3) or \
a string ('name'""")
print("reading values from sheet '%s'" % self.doc.get_sheet_name())
def _readOut(self, readout_one_line, end_readOut):
while True:
for i in range(self._readout_every_n_line):
done_readout = self._updateCoordinates()
if done_readout:
return True
self._grabODSValues()
self._assignValues(self.file_dim)
if readout_one_line:
return False
if end_readOut:
return True
return True # means i'm done with readout
def _updateCoordinates(self):
def update(dim):
self.coord_list[dim.index] = [dim.X_step, dim.Y_step]
dim.Y_step += 1
if dim.Y_step > dim.Y_stop:#at end of line
dim.Y_step = dim.Y_start
dim.X_step += 1
if dim.X_step > dim.X_stop:
#as soon as the first dim reaches the end of the coord-range
return True #done readout
for dim in self.basis_dim:
done_readout = update(dim)
if not done_readout:
for dim in self.merge_dim:
done_readout = update(dim)
return done_readout #continue readout
def _grabODSValues(self):
'''
in: coord_list = [ [x1,y1] ,..., [xN,yN] ]
out: value_list = [ ["value in x1","value in y1"] ,... ]
'''
#value_list = []
for n,c in enumerate(self.coord_list):
try:
self.file_dim[n] = self.doc.get_cell_value(c[0],c[1])[1]
except TypeError:
if self.print_error_when_cell_is_empty:
#print("First and last ODS-Values: %s ... %s"
#% (value_list[0], value_list[-1]))
sys.exit("""ERROR while reading value from the ODS-file...
are empty cells in your range?""")
else:
self.file_dim[n] = ""
except UnicodeEncodeError:
self.file_dim[n] = ""