| 374 | escape(self.text)) |
| 375 | |
| 376 | class FormulaCell(BaseCell): |
| 377 | |
| 378 | def __init__(self, formula, fmt="%s", alignment=RIGHT): |
| 379 | assert alignment in (LEFT, CENTER, RIGHT) |
| 380 | self.formula = formula |
| 381 | self.translated = translate(self.formula) |
| 382 | self.fmt = fmt |
| 383 | self.alignment = alignment |
| 384 | self.reset() |
| 385 | |
| 386 | def reset(self): |
| 387 | self.value = None |
| 388 | |
| 389 | def recalc(self, ns): |
| 390 | if self.value is None: |
| 391 | try: |
| 392 | self.value = eval(self.translated, ns) |
| 393 | except: |
| 394 | exc = sys.exc_info()[0] |
| 395 | if hasattr(exc, "__name__"): |
| 396 | self.value = exc.__name__ |
| 397 | else: |
| 398 | self.value = str(exc) |
| 399 | return self.value |
| 400 | |
| 401 | def format(self): |
| 402 | try: |
| 403 | text = self.fmt % self.value |
| 404 | except: |
| 405 | text = str(self.value) |
| 406 | return text, self.alignment |
| 407 | |
| 408 | def xml(self): |
| 409 | return '<formula align="%s" format="%s">%s</formula>' % ( |
| 410 | align2xml[self.alignment], |
| 411 | self.fmt, |
| 412 | escape(self.formula)) |
| 413 | |
| 414 | def renumber(self, x1, y1, x2, y2, dx, dy): |
| 415 | out = [] |
| 416 | for part in re.split(r'(\w+)', self.formula): |
| 417 | m = re.match('^([A-Z]+)([1-9][0-9]*)$', part) |
| 418 | if m is not None: |
| 419 | sx, sy = m.groups() |
| 420 | x = colname2num(sx) |
| 421 | y = int(sy) |
| 422 | if x1 <= x <= x2 and y1 <= y <= y2: |
| 423 | part = cellname(x+dx, y+dy) |
| 424 | out.append(part) |
| 425 | return FormulaCell("".join(out), self.fmt, self.alignment) |
| 426 | |
| 427 | def translate(formula): |
| 428 | """Translate a formula containing fancy cell names to valid Python code. |
no outgoing calls