Пример #1
0
    def set_columns_width(self, begin, end, start_cell):
        """
        Копирование ширины колонок
        :param begin: начало секции, пример ('A', 1)
        :type begin: 2-tuple
        :param end: конец секции, пример ('E', 6)
        :type end: 2-tuple
        :param start_cell: ячейка с которой выводилась секция
        :type start_cell: 2-tuple
        """
        # определим интервал столбцов из которых надо взять ширину
        end = self.get_cell_end(end)
        cols = list(ColumnHelper.get_range(begin[0], end[0]))

        # определим интервал столбцов, начинаемый со столбца начальной ячейки, куда надо прописать ширину
        end_col = ColumnHelper.add(start_cell[0], ColumnHelper.difference(end[0], begin[0]))
        new_cols = list(ColumnHelper.get_range(start_cell[0], end_col))

        # запишем ширину столбцов в интервал
        for index, src_col in enumerate(cols):
            dst_col = new_cols[index]
            src_col_el = self._create_or_get_output_col(src_col)
            # если нет исходной колонки, то не надо копировать
            if not src_col_el is None:
                # копируем данные
                attrib_col = dict(src_col_el.items())
                dst_col_el = self._create_or_get_output_col(dst_col, attrib_col)
                # записываем в новую колонку
                self._set_new_column_width(dst_col, src_col_el, dst_col_el)
Пример #2
0
    def set_columns_width(self, begin, end, start_cell):
        """
        Копирование ширины колонок
        :param begin: начало секции, пример ('A', 1)
        :type begin: 2-tuple
        :param end: конец секции, пример ('E', 6)
        :type end: 2-tuple
        :param start_cell: ячейка с которой выводилась секция
        :type start_cell: 2-tuple
        """
        # определим интервал столбцов из которых надо взять ширину
        end = self.get_cell_end(end)
        cols = list(ColumnHelper.get_range(begin[0], end[0]))

        # определим интервал столбцов, начинаемый со столбца начальной ячейки, куда надо прописать ширину
        end_col = ColumnHelper.add(start_cell[0],
                                   ColumnHelper.difference(end[0], begin[0]))
        new_cols = list(ColumnHelper.get_range(start_cell[0], end_col))

        # запишем ширину столбцов в интервал
        for index, src_col in enumerate(cols):
            dst_col = new_cols[index]
            src_col_el = self._create_or_get_output_col(src_col)
            # если нет исходной колонки, то не надо копировать
            if not src_col_el is None:
                # копируем данные
                attrib_col = dict(src_col_el.items())
                dst_col_el = self._create_or_get_output_col(
                    dst_col, attrib_col)
                # записываем в новую колонку
                self._set_new_column_width(dst_col, src_col_el, dst_col_el)
Пример #3
0
        def cell_dimensions(section, merge_cell, start_cell):
            """
            Получение координаты ячейки после смещения из-за
            объединения ячеек
            
            :param section: начало секции
            :type section: 2-tuple
            :param merge_cell: начало объединенной ячейки
            :type merge_cell: 2-tuple
            :param start_cell: стартовая ячейка
            :type start_cell: 2-tuple
            """

            section_begin_col, section_begin_row = section

            start_col, start_row = start_cell

            begin_col, begin_row = merge_cell

            new_begin_row = start_row + begin_row - section_begin_row
            new_begin_col = ColumnHelper.add(
                start_col, ColumnHelper.difference(begin_col,
                                                   section_begin_col))

            return new_begin_col + str(new_begin_row)
Пример #4
0
    def test_range_cols(self):
        section_range = list(ColumnHelper.get_range(('ALC'), ('AVB')))
        self.assertIn('ALC', section_range)
        self.assertIn('AVB', section_range)
        self.assertIn('AVA', section_range)
        self.assertNotIn('ALA', section_range)
        self.assertNotIn('AVC', section_range)

        section_range = list(ColumnHelper.get_range(('X'), ('AB')))
        self.assertIn('X', section_range)
        self.assertIn('Y', section_range)
        self.assertIn('AA', section_range)
        self.assertNotIn('Q', section_range)
        self.assertNotIn('AC', section_range)
        self.assertEqual(len(section_range), 5)

        section_range = list(ColumnHelper.get_range(('B'), ('CBD')))
        self.assertIn('B', section_range)
        self.assertIn('C', section_range)
        self.assertIn('AAA', section_range)
        self.assertIn('ZZ', section_range)
        self.assertIn('ABA', section_range)
        self.assertIn('CBD', section_range)
        self.assertIn('CAA', section_range)
        self.assertIn('BZZ', section_range)
        self.assertNotIn('CBE', section_range)

        section_range = list(ColumnHelper.get_range(('BCCC'), ('BCCD')))
        self.assertIn('BCCC', section_range)
        self.assertIn('BCCD', section_range)
        self.assertNotIn('A', section_range)
        self.assertNotIn('BCCE', section_range)
        self.assertEqual(len(section_range), 2)
