Merge lp:~luc-demeyer/openerp-reporting-engines/datetime-fix-report_xls into lp:openerp-reporting-engines
- datetime-fix-report_xls
- Merge into 7.0
Proposed by
Luc De Meyer (Noviat)
Status: | Merged |
---|---|
Merged at revision: | 3 |
Proposed branch: | lp:~luc-demeyer/openerp-reporting-engines/datetime-fix-report_xls |
Merge into: | lp:openerp-reporting-engines |
Diff against target: |
351 lines (+100/-58) 4 files modified
report_xls/__init__.py (+1/-1) report_xls/__openerp__.py (+48/-12) report_xls/report_xls.py (+45/-40) report_xls/utils.py (+6/-5) |
To merge this branch: | bzr merge lp:~luc-demeyer/openerp-reporting-engines/datetime-fix-report_xls |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guewen Baconnier @ Camptocamp | Approve | ||
Pedro Manuel Baeza | code review | Approve | |
Joël Grand-Guillaume @ camptocamp | code review, no tests | Approve | |
Review via email: mp+200604@code.launchpad.net |
Commit message
Description of the change
style & documentation refresh
xls footer datetime fix
To post a comment you must log in.
Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote : | # |
review:
Approve
(code review, no tests)
Revision history for this message
Pedro Manuel Baeza (pedro.baeza) wrote : | # |
LGTM
review:
Approve
(code review)
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'report_xls/__init__.py' | |||
2 | --- report_xls/__init__.py 2013-11-15 15:56:47 +0000 | |||
3 | +++ report_xls/__init__.py 2014-01-06 22:32:08 +0000 | |||
4 | @@ -12,7 +12,7 @@ | |||
5 | 12 | # | 12 | # |
6 | 13 | # This program is distributed in the hope that it will be useful, | 13 | # This program is distributed in the hope that it will be useful, |
7 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | 16 | # GNU Affero General Public License for more details. | 16 | # GNU Affero General Public License for more details. |
11 | 17 | # | 17 | # |
12 | 18 | # You should have received a copy of the GNU Affero General Public License | 18 | # You should have received a copy of the GNU Affero General Public License |
13 | 19 | 19 | ||
14 | === modified file 'report_xls/__openerp__.py' | |||
15 | --- report_xls/__openerp__.py 2013-11-15 15:56:47 +0000 | |||
16 | +++ report_xls/__openerp__.py 2014-01-06 22:32:08 +0000 | |||
17 | @@ -12,7 +12,7 @@ | |||
18 | 12 | # | 12 | # |
19 | 13 | # This program is distributed in the hope that it will be useful, | 13 | # This program is distributed in the hope that it will be useful, |
20 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | 16 | # GNU Affero General Public License for more details. | 16 | # GNU Affero General Public License for more details. |
24 | 17 | # | 17 | # |
25 | 18 | # You should have received a copy of the GNU Affero General Public License | 18 | # You should have received a copy of the GNU Affero General Public License |
26 | @@ -20,24 +20,60 @@ | |||
27 | 20 | # | 20 | # |
28 | 21 | ############################################################################## | 21 | ############################################################################## |
29 | 22 | { | 22 | { |
32 | 23 | 'name': 'XLS report engine', | 23 | 'name': 'Excel report engine', |
33 | 24 | 'version': '0.3', | 24 | 'version': '0.4', |
34 | 25 | 'license': 'AGPL-3', | 25 | 'license': 'AGPL-3', |
35 | 26 | 'author': 'Noviat', | 26 | 'author': 'Noviat', |
36 | 27 | 'website': 'http://www.noviat.com', | 27 | 'website': 'http://www.noviat.com', |
37 | 28 | 'category': 'Reporting', | 28 | 'category': 'Reporting', |
44 | 29 | 'description': """ | 29 | 'description': """ |
45 | 30 | 30 | Excel report engine | |
46 | 31 | This module adds XLS export capabilities to the standard OpenERP reporting engine. | 31 | =================== |
47 | 32 | 32 | ||
48 | 33 | In order to generate an XLS export you can define a report of type 'xls' or alternatively pass {'xls_export' : 1) via the context to create method of the report. | 33 | This module adds Excel export capabilities to the standard OpenERP reporting engine. |
49 | 34 | 34 | ||
50 | 35 | Report development | ||
51 | 36 | '''''''''''''''''' | ||
52 | 37 | In order to create an Excel report you can\n | ||
53 | 38 | - define a report of type 'xls' | ||
54 | 39 | - pass ``{'xls_export': 1}`` via the context to the report create method | ||
55 | 40 | |||
56 | 41 | The ``report_xls`` class contains a number of attributes and methods to facilitate | ||
57 | 42 | the creation XLS reports in OpenERP. | ||
58 | 43 | |||
59 | 44 | * cell types | ||
60 | 45 | |||
61 | 46 | Supported cell types : text, number, boolean, date. | ||
62 | 47 | |||
63 | 48 | * cell styles | ||
64 | 49 | |||
65 | 50 | The predefined cell style definitions result in a consistent | ||
66 | 51 | look and feel of the OpenERP Excel reports. | ||
67 | 52 | |||
68 | 53 | * cell formulas | ||
69 | 54 | |||
70 | 55 | Cell formulas can be easily added with the help of the ``rowcol_to_cell()`` function which | ||
71 | 56 | you can import from the ``utils.py`` module. | ||
72 | 57 | |||
73 | 58 | * Excel templates | ||
74 | 59 | |||
75 | 60 | It is possible to define Excel templates which can be adapted by 'inherited' modules. | ||
76 | 61 | Download the ``account_move_line_report_xls`` module from http://apps.openerp.com | ||
77 | 62 | as example. | ||
78 | 63 | |||
79 | 64 | * XLS with multiple sheets | ||
80 | 65 | |||
81 | 66 | Download the ``account_journal_report_xls`` module from http://apps.openerp.com as example. | ||
82 | 67 | |||
83 | 68 | Development assistance | ||
84 | 69 | '''''''''''''''''''''' | ||
85 | 70 | Contact info@noviat.com for help with the development of Excel reports in OpenERP, . | ||
86 | 71 | |||
87 | 35 | """, | 72 | """, |
88 | 36 | 'depends': ['base'], | 73 | 'depends': ['base'], |
89 | 37 | 'external_dependencies': {'python': ['xlwt']}, | 74 | 'external_dependencies': {'python': ['xlwt']}, |
93 | 38 | 'demo_xml': [], | 75 | 'demo': [], |
94 | 39 | 'init_xml': [], | 76 | 'data': [], |
92 | 40 | 'update_xml' : [], | ||
95 | 41 | 'active': False, | 77 | 'active': False, |
96 | 42 | 'installable': True, | 78 | 'installable': True, |
97 | 43 | } | 79 | } |
98 | 44 | 80 | ||
99 | === modified file 'report_xls/report_xls.py' | |||
100 | --- report_xls/report_xls.py 2013-11-15 15:56:47 +0000 | |||
101 | +++ report_xls/report_xls.py 2014-01-06 22:32:08 +0000 | |||
102 | @@ -2,8 +2,8 @@ | |||
103 | 2 | ############################################################################## | 2 | ############################################################################## |
104 | 3 | # | 3 | # |
105 | 4 | # OpenERP, Open Source Management Solution | 4 | # OpenERP, Open Source Management Solution |
108 | 5 | # | 5 | # |
109 | 6 | #Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved. | 6 | # Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved. |
110 | 7 | # | 7 | # |
111 | 8 | # This program is free software: you can redistribute it and/or modify | 8 | # This program is free software: you can redistribute it and/or modify |
112 | 9 | # it under the terms of the GNU Affero General Public License as | 9 | # it under the terms of the GNU Affero General Public License as |
113 | @@ -12,7 +12,7 @@ | |||
114 | 12 | # | 12 | # |
115 | 13 | # This program is distributed in the hope that it will be useful, | 13 | # This program is distributed in the hope that it will be useful, |
116 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
118 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
119 | 16 | # GNU Affero General Public License for more details. | 16 | # GNU Affero General Public License for more details. |
120 | 17 | # | 17 | # |
121 | 18 | # You should have received a copy of the GNU Affero General Public License | 18 | # You should have received a copy of the GNU Affero General Public License |
122 | @@ -23,7 +23,8 @@ | |||
123 | 23 | import xlwt | 23 | import xlwt |
124 | 24 | from xlwt.Style import default_style | 24 | from xlwt.Style import default_style |
125 | 25 | import cStringIO | 25 | import cStringIO |
127 | 26 | import datetime, time | 26 | from datetime import datetime |
128 | 27 | from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT | ||
129 | 27 | import inspect | 28 | import inspect |
130 | 28 | from types import CodeType | 29 | from types import CodeType |
131 | 29 | from openerp.report.report_sxw import * | 30 | from openerp.report.report_sxw import * |
132 | @@ -32,13 +33,15 @@ | |||
133 | 32 | import logging | 33 | import logging |
134 | 33 | _logger = logging.getLogger(__name__) | 34 | _logger = logging.getLogger(__name__) |
135 | 34 | 35 | ||
136 | 36 | |||
137 | 35 | class AttrDict(dict): | 37 | class AttrDict(dict): |
138 | 36 | def __init__(self, *args, **kwargs): | 38 | def __init__(self, *args, **kwargs): |
139 | 37 | super(AttrDict, self).__init__(*args, **kwargs) | 39 | super(AttrDict, self).__init__(*args, **kwargs) |
140 | 38 | self.__dict__ = self | 40 | self.__dict__ = self |
141 | 39 | 41 | ||
142 | 42 | |||
143 | 40 | class report_xls(report_sxw): | 43 | class report_xls(report_sxw): |
145 | 41 | 44 | ||
146 | 42 | xls_types = { | 45 | xls_types = { |
147 | 43 | 'bool': xlwt.Row.set_cell_boolean, | 46 | 'bool': xlwt.Row.set_cell_boolean, |
148 | 44 | 'date': xlwt.Row.set_cell_date, | 47 | 'date': xlwt.Row.set_cell_date, |
149 | @@ -53,36 +56,29 @@ | |||
150 | 53 | } | 56 | } |
151 | 54 | 57 | ||
152 | 55 | # TO DO: move parameters infra to configurable data | 58 | # TO DO: move parameters infra to configurable data |
154 | 56 | 59 | ||
155 | 57 | # header/footer | 60 | # header/footer |
157 | 58 | DT_FORMAT = '%Y-%m-%d %H:%M:%S' | 61 | DT_FORMAT = '%Y-%m-%d %H:%M:%S' |
158 | 59 | hf_params = { | 62 | hf_params = { |
159 | 60 | 'font_size': 8, | 63 | 'font_size': 8, |
170 | 61 | 'font_style': 'I', # B: Bold, I: Italic, U: Underline | 64 | 'font_style': 'I', # B: Bold, I: Italic, U: Underline |
171 | 62 | } | 65 | } |
172 | 63 | xls_headers = { | 66 | |
163 | 64 | 'standard': '' | ||
164 | 65 | } | ||
165 | 66 | xls_footers = { | ||
166 | 67 | 'standard': ('&L&%(font_size)s&%(font_style)s' + datetime.now().strftime(DT_FORMAT) + | ||
167 | 68 | '&R&%(font_size)s&%(font_style)s&P / &N') %hf_params | ||
168 | 69 | } | ||
169 | 70 | |||
173 | 71 | # styles | 67 | # styles |
176 | 72 | _pfc = '26' # default pattern fore_color | 68 | _pfc = '26' # default pattern fore_color |
177 | 73 | _bc = '22' # borders color | 69 | _bc = '22' # borders color |
178 | 74 | decimal_format = '#,##0.00' | 70 | decimal_format = '#,##0.00' |
180 | 75 | date_format = 'YYYY-MM-DD' | 71 | date_format = 'YYYY-MM-DD' |
181 | 76 | xls_styles = { | 72 | xls_styles = { |
182 | 77 | 'xls_title': 'font: bold true, height 240;', | 73 | 'xls_title': 'font: bold true, height 240;', |
183 | 78 | 'bold': 'font: bold true;', | 74 | 'bold': 'font: bold true;', |
184 | 79 | 'underline': 'font: underline true;', | 75 | 'underline': 'font: underline true;', |
185 | 80 | 'italic': 'font: italic true;', | 76 | 'italic': 'font: italic true;', |
191 | 81 | 'fill': 'pattern: pattern solid, fore_color %s;' %_pfc, | 77 | 'fill': 'pattern: pattern solid, fore_color %s;' % _pfc, |
192 | 82 | 'fill_blue' : 'pattern: pattern solid, fore_color 27;', | 78 | 'fill_blue': 'pattern: pattern solid, fore_color 27;', |
193 | 83 | 'fill_grey' : 'pattern: pattern solid, fore_color 22;', | 79 | 'fill_grey': 'pattern: pattern solid, fore_color 22;', |
194 | 84 | 'borders_all': 'borders: left thin, right thin, top thin, bottom thin, ' \ | 80 | 'borders_all': 'borders: left thin, right thin, top thin, bottom thin, ' |
195 | 85 | 'left_colour %s, right_colour %s, top_colour %s, bottom_colour %s;' %(_bc,_bc,_bc,_bc), | 81 | 'left_colour %s, right_colour %s, top_colour %s, bottom_colour %s;' % (_bc, _bc, _bc, _bc), |
196 | 86 | 'left': 'align: horz left;', | 82 | 'left': 'align: horz left;', |
197 | 87 | 'center': 'align: horz center;', | 83 | 'center': 'align: horz center;', |
198 | 88 | 'right': 'align: horz right;', | 84 | 'right': 'align: horz right;', |
199 | @@ -91,8 +87,8 @@ | |||
200 | 91 | 'bottom': 'align: vert bottom;', | 87 | 'bottom': 'align: vert bottom;', |
201 | 92 | } | 88 | } |
202 | 93 | # TO DO: move parameters supra to configurable data | 89 | # TO DO: move parameters supra to configurable data |
205 | 94 | 90 | ||
206 | 95 | def create(self, cr, uid, ids, data, context=None): | 91 | def create(self, cr, uid, ids, data, context=None): |
207 | 96 | self.pool = pooler.get_pool(cr.dbname) | 92 | self.pool = pooler.get_pool(cr.dbname) |
208 | 97 | self.cr = cr | 93 | self.cr = cr |
209 | 98 | self.uid = uid | 94 | self.uid = uid |
210 | @@ -105,11 +101,13 @@ | |||
211 | 105 | if report_xml.report_type == 'xls': | 101 | if report_xml.report_type == 'xls': |
212 | 106 | return self.create_source_xls(cr, uid, ids, data, context) | 102 | return self.create_source_xls(cr, uid, ids, data, context) |
213 | 107 | elif context.get('xls_export'): | 103 | elif context.get('xls_export'): |
214 | 104 | self.table = data.get('model') or self.table # use model from 'data' when no ir.actions.report.xml entry | ||
215 | 108 | return self.create_source_xls(cr, uid, ids, data, context) | 105 | return self.create_source_xls(cr, uid, ids, data, context) |
216 | 109 | return super(report_xls, self).create(cr, uid, ids, data, context) | 106 | return super(report_xls, self).create(cr, uid, ids, data, context) |
217 | 110 | 107 | ||
218 | 111 | def create_source_xls(self, cr, uid, ids, data, context=None): | 108 | def create_source_xls(self, cr, uid, ids, data, context=None): |
220 | 112 | if not context: context = {} | 109 | if not context: |
221 | 110 | context = {} | ||
222 | 113 | parser_instance = self.parser(cr, uid, self.name2, context) | 111 | parser_instance = self.parser(cr, uid, self.name2, context) |
223 | 114 | self.parser_instance = parser_instance | 112 | self.parser_instance = parser_instance |
224 | 115 | objs = self.getObjects(cr, uid, ids, context) | 113 | objs = self.getObjects(cr, uid, ids, context) |
225 | @@ -119,15 +117,22 @@ | |||
226 | 119 | wb = xlwt.Workbook(encoding='utf-8') | 117 | wb = xlwt.Workbook(encoding='utf-8') |
227 | 120 | _p = AttrDict(parser_instance.localcontext) | 118 | _p = AttrDict(parser_instance.localcontext) |
228 | 121 | _xs = self.xls_styles | 119 | _xs = self.xls_styles |
229 | 120 | self.xls_headers = { | ||
230 | 121 | 'standard': '', | ||
231 | 122 | } | ||
232 | 123 | self.xls_footers = { | ||
233 | 124 | 'standard': ('&L&%(font_size)s&%(font_style)s' + datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT) + | ||
234 | 125 | '&R&%(font_size)s&%(font_style)s&P / &N') % self.hf_params, | ||
235 | 126 | } | ||
236 | 122 | self.generate_xls_report(_p, _xs, data, objs, wb) | 127 | self.generate_xls_report(_p, _xs, data, objs, wb) |
237 | 123 | wb.save(n) | 128 | wb.save(n) |
238 | 124 | n.seek(0) | 129 | n.seek(0) |
241 | 125 | return (n.read(), 'xls') | 130 | return (n.read(), 'xls') |
242 | 126 | 131 | ||
243 | 127 | def render(self, wanted, col_specs, rowtype, render_space='empty'): | 132 | def render(self, wanted, col_specs, rowtype, render_space='empty'): |
244 | 128 | """ | 133 | """ |
247 | 129 | returns 'mako'-rendered col_specs | 134 | returns 'evaluated' col_specs |
248 | 130 | 135 | ||
249 | 131 | Input: | 136 | Input: |
250 | 132 | - wanted: element from the wanted_list | 137 | - wanted: element from the wanted_list |
251 | 133 | - col_specs : cf. specs[1:] documented in xls_row_template method | 138 | - col_specs : cf. specs[1:] documented in xls_row_template method |
252 | @@ -139,7 +144,7 @@ | |||
253 | 139 | caller_space = inspect.currentframe().f_back.f_back.f_locals | 144 | caller_space = inspect.currentframe().f_back.f_back.f_locals |
254 | 140 | localcontext = self.parser_instance.localcontext | 145 | localcontext = self.parser_instance.localcontext |
255 | 141 | render_space.update(caller_space) | 146 | render_space.update(caller_space) |
257 | 142 | render_space.update(localcontext) | 147 | render_space.update(localcontext) |
258 | 143 | row = col_specs[wanted][rowtype][:] | 148 | row = col_specs[wanted][rowtype][:] |
259 | 144 | for i in range(len(row)): | 149 | for i in range(len(row)): |
260 | 145 | if isinstance(row[i], CodeType): | 150 | if isinstance(row[i], CodeType): |
261 | @@ -155,9 +160,9 @@ | |||
262 | 155 | def xls_row_template(self, specs, wanted_list): | 160 | def xls_row_template(self, specs, wanted_list): |
263 | 156 | """ | 161 | """ |
264 | 157 | Returns a row template. | 162 | Returns a row template. |
266 | 158 | 163 | ||
267 | 159 | Input : | 164 | Input : |
269 | 160 | - 'wanted_list': list of Columns that will be returned in the row_template | 165 | - 'wanted_list': list of Columns that will be returned in the row_template |
270 | 161 | - 'specs': list with Column Characteristics | 166 | - 'specs': list with Column Characteristics |
271 | 162 | 0: Column Name (from wanted_list) | 167 | 0: Column Name (from wanted_list) |
272 | 163 | 1: Column Colspan | 168 | 1: Column Colspan |
273 | @@ -190,14 +195,14 @@ | |||
274 | 190 | if s_len > 7 and s[7] is not None: | 195 | if s_len > 7 and s[7] is not None: |
275 | 191 | c.append(s[7]) | 196 | c.append(s[7]) |
276 | 192 | else: | 197 | else: |
278 | 193 | c.append(None) | 198 | c.append(None) |
279 | 194 | r.append((col, c[1], c)) | 199 | r.append((col, c[1], c)) |
280 | 195 | col += c[1] | 200 | col += c[1] |
281 | 196 | break | 201 | break |
282 | 197 | if not found: | 202 | if not found: |
283 | 198 | _logger.warn("report_xls.xls_row_template, column '%s' not found in specs", w) | 203 | _logger.warn("report_xls.xls_row_template, column '%s' not found in specs", w) |
284 | 199 | return r | 204 | return r |
286 | 200 | 205 | ||
287 | 201 | def xls_write_row(self, ws, row_pos, row_data, row_style=default_style, set_column_size=False): | 206 | def xls_write_row(self, ws, row_pos, row_data, row_style=default_style, set_column_size=False): |
288 | 202 | r = ws.row(row_pos) | 207 | r = ws.row(row_pos) |
289 | 203 | for col, size, spec in row_data: | 208 | for col, size, spec in row_data: |
290 | @@ -209,9 +214,9 @@ | |||
291 | 209 | data = report_xls.xls_types_default[spec[3]] | 214 | data = report_xls.xls_types_default[spec[3]] |
292 | 210 | if size != 1: | 215 | if size != 1: |
293 | 211 | if formula: | 216 | if formula: |
295 | 212 | ws.write_merge(row_pos, row_pos, col, col+size-1, data, style) | 217 | ws.write_merge(row_pos, row_pos, col, col + size - 1, data, style) |
296 | 213 | else: | 218 | else: |
298 | 214 | ws.write_merge(row_pos, row_pos, col, col+size-1, data, style) | 219 | ws.write_merge(row_pos, row_pos, col, col + size - 1, data, style) |
299 | 215 | else: | 220 | else: |
300 | 216 | if formula: | 221 | if formula: |
301 | 217 | ws.write(row_pos, col, formula, style) | 222 | ws.write(row_pos, col, formula, style) |
302 | @@ -220,5 +225,5 @@ | |||
303 | 220 | if set_column_size: | 225 | if set_column_size: |
304 | 221 | ws.col(col).width = spec[2] * 256 | 226 | ws.col(col).width = spec[2] * 256 |
305 | 222 | return row_pos + 1 | 227 | return row_pos + 1 |
307 | 223 | 228 | ||
308 | 224 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | 229 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
309 | 225 | 230 | ||
310 | === added directory 'report_xls/static' | |||
311 | === added directory 'report_xls/static/src' | |||
312 | === added directory 'report_xls/static/src/img' | |||
313 | === added file 'report_xls/static/src/img/icon.png' | |||
314 | 226 | Binary files report_xls/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and report_xls/static/src/img/icon.png 2014-01-06 22:32:08 +0000 differ | 231 | Binary files report_xls/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and report_xls/static/src/img/icon.png 2014-01-06 22:32:08 +0000 differ |
315 | === modified file 'report_xls/utils.py' | |||
316 | --- report_xls/utils.py 2013-11-15 15:56:47 +0000 | |||
317 | +++ report_xls/utils.py 2014-01-06 22:32:08 +0000 | |||
318 | @@ -12,17 +12,18 @@ | |||
319 | 12 | # | 12 | # |
320 | 13 | # This program is distributed in the hope that it will be useful, | 13 | # This program is distributed in the hope that it will be useful, |
321 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
323 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
324 | 16 | # GNU Affero General Public License for more details. | 16 | # GNU Affero General Public License for more details. |
325 | 17 | # | 17 | # |
326 | 18 | # You should have received a copy of the GNU Affero General Public License | 18 | # You should have received a copy of the GNU Affero General Public License |
327 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
328 | 20 | # | 20 | # |
329 | 21 | ############################################################################## | 21 | ############################################################################## |
331 | 22 | # | 22 | |
332 | 23 | 23 | ||
333 | 24 | def _render(code): | 24 | def _render(code): |
335 | 25 | return compile(code, '<string>', 'eval') | 25 | return compile(code, '<string>', 'eval') |
336 | 26 | |||
337 | 26 | 27 | ||
338 | 27 | def rowcol_to_cell(row, col, row_abs=False, col_abs=False): | 28 | def rowcol_to_cell(row, col, row_abs=False, col_abs=False): |
339 | 28 | # Code based upon utils from xlwt distribution | 29 | # Code based upon utils from xlwt distribution |
340 | @@ -41,9 +42,9 @@ | |||
341 | 41 | else: | 42 | else: |
342 | 42 | col_abs = '' | 43 | col_abs = '' |
343 | 43 | if d > 0: | 44 | if d > 0: |
345 | 44 | chr1 = chr(ord('A') + d - 1) | 45 | chr1 = chr(ord('A') + d - 1) |
346 | 45 | chr2 = chr(ord('A') + m) | 46 | chr2 = chr(ord('A') + m) |
347 | 46 | # Zero index to 1-index | 47 | # Zero index to 1-index |
348 | 47 | return col_abs + chr1 + chr2 + row_abs + str(row + 1) | 48 | return col_abs + chr1 + chr2 + row_abs + str(row + 1) |
350 | 48 | 49 | ||
351 | 49 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | 50 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
Hi,
Thanks for this cleanup, very much appreciated.
LGTM,
Regards,