~unifield-team/unifield-wm/us-826

« back to all changes in this revision

Viewing changes to spreadsheet_xml/spreadsheet_xml.py

  • Committer: jf
  • Date: 2011-03-23 13:23:55 UTC
  • Revision ID: jf@tempo4-20110323132355-agyf1soy7m5ewatr
Initial Import

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
 
3
 
from lxml import etree
4
 
from mx import DateTime
5
 
from tools.translate import _
6
 
from osv import osv
7
 
import csv
8
 
 
9
 
 
10
 
# example to read a Excel XML file in consumption_calculation/wizard/wizard_import_rac.py
11
 
class SpreadsheetTools():
12
 
    defaultns = 'urn:schemas-microsoft-com:office:spreadsheet'
13
 
    namespaces = {'ss': defaultns}
14
 
    xa = {'namespaces': namespaces}
15
 
 
16
 
    def get(self, node, attr, default=None):
17
 
        return node.get(etree.QName(self.defaultns, attr), default)
18
 
 
19
 
class SpreadsheetCell(SpreadsheetTools):
20
 
    type = None
21
 
    data = None
22
 
 
23
 
    def __init__(self, node=None):
24
 
        if node is not None:
25
 
            data = node.find(etree.QName(self.defaultns, 'Data'))
26
 
            if data is not None:
27
 
                dtype = self.get(data, 'Type')
28
 
                self.data = data.text
29
 
                if dtype == 'Number':
30
 
                    if not self.data or '.' in self.data:
31
 
                        self.type = 'float'
32
 
                        self.data = float(self.data or 0.0)
33
 
                    else:
34
 
                        self.type = 'int'
35
 
                        self.data = int(self.data)
36
 
                elif dtype == 'Boolean':
37
 
                    self.data = self.data in ('1', 'T', 't', 'True', 'true')
38
 
                    self.type = 'bool'
39
 
                elif dtype == 'DateTime':
40
 
                    self.data = DateTime.ISO.ParseDateTime(self.data)
41
 
                    self.type = 'datetime'
42
 
                elif dtype == 'String':
43
 
                    self.type = 'str'
44
 
 
45
 
    def __str__(self):
46
 
        return "%s"%(self.data, )
47
 
 
48
 
    def __repr__(self):
49
 
        return "%s(<%s> %s)" % (self.__class__, self.type, self.data)
50
 
 
51
 
 
52
 
class SpreadsheetRow(SpreadsheetTools):
53
 
 
54
 
    def __init__(self, node):
55
 
        self.node = node
56
 
        self.cell_list = []
57
 
        self.cell_index = 0
58
 
 
59
 
    def __iter__(self):
60
 
        return self
61
 
 
62
 
    def next(self):
63
 
        return SpreadsheetRow(self.node.next())
64
 
 
65
 
    def len(self):
66
 
        """
67
 
            returns the num. of cells
68
 
        """
69
 
        index = 0
70
 
        for cell in self.node.xpath('ss:Cell', **self.xa):
71
 
            currindex = self.get(cell, 'Index')
72
 
            if not currindex:
73
 
                index += 1
74
 
            else:
75
 
                index = int(currindex)
76
 
            merged =  self.get(cell, 'MergeAcross', 0)
77
 
            if merged:
78
 
                index += int(merged)
79
 
        return index
80
 
 
81
 
    def __len__(self):
82
 
        return self.len()
83
 
 
84
 
    def iter_cells(self):
85
 
        index = 0
86
 
        for cell in self.node.xpath('ss:Cell', **self.xa):
87
 
            currindex = self.get(cell, 'Index')
88
 
            if not currindex:
89
 
                index += 1
90
 
            else:
91
 
                currindex = int(currindex)
92
 
                for i in xrange(index+1, currindex):
93
 
                    yield SpreadsheetCell()
94
 
                index = currindex
95
 
            merged =  self.get(cell, 'MergeAcross', 0)
96
 
            yield SpreadsheetCell(cell)
97
 
            for i in xrange(0, int(merged)):
98
 
                yield SpreadsheetCell()
99
 
 
100
 
    def gen_cell_list(self):
101
 
        for cell in self.iter_cells():
102
 
            self.cell_list.append(cell)
103
 
 
104
 
    def __getattr__(self, attr):
105
 
        if attr == 'cells':
106
 
            if not self.cell_list:
107
 
                self.gen_cell_list()
108
 
            return self.cell_list
109
 
        raise AttributeError
110
 
 
111
 
    def __getitem__(self, attr):
112
 
        if not self.cell_list:
113
 
            self.gen_cell_list()
114
 
        return self.cell_list[attr]
115
 
 
116
 
class SpreadsheetXML(SpreadsheetTools):
117
 
 
118
 
    def __init__(self, xmlfile=False, xmlstring=False):
119
 
        try:
120
 
            if xmlfile:
121
 
                self.xmlobj = etree.parse(xmlfile)
122
 
            else:
123
 
                self.xmlobj = etree.XML(xmlstring)
124
 
        except etree.XMLSyntaxError as e:
125
 
            raise osv.except_osv(_('Error'), _('Wrong format: it should be in Spreadsheet XML 2003'))
126
 
 
127
 
    def getWorksheets(self):
128
 
        ret = []
129
 
        for wb in self.xmlobj.xpath('//ss:Worksheet', **self.xa):
130
 
            ret.append(self.get(wb, 'Name'))
131
 
        return ret
132
 
 
133
 
    def getRows(self,worksheet=1):
134
 
        table = self.xmlobj.xpath('//ss:Worksheet[%d]/ss:Table[1]'%(worksheet, ), **self.xa)
135
 
        return SpreadsheetRow(table[0].getiterator(etree.QName(self.defaultns, 'Row')))
136
 
 
137
 
    def enc(self, s):
138
 
        if isinstance(s, unicode):
139
 
            return s.encode('utf8')
140
 
        return s
141
 
 
142
 
    def to_csv(self, to_file=False, worksheet=1):
143
 
        if to_file:
144
 
            writer=csv.writer(to_file, 'UNIX')
145
 
        else:
146
 
            data = []
147
 
        for row in self.getRows(worksheet):
148
 
                if to_file:
149
 
                    writer.writerow([self.enc(x.data) for x in row.iter_cells()])
150
 
                else:
151
 
                    data.append([self.enc(x.data) for x in row.iter_cells()])
152
 
        if to_file:
153
 
            return True
154
 
        return data
155
 
 
156
 
 
157
 
 
158
 
if __name__=='__main__':
159
 
    spreadML = SpreadsheetXML('/mnt/Tempo/TestJFB/test_dates.xml')
160
 
    spreadML.getWorksheets()
161
 
    # Iterates through all sheets
162
 
    for ws_number in xrange(1, len(spreadML.getWorksheets())):
163
 
        rows = spreadML.getRows(ws_number)
164
 
        # ignore the 1st row
165
 
        rows.next()
166
 
        for row in rows:
167
 
            # number of cells: row.len()
168
 
            # cells can be retrieve like a list: row.cells[0] or like an iterator:
169
 
            for cell in row.iter_cells():
170
 
                print "%s |"%cell.data,
171
 
            print
172
 
            print "-"*4