Esempio n. 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)
Esempio n. 2
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)
Esempio n. 3
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)
Esempio n. 4
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))
Esempio n. 5
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)
Esempio n. 6
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)
Esempio n. 7
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)
Esempio n. 8
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)
Esempio n. 9
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
Esempio n. 10
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
Esempio n. 11
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)
Esempio n. 12
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)
Esempio n. 13
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)
Esempio n. 14
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'))
Esempio n. 15
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'))