Source code for simple_report.xlsx.formula

# coding: utf-8

import re

from simple_report.utils import ColumnHelper
# TODO: кажется, нигде не используется

[docs]class Formula(object): u""" Изменение формулы для последующего вывода """ # Регулярка для поиска индекса колонки (набор латинских букв в верхнем регистре длины >= 1). col_ind = '[A-Z]+' # Регулярка для поиска индекса строки (набор цифр длины >= 1. Первая цифра не нуль). row_ind = '[1-9][0-9]*' # Регулярка для поиска адреса ячейки. cell_coord = '[$]?'.join(['', col_ind, row_ind]) col_re = re.compile(col_ind) row_re = re.compile(row_ind) # Так выглядит адрес ячейки в электронной таблице cell_coordinates_re = re.compile(cell_coord) # Кэш формул. _cache = {} @classmethod
[docs] def get_instance(cls, formula): """ Получение формулы :param formula: :type formula: """ return Formula._cache.get(formula) or Formula(formula)
def __init__(self, formula): self.formula = formula # Флаг того, что формула вычисляется впервые. В этом случае изменять её, # нет необходимости self.first = True self._last_row = 0 self._last_column = 'A' if formula not in Formula._cache: Formula._cache[formula] = self def _get_cell_coord(self): """ Возвращает индексы начала и конца подстроки с адресом ячейки """ iterator = self.cell_coordinates_re.finditer(self.formula) for i in iterator: yield i.start(), i.end() def _change_analyze(self, cell_coord): """ Смотрит на адрес ячейки и в зависимости от наличия (отсутствия) символа $ сообщает, что колонку можно менять (или нет) Например: $A11 -> (false, true), A$12 -> (true, false) """ column = re.compile('[$]?[A-Z]+') row = re.compile('[$]?[1-9][0-9]*') change_column = change_row = True # Проверяем, первый символ это $? Если да, то менять ничего нельзя. if column.search(cell_coord).group()[0] == '$': change_column = False if row.search(cell_coord).group()[0] == '$': change_row = False return change_column, change_row def _get_next_index(self, cell_coord, may_change, diff, is_column): """ Изменяем индекс у столбца(строки) ячейки(в зависимости от флага is_column) may_change - можно ли индекс изменять diff - на сколько нужно изменить индекс """ reg_exp = self.col_re if is_column else self.row_re index = reg_exp.search(cell_coord).group() if may_change: if is_column: index = ColumnHelper.add(index, diff) else: index = str(int(index) + diff) else: index = ''.join(['$', index]) return index
[docs] def get_next_formula(self, row, column): """ Изменяем формулу и отдаём """ diff_row = row - self._last_row self._last_row = row diff_column = ColumnHelper.difference(column, self._last_column) self._last_column = column if not self.first: formula = self.formula for start, end in self._get_cell_coord(): # Подстрока с адресом ячейки cell_coord = self.formula[start:end] change_column, change_row = self._change_analyze(cell_coord) column_index = self._get_next_index(cell_coord, change_column, diff_column, is_column=True) row_index = self._get_next_index(cell_coord, change_row, diff_row, is_column=False) # Сцепляем индекс колонки и индекс ячейки new_cell_coord = ''.join([column_index, row_index]) # Заменяем подстроку в формуле formula = formula.replace(cell_coord, new_cell_coord) self.formula = formula else: self.first = False return self.formula