2025-10-10 09:46:41 +02:00

101 lines
2.9 KiB
Python

#!/usr/bin/env python
#coding:utf-8
# Purpose: table utils
# Created: 13.02.2011
# Copyright (C) 2011, Manfred Moitzi
# License: MIT license
from __future__ import unicode_literals, print_function, division
__author__ = "mozman <mozman@gmx.at>"
import re
from .compatibility import tostr, is_string
from .xmlns import CN, etree
def iter_cell_range(pos, size):
start_row, start_column = pos
if (start_row < 0) or (start_column < 0):
raise ValueError("invalid start pos: %s" % tostr(pos))
nrows, ncolumns = size
if (nrows < 1) or (ncolumns < 1):
raise ValueError("invalid size: %s" % tostr(size))
for row in range(start_row, start_row + nrows):
for column in range(start_column, start_column + ncolumns):
yield (row, column)
def iter_cell_range_without_start_pos(pos, size):
generator = iter_cell_range(pos, size)
next(generator)
return generator
CELL_ADDRESS = re.compile('^([A-Z]+)(\d+)$')
def address_to_index(address):
def column_name_to_index(colname):
index = 0
power = 1
base = ord('A') - 1
for char in reversed(colname):
index += (ord(char) - base) * power
power *= 26
return index - 1
res = CELL_ADDRESS.match(address.upper())
if res:
column_name, row_name = res.groups()
return (int(row_name)-1, column_name_to_index(column_name))
else:
raise ValueError('Invalid cell address: %s' % address)
def get_cell_index(reference):
if isinstance(reference, tuple): # key => (row, column)
return reference
elif is_string(reference): # key => 'A1'
return address_to_index(reference)
else:
raise TypeError(tostr(type(key)))
def get_min_max_cell_count(xmltable):
count = [count_cells_in_row(xmlrow) for xmlrow in get_table_rows(xmltable)]
if len(count) > 0:
return min(count), max(count)
else:
return (0, 0)
def get_table_rows(xmltable):
return xmltable.findall('.//'+CN('table:table-row'))
def count_cells_in_row(xmlrow):
return sum( (RepetitionAttribute(xmlcell).cols for xmlcell in xmlrow) )
def new_empty_cell():
return etree.Element(CN('table:table-cell'))
def is_table(xmlnode):
if (xmlnode is None) or (xmlnode.tag != CN('table:table')):
return False
else:
return True
class RepetitionAttribute(object):
def __init__(self, xmlnode):
self.xmlnode = xmlnode
@property
def cols(self):
count = self.xmlnode.get(CN('table:number-columns-repeated'))
return 1 if count is None else int(count)
@property
def rows(self):
count = self.xmlnode.get(CN('table:number-rows-repeated'))
return 1 if count is None else int(count)
@cols.deleter
def cols(self):
del self.xmlnode.attrib[CN('table:number-columns-repeated')]
@rows.deleter
def rows(self):
del self.xmlnode.attrib[CN('table:number-rows-repeated')]