Пример #5
0
    def _calculate_merge_column(self, column):

        column_number = ColumnHelper.column_to_number(column)

        first_section_column = ColumnHelper.number_to_column(column_number - self.section.get_width())
        last_section_column = ColumnHelper.number_to_column(column_number - 1)

        return first_section_column, last_section_column
Пример #6
0
    def _calculate_merge_column(self, column):

        column_number = ColumnHelper.column_to_number(column)

        first_section_column = ColumnHelper.number_to_column(
            column_number - self.section.get_width())
        last_section_column = ColumnHelper.number_to_column(column_number - 1)

        return first_section_column, last_section_column
Пример #7
0
    def calculate_indent(self, column, w):
        """
        Получение колонки на `w` раньше чем `column`

        :param column: строковое представление колонки
        :type column: str
        :param w: смещение
        :type w: int
        """
        return ColumnHelper.number_to_column(
            ColumnHelper.column_to_number(column) - w)
Пример #8
0
    def calculate_indent(self, column, w):
        """
        Получение колонки на `w` раньше чем `column`

        :param column: строковое представление колонки
        :type column: str
        :param w: смещение
        :type w: int
        """
        return ColumnHelper.number_to_column(
            ColumnHelper.column_to_number(column) - w)
Пример #9
0
    def get_next_column(self, current_col, end_col, begin_col):
        """
        Получение следующей колонки

        :param current_col: текущая колонка
        :type current_col: str
        :param end_col: конечная колонка
        :type end_col: str
        :param begin_col: начальная колонка
        :type begin_col: str
        """

        return ColumnHelper.add(current_col, ColumnHelper.difference(end_col, begin_col) + 1)
Пример #10
0
    def get_next_column(self, current_col, end_col, begin_col):
        """
        Получение следующей колонки

        :param current_col: текущая колонка
        :type current_col: str
        :param end_col: конечная колонка
        :type end_col: str
        :param begin_col: начальная колонка
        :type begin_col: str
        """

        return ColumnHelper.add(
            current_col,
            ColumnHelper.difference(end_col, begin_col) + 1)
Пример #11
0
    def _create_or_get_output_col(self, col_index, attrib_col=None):
        """
        Найдем существующую колонку в результирующих данных
        Если не передали начальные данные, то колонка не создается,
        если не найдена,
        
        :param col_index: индекс колонки
        :type col_index: int
        :param attrib_col: атрибуты элемента колонки
        :type attrib_col: dict
        """
        # найдем интервал, в который попадаем искомый индекс
        col_index = ColumnHelper.column_to_number(col_index) + 1
        col_el = None
        for col in self.write_cols.getchildren():
            begin_col = int(col.attrib['min'])
            end_col = int(col.attrib['max'])
            if begin_col <= col_index <= end_col:
                col_el = col
                break

        if col_el is None:
            # если не нашли - создадим
            if attrib_col is None:
                return None
            attrib_col["min"] = str(col_index)
            attrib_col["max"] = str(col_index)
            col_el = SubElement(self.write_cols, 'col', attrib=attrib_col)
        return col_el
Пример #12
0
    def _create_or_get_output_col(self, col_index, attrib_col=None):
        """
        Найдем существующую колонку в результирующих данных
        Если не передали начальные данные, то колонка не создается,
        если не найдена,
        
        :param col_index: индекс колонки
        :type col_index: int
        :param attrib_col: атрибуты элемента колонки
        :type attrib_col: dict
        """
        # найдем интервал, в который попадаем искомый индекс
        col_index = ColumnHelper.column_to_number(col_index) + 1
        col_el = None
        for col in self.write_cols.getchildren():
            begin_col = int(col.attrib['min'])
            end_col = int(col.attrib['max'])
            if begin_col <= col_index <= end_col:
                col_el = col
                break

        if col_el is None:
            # если не нашли - создадим
            if attrib_col is None:
                return None
            attrib_col["min"] = str(col_index)
            attrib_col["max"] = str(col_index)
            col_el = SubElement(self.write_cols, 'col', attrib=attrib_col)
        return col_el
Пример #13
0
    def get_width(self):
        u"""
        Получение ширины секции
        """

        begin_col, begin_row = self.begin
        end_col, end_row = self.sheet_data.get_cell_end(self.end)

        return ColumnHelper.difference(end_col, begin_col) + 1
