auf-libreoffice-extension 1404.2
[macros-openoffice.git] / auf-libreoffice-extension / extension / calc2moin.py
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
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
20
21 _settings = {
22 'MoinMoinOldStyle': True,
23 'MoinMoinVertOnMulti': True,
24 }
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)
31
32 def getCellRealPosition(cursor, column, row):
33 r = cursor.getRangeAddress()
34 return (r.StartColumn + column, r.StartRow + row)
35
36 def cell2moin(cell):
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
45
46 def calc2moin(ctx):
47 global _settings
48 data = list()
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"):
56 raise RuntimeError(u"Ce n'est pas un document de type Spreadsheet (Calc).")
57 controller = curdoc.getCurrentController()
58 sheet = controller.getActiveSheet()
59 #open('/tmp/calc2moin.log','a').write('sheet=[%s]\n' % ', '.join(dir(sheet)))
60
61 # localisation de la la zone déjà utilisée
62 cursor = sheet.createCursor()
63 cursor.gotoEndOfUsedArea(False)
64 cursor.gotoStartOfUsedArea(True)
65 columns, rows = getRangeSize(sheet, cursor)
66 column_rowspan = {}
67 for row in range(rows):
68 row_data = list()
69 row_has_multiline_cell = False
70 column = 0
71 while column < columns:
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
78 cell = cursor.getCellByPosition(column, row)
79 cell_type = cell.getType()
80 cell_string = cell.getString()
81 if not row_has_multiline_cell:
82 row_has_multiline_cell = '\n' in cell_string
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)
90 for n in range(0, cell_colspan):
91 column_rowspan[column + n] = cell_rowspan - 1
92 #open('/tmp/calc2moin.log','a').write('Merged(%d,%d)=[%d,%d]\n' % (column,row,cell_colspan,cell_rowspan))
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'):
99 horiJustify = cell.getPropertyValue('HoriJustify')
100 if horiJustify == LEFT:
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 = ''
107 elif horiJustify == CENTER:
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 = ''
114 elif horiJustify == RIGHT:
115 text_align = 'right'
116 text_align_old = ')'
117 else:
118 if cell_type == TEXT:
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 = ''
125 elif cell_type != EMPTY:
126 text_align = 'right'
127 text_align_old = ')'
128 if text_align:
129 if _settings['MoinMoinOldStyle']:
130 cell_attributes.append(text_align_old)
131 else:
132 cell_styles.append('text-align: ' + text_align)
133 if cell_string and hasattr(cell, 'VertJustify') and \
134 (row_has_multiline_cell or not _settings['MoinMoinVertOnMulti']):
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:
146 if _settings['MoinMoinOldStyle']:
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')
152 if charWeight == BOLD and not _settings['MoinMoinOldStyle']:
153 cell_styles.append('font-weight: bold')
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:
161 if _settings['MoinMoinOldStyle']:
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
170 if cell_styles:
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) + '>')
176 if cell_string:
177 cell_data.append(cell2moin(cell))
178 else:
179 cell_data.append(' ')
180 row_data.append(''.join(cell_data))
181 column += cell_colspan
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
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
215 g_exportedScripts = (copier, )
216
217 ##############################################################################
218
219 class CopierJob(unohelper.Base, XJobExecutor):
220 def __init__(self, context):
221 self._context = context
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))
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",),)