Commit | Line | Data |
---|---|---|
4d9c5a11 P |
1 | #! |
2 | # -*- coding: utf-8 -*- | |
3 | """ | |
4 | Macro pour faciliter l'intégration des données d'une feuille de calcul | |
5 | vers un wiki MoinMoin. | |
6 | ||
7 | Copyright : Agence universitaire de la Francophonie | |
8 | Licence : GNU General Public Licence, version 2 | |
9 | Auteur : Jean Christophe André | |
10 | Date de création : septembre 2009 | |
11 | """ | |
12 | import uno | |
13 | import unohelper | |
14 | from com.sun.star.task import XJobExecutor | |
15 | from com.sun.star.beans import PropertyValue | |
16 | from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA | |
17 | from com.sun.star.table.CellHoriJustify import STANDARD, LEFT, CENTER, RIGHT | |
fd5790fa P |
18 | from com.sun.star.table.CellVertJustify import STANDARD, TOP, CENTER as MIDDLE, BOTTOM |
19 | from com.sun.star.awt.FontWeight import DONTKNOW, NORMAL, BOLD | |
4d9c5a11 | 20 | |
7b4557ff P |
21 | _settings = { |
22 | 'MoinMoinOldStyle': True, | |
23 | 'MoinMoinVertOnMulti': True, | |
24 | } | |
fd5790fa P |
25 | |
26 | def getRangeSize(sheet, cursor): | |
27 | r = cursor.getRangeAddress() | |
28 | realRange = sheet.getCellRangeByPosition(r.StartColumn, r.StartRow, | |
29 | r.EndColumn, r.EndRow) | |
30 | return (realRange.Columns.Count, realRange.Rows.Count) | |
4d9c5a11 | 31 | |
fd5790fa P |
32 | def getCellRealPosition(cursor, column, row): |
33 | r = cursor.getRangeAddress() | |
34 | return (r.StartColumn + column, r.StartRow + row) | |
35 | ||
36 | def cell2moin(cell): | |
7b4557ff P |
37 | global _settings |
38 | cell_string = cell.getString() | |
39 | if not cell_string: return '' | |
40 | cell_string = cell_string.replace('\n','<<BR>>') | |
41 | if _settings['MoinMoinOldStyle']: | |
42 | if hasattr(cell, 'CharWeight') and cell.CharWeight == BOLD: | |
43 | cell_string = "'''%s'''" % cell_string | |
44 | return cell_string | |
fd5790fa P |
45 | |
46 | def calc2moin(ctx): | |
7b4557ff | 47 | global _settings |
fd5790fa | 48 | data = list() |
4d9c5a11 P |
49 | |
50 | # récupération du document en cours, vérification du type Spreadsheet | |
51 | smgr = ctx.ServiceManager | |
52 | desktop = smgr.createInstanceWithContext( | |
53 | "com.sun.star.frame.Desktop", ctx) | |
54 | curdoc = desktop.getCurrentComponent() | |
55 | if not curdoc.supportsService("com.sun.star.sheet.SpreadsheetDocument"): | |
c842a98f | 56 | raise RuntimeError(u"Ce n'est pas un document de type Spreadsheet (Calc).") |
4d9c5a11 P |
57 | controller = curdoc.getCurrentController() |
58 | sheet = controller.getActiveSheet() | |
7b4557ff | 59 | #open('/tmp/calc2moin.log','a').write('sheet=[%s]\n' % ', '.join(dir(sheet))) |
4d9c5a11 P |
60 | |
61 | # localisation de la la zone déjà utilisée | |
62 | cursor = sheet.createCursor() | |
63 | cursor.gotoEndOfUsedArea(False) | |
64 | cursor.gotoStartOfUsedArea(True) | |
fd5790fa | 65 | columns, rows = getRangeSize(sheet, cursor) |
6d1fe0d5 | 66 | column_rowspan = {} |
4d9c5a11 | 67 | for row in range(rows): |
fd5790fa | 68 | row_data = list() |
7b4557ff | 69 | row_has_multiline_cell = False |
fd5790fa P |
70 | column = 0 |
71 | while column < columns: | |
6d1fe0d5 P |
72 | # saut des colonnes cachées par un rowspan précédent |
73 | if column_rowspan.get(column, 0) > 0: | |
74 | column_rowspan[column] -= 1 | |
75 | column += 1 | |
76 | continue | |
77 | # récupération des infos sur la cellule courante | |
4d9c5a11 P |
78 | cell = cursor.getCellByPosition(column, row) |
79 | cell_type = cell.getType() | |
80 | cell_string = cell.getString() | |
7b4557ff P |
81 | if not row_has_multiline_cell: |
82 | row_has_multiline_cell = '\n' in cell_string | |
fd5790fa P |
83 | # calcul de l'étendue de la cellule courante |
84 | if cell.getIsMerged(): | |
85 | c, r = getCellRealPosition(cursor, column, row) | |
86 | cellRange = sheet.getCellRangeByPosition(c, r, c, r) | |
87 | cursor2 = sheet.createCursorByRange(cellRange) | |
88 | cursor2.collapseToMergedArea() | |
89 | cell_colspan, cell_rowspan = getRangeSize(sheet, cursor2) | |
6d1fe0d5 P |
90 | for n in range(0, cell_colspan): |
91 | column_rowspan[column + n] = cell_rowspan - 1 | |
7b4557ff | 92 | #open('/tmp/calc2moin.log','a').write('Merged(%d,%d)=[%d,%d]\n' % (column,row,cell_colspan,cell_rowspan)) |
fd5790fa P |
93 | else: |
94 | cell_colspan, cell_rowspan = 1, 1 | |
95 | # traitement des attributs et styles de la cellule | |
96 | cell_attributes = list() | |
97 | cell_styles = list() | |
98 | if cell_string and hasattr(cell, 'HoriJustify'): | |
4d9c5a11 P |
99 | horiJustify = cell.getPropertyValue('HoriJustify') |
100 | if horiJustify == LEFT: | |
fd5790fa P |
101 | if cell_colspan > 1 or cell_rowspan > 1: |
102 | text_align = 'left' | |
103 | text_align_old = '(' | |
104 | else: | |
105 | text_align = '' # left par défaut si span == 1 | |
106 | text_align_old = '' | |
4d9c5a11 | 107 | elif horiJustify == CENTER: |
fd5790fa P |
108 | if cell_colspan == 1 and cell_rowspan == 1: |
109 | text_align = 'center' | |
110 | text_align_old = ':' | |
111 | else: | |
112 | text_align = '' # center par défaut si span > 1 | |
113 | text_align_old = '' | |
4d9c5a11 P |
114 | elif horiJustify == RIGHT: |
115 | text_align = 'right' | |
fd5790fa | 116 | text_align_old = ')' |
4d9c5a11 P |
117 | else: |
118 | if cell_type == TEXT: | |
7b4557ff P |
119 | if cell_colspan > 1 or cell_rowspan > 1: |
120 | text_align = 'left' | |
121 | text_align_old = '(' | |
122 | else: | |
123 | text_align = '' # left par défaut si span == 1 | |
124 | text_align_old = '' | |
4d9c5a11 P |
125 | elif cell_type != EMPTY: |
126 | text_align = 'right' | |
fd5790fa P |
127 | text_align_old = ')' |
128 | if text_align: | |
7b4557ff | 129 | if _settings['MoinMoinOldStyle']: |
fd5790fa P |
130 | cell_attributes.append(text_align_old) |
131 | else: | |
132 | cell_styles.append('text-align: ' + text_align) | |
7b4557ff P |
133 | if cell_string and hasattr(cell, 'VertJustify') and \ |
134 | (row_has_multiline_cell or not _settings['MoinMoinVertOnMulti']): | |
fd5790fa P |
135 | vertJustify = cell.getPropertyValue('VertJustify') |
136 | if vertJustify == 1: #TOP(1) | |
137 | vertical_align = 'top' | |
138 | vertical_align_old = '^' | |
139 | elif vertJustify == 2: #MIDDLE(2) | |
140 | vertical_align = '' # middle par défaut | |
141 | vertical_align_old = '' | |
142 | else: #STANDARD(0), BOTTOM(3) | |
143 | vertical_align = 'bottom' | |
144 | vertical_align_old = 'v' | |
145 | if vertical_align: | |
7b4557ff | 146 | if _settings['MoinMoinOldStyle']: |
fd5790fa P |
147 | cell_attributes.append(vertical_align_old) |
148 | else: | |
149 | cell_styles.append('vertical-align: ' + vertical_align) | |
150 | if cell_string and hasattr(cell, 'CharWeight'): | |
151 | charWeight = cell.getPropertyValue('CharWeight') | |
7b4557ff P |
152 | if charWeight == BOLD and not _settings['MoinMoinOldStyle']: |
153 | cell_styles.append('font-weight: bold') | |
fd5790fa P |
154 | if cell_rowspan > 1: |
155 | cell_attributes.append('|%d' % cell_rowspan) | |
156 | if cell_colspan > 1: | |
157 | cell_attributes.append('-%d' % cell_colspan) | |
158 | if hasattr(cell, 'CellBackColor'): | |
159 | color = cell.getPropertyValue('CellBackColor') | |
160 | if color >= 0: | |
7b4557ff | 161 | if _settings['MoinMoinOldStyle']: |
fd5790fa P |
162 | cell_attributes.append('#%06x' % color) |
163 | else: | |
164 | cell_styles.append('background: #%06x' % color) | |
165 | if hasattr(cell, 'CharColor'): | |
166 | color = cell.getPropertyValue('CharColor') | |
167 | if color >= 0: | |
168 | cell_styles.append('color: #%06x' % color) | |
169 | # compilation des styles de la cellule | |
4d9c5a11 | 170 | if cell_styles: |
fd5790fa P |
171 | cell_attributes.insert(0, 'style="%s;"' % '; '.join(cell_styles)) |
172 | # ajout de la définition de la cellule à la ligne courante | |
173 | cell_data = list() | |
174 | if cell_attributes: | |
175 | cell_data.append('<' + ''.join(cell_attributes) + '>') | |
4d9c5a11 | 176 | if cell_string: |
fd5790fa | 177 | cell_data.append(cell2moin(cell)) |
4d9c5a11 P |
178 | else: |
179 | cell_data.append(' ') | |
180 | row_data.append(''.join(cell_data)) | |
fd5790fa | 181 | column += cell_colspan |
4d9c5a11 P |
182 | # display row's code |
183 | data.append('||' + '||'.join(row_data) + '||') | |
184 | ||
185 | # | |
186 | # création d'un document Writer pour écrire le code MoinMoin | |
187 | # | |
188 | # ouverture d'un document Writer caché | |
189 | hidden = PropertyValue() | |
190 | hidden.Name = "Hidden" | |
191 | hidden.Value = True | |
192 | doc = desktop.loadComponentFromURL( | |
193 | "private:factory/swriter", "_blank", 0, (hidden, ) ) | |
194 | text = doc.Text | |
195 | textcursor = text.createTextCursor() | |
196 | text.insertString(textcursor, '\n'.join(data) + '\n', 0) | |
197 | # on copie ça dans le presse papier | |
198 | dispatcher = smgr.createInstanceWithContext( | |
199 | "com.sun.star.frame.DispatchHelper", ctx) | |
200 | frame = doc.getCurrentController().getFrame() | |
201 | dispatcher.executeDispatch(frame, ".uno:SelectAll", "", 0, ()) | |
202 | dispatcher.executeDispatch(frame, ".uno:Copy", "", 0, ()) | |
203 | doc.close(True) | |
204 | ||
205 | ############################################################################## | |
206 | ||
207 | def copier(event=False): | |
208 | u"""Copier une feuille de calcul vers un wiki MoinMoin.""" | |
209 | ctx = uno.getComponentContext() | |
210 | calc2moin(ctx) | |
211 | return None | |
212 | ||
fd5790fa P |
213 | # lists the scripts, that shall be visible inside OOo. Can be omited, if |
214 | # all functions shall be visible, however here getNewString shall be surpressed | |
4d9c5a11 P |
215 | g_exportedScripts = (copier, ) |
216 | ||
217 | ############################################################################## | |
218 | ||
219 | class CopierJob(unohelper.Base, XJobExecutor): | |
220 | def __init__(self, context): | |
221 | self._context = context | |
7b4557ff P |
222 | self._readConfig() |
223 | ||
224 | def _readConfig(self): | |
225 | cfgprov = self._context.ServiceManager.createInstanceWithContext( | |
226 | "com.sun.star.configuration.ConfigurationProvider", self._context) | |
227 | node = PropertyValue() | |
228 | node.Name = "nodepath" | |
229 | node.Value = "/org.auf.openoffice.macros/General" | |
230 | ConfigReader = cfgprov.createInstanceWithArguments( | |
231 | "com.sun.star.configuration.ConfigurationAccess", (node,)) | |
232 | cfgnames = ("MoinMoinOldStyle", "MoinMoinVertOnMulti", ) | |
233 | cfgvalues = ConfigReader.getPropertyValues(cfgnames) | |
234 | if not cfgvalues: | |
235 | raise RuntimeError("Unable to read the configuration.") | |
236 | global _settings | |
237 | _settings = dict(zip(cfgnames, cfgvalues)) | |
4d9c5a11 P |
238 | |
239 | def trigger(self, args): | |
240 | calc2moin(self._context) | |
241 | ||
242 | g_ImplementationHelper = unohelper.ImplementationHelper() | |
243 | g_ImplementationHelper.addImplementation( \ | |
244 | CopierJob, "org.auf.openoffice.calc2moin.Copier", \ | |
245 | ("com.sun.star.task.Job",),) |