Пример #14
0
    def get_width(self):
        u"""
        Получение ширины секции
        """

        begin_col, begin_row = self.begin
        end_col, end_row = self.sheet_data.get_cell_end(self.end)

        return ColumnHelper.difference(end_col, begin_col) + 1
Пример #15
0
 def test_horizontal(self, report=None):
     if report is None:
         return
     for i in range(3):
         section3 = report.get_section('Section3')
         section3.flush({'section3': i}, oriented=Section.HORIZONTAL)
         self.assertEqual(section3.sheet_data.cursor.row, ('C', 9))
         self.assertEqual(section3.sheet_data.cursor.column,
                          (ColumnHelper.add('G', 2 * i), 7))
Пример #16
0
    def set_dimension(self):
        u"""
        Установка диапазона
        """
        _, row_index = self.cursor.row
        col_index, _ = self.cursor.column

        dimension = 'A1:%s' % \
                    (ColumnHelper.add(col_index, -1) + str(row_index - 1))

        self.write_dimension.set('ref', dimension)
Пример #17
0
    def set_dimension(self):
        u"""
        Установка диапазона
        """
        _, row_index = self.cursor.row
        col_index, _ = self.cursor.column

        dimension = 'A1:%s' % \
                    (ColumnHelper.add(col_index, -1) + str(row_index - 1))

        self.write_dimension.set('ref', dimension)
Пример #18
0
    def flush(
        self, params, oriented=ISpreadsheetSection.LEFT_DOWN,
        used_formulas=None
    ):
        """
        Вывод. Имеется два механизма вывода.
        Для использования старого не передавать direction
        
        :param params: параметры замены
        :type params: dict
        :param oriented: направление ориентации
        :type oriented: ISpreadsheetSection
        :param used_formulas: использованные формулы
        :type used_formulas: dict
        """
        assert isinstance(params, dict)
        assert oriented in (Section.VERTICAL,
                            Section.HORIZONTAL,
                            Section.LEFT_DOWN,
                            Section.RIGHT_UP,
                            Section.RIGHT,
                            Section.HIERARCHICAL)

        # Тут смещение курсора, копирование данных из листа и общих строк
        # Генерация новых данных и новых общих строк

        cursor = self.sheet_data.cursor

        begin_col, begin_row = self.begin
        end_col, end_row = self.sheet_data.get_cell_end(self.end)

        current_col, current_row = CalculateNextCursorXLSX().get_next_cursor(cursor, (begin_col, begin_row),
                        (end_col, end_row), oriented, self)

        self.sheet_data.last_section.row = (current_col, current_row)
        self.sheet_data.last_section.column = (ColumnHelper.add(current_col,
        ColumnHelper.difference(end_col, begin_col)), current_row + end_row - begin_row)

        self.sheet_data.flush(self.begin, self.end, (current_col, current_row),
            params, used_formulas)
Пример #19
0
    def set_pagebreaks(self, begin, end, start_cell):
        """
        Копирование разделителей страниц
        :param begin: начало секции, пример ('A', 1)
        :type begin: 2-tuple
        :param end: конец секции, пример ('E', 6)
        :type end: 2-tuple
        :param start_cell: ячейка с которой выводилась секция
        :type start_cell: 2-tuple
        """
        # определим интервал столбцов и колонок из которых надо взять разделители
        end = self.get_cell_end(end)
        begin_col = ColumnHelper.column_to_number(begin[0])
        end_col = ColumnHelper.column_to_number(end[0])
        begin_row = int(begin[1])
        end_row = int(end[1])
        # определим интервал столбцов и колонок, начинаемый с начальной ячейки, куда надо добавить разделители
        new_begin_col = ColumnHelper.column_to_number(start_cell[0])
        new_begin_row = int(start_cell[1])
        # вытащим смещение индексов столбцов у которых есть разделители и которые попали в этот интервал
        colbreaks = []
        if self.read_colbreaks is not None:
            for elem in self.read_colbreaks.getchildren():
                col_index = int(elem.attrib['id'])
                if begin_col <= col_index - 1 <= end_col:
                    colbreaks.append(col_index - begin_col + new_begin_col)

        self._set_colpagebreaks(colbreaks)

        # вытащим смещение индексов строк у которых есть разделители и которые попали в этот интервал
        rowbreaks = []
        if self.read_rowbreaks is not None:
            for elem in self.read_rowbreaks.getchildren():
                row_index = int(elem.attrib['id'])
                if begin_row <= row_index <= end_row:
                    rowbreaks.append(row_index - begin_row + new_begin_row)

        self._set_rowpagebreaks(rowbreaks)
