Now that we're closer to switching to P3 for good, these helpers have outlived their usefulness, and mostly add noise. All remaining dict.iter*() or dict.view*() must be converted to the normal keys(), values() or items() calls. Whenever the result is likely to be used for more than the scope of a loop, or when the dict needs to be modified during iteration, the calls must be wrapped in a ``list()``, to protect the new P3 semantics. Those cases are very exceptional. Also removed some dead code or improved the API to remove unnecessary conversions.
99 lines
3.5 KiB
Python
99 lines
3.5 KiB
Python
# Copyright 2011 Marco Conti
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# sourced from https://github.com/marcoconti83/read-ods-with-odfpy
|
|
# further altered locally
|
|
|
|
from odf import opendocument
|
|
from odf.table import Table, TableRow, TableCell
|
|
from odf.text import P
|
|
|
|
|
|
class ODSReader(object):
|
|
|
|
# loads the file
|
|
def __init__(self, file=None, content=None, clonespannedcolumns=None):
|
|
if not content:
|
|
self.clonespannedcolumns = clonespannedcolumns
|
|
self.doc = opendocument.load(file)
|
|
else:
|
|
self.clonespannedcolumns = clonespannedcolumns
|
|
self.doc = content
|
|
self.SHEETS = {}
|
|
for sheet in self.doc.spreadsheet.getElementsByType(Table):
|
|
self.readSheet(sheet)
|
|
|
|
# reads a sheet in the sheet dictionary, storing each sheet as an
|
|
# array (rows) of arrays (columns)
|
|
def readSheet(self, sheet):
|
|
name = sheet.getAttribute("name")
|
|
rows = sheet.getElementsByType(TableRow)
|
|
arrRows = []
|
|
|
|
# for each row
|
|
for row in rows:
|
|
arrCells = []
|
|
cells = row.getElementsByType(TableCell)
|
|
|
|
# for each cell
|
|
for count, cell in enumerate(cells, start=1):
|
|
# repeated value?
|
|
repeat = 0
|
|
if count != len(cells):
|
|
repeat = cell.getAttribute("numbercolumnsrepeated")
|
|
if not repeat:
|
|
repeat = 1
|
|
spanned = int(cell.getAttribute('numbercolumnsspanned') or 0)
|
|
# clone spanned cells
|
|
if self.clonespannedcolumns is not None and spanned > 1:
|
|
repeat = spanned
|
|
|
|
ps = cell.getElementsByType(P)
|
|
textContent = u""
|
|
|
|
# for each text/text:span node
|
|
for p in ps:
|
|
for n in p.childNodes:
|
|
if n.nodeType == 1 and n.tagName == "text:span":
|
|
for c in n.childNodes:
|
|
if c.nodeType == 3:
|
|
textContent = u'{}{}'.format(textContent, n.data)
|
|
|
|
if n.nodeType == 3:
|
|
textContent = u'{}{}'.format(textContent, n.data)
|
|
|
|
if textContent:
|
|
if not textContent.startswith("#"): # ignore comments cells
|
|
for rr in range(int(repeat)): # repeated?
|
|
arrCells.append(textContent)
|
|
else:
|
|
for rr in range(int(repeat)):
|
|
arrCells.append("")
|
|
|
|
# if row contained something
|
|
if arrCells:
|
|
arrRows.append(arrCells)
|
|
|
|
#else:
|
|
# print ("Empty or commented row (", row_comment, ")")
|
|
|
|
self.SHEETS[name] = arrRows
|
|
|
|
# returns a sheet as an array (rows) of arrays (columns)
|
|
def getSheet(self, name):
|
|
return self.SHEETS[name]
|
|
|
|
def getFirstSheet(self):
|
|
return next(iter(self.SHEETS.values()))
|