Пример #20
0
    def set_pagebreaks(self, begin, end, start_cell):
        """
        Копирование разделителей страниц
        :param begin: начало секции, пример ('A', 1)
        :type begin: 2-tuple
        :param end: конец секции, пример ('E', 6)
        :type end: 2-tuple
        :param start_cell: ячейка с которой выводилась секция
        :type start_cell: 2-tuple
        """
        # определим интервал столбцов и колонок из которых надо взять разделители
        end = self.get_cell_end(end)
        begin_col = ColumnHelper.column_to_number(begin[0])
        end_col = ColumnHelper.column_to_number(end[0])
        begin_row = int(begin[1])
        end_row = int(end[1])
        # определим интервал столбцов и колонок, начинаемый с начальной ячейки, куда надо добавить разделители
        new_begin_col = ColumnHelper.column_to_number(start_cell[0])
        new_begin_row = int(start_cell[1])
        # вытащим смещение индексов столбцов у которых есть разделители и которые попали в этот интервал
        colbreaks = []
        if self.read_colbreaks is not None:
            for elem in self.read_colbreaks.getchildren():
                col_index = int(elem.attrib['id'])
                if begin_col <= col_index - 1 <= end_col:
                    colbreaks.append(col_index - begin_col + new_begin_col)

        self._set_colpagebreaks(colbreaks)

        # вытащим смещение индексов строк у которых есть разделители и которые попали в этот интервал
        rowbreaks = []
        if self.read_rowbreaks is not None:
            for elem in self.read_rowbreaks.getchildren():
                row_index = int(elem.attrib['id'])
                if begin_row <= row_index <= end_row:
                    rowbreaks.append(row_index - begin_row + new_begin_row)

        self._set_rowpagebreaks(rowbreaks)
Пример #21
0
    def flush(self,
              params,
              oriented=ISpreadsheetSection.LEFT_DOWN,
              used_formulas=None):
        """
        Вывод. Имеется два механизма вывода.
        Для использования старого не передавать direction
        
        :param params: параметры замены
        :type params: dict
        :param oriented: направление ориентации
        :type oriented: ISpreadsheetSection
        :param used_formulas: использованные формулы
        :type used_formulas: dict
        """
        assert isinstance(params, dict)
        assert oriented in (Section.VERTICAL, Section.HORIZONTAL,
                            Section.LEFT_DOWN, Section.RIGHT_UP, Section.RIGHT,
                            Section.HIERARCHICAL)

        # Тут смещение курсора, копирование данных из листа и общих строк
        # Генерация новых данных и новых общих строк

        cursor = self.sheet_data.cursor

        begin_col, begin_row = self.begin
        end_col, end_row = self.sheet_data.get_cell_end(self.end)

        current_col, current_row = CalculateNextCursorXLSX().get_next_cursor(
            cursor, (begin_col, begin_row), (end_col, end_row), oriented, self)

        self.sheet_data.last_section.row = (current_col, current_row)
        self.sheet_data.last_section.column = (ColumnHelper.add(
            current_col, ColumnHelper.difference(
                end_col, begin_col)), current_row + end_row - begin_row)

        self.sheet_data.flush(self.begin, self.end, (current_col, current_row),
                              params, used_formulas)
Пример #22
0
        def cell_dimensions(section, merge_cell, start_cell):
            """
            Получение координаты ячейки после смещения из-за
            объединения ячеек
            
            :param section: начало секции
            :type section: 2-tuple
            :param merge_cell: начало объединенной ячейки
            :type merge_cell: 2-tuple
            :param start_cell: стартовая ячейка
            :type start_cell: 2-tuple
            """

            section_begin_col, section_begin_row = section

            start_col, start_row = start_cell

            begin_col, begin_row = merge_cell

            new_begin_row = start_row + begin_row - section_begin_row
            new_begin_col = ColumnHelper.add(start_col, ColumnHelper.difference(begin_col, section_begin_col))

            return new_begin_col + str(new_begin_row)
Пример #23
0
 def _addr_in_range(self, addr, begin, end):
     u"""
     Проверяет, попадает ли адрес в диапазон
     
     :param addr: адрес ячейки
     :type addr: 2-tuple
     :param begin: начальная ячейка диапазона
     :type begin: 2-tuple
     :param end: конечная ячейка диапазона
     :type end: 2-tuple
     """
     col, row = addr
     rows = xrange(begin[1], end[1] + 1)
     cols = list(ColumnHelper.get_range(begin[0], end[0]))
     return all([col in cols, row in rows])
Пример #24
0
 def _addr_in_range(self, addr, begin, end):
     u"""
     Проверяет, попадает ли адрес в диапазон
     
     :param addr: адрес ячейки
     :type addr: 2-tuple
     :param begin: начальная ячейка диапазона
     :type begin: 2-tuple
     :param end: конечная ячейка диапазона
     :type end: 2-tuple
     """
     col, row = addr
     rows = xrange(begin[1], end[1] + 1)
     cols = list(ColumnHelper.get_range(begin[0], end[0]))
     return all([col in cols, row in rows])
Пример #25
0
    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
Пример #26
0
    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
Пример #27
0
    def _set_new_column_width(self, col_index, src_col, dst_col):
        """
        Установка новой ширины колонки
        Особенность в том, что нужно разбивать интервалы, если потребуется
        
        :param col_index: индекс колонки
        :type col_index: int
        :param src_col: элемент исходной колонки
        :type src_col: lxml.etree.Element
        :param dst_col: элемент выходной колонки
        :type dst_col: lxml.etree.Element
        """
        col_index = ColumnHelper.column_to_number(col_index) + 1
        # если ширина колонок отличается и колонка-приемник является интервалом,
        # то нужно разбить интервал на части с разной шириной колонок
        if dst_col.attrib["width"] != src_col.attrib["width"]:
            begin_col = int(dst_col.attrib['min'])
            end_col = int(dst_col.attrib['max'])
            # если задано интервалом, то будем разбивать
            if end_col - begin_col > 0:
                if col_index > begin_col:
                    # предыдущий интервал: max = col-1
                    prev_attrib_col = dict(dst_col.items())
                    prev_attrib_col['max'] = str(col_index - 1)
                    prev_col_el = SubElement(self.write_cols,
                                             'col',
                                             attrib=prev_attrib_col)

                if col_index < end_col:
                    # следующий интервал: min = col+1
                    next_attrib_col = dict(dst_col.items())
                    next_attrib_col["min"] = str(col_index + 1)
                    next_col_el = SubElement(self.write_cols,
                                             'col',
                                             attrib=next_attrib_col)

                # интервал для текущей колонки: min = max = col
                dst_col.attrib["min"] = str(col_index)
                dst_col.attrib["max"] = str(col_index)

            dst_col.attrib["width"] = src_col.attrib["width"]
Пример #28
0
    def _range(self, begin, end):
        u"""
        Диапазон строк, колонок
        
        :param begin: начальная ячейка 
        :type begin: 2-tuple
        :param end: конечная ячейка
        :type end: 2-tuple
        """

        # Если есть объединенная ячейка, и она попадает на конец секции, то адресс конца секции записывается как конец
        # объединенной ячейки
        end = self.get_cell_end(end)

        rows = begin[1], end[1] + 1
        cols = begin[0], end[0]

        range_rows = xrange(*rows)
        range_cols = list(ColumnHelper.get_range(*cols))

        return range_rows, range_cols
Пример #29
0
    def _range(self, begin, end):
        u"""
        Диапазон строк, колонок
        
        :param begin: начальная ячейка 
        :type begin: 2-tuple
        :param end: конечная ячейка
        :type end: 2-tuple
        """

        # Если есть объединенная ячейка, и она попадает на конец секции, то адресс конца секции записывается как конец
        # объединенной ячейки
        end = self.get_cell_end(end)

        rows = begin[1], end[1] + 1
        cols = begin[0], end[0]

        range_rows = xrange(*rows)
        range_cols = list(ColumnHelper.get_range(*cols))

        return range_rows, range_cols
Пример #30
0
    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
Пример #31
0
    def _set_new_column_width(self, col_index, src_col, dst_col):
        """
        Установка новой ширины колонки
        Особенность в том, что нужно разбивать интервалы, если потребуется
        
        :param col_index: индекс колонки
        :type col_index: int
        :param src_col: элемент исходной колонки
        :type src_col: lxml.etree.Element
        :param dst_col: элемент выходной колонки
        :type dst_col: lxml.etree.Element
        """
        col_index = ColumnHelper.column_to_number(col_index) + 1
        # если ширина колонок отличается и колонка-приемник является интервалом,
        # то нужно разбить интервал на части с разной шириной колонок
        if dst_col.attrib["width"] != src_col.attrib["width"]:
            begin_col = int(dst_col.attrib['min'])
            end_col = int(dst_col.attrib['max'])
            # если задано интервалом, то будем разбивать
            if end_col - begin_col > 0:
                if col_index > begin_col:
                    # предыдущий интервал: max = col-1
                    prev_attrib_col = dict(dst_col.items())
                    prev_attrib_col['max'] = str(col_index - 1)
                    prev_col_el = SubElement(self.write_cols, 'col', attrib=prev_attrib_col)

                if col_index < end_col:
                    # следующий интервал: min = col+1
                    next_attrib_col = dict(dst_col.items())
                    next_attrib_col["min"] = str(col_index + 1)
                    next_col_el = SubElement(self.write_cols, 'col', attrib=next_attrib_col)

                # интервал для текущей колонки: min = max = col
                dst_col.attrib["min"] = str(col_index)
                dst_col.attrib["max"] = str(col_index)

            dst_col.attrib["width"] = src_col.attrib["width"]
Пример #32
0
    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
Пример #33
0
    def set_section(self, begin, end, start_cell, params, used_formulas=None):
        u"""
        Вывод секции
        
        :param begin: начальная ячейка секции
        :type begin: 2-tuple
        :param end: конечная ячейка секции
        :type end: 2-tuple
        :param start_cell: стартовая ячейка (с которой начинается запись)
        :type start_cell: 2-tuple
        :param params: параметры отчета
        :type params: dict
        :param used_formulas: используемые формулы
        :type used_formulas: dict
        """
        # TODO: разбить на методы
        range_rows, range_cols = self._range(begin, end)
        start_column, start_row = start_cell
        if used_formulas is None:
            used_formulas = {}

        for i, num_row, row in self._find_rows(range_rows):
            attrib_row = dict(row.items())

            row_index = start_row + i
            attrib_row['r'] = str(row_index)
            # следующая строка создает линейное время для флаша от числа флашей
            row_el = self._create_or_get_output_row(row_index, attrib_row)

            for j, col, cell in self._find_cells(range_cols, num_row, row):
                attrib_cell = dict(cell.items())

                col_index = ColumnHelper.add(start_column, j)

                attrib_cell['r'] = col_index + str(row_index)

                cell_el = self._create_or_get_output_cell(row_el, col_index + str(row_index), attrib_cell)

                # Перенос формул
                formula = self._get_tag_formula(cell)
                if formula is not None:
                    formula_el = SubElement(cell_el, 'f')

                    row_cursor_column, row_cursor_row = self.cursor.row
                    column_cursor_column, column_cursor_row = self.cursor.column
                    formula_el.text = Formula.get_instance(formula.text).get_next_formula(row_cursor_row,
                                                                                          column_cursor_column)
                    # Если есть формула, то значение является вычисляемым параметром и не сильно интересует
                    continue

                value = self._get_tag_value(cell)
                if not value is None:
                    value_el = SubElement(cell_el, 'v')

                    if attrib_cell.get('t') in ('n', None):  # number

                        value_el.text = value.text

                    elif attrib_cell.get('t') == 's':  # 't' = 's' - значит есть значения shared strings

                        index_value = int(value.text)
                        value_string = self.shared_table.get_value(index_value)

                        who_found_params = self._get_values_by_re(value_string)
                        is_int = False
                        if who_found_params:
                            for found_param in who_found_params:
                                param_name = found_param[1:-1]

                                param_value = params.get(param_name)
                                if used_formulas:
                                    formula_id_list = used_formulas.get(param_name)
                                    assert (
                                        formula_id_list is None or
                                        isinstance(
                                            formula_id_list,
                                            (list, tuple))
                                    ), ("used_formulas values must be "
                                        "lists or tuples")
                                    if formula_id_list is not None:
                                        for formula_id in formula_id_list:
                                            cell_string = ''.join([col_index,
                                                                str(row_index)])
                                            self.formula_id_dict.setdefault(
                                                formula_id, []).append(cell_string)
                                # Находим теги шаблонов, если есть таковые
                                if param_name[0] == self.PREFIX_TAG and param_name[-1] == self.PREFIX_TAG:
                                    param_value = self.tags.get(param_name[1:-1])

                                if isinstance(param_value, datetime) and found_param == value_string:
                                    # В OpenXML хранится дата относительно 1900 года
                                    days = date_to_float(param_value)
                                    if days > 0:
                                        # Дата конвертируется в int, начиная с 31.12.1899
                                        is_int = True
                                        cell_el.attrib['t'] = 'n'  # type - number
                                        value_el.text = unicode(days)
                                    else:
                                        date_less_1900 = '%s.%s.%s' % (
                                            param_value.date().day,
                                            param_value.date().month,
                                            param_value.date().year
                                        )
                                        # strftime(param_value, locale.nl_langinfo(locale.D_FMT)) - неработает для 1900 и ниже
                                        value_string = value_string.replace(found_param, unicode(date_less_1900))

                                # Добавил long, возможно нужно использовать
                                # общего предка numbers.Number
                                elif isinstance(
                                    param_value,
                                    (int, float, long, Decimal)
                                ) and found_param == value_string:
                                    # В первую очередь добавляем числовые значения
                                    is_int = True

                                    cell_el.attrib['t'] = 'n'  # type - number
                                    value_el.text = unicode(param_value)

                                elif isinstance(param_value, basestring):
                                    # Строковые параметры

                                    value_string = value_string.replace(found_param, unicode(param_value))

                                elif isinstance(param_value, FormulaWriteExcel):
                                    # Записываем формулу, которой не было в
                                    # шаблоне
                                    func_ = param_value.excel_function
                                    f_id = param_value.formula_id
                                    if f_id and func_:
                                        attrib_cell['t'] = 'e'
                                        # тип вычислимого по формуле поля
                                        cell_el.remove(value_el)
                                        # значения в ячейке с формулой нет
                                        formula_el = SubElement(cell_el, 'f')
                                        row_cursor_column, row_cursor_row = self.cursor.row
                                        column_cursor_column, column_cursor_row = self.cursor.column
                                        f_cells = self.formula_id_dict.get(
                                            f_id, [])
                                        if param_value.ranged and f_cells:
                                            formula_el.text = '%s(%s)' % (
                                                func_, ':'.join([f_cells[0],
                                                                f_cells[-1]])
                                                )
                                        elif f_cells:
                                            # Группируем по 30 элементов
                                            cells_number = int(
                                                len(f_cells) / XLSX_GROUPING_COUNT
                                            ) + 1
                                            val_list = []
                                            for x in range(cells_number):
                                                sub_args = (
                                                    ','.join(
                                                        f_cells[x * XLSX_GROUPING_COUNT:(x + 1) * XLSX_GROUPING_COUNT]
                                                    )
                                                )
                                                if sub_args:
                                                    sub_val = '(%s)' % (
                                                        sub_args
                                                    )
                                                    val_list.append(sub_val)

                                            formula_el.text = '%s(%s)' % (
                                                func_,
                                                ','.join(val_list)
                                            )

                                        self.formula_id_dict[f_id] = []
                                    else:
                                        continue

                                elif param_value:
                                    # любой объект, например список или
                                    # словарь. Вынесено для производительности

                                    value_string = value_string.replace(found_param, unicode(param_value))

                                else:
                                    # Не передано значение параметра
                                    value_string = value_string.replace(found_param, '')

                            if not is_int:
                                # Добавим данные в shared strings

                                new_index = self.shared_table.get_new_index(value_string)
                                value_el.text = new_index

                        else:
                            # Параметры в поле не найдены

                            index = self.shared_table.get_new_index(value_string)
                            value_el.text = index

                    elif attrib_cell.get('t'):
                        raise SheetDataException("Unknown value '%s' for tag t" % attrib_cell.get('t'))
Пример #34
0
    def set_section(self, begin, end, start_cell, params, used_formulas=None):
        u"""
        Вывод секции
        
        :param begin: начальная ячейка секции
        :type begin: 2-tuple
        :param end: конечная ячейка секции
        :type end: 2-tuple
        :param start_cell: стартовая ячейка (с которой начинается запись)
        :type start_cell: 2-tuple
        :param params: параметры отчета
        :type params: dict
        :param used_formulas: используемые формулы
        :type used_formulas: dict
        """
        # TODO: разбить на методы
        range_rows, range_cols = self._range(begin, end)
        start_column, start_row = start_cell
        if used_formulas is None:
            used_formulas = {}

        for i, num_row, row in self._find_rows(range_rows):
            attrib_row = dict(row.items())

            row_index = start_row + i
            attrib_row['r'] = str(row_index)
            # следующая строка создает линейное время для флаша от числа флашей
            row_el = self._create_or_get_output_row(row_index, attrib_row)

            for j, col, cell in self._find_cells(range_cols, num_row, row):
                attrib_cell = dict(cell.items())

                col_index = ColumnHelper.add(start_column, j)

                attrib_cell['r'] = col_index + str(row_index)

                cell_el = self._create_or_get_output_cell(
                    row_el, col_index + str(row_index), attrib_cell)

                # Перенос формул
                formula = self._get_tag_formula(cell)
                if formula is not None:
                    formula_el = SubElement(cell_el, 'f')

                    row_cursor_column, row_cursor_row = self.cursor.row
                    column_cursor_column, column_cursor_row = self.cursor.column
                    formula_el.text = Formula.get_instance(
                        formula.text).get_next_formula(row_cursor_row,
                                                       column_cursor_column)
                    # Если есть формула, то значение является вычисляемым параметром и не сильно интересует
                    continue

                value = self._get_tag_value(cell)
                if not value is None:
                    value_el = SubElement(cell_el, 'v')

                    if attrib_cell.get('t') in ('n', None):  # number

                        value_el.text = value.text

                    elif attrib_cell.get(
                            't'
                    ) == 's':  # 't' = 's' - значит есть значения shared strings

                        index_value = int(value.text)
                        value_string = self.shared_table.get_value(index_value)

                        who_found_params = self._get_values_by_re(value_string)
                        is_int = False
                        if who_found_params:
                            for found_param in who_found_params:
                                param_name = found_param[1:-1]

                                param_value = params.get(param_name)
                                if used_formulas:
                                    formula_id_list = used_formulas.get(
                                        param_name)
                                    assert (formula_id_list is None
                                            or isinstance(
                                                formula_id_list, (list, tuple))
                                            ), ("used_formulas values must be "
                                                "lists or tuples")
                                    if formula_id_list is not None:
                                        for formula_id in formula_id_list:
                                            cell_string = ''.join(
                                                [col_index,
                                                 str(row_index)])
                                            self.formula_id_dict.setdefault(
                                                formula_id,
                                                []).append(cell_string)
                                # Находим теги шаблонов, если есть таковые
                                if param_name[
                                        0] == self.PREFIX_TAG and param_name[
                                            -1] == self.PREFIX_TAG:
                                    param_value = self.tags.get(
                                        param_name[1:-1])

                                if isinstance(
                                        param_value, datetime
                                ) and found_param == value_string:
                                    # В OpenXML хранится дата относительно 1900 года
                                    days = date_to_float(param_value)
                                    if days > 0:
                                        # Дата конвертируется в int, начиная с 31.12.1899
                                        is_int = True
                                        cell_el.attrib[
                                            't'] = 'n'  # type - number
                                        value_el.text = unicode(days)
                                    else:
                                        date_less_1900 = '%s.%s.%s' % (
                                            param_value.date().day,
                                            param_value.date().month,
                                            param_value.date().year)
                                        # strftime(param_value, locale.nl_langinfo(locale.D_FMT)) - неработает для 1900 и ниже
                                        value_string = value_string.replace(
                                            found_param,
                                            unicode(date_less_1900))

                                # Добавил long, возможно нужно использовать
                                # общего предка numbers.Number
                                elif isinstance(
                                        param_value,
                                    (int, float, long,
                                     Decimal)) and found_param == value_string:
                                    # В первую очередь добавляем числовые значения
                                    is_int = True

                                    cell_el.attrib['t'] = 'n'  # type - number
                                    value_el.text = unicode(param_value)

                                elif isinstance(param_value, basestring):
                                    # Строковые параметры

                                    value_string = value_string.replace(
                                        found_param, unicode(param_value))

                                elif isinstance(param_value,
                                                FormulaWriteExcel):
                                    # Записываем формулу, которой не было в
                                    # шаблоне
                                    func_ = param_value.excel_function
                                    f_id = param_value.formula_id
                                    if f_id and func_:
                                        attrib_cell['t'] = 'e'
                                        # тип вычислимого по формуле поля
                                        cell_el.remove(value_el)
                                        # значения в ячейке с формулой нет
                                        formula_el = SubElement(cell_el, 'f')
                                        row_cursor_column, row_cursor_row = self.cursor.row
                                        column_cursor_column, column_cursor_row = self.cursor.column
                                        f_cells = self.formula_id_dict.get(
                                            f_id, [])
                                        if param_value.ranged and f_cells:
                                            formula_el.text = '%s(%s)' % (
                                                func_, ':'.join(
                                                    [f_cells[0], f_cells[-1]]))
                                        elif f_cells:
                                            # Группируем по 30 элементов
                                            cells_number = int(
                                                len(f_cells) /
                                                XLSX_GROUPING_COUNT) + 1
                                            val_list = []
                                            for x in range(cells_number):
                                                sub_args = (','.join(f_cells[
                                                    x *
                                                    XLSX_GROUPING_COUNT:(x +
                                                                         1) *
                                                    XLSX_GROUPING_COUNT]))
                                                if sub_args:
                                                    sub_val = '(%s)' % (
                                                        sub_args)
                                                    val_list.append(sub_val)

                                            formula_el.text = '%s(%s)' % (
                                                func_, ','.join(val_list))

                                        self.formula_id_dict[f_id] = []
                                    else:
                                        continue

                                elif param_value:
                                    # любой объект, например список или
                                    # словарь. Вынесено для производительности

                                    value_string = value_string.replace(
                                        found_param, unicode(param_value))

                                else:
                                    # Не передано значение параметра
                                    value_string = value_string.replace(
                                        found_param, '')

                            if not is_int:
                                # Добавим данные в shared strings

                                new_index = self.shared_table.get_new_index(
                                    value_string)
                                value_el.text = new_index

                        else:
                            # Параметры в поле не найдены

                            index = self.shared_table.get_new_index(
                                value_string)
                            value_el.text = index

                    elif attrib_cell.get('t'):
                        raise SheetDataException(
                            "Unknown value '%s' for tag t" %
                            attrib_cell.get('t'))