Ejemplo n.º 1
0
def getReportResourceFilename(report_filename='', report_dir=''):
    """
    Получить полное имя файла шаблона отчета.
    @param report_filename: Имя файла отчета в кратком виде.
    @param report_dir: Папка отчетов.
    @return: Полное имя файла отчета.
    """
    # Проверить расширение
    rprt_filename = report_filename
    if not rprt_filename.endswith(DEFAULT_REPORT_FILE_EXT):
        rprt_filename = os.path.splitext(
            rprt_filename)[0] + DEFAULT_REPORT_FILE_EXT

    # Проверить актуальность шаблона
    full_src_filename = getPathFilename(report_filename, report_dir)
    full_rprt_filename = getPathFilename(rprt_filename, report_dir)
    if isNewReportTemplateFile(full_src_filename, full_rprt_filename):
        # Если исходный шаблон изменен позже чем рабочий файл шаблона <rprt>
        # то необходимо сделать изменения
        updateReportTemplateFile(full_src_filename, full_rprt_filename)

    if os.path.exists(rprt_filename):
        # Проверить может быть задано абсолютное имя файла
        filename = rprt_filename
    else:
        # Задано скорее всего относительное имя файла
        # относительно папки отчетов
        filename = full_rprt_filename
        if not os.path.exists(filename):
            # Нет такого файла
            log.warning(u'Файл шаблона отчета <%s> не найден' %
                        textfunc.toUnicode(filename))
            filename = createReportResourceFile(filename)
    log.debug(u'Полное имя файла шаблона <%s>' % textfunc.toUnicode(filename))
    return filename
Ejemplo n.º 2
0
 def setExtOptions(self, **options):
     """
     Установить дополнительные опции.
     @param options: Словарь опций.
     """
     log.debug(u'Опции сканирования: %s' % options)
     if options:
         if 'scanner' in options:
             self.scanner = options.get('scanner', None)
         if 'source' in options:
             self.scan_source = options.get('source', None)
         if 'mode' in options:
             self.scan_mode = options.get('mode', None)
         if 'is_multi_scan' in options:
             self.is_multi_scan = options.get('is_multi_scan', None)
         if 'is_preview' in options:
             self.is_preview = options.get('is_preview', None)
         if 'page_size' in options:
             self.page_size = options.get('page_size', None)
         if 'area' in options:
             self.scan_area = options.get('area', None)
         if 'scan_dir' in options:
             self.scan_dir = options.get('scan_dir', None)
         if 'file_name' in options:
             self.scan_filename = options.get('file_name', None)
         if 'file_type' in options:
             self.scan_filetype = options.get('file_type', None)
         if 'depth' in options:
             self.depth = options.get('depth', None)
         if 'ext_scan_cmd' in options:
             self.ext_scan_cmd = options.get('ext_scan_cmd', None)
     else:
         log.warning(u'Не определены опции сканирования для установки')
Ejemplo n.º 3
0
    def NewByOffice(self, dst_path=None):
        """
        Создание нового отчета средствами LibreOffice Calc.
        @param dst_path: Результирующая папка, в которую будет помещен новый файл.
        """
        try:
            src_filename = DEFAULT_REP_TMPL_FILE
            new_filename = dlg.getTextInputDlg(
                self._ParentForm, u'Создание нового файла',
                u'Введите имя файла шаблона отчета')
            if os.path.splitext(new_filename)[1] != '.ods':
                new_filename += '.ods'

            if dst_path is None:
                # Необходимо определить результирующий путь
                dst_path = dlg.getDirDlg(self._ParentForm, u'Папка хранения')
                if not dst_path:
                    dst_path = os.getcwd()

            dst_filename = os.path.join(dst_path, new_filename)
            if os.path.exists(dst_filename):
                if dlg.getAskBox(u'Заменить существующий файл?'):
                    shutil.copyfile(src_filename, dst_filename)
            else:
                shutil.copyfile(src_filename, dst_filename)

            cmd = OFFICE_OPEN_CMD_FORMAT % dst_filename
            log.debug(u'Command <%s>' % textfunc.toUnicode(cmd))
            os.system(cmd)

            return True
        except:
            # Вывести сообщение об ошибке в лог
            log.fatal(u'New report template by LibreOffice Calc')
Ejemplo n.º 4
0
    def Edit(self, RepFileName_=None):
        """
        Редактирование отчета.
        @param RepFileName_: Полное имя файла шаблона отчета.
        """
        # Создание связи с ActiveX
        rprt_file_name = os.path.abspath(RepFileName_)
        rep = ic_res.LoadResource(rprt_file_name)
        report_dir = os.path.abspath(ic.engine.ic_user.icGet('REPORT_DIR'))
        rep_file = os.path.abspath(rep['generator'], report_dir)
        
        reportman_designer_key = ic_util.GetRegValue('Software\\Classes\\Report Manager Designer\\shell\\open\\command', None)
        if reportman_designer_key:
            reportman_designer_run = reportman_designer_key.replace('\'%1\'', '\'%s\'') % rep_file
            cmd = 'start %s' % reportman_designer_run
            log.debug(u'Запуск команды ОС: <%s>' % cmd)
            # и запустить Report Manager Designer
            os.system(cmd)
        else:
            msg = u'Не определен дизайнер отчетов Report Manager Designer %s' % reportman_designer_key
            log.warning(msg)
            ic_dlg.icWarningBox(u'ВНИМАНИЕ!', msg)

        # Определить файл *.xml
        xml_file = os.path.normpath(os.path.abspath(os.path.splitext(RepFileName_)[0]+'.xml'))
        cmd = 'start excel.exe \'%s\'' % xml_file
        log.debug(u'Запуск команды ОС: <%s>' % cmd)
        # и запустить MSExcel
        os.system(cmd)
Ejemplo n.º 5
0
    def _getPageSetup(self, PageSetup_):
        """
        Определить параметры страницы.
        """
        page_setup = {}
        # Ориентиция
        layouts = [obj for obj in PageSetup_['children'] if obj['name'] == 'Layout']
        log.debug('Layout %s' % layouts)
        if layouts:
            layout = layouts[0]
            if 'Orientation' in layout:
                if layout['Orientation'] == 'Landscape':
                    page_setup['orientation'] = icrepgen.IC_REP_ORIENTATION_LANDSCAPE
                elif layout['Orientation'] == 'Portrait':
                    page_setup['orientation'] = icrepgen.IC_REP_ORIENTATION_PORTRAIT
            # Начало нумерации страниц
            if 'StartPageNumber' in layout:
                page_setup['start_num'] = int(layout['StartPageNumber'])
        # Поля
        page_margins = [obj for obj in PageSetup_['children'] if obj['name'] == 'PageMargins']
        log.debug('PageMargins %s' % page_margins)
        if page_margins:
            page_margin = page_margins[0]
            page_setup['page_margins'] = []
            page_setup['page_margins'].append(float(page_margin.get('Left', 0)))
            page_setup['page_margins'].append(float(page_margin.get('Right', 0)))
            page_setup['page_margins'].append(float(page_margin.get('Top', 0)))
            page_setup['page_margins'].append(float(page_margin.get('Bottom', 0)))
            page_setup['page_margins'] = tuple(page_setup['page_margins'])

        return page_setup
Ejemplo n.º 6
0
def glue_pdf_files(out_pdf_filename, *pdf_filenames):
    """
    Процедура склеивания/объединения PDf файлов в один.
    @param out_pdf_filename: Полное наименование результирующего PDF файла.
    @param pdf_filenames: Список имен файлов-источников.
        Объединение происходит в порядке указанном списком pdf_filenames.
        Если какой либо файл отсутствует, то объединение происходит без него.
    @return: True - объединение прошло успешно / False - ошибка по какой-либо причине.
    """
    try:
        merger = PyPDF2.PdfFileMerger()
        filenames = [
            filename for filename in pdf_filenames
            if filename.lower().endswith('.pdf') and os.path.exists(filename)
        ]
        for filename in filenames:
            pdf_file = open(filename, 'rb')
            log.debug(u'Объединение PDF файла <%s> => <%s>' %
                      (filename, out_pdf_filename))
            reader = PyPDF2.PdfFileReader(pdf_file)
            merger.append(reader)

        out_pdf_filename = os.path.abspath(out_pdf_filename)
        if os.path.exists(out_pdf_filename):
            log.info(u'Удаление файла <%s>' % out_pdf_filename)
            try:
                os.remove(out_pdf_filename)
            except:
                log.fatal(u'Ошибка удаления файла <%s>' % out_pdf_filename)
        log.debug(u'Запись результирующего файла <%s>' % out_pdf_filename)
        merger.write(out_pdf_filename)
        return True
    except:
        log.fatal(u'Ошибка склеивания/объединения PDF файлов')
    return False
Ejemplo n.º 7
0
def get_current_dir():
    """
    Текущая папка.
    Относительнай путь считается от папки defis.
    @return:
    """
    cur_dir = os.path.dirname(os.path.dirname(ic.config.__file__))
    log.debug(u'Текущая папка определена как <%s>' % cur_dir)
    return cur_dir
Ejemplo n.º 8
0
    def scan_pack(self, scan_filenames=()):
        """
        Сканировать документы в пакетном режиме и сохранить их в файлы.        
        @param scan_filenames: Имена файлов скана с указанием количества листов
            и признаком 2-стороннего сканирования.
            Например:
                ('D:/tmp/scan001', 3, True), ('D:/tmp/scan002', 1, False), ('D:/tmp/scn003', 2, True), ...
        @return: Список имен файлов скана. None - в случае ошибки.
        """
        result = list()
        # Счетчик отсканированных листов
        tray_sheet_count = 0
        # Объем лотка в листах
        max_sheets = self.getMaxSheets()

        # В пакетном режиме не используем диалоговое окно
        # Но в случае режима склеивания документа по частям диалоговые окна используются
        # Объект приложения для управления диалоговыми окнами
        wx_app = None

        for scan_filename, n_pages, is_duplex in scan_filenames:
            tray_sheet_count += n_pages if not is_duplex else n_pages/2

            if tray_sheet_count <= max_sheets:
                # Пока счетчик сканирования не превысил ограничение объема лотка,
                # то продолжаем обычное сканирование
                scan_result = self.scan_pack_part(scan_filename, n_pages, is_duplex)
                result.append(scan_filename if scan_result and os.path.exists(scan_filename) else None)
            else:
                log.debug(u'Включение режима сканирования документа <%s> по частям. Количество страниц [%d] Текущий счетчик %d. ' % (scan_filename, n_pages, tray_sheet_count))
                if wx_app is None:
                    # Внимание! Приложение создается для
                    # управления диалоговыми окнами
                    wx_app = wx.PySimpleApp()
                    # ВНИМАНИЕ! Выставить русскую локаль
                    # Это необходимо для корректного отображения календарей,
                    # форматов дат, времени, данных и т.п.
                    locale = wx.Locale()
                    locale.Init(wx.LANGUAGE_RUSSIAN)

                # Если в лотке кончилась бумага, то надо запустить процедуру склейки последнего
                # документа
                glue_result = self.scan_glue(scan_filename, n_pages, is_duplex)
                # М.б. нажата <Отмена> или какая то ошибка
                result.append(scan_filename if glue_result and os.path.exists(scan_filename) else None)

                # ВНИМАНИЕ! После успешно отсканированного большого документа
                # сбрасываем счетчик отсканированных листов
                tray_sheet_count = 0

        # ВНИМАНИЕ! Т.к. взаимодействие построено на модальных диалоговых
        # окнах, то MainLoop делать не надо иначе основное приложение зависает
        # if wx_app:
        #    wx_app.MainLoop()

        return result
Ejemplo n.º 9
0
    def Update(self, RepTemplateFileName_=None):
        """
        Обновить шаблон отчета в системе генератора отчетов.
        @param RepTemplateFileName_: Имя файла шаблона отчета.
            Если None, то должен производиться запрос на выбор этого файла.
        @return: Имя файла файла шаблона или None в случае ошибки.
        """
        if RepTemplateFileName_ is None:
            filename = dlg.getFileDlg(
                self._ParentForm, u'Выберите шаблон отчета:',
                u'Microsoft Excel 2003 XML (*.xml)|*.xml|Электронные таблицы ODF (*.ods)|*.ods',
                self.getReportDir())
        else:
            filename = os.path.abspath(os.path.normpath(RepTemplateFileName_))

        if os.path.isfile(filename):

            # Конвертация
            log.debug(u'Начало конвертации <%s>' % filename)
            tmpl_filename = None
            template = None
            if os.path.exists(
                    os.path.splitext(filename)[0] + DEFAULT_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + DEFAULT_TEMPLATE_EXT
                template = icreptemplate.icODSReportTemplate()
            elif os.path.exists(
                    os.path.splitext(filename)[0] + ODS_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + ODS_TEMPLATE_EXT
                template = icreptemplate.icODSReportTemplate()
            elif os.path.exists(
                    os.path.splitext(filename)[0] + XLS_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + XLS_TEMPLATE_EXT
                template = icreptemplate.icXLSReportTemplate()
            elif os.path.exists(
                    os.path.splitext(filename)[0] + XML_TEMPLATE_EXT):
                tmpl_filename = os.path.splitext(
                    filename)[0] + XML_TEMPLATE_EXT
                template = icreptemplate.icExcelXMLReportTemplate()
            else:
                log.warning(u'Not find report template for <%s>' % filename)
            if template:
                rep_template = template.read(tmpl_filename)
                new_filename = os.path.splitext(
                    filename)[0] + DEFAULT_REPORT_TEMPLATE_EXT
                res.saveResourcePickle(new_filename, rep_template)
            log.info(u'Конец конвертации')
            return new_filename
        else:
            log.warning(u'Не найден файл источника шаблона <%s>' % filename)
        return None
Ejemplo n.º 10
0
 def _execQueryFunc(self, Query_, vars=None):
     """
     Получить запрос из функции.
     @param Query_: Текст запроса.
     @param vars: Внешние переменные.
     @return: Возвращает запрос в разрешенном формате.
     """
     # Убрать сигнатуру определения функции
     func = Query_.replace(PY_SIGNATURE, '').strip()
     var_names = vars.keys() if vars else None
     log.debug(u'Выполнение функции: <%s>. Дополнительные переменные %s' %
               (func, var_names))
     return execfunc.exec_code(func, name_space=locals(), kwargs=vars)
Ejemplo n.º 11
0
 def OnPreviewRepButton(self, event):
     """
     Обработчик нажатия кнопки 'Предварительный просмотр/Печать'.
     """
     # Определить выбранный пункт дерева
     item = self.rep_tree.GetSelection()
     item_data = self.rep_tree.GetPyData(item)
     log.debug(u'Preview <%s>' % item_data[REP_FILE_IDX])
     # Если это файл отчета, то получить его
     if item_data is not None and item_data[REP_ITEMS_IDX] is None:
         # Получение отчета
         report_generator.getReportGeneratorSystem(item_data[REP_FILE_IDX],
                                                   ParentForm_=self,
                                                   bRefresh=True).Preview()
     # Если это папка, то вывести сообщение
     else:
         dlg.getMsgBox(u'Необходимо выбрать отчет!', parent=self)
Ejemplo n.º 12
0
    def OnConvertRepButton(self, event):
        """
        Обработчик нажатия кнопки 'Конвертация'.
        """
        # Определить выбранный пункт дерева
        item = self.rep_tree.GetSelection()
        item_data = self.rep_tree.GetPyData(item)
        log.debug(u'Convert <%s>' % item_data[REP_FILE_IDX])
        # Если это файл отчета, то получить его
        if item_data is not None and item_data[REP_ITEMS_IDX] is None:
            # Получение отчета
            report_generator.getReportGeneratorSystem(item_data[REP_FILE_IDX],
                                                      ParentForm_=self,
                                                      bRefresh=True).Convert()
        else:
            dlg.getMsgBox(u'Необходимо выбрать отчет!', parent=self)

        event.Skip()
Ejemplo n.º 13
0
 def scanSingle(self, scan_filename=None):
     """
     Одностраничное сканирование
     Если вкл. ДУПЛЕКС и выключено многостраничное сканирование,
     то надо отсканировать 1 лист с 2-х сторон.
     @param scan_filename: Имя файла скана.
         Если имя файла не указано, то происходит сканирование и
         возвращается объект PIL.Image.
     @return: True - все прошло успешно. False - ошибка.
     """
     if self.isDuplexOption():
         # Если вкл. ДУПЛЕКС и выключено многостраничное сканирование,
         # то надо отсканировать 1 лист с 2-х сторон
         log.debug(u'Сканирование дуплекс')
         return self.scanMulti(scan_filename, 2)
     # Сканирование одной страницы
     log.debug(u'Одностороннее сканирование')
     self.startScan()
     scan_obj = self.scan(scan_filename)
     return scan_obj is not None
Ejemplo n.º 14
0
def view_file_ext(filename):
    """
    Запуск просмотра файла внешней программой.
    Определение какой программой производить просмотр определяется по расширению файла.
    @param filename: Полное имя файла.
    @return: True/False.
    """
    if not os.path.exists(filename):
        log.warning(u'Просмотр файла внешней программой. Файл <%s> не наден.' %
                    filename)
        return False
    file_type = os.path.splitext(filename)[1]
    file_ext = file_type.lower()

    for file_extensions, view_cmd_associate in ASSOCIATION_VIEW_FILE.items():
        if file_ext in file_extensions:
            cmd = view_cmd_associate % filename
            log.debug(u'Запуск комманды <%s>' % cmd)
            os.system(cmd)
    return True
Ejemplo n.º 15
0
 def _genHeader(self, Header_):
     """
     Сгенерировать заголовок отчета и перенести ее в выходной отчет.
     @param Header_: Бэнд заголовка.
     @return: Возвращает результат выполнения операции True/False.
     """
     try:
         log.debug(u'Генерация заголовка')
         # Добавлять будем в конец отчета,
         # поэтому опреелить максимальную строчку
         max_row = len(self._Rep['sheet'])
         i_row = 0
         cur_height = 0
         # Перебрать все ячейки бэнда
         for row in range(Header_['row'],
                          Header_['row'] + Header_['row_size']):
             for col in range(Header_['col'],
                              Header_['col'] + Header_['col_size']):
                 if self._TemplateSheet[row][col]:
                     self._genCell(self._TemplateSheet, row, col, self._Rep,
                                   max_row + i_row, col, self._CurRec)
                     cur_height = self._TemplateSheet[row][col]['height']
             i_row += 1
             # Увеличить текущую координату Y
             self._cur_top += cur_height
         # Прописать область
         self._Rep['header'] = {
             'row': max_row,
             'col': Header_['col'],
             'row_size': i_row,
             'col_size': Header_['col_size'],
         }
         # Очистить сумы суммирующих ячеек
         self._TemplateSheet = self._clearSum(self._TemplateSheet, 0,
                                              len(self._TemplateSheet))
         return True
     except:
         # Вывести сообщение об ошибке в лог
         log.fatal(u'Ошибка генерации заголовка отчета <%s>.' %
                   textfunc.toUnicode(self._RepName))
         return False
Ejemplo n.º 16
0
    def OnUpdateRepButton(self, event):
        """
        Обработчик нажатия кнопки 'Обновление отчета'.
        """
        # Определить выбранный пункт дерева
        item = self.rep_tree.GetSelection()
        item_data = self.rep_tree.GetPyData(item)
        # Если это файл отчета, то запустить обновление шаблона
        if item_data is not None and item_data[REP_ITEMS_IDX] is None:
            # Запустить обновление шаблона отчета
            log.debug('Update <%s> report' % item_data[0])
            report_generator.getReportGeneratorSystem(item_data[REP_FILE_IDX],
                                                      ParentForm_=self).Update(
                                                          item_data[0])
        else:
            report_generator.getCurReportGeneratorSystem(self).Update()

        # Заполнить дерево отчетов
        self._fillReportTree(self._ReportDir)

        event.Skip()
Ejemplo n.º 17
0
    def _getFontStyle(self, style):
        """
        Взять описание шрифта из стиля.
        @param style: Описание стиля.
        """
        # Шрифт описанный в стиле
        style_font = [style_attr for style_attr in style['children'] if style_attr['name'] == 'Font']
        log.debug('Font <%s> Style <%s>' % (style_font, style['ID']))
        if style_font:
            style_font = style_font[0]
        else:
            style_font = {}
        
        # Выходная структура шрифта
        font = {'name': 'Arial Cyr',
                'size': 10,
                'family': 'default',
                'faceName': None,
                'underline': False,
                'style': 'regular',
                }
        if 'FontName' in style_font:
            font['name'] = style_font['FontName']
            font['faceName'] = style_font['FontName']
        if 'Size' in style_font:
            font['size'] = float(style_font['Size'])

        if 'Underline' in style_font:
            font['underline'] = True
    
        if 'Bold' in style_font and style_font['Bold'] == '1':
            style = 'bold'
            if 'Italic' in style_font and style_font['Italic'] == '1':
                style = 'boldItalic'
            font['style'] = style
        elif 'Italic' in style_font and style_font['Italic'] == '1':
            font['style'] = 'italic'
            
        return font
Ejemplo n.º 18
0
    def runScan(self):
        """
        Запусть процесс сканирования,
        согласно выставленным параметрам.
        @return: True/False
        """
        if self.scan_manager is None:
            log.warning(u'Не определен менеджер сканирования')
            return False
        if self.scanner is None:
            log.warning(u'Не определено устройство сканирования')
            return False

        self.scan_manager.init()

        self.scan_manager.open(self.scanner)

        # Выставить все опции
        options = dict()
        if self.scan_source:
            options['source'] = self.scan_source
        if self.scan_mode:
            options['mode'] = self.scan_mode
        if self.depth:
            options['depth'] = self.depth
        if self.page_size:
            options['page_width'] = self.page_size[0]
            options['page_height'] = self.page_size[1]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['page_width'] = 210.0
            options['page_height'] = 297.0
        if self.scan_area:
            options['tl_x'] = self.scan_area[0]
            options['tl_y'] = self.scan_area[1]
        if self.scan_area and self.page_size:
            options['br_x'] = self.page_size[0] - self.scan_area[2]
            options['br_y'] = self.page_size[1] - self.scan_area[3]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['br_x'] = 210.0
            options['br_y'] = 297.0

        self.scan_manager.setScanOptions(**options)

        # Определение имени файла сканирования
        scan_filename = os.path.join(
            ic_file.getHomeDir(), config.PROFILE_DIRNAME, self.scan_filename +
            '.' + self.scan_filetype
        ) if self.scan_filename else config.DEFAULT_SCAN_FILENAME
        if os.path.exists(scan_filename):
            # Удалить старый файл сканирования
            try:
                os.remove(scan_filename)
                log.info(u'Удален файл <%s>' % scan_filename)
            except OSError:
                log.fatal(u'Ошибка удаления файла <%s>' % scan_filename)
        log.debug(u'Сканирование в файл <%s>' % scan_filename)

        try:
            if not self.is_multi_scan:
                result = self.scan_manager.singleScan(scan_filename)
            else:
                result = self.scan_manager.multiScan(scan_filename)

            if not result:
                # Какая-то ошибка сканирования
                dlg.getErrBox(
                    u'ОШИБКА',
                    u'Ошибка сканирования. Проверте листы в лотке сканера')
                return False

            if self.scan_dir:
                self.copyToScanDir(scan_filename, self.scan_dir)

            if self.is_preview:
                self.previewScanFile(scan_filename)
            return True
        except:
            log.fatal(u'Ошибка сканирования')
        return False
Ejemplo n.º 19
0
def loadResourceFile(filename, dictRpl={}, bRefresh=False, *arg, **kwarg):
    """
    Загрузить ресурс из файла. Функция читает файл и выполняет его.
    @type filename: C{string}
    @param filename: Имя ресурсного файла.
    @type dictRpl: C{dictionary}
    @param dictRpl: Словарь замен.
    @type bRefresh: C{bool}
    @param bRefresh: Признак того, что файл надо перечитать даже если он
        буферезирован.
    """
    obj = None
    filename = filename.strip()
    try:
        # Проверяем есть ли в буфферном файле такой объект, если есть, то его и возвращаем
        if not bRefresh and filename in Buff_readAndEvalFile:
            log.debug(' ' * 3 + '[b] ' +
                      'Return from buffer file: <%s>' % filename)
            return Buff_readAndEvalFile[filename]

        nm = os.path.basename(filename)
        pt = nm.find('.')
        if pt >= 0:
            filepcl = os.path.dirname(
                filename) + '/' + nm[:pt] + '_pkl' + nm[pt:]
        else:
            filepcl = os.path.dirname(filename) + '/' + nm + '_pkl'

        # Проверяем нужно ли компилировать данную структуру по следующим признакам:
        # наличие скомпилированного файла, по времени последней модификации.
        try:
            if (os.path.isfile(filepcl) and not os.path.isfile(filename)) or \
                    (os.path.getmtime(filename) < os.path.getmtime(filepcl)):
                # Пытаеся прочитать сохраненную структуру если время последней
                # модификации текстового представления меньше, времени
                # последней модификации транслированного варианта.
                fpcl = None
                try:
                    fpcl = open(filepcl)
                    obj = cPickle.load(fpcl)
                    fpcl.close()
                    # Сохраняем объект в буфере
                    Buff_readAndEvalFile[filename] = obj
                    log.debug('   [+] Load from: %s' % filepcl)
                    return obj
                except IOError:
                    log.error('   [-] readAndEvalFile: Open file <%s> error.' %
                              filepcl)
                except:
                    if fpcl:
                        fpcl.close()
        except:
            pass
        # Пытаемся прочитать cPickle, если не удается считаем, что в файле
        # хранится текст. Читаем его, выполняем, полученный объект сохраняем
        # на диске для последующего использования
        if os.path.isfile(filename):
            try:
                fpcl = open(filename)
                obj = cPickle.load(fpcl)
                fpcl.close()
                # Сохраняем объект в буфере
                Buff_readAndEvalFile[filename] = obj
                log.debug('   [+] Load file <%s> cPickle Format.' % filename)
                return obj
            except Exception, msg:
                log.error(
                    '   [*] Non cPickle Format file <%s>. Try to compile text'
                    % filename)

        # Открываем текстовое представление, если его нет, то создаем его
        f = open(filename, 'rb')
        txt = f.read().replace('\r\n', '\n')
        f.close()
        for key in dictRpl:
            txt = txt.replace(key, dictRpl[key])

        # Выполняем
        obj = eval(txt)
        # Сохраняем объект в буфере
        Buff_readAndEvalFile[filename] = obj

        # Сохраняем транслированный вариант
        fpcl = open(filepcl, 'w')
        log.debug('Create cPickle <%s>' % filepcl)
        cPickle.dump(obj, fpcl, PICKLE_PROTOCOL)
        fpcl.close()
Ejemplo n.º 20
0
 def _defBand(self, BandTag_, Row_, ColCount_, TitleRow_, Rep_):
     """
     Заполнить описание бенда.
     @param BandTag_: Тег бэнда.
     @param Row_: Номер строки.
     @param TitleRow_: Количество строк заголовочных бендов.
     @param ColCount_: Количество колонок.
     @param Rep_: Описание данных отчета.
     @return: Описание данных отчета.
     """
     try:
         # Сделать копию данных отчета для возможного отката.
         rep = copy.deepcopy(Rep_)
         
         log.debug(u'Определение бэнда. Тег: <%s>' % BandTag_)
         if BandTag_.strip() == HEADER_TAG:
             # Заполнить бэнд
             rep['header'] = self._band(rep['header'], Row_-TitleRow_, ColCount_)
         elif BandTag_.strip() == DETAIL_TAG:
             # Заполнить бэнд
             rep['detail'] = self._band(rep['detail'], Row_-TitleRow_, ColCount_)
             self._normDetail(rep['detail'], rep)
         elif BandTag_.strip() == FOOTER_TAG:
             # Заполнить бэнд
             rep['footer'] = self._band(rep['footer'], Row_-TitleRow_, ColCount_)
         elif HEADER_GROUP_TAG in BandTag_:
             # Определить имя поля группировки
             field_name = re.split(icrepgen.REP_FIELD_PATT, BandTag_)[1].strip()[2:-2]
             # Если такой группы не зарегестрировано, то прописать ее
             if reduce(lambda x, grp: grp['field'] == field_name or x, rep['groups'], 0) == 0:
                 # Записать в соответствии с положением относительно др. групп
                 rep['groups'].append(copy.deepcopy(icrepgen.IC_REP_GRP))
                 rep['groups'][-1]['field'] = field_name
             # Записать заголовок группы
             grp_field = [grp for grp in rep['groups'] if grp['field'] == field_name][0]
             # Заполнить бэнд
             grp_field['header'] = self._band(grp_field['header'], Row_-TitleRow_, ColCount_)
         elif FOOTER_GROUP_TAG in BandTag_:
             # Определить имя поля группировки
             field_name = re.split(icrepgen.REP_FIELD_PATT, BandTag_)[1].strip()[2:-2]
             # Если такой группы не зарегестрировано, то прописать ее
             if reduce(lambda x, grp: grp['field'] == field_name or x, rep['groups'], 0) == 0:
                 # Записать в соответствии с положением относительно др. групп
                 rep['groups'].append(copy.deepcopy(icrepgen.IC_REP_GRP))
                 rep['groups'][-1]['field'] = field_name
             # Записать примечание группы
             grp_field = [grp for grp in rep['groups'] if grp['field'] == field_name][0]
             # Заполнить бэнд
             grp_field['footer'] = self._band(grp_field['footer'], Row_-TitleRow_, ColCount_)
         elif BandTag_.strip() == UPPER_TAG:
             # Верхний колонтитул
             rep['upper'] = self._band(rep['upper'], Row_-TitleRow_, ColCount_)
         elif BandTag_.strip() == UNDER_TAG:
             # Нижний колонтитул
             rep['under'] = self._band(rep['under'], Row_-TitleRow_, ColCount_)
         else:
             # Вывести сообщение об ошибке в лог
             log.warning(u'Не определенный тип бэнда <%s>.' % BandTag_)
         # Заполнить колонтитулы
         rep['upper'] = self._bandUpper(rep['upper'], self._rep_worksheet)
         rep['under'] = self._bandUnder(rep['under'], self._rep_worksheet)
         
         return rep
     except:
         log.fatal(u'Ошибка определения бэнда <%s>.' % BandTag_)
         return Rep_
Ejemplo n.º 21
0
    def parse(self, TemplateData_, template_name=None):
        """
        Разобрать/преобразовать прочитанную структуру.
        @param TemplateData_: Словарь описания шаблона.
        @param template_name: Имя шаблона(листа), если None то первый лист.
        """
        try:
            # Создать первоначальный шаблон
            rep = copy.deepcopy(icrepgen.IC_REP_TMPL)

            # 0. Определение основных структур
            workbook = TemplateData_['children'][0]
            # Стили (в виде словаря)
            styles = dict([(style['ID'], style) for style in [element for element in workbook['children']
                                                              if element['name'] == 'Styles'][0]['children']])
            worksheets = [element for element in workbook['children'] if element['name'] == 'Worksheet']

            # I. Определить все бэнды в шаблоне
            # Если имя шаблона не определено, тогда взять первый лист
            if template_name is None:
                template_name = worksheets[0]['Name']
                self._rep_worksheet = worksheets[0]
            else:
                # Установить активной страницу выбранного шаблона отчета
                self._rep_worksheet = [sheet for sheet in worksheets if sheet['Name'] == template_name][0]
            # Прописать имя отчета
            rep['name'] = template_name
            
            # Взять таблицу
            rep_template_tabs = [rep_obj for rep_obj in self._rep_worksheet['children'] if rep_obj['name'] == 'Table']
            self._setDefaultCellSize(rep_template_tabs[0])
            # Привести таблицу к нормальному виду
            rep_template_tab = self._normTable(rep_template_tabs[0])

            # Взять описания колонок
            rep_template_cols = [element for element in rep_template_tab['children'] if element['name'] == 'Column']
            rep_template_cols = self._defineSpan(rep_template_cols)
            # Взять описания строк
            rep_template_rows = [element for element in rep_template_tab['children'] if element['name'] == 'Row']
            rep_template_rows = self._defineSpan(rep_template_rows)

            # Количество колонок без колонки тегов бендов
            col_count = self._getColumnCount(rep_template_rows)
            log.debug(u'Количество колонок: %d' % col_count)

            # II. Определить все ячейки листа
            used_rows = range(len(rep_template_rows))
            used_cols = range(col_count)

            self.__cur_band = None  # Тег текущего бенда
            # Перебор по строкам
            for cur_row in used_rows:
                if not self._isTitleBand(rep_template_rows, cur_row):
                    # Не колонтитулы, добавить ячейки в общий лист
                    rep['sheet'].append([])
                    for cur_col in used_cols:
                        cell_attr = self._getCellAttr(rep_template_rows, rep_template_cols, styles, cur_row, cur_col)
                        if not self._isTag(cell_attr['value']):
                            rep['sheet'][-1].append(cell_attr)
                        else:
                            rep['sheet'][-1].append(None)

            # III. Определить бэнды в шаблоне
            # Перебрать все ячейки первой колонки
            self.__cur_band = None  # Тег текущего бенда
            title_row = 0   # Счетчик строк колонтитулов/заголовочных бендов
    
            # Перебор всех строк в шаблоне
            for cur_row in range(len(rep_template_rows)):
                tag = self._getTagBandRow(rep_template_rows, cur_row)
                # Если это ячейка с определенным тегом, значит новый бенд
                if tag:
                    # Определить текущий бэнд
                    self.__cur_band = tag
                    if tag in TITLE_TAGS:
                        # Обработка строк заголовочных тегов
                        parse_func = self._TitleTagParse.setdefault(tag, None)
                        try:
                            parse_func(self, rep, rep_template_rows[cur_row]['children'])
                        except:
                            log.fatal(u'Ошибка парсинга функции <%s>' % textfunc.toUnicode(parse_func))
                        title_row += 1
                    else:
                        # Определить бэнд внутри объекта
                        rep = self._defBand(self.__cur_band, cur_row, col_count, title_row, rep)
                else:
                    log.error(u'Не корректный тег строки [%d]' % cur_row)

            # Прочитать в шаблон параметры страницы
            rep['page_setup'] = copy.deepcopy(icrepgen.IC_REP_PAGESETUP)
            sheet_options = [rep_obj for rep_obj in self._rep_worksheet['children']
                             if rep_obj['name'] == 'WorksheetOptions']

            page_setup = [rep_obj for rep_obj in sheet_options[0]['children'] if rep_obj['name'] == 'PageSetup'][0]
            rep['page_setup'].update(self._getPageSetup(page_setup))
            print_setup = [rep_obj for rep_obj in sheet_options[0]['children'] if rep_obj['name'] == 'Print']
            if print_setup:
                rep['page_setup'].update(self._getPrintSetup(print_setup[0]))

            # Проверить заполнение генератора отчета
            if not rep['generator']:
                tmpl_filename = self.getTemplateFilename()
                rep['generator'] = os.path.splitext(tmpl_filename)[1].upper() if tmpl_filename else '.ODS'

            return rep
        except:
            log.fatal(u'Ошибка парсинга шаблона отчета <%s>' % textfunc.toUnicode(template_name))
        return None
Ejemplo n.º 22
0
def scan_glue_mode(scan_manager,
                   scan_filename,
                   n_sheets,
                   is_duplex=False,
                   max_tray_sheets=60):
    """
    Запуск режима склеивания документа по частям.
    @param scan_manager: Менеджер сканирования.
    @param scan_filename: Имя результирующего файла скана.
    @param n_sheets: Количество листов.
    @param is_duplex: Двустороннее сканирование?
    @param max_tray_sheets: Максимально допустимое количество листов в лотке сканера.
    @return: True/False.
    """
    # Основной цикл сканирования документа по частям и последующая склейка
    n_part = 1
    scan_file_path, scan_file_ext = os.path.splitext(scan_filename)
    part_suffix = '_part%03d' % n_part
    new_scan_filename = scan_file_path + part_suffix + scan_file_ext
    sheets = scan_glue_load_sheets(None, min(max_tray_sheets, n_sheets))
    scan_sheet_count = sheets
    is_cancel = scan_sheet_count <= 0

    while (0 < scan_sheet_count <= n_sheets) or is_cancel:
        log.debug(u'Сканирование файла <%s> Сканировать листов [%d]' %
                  (new_scan_filename, sheets))
        # Если используется дуплекс, то надо увеличить количество страниц
        scan_n_pages = sheets * 2 if is_duplex else sheets
        # Запуск процесса сканирования
        scan_result = scan_manager.scanMulti(new_scan_filename, scan_n_pages)
        if scan_result and os.path.exists(new_scan_filename):
            verify_result = scan_glue_verify(None, new_scan_filename)
            if verify_result:
                n_part += 1
                part_suffix = '_part%03d' % n_part
                new_scan_filename = scan_file_path + part_suffix + scan_file_ext
                do_scan_sheet_count = min(max_tray_sheets,
                                          n_sheets - scan_sheet_count)
                if do_scan_sheet_count <= 0:
                    # Все листы отсканированны
                    break
                sheets = scan_glue_load_sheets(None, do_scan_sheet_count)
                if sheets <= 0:
                    # Нажата <Отмена>
                    is_cancel = True
                    break
                scan_sheet_count += sheets
            elif verify_result is None:
                scan_sheet_count -= sheets
                sheets = scan_glue_load_sheets(None,
                                               min(max_tray_sheets, n_sheets))
                if sheets <= 0:
                    # Нажата <Отмена>
                    is_cancel = True
                    break
                scan_sheet_count += sheets
            else:
                is_cancel = True
                log.warning(u'Сканирование по частям файла <%s> отменено' %
                            new_scan_filename)
                break
        else:
            is_cancel = True
            log.warning(u'Ошибка сканирования файла <%s>' % new_scan_filename)

    # Склеить отсканированные части документа
    if not is_cancel:
        part_pdf_filenames = [
            scan_file_path + ('_part%03d' % i_part) + scan_file_ext
            for i_part in range(1, n_part)
        ]
        log.debug(u'Объединение %d частей скана %s в PDF файл %s' %
                  (n_part - 1, part_pdf_filenames, scan_filename))
        glue_result = pdffunc.glue_pdf_files(scan_filename,
                                             *part_pdf_filenames)

        dlgfunc.getMsgBox(
            u'СКАНИРОВАНИЕ',
            u'Загрузите в лоток сканера документы для последующего сканирования'
        )
        return glue_result
    else:
        log.warning(
            u'Режим объединения сканированного документа по частям отменен')

    return False
Ejemplo n.º 23
0
    def generate(self,
                 RepTemplate_,
                 QueryTable_,
                 NameSpace_=None,
                 CoordFill_=None):
        """
        Генерация отчета.
        @param RepTemplate_: Структура шаблона отчета (см. спецификации).
        @param QueryTable_: Таблица запроса. 
            Словарь следующей структуры:
                {
                    '__name__':имя таблицы запроса,
                    '__fields__':[имена полей],
                    '__data__':[список списков значений],
                    '__sub__':{словарь данных подотчетов},
                }.
        @param NameSpace_: Пространство имен шаблона.
            Обычный словарь:
                {
                    'имя переменной': значение переменной, 
                }.
            ВНИМАНИЕ! Этот словарь может передаваться в таблице запроса
                ключ __variables__.
        @param CoordFill_: Координатное заполнение значений ячеек.
            Формат:
                {
                    (Row,Col): 'Значение',
                }.
            ВНИМАНИЕ! Этот словарь может передаваться в таблице запроса
                ключ __coord_fill__.
        @return: Заполненную структуру отчета.
        """
        try:
            # Покоординатная замена значений ячеек
            self._CoordFill = CoordFill_
            if QueryTable_ and '__coord_fill__' in QueryTable_:
                if self._CoordFill is None:
                    self._CoordFill = dict()
                self._CoordFill.update(QueryTable_['__coord_fill__'])

            # Инициализация списка групп
            self._RepGrp = list()

            # I. Определить все бэнды в шаблоне и ячейки сумм
            if isinstance(RepTemplate_, dict):
                self._Template = RepTemplate_
            else:
                # Вывести сообщение об ошибке в лог
                log.warning(u'Ошибка типа шаблона отчета <%s>.' %
                            type(RepTemplate_))
                return None

            # Инициализация имени отчета
            if 'name' in QueryTable_ and QueryTable_['name']:
                # Если таблица запроса именована, то значит это имя готового отчета
                self._RepName = str(QueryTable_['name'])
            elif 'name' in self._Template:
                self._RepName = self._Template['name']

            # Заполнить пространство имен
            self._NameSpace = NameSpace_
            if self._NameSpace is None:
                self._NameSpace = dict()
            self._NameSpace.update(self._Template['variables'])
            if QueryTable_ and '__variables__' in QueryTable_:
                self._NameSpace.update(QueryTable_['__variables__'])
            log.debug(u'Переменные отчета: %s' % self._NameSpace.keys())

            # Библиотека стилей
            self._StyleLib = None
            if 'style_lib' in self._Template:
                self._StyleLib = self._Template['style_lib']

            self._TemplateSheet = self._Template['sheet']
            self._TemplateSheet = self._initSumCells(self._TemplateSheet)

            # II. Инициализация таблицы запроса
            self._QueryTbl = QueryTable_
            # Определить количество записей в таблице запроса
            self._QueryTblRecCount = 0
            if self._QueryTbl and '__data__' in self._QueryTbl:
                self._QueryTblRecCount = len(self._QueryTbl['__data__'])

            # Проинициализировать бенды групп
            for grp in self._Template['groups']:
                grp['old_rec'] = None

            time_start = time.time()
            log.info(u'Отчет <%s>. Запуск генерации' %
                     textfunc.toUnicode(self._RepName))

            # III. Вывод данных в отчет
            # Создать отчет
            self._Rep = copy.deepcopy(IC_REP_TMPL)
            self._Rep['name'] = self._RepName

            # Инициализация необходимых переменных
            field_idx = {}  # Индексы полей
            i = 0
            i_rec = 0
            # Перебор полей таблицы запроса
            if self._QueryTbl and '__fields__' in self._QueryTbl:
                for cur_field in self._QueryTbl['__fields__']:
                    field_idx[cur_field] = i
                    i += 1

            # Если записи в таблице запроса есть, то ...
            if self._QueryTblRecCount:
                # Проинициализировать текущую строку для использования
                # ее в заголовке отчета
                rec = self._QueryTbl['__data__'][i_rec]
                # Заполнить словарь текущей записи
                for field_name in field_idx.keys():
                    val = rec[field_idx[field_name]]
                    # Предгенерация значения данных ячейки
                    self._CurRec[field_name] = val
                # Прописать индекс текущей записи
                self._CurRec['ic_sys_num_rec'] = i_rec

            # Верхний колонтитул
            if self._Template['upper']:
                self._genUpper(self._Template['upper'])

            # Вывести в отчет заголовок
            self._genHeader(self._Template['header'])

            # Главный цикл
            # Перебор записей таблицы запроса
            while i_rec < self._QueryTblRecCount:
                # Обработка групп
                # Проверка смены группы в описании всех групп
                # и найти индекс самой общей смененной группы
                i_grp_out = -1  # индекс самой общей смененной группы
                # Флаг начала генерации (примечания групп не выводяться)
                start_gen = False
                for i_grp in range(len(self._Template['groups'])):
                    grp = self._Template['groups'][i_grp]
                    if grp['old_rec']:
                        # Проверить условие вывода примечания группы
                        if self._CurRec[grp['field']] != grp['old_rec'][
                                grp['field']]:
                            i_grp_out = i_grp
                            break
                    else:
                        i_grp_out = 0
                        start_gen = True
                        break
                if i_grp_out != -1:
                    # Вывести примечания
                    if start_gen is False:
                        for i_grp in range(
                                len(self._Template['groups']) - 1,
                                i_grp_out - 1, -1):
                            grp = self._Template['groups'][i_grp]
                            self._genGrpFooter(grp)
                    # Вывести заголовки
                    for i_grp in range(i_grp_out,
                                       len(self._Template['groups'])):
                        grp = self._Template['groups'][i_grp]
                        grp['old_rec'] = copy.deepcopy(self._CurRec)
                        self._genGrpHeader(grp)

                # Область данных
                self._genDetail(self._Template['detail'])

                # Увеличить суммы суммирующих ячеек
                self._sumIterate(self._TemplateSheet, self._CurRec)

                # Перейти на следующую запись
                i_rec += 1
                # Заполнить словарь текущей записи
                if i_rec < self._QueryTblRecCount:
                    rec = self._QueryTbl['__data__'][i_rec]
                    # Заполнить словарь текущей записи
                    for field_name in field_idx.keys():
                        val = rec[field_idx[field_name]]
                        # Предгенерация значения данных ячейки
                        self._CurRec[field_name] = val
                    # Прописать индекс текущей записи
                    self._CurRec['ic_sys_num_rec'] = i_rec

            # Вывести примечания после области данных
            for i_grp in range(len(self._Template['groups']) - 1, -1, -1):
                grp = self._Template['groups'][i_grp]
                if grp['old_rec']:
                    self._genGrpFooter(grp)
                else:
                    break
            # Вывести в отчет примечание отчета
            self._genFooter(self._Template['footer'])
            # Нижний колонтитул
            if self._Template['under']:
                self._genUnder(self._Template['under'])

            # Параметры страницы
            self._Rep['page_setup'] = self._Template['page_setup']

            # Прогресс бар
            log.info(
                u'Отчет <%s>. Окончание генерации. Время: %d сек.' %
                (textfunc.toUnicode(self._RepName), time.time() - time_start))

            return self._Rep
        except:
            # Вывести сообщение об ошибке в лог
            log.fatal(u'Ошибка генерации отчета.')
            return None
Ejemplo n.º 24
0
    def showOptions(self):
        """
        Выставить параметры сканирования в контролах окна.
        """
        if self.scanner:
            self.scanner_comboBox.SetStringSelection(self.scanner)

        if self.scan_source:
            i = 0
            try:
                log.debug(u'Установка источника сканирования <%s>' %
                          self.scan_source)
                i = scan_manager.SCAN_SOURCES.index(self.scan_source)
            except ValueError:
                log.warning(u'Не найден источник сканирования <%s>' %
                            self.scan_source)
            self.source_comboBox.Select(i)

        if self.scan_mode:
            i = 0
            try:
                i = scan_manager.SCAN_MODES.index(self.scan_mode)
            except ValueError:
                log.warning(u'Не найден режим сканирования <%s>' %
                            self.scan_mode)
            self.mode_comboBox.Select(i)

        self.multiscan_checkBox.SetValue(bool(self.is_multi_scan))
        self.preview_checkBox.SetValue(bool(self.is_preview))

        if self.page_size:
            i = 0
            try:
                i = scan_manager.SCAN_PAGE_SIZES.index(self.page_size)
            except ValueError:
                log.warning(u'Не найден размер страницы сканирования <%s>' %
                            self.page_size)
            self.pagesize_comboBox.Select(i)

        if self.scan_area:
            self.left_spinCtrl.SetValue(self.scan_area[0])
            self.top_spinCtrl.SetValue(self.scan_area[1])
            self.right_spinCtrl.SetValue(self.scan_area[2])
            self.bottom_spinCtrl.SetValue(self.scan_area[3])

        if self.scan_dir:
            self.scan_dirPicker.SetPath(self.scan_dir)

        if self.scan_filename:
            self.filename_textCtrl.SetValue(self.scan_filename)

        if self.scan_filetype:
            i = 0
            try:
                i = scan_manager.SCAN_FILE_TYPES.index(self.scan_filetype)
            except ValueError:
                log.warning(u'Не найден тип файла сканирования <%s>' %
                            self.scan_filetype)
            self.fileext_comboBox.Select(i)

        if self.depth:
            self.depth_spinCtrl.SetValue(self.depth)

        if self.ext_scan_cmd:
            self.extern_cmd_textCtrl.SetValue(self.ext_scan_cmd)
Ejemplo n.º 25
0
    def _genTxt(self, cell, record=None, CellRow_=None, CellCol_=None):
        """
        Генерация текста.
        @param cell: Ячейка.
        @param record: Словарь, описывающий текущую запись таблицы запроса.
            Формат: { <имя поля> : <значение поля>, ...}
        @param CellRow_: Номер строки ячейки в результирующем отчете.
        @param CellCol_: Номер колонки ячейки в результирующем отчете.
        @return: Возвращает сгенерированное значение.
        """
        try:
            # Проверка на преобразование типов
            cell_val = cell['value']
            if cell_val is not None and type(cell_val) not in (str, unicode):
                cell_val = str(cell_val)
            if cell_val not in self._cellFmt:
                parsed_fmt = self.funcStrParse(cell_val)
                self._cellFmt[cell_val] = parsed_fmt
            else:
                parsed_fmt = self._cellFmt[cell_val]

            func_str = []  # Выходной список значений
            i_sum = 0
            # Перебрать строки функционала
            for cur_func in parsed_fmt['func']:

                # Функция
                if re.search(REP_FUNC_PATT, cur_func):
                    value = str(self._execFuncGen(cur_func[2:-2], locals()))

                # Ламбда-выражение
                elif re.search(REP_LAMBDA_PATT, cur_func):
                    # ВНИМАНИЕ: Лямбда-выражение в шаблоне должно иметь
                    #     1 аргумент это словарь записи.
                    #     Например:
                    #         [~rec: rec['name']=='Петров'~]
                    lambda_func = eval('lambda ' + cur_func[2:-2])
                    value = str(lambda_func(record))

                # Переменная
                elif re.search(REP_VAR_PATT, cur_func):
                    var_name = cur_func[2:-2]
                    if var_name in self._NameSpace:
                        log.debug(u'Обработка переменной <%s>' % var_name)
                    else:
                        log.warning(
                            u'Переменная <%s> не найдена в пространстве имен' %
                            var_name)
                    value = str(self._NameSpace.setdefault(var_name, u''))

                # Блок кода
                elif re.search(REP_EXEC_PATT, cur_func):
                    # ВНИМАНИЕ: В блоке кода доступны объекты cell и record.
                    #     Если надо вывести информацию, то ее надо выводить в
                    #     переменную value.
                    #     Например:
                    #         [=if record['name']=='Петров':
                    #             value='-'=]
                    value = ''
                    exec_func = cur_func[2:-2].strip()
                    try:
                        exec exec_func
                    except:
                        log.fatal(u'Ошибка выполнения блока кода <%s>' %
                                  textfunc.toUnicode(exec_func))

                # Системная функция
                elif re.search(REP_SYS_PATT, cur_func):
                    # Функция суммирования
                    if cur_func[2:6].lower() == 'sum(':
                        value = str(cell['sum'][i_sum]['value'])
                        i_sum += 1  # Перейти к следующей сумме
                    # Функция вычисления среднего значения
                    elif cur_func[2:6].lower() == 'avg(':
                        if 'ic_sys_num_rec' not in record:
                            record['ic_sys_num_rec'] = 0
                        value = str(cell['sum'][i_sum]['value'] /
                                    (record['ic_sys_num_rec'] + 1))
                        i_sum += 1  # Перейти к следующей сумме
                    elif cur_func[2:-2].lower() == 'n':
                        if 'ic_sys_num_rec' not in record:
                            record['ic_sys_num_rec'] = 0
                        sys_num_rec = record['ic_sys_num_rec']
                        value = str(sys_num_rec + 1)
                    else:
                        # Вывести сообщение об ошибке в лог
                        log.warning(
                            u'Неизвестная системная функция <%s> шаблона <%s>.'
                            % (textfunc.toUnicode(cur_func), self._RepName))
                        value = ''

                # Стиль
                elif re.search(REP_STYLE_PATT, cur_func):
                    value = ''
                    style_name = cur_func[2:-2]
                    self._setStyleAttr(style_name)

                # Под-отчеты
                elif re.search(REP_SUBREPORT_PATT, cur_func):
                    value = ''
                    subreport_name = cur_func[2:-2]
                    self._genSubReport(subreport_name, CellRow_)

                # Поле
                elif re.search(REP_FIELD_PATT, cur_func):
                    field_name = str((cur_func[2:-2]))
                    try:
                        value = record[field_name]
                    except KeyError:
                        log.warning(u'В строке (%s) поле <%s> не найдено' %
                                    (textfunc.toUnicode(record),
                                     textfunc.toUnicode(field_name)))
                        value = ''

                # ВНИМАНИЕ! В значении ячейки тоже могут быть управляющие коды
                value = self._genTxt({'value': value}, record)
                func_str.append(value)

            # Заполнение формата
            return self._valueFormat(parsed_fmt['fmt'], func_str)
        except:
            # Вывести сообщение об ошибке в лог
            log.fatal(u'Ошибка генерации текста ячейки <%s> шаблона <%s>.' %
                      (textfunc.toUnicode(cell['value']), self._RepName))
            return None
Ejemplo n.º 26
0
def main(argv):
    """
    Основная запускающая функция.
    @param argv: Список параметров коммандной строки.
    """
    # Инициализоция системы журналирования
    log.init(config)

    # Разбираем аргументы командной строки
    try:
        options, args = getopt.getopt(argv, 'h?vdVEDpPES', [
            'help', 'version', 'debug', 'log', 'viewer', 'editor', 'postprint',
            'postpreview', 'postexport', 'print=', 'preview=', 'export=',
            'select=', 'gen=', 'db=', 'sql=', 'stylelib=', 'var=', 'path=',
            'no_gui'
        ])
    except getopt.error as err:
        log.error(err.msg, bForcePrint=True)
        log.warning('For help use --help option', bForcePrint=True)
        sys.exit(2)

    # Параметры запуска генерации отчета из коммандной строки
    report_filename = None
    db = None
    sql = None
    do_cmd = None
    stylelib = None
    vars = dict()
    path = None
    mode = 'default'
    mode_arg = None

    for option, arg in options:
        if option in ('-h', '--help', '-?'):
            print(__doc__)
            sys.exit(0)
        elif option in ('-v', '--version'):
            print('icReport version: %s' %
                  '.'.join([str(ver) for ver in __version__]))
            sys.exit(0)
        elif option in ('-d', '--debug'):
            config.set_glob_var('DEBUG_MODE', True)
        elif option in ('-l', '--log'):
            config.set_glob_var('LOG_MODE', True)
        elif option in ('-V', '--viewer'):
            mode = 'view'
        elif option in ('-E', '--editor'):
            mode = 'edit'
        elif option in ('-p', '--print'):
            mode = 'print'
            mode_arg = arg
        elif option in ('-P', '--preview'):
            mode = 'preview'
            mode_arg = arg
        elif option in ('-E', '--export'):
            mode = 'export'
            mode_arg = arg
        elif option in ('-S', '--select'):
            mode = 'select'
            mode_arg = arg
        elif option in ('--gen', ):
            report_filename = arg
        elif option in ('--db', ):
            db = arg
        elif option in ('--sql', ):
            sql = arg
        elif option in ('--postprint', ):
            do_cmd = do_report.DO_COMMAND_PRINT
        elif option in ('--postpreview', ):
            do_cmd = do_report.DO_COMMAND_PREVIEW
        elif option in ('--postexport', ):
            do_cmd = do_report.DO_COMMAND_EXPORT
        elif option in ('--stylelib', ):
            stylelib = arg
        elif option in ('--var', ):
            var_name = arg.split('=')[0].strip()
            var_value = arg.split('=')[-1].strip()
            vars[var_name] = var_value
            log.debug(u'Дополнительная переменная <%s>. Значение [%s]' %
                      (unicode(var_name, config.DEFAULT_ENCODING),
                       unicode(var_value, config.DEFAULT_ENCODING)))
        elif option in ('--path', ):
            path = arg
        elif option in ('--no_gui', ):
            config.set_glob_var('NO_GUI_MODE', True)

    # ВНИМАНИЕ! Небходимо добавить путь к папке отчетов,
    # чтобы проходили импорты модулей отчетов
    if path is None:
        path = DEFAULT_REPORTS_PATH
    if os.path.exists(path) and os.path.isdir(path) and path not in sys.path:
        sys.path.append(path)

    # Внимание! Приложение создается для
    # управления диалоговыми окнами отчетов
    app = wx.PySimpleApp()
    # ВНИМАНИЕ! Выставить русскую локаль
    # Это необходимо для корректного отображения календарей,
    # форматов дат, времени, данных и т.п.
    locale = wx.Locale()
    locale.Init(wx.LANGUAGE_RUSSIAN)

    if mode == 'default':
        if report_filename:
            # Запустить генерацию отчета из комадной строки
            do_report.doReport(report_filename=report_filename,
                               report_dir=path,
                               db_url=db,
                               sql=sql,
                               command=do_cmd,
                               stylelib_filename=stylelib,
                               variables=vars)
    elif mode == 'view':
        do_report.ReportViewer(report_dir=path)
    elif mode == 'edit':
        do_report.ReportEditor(report_dir=path)
    elif mode == 'print':
        do_report.ReportPrint(report_filename=mode_arg,
                              report_dir=path,
                              db_url=db,
                              sql=sql,
                              command=do_cmd,
                              stylelib_filename=stylelib,
                              variables=vars)
    elif mode == 'preview':
        do_report.ReportPreview(report_filename=mode_arg,
                                report_dir=path,
                                db_url=db,
                                sql=sql,
                                command=do_cmd,
                                stylelib_filename=stylelib,
                                variables=vars)
    elif mode == 'export':
        do_report.ReportExport(report_filename=mode_arg,
                               report_dir=path,
                               db_url=db,
                               sql=sql,
                               command=do_cmd,
                               stylelib_filename=stylelib,
                               variables=vars)
    elif mode == 'select':
        do_report.ReportSelect(report_filename=mode_arg,
                               report_dir=path,
                               db_url=db,
                               sql=sql,
                               command=do_cmd,
                               stylelib_filename=stylelib,
                               variables=vars)

    app.MainLoop()
Ejemplo n.º 27
0
    def runScanPack(self, *scan_filenames):
        """
        Запусть процесс сканирования в режиме пакетной обработки,
        согласно выставленным параметрам.
        @param scan_filenames: Имена файлов скана с указанием количества листов
            и признака 2-стороннего сканирования.
            Например:
                (scan001, 3, True), (scan002, 1, False), (scn003, 2, True), ...
        @return: True/False
        """
        if self.scan_manager is None:
            log.warning(u'Не определен менеджер сканирования')
            return False
        if self.scanner is None:
            log.warning(u'Не определено устройство сканирования')
            return False

        self.scan_manager.init()
        self.scan_manager.open(self.scanner)

        # Выставить все опции
        options = dict()
        if self.scan_source:
            options['source'] = self.scan_source
        if self.scan_mode:
            options['mode'] = self.scan_mode
        if self.depth:
            options['depth'] = self.depth
        if self.page_size:
            options['page_width'] = self.page_size[0]
            options['page_height'] = self.page_size[1]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['page_width'] = 210.0
            options['page_height'] = 297.0
        if self.scan_area:
            options['tl_x'] = self.scan_area[0]
            options['tl_y'] = self.scan_area[1]
        if self.scan_area and self.page_size:
            options['br_x'] = self.page_size[0] - self.scan_area[2]
            options['br_y'] = self.page_size[1] - self.scan_area[3]
        else:
            # ВНИМАНИЕ! Если не определить размер страницы
            # край скана будет обрезаться
            # По умолчанию A4 портретной ориентации
            options['br_x'] = 210.0
            options['br_y'] = 297.0

        self.scan_manager.setScanOptions(**options)

        scans = [(os.path.join(ic_file.getHomeDir(), config.PROFILE_DIRNAME,
                               scan_filename + '.' + self.scan_filetype)
                  if scan_filename else config.DEFAULT_SCAN_FILENAME,
                  int(n_pages), bool(is_duplex))
                 for scan_filename, n_pages, is_duplex in scan_filenames]
        for scan_filename, n_pages, is_duplex in scans:
            full_scan_filename = os.path.join(
                os.environ.get('HOME', '/home/user'), config.PROFILE_DIRNAME,
                scan_filename)
            if os.path.exists(full_scan_filename):
                # Удалить старый файл сканирования
                try:
                    os.remove(full_scan_filename)
                    log.info(u'Удален ранее отсканированный файл <%s>' %
                             full_scan_filename)
                except OSError:
                    log.fatal(u'Ошибка удаления файла <%s>' %
                              full_scan_filename)

        try:
            scan_filenames = self.scan_manager.scan_pack(scan_filenames=scans)

            # Перенос отсканированных файлов в результирующую папку
            if self.scan_dir and os.path.exists(self.scan_dir):
                for scan_filename in scan_filenames:
                    if scan_filename and os.path.exists(scan_filename):
                        log.debug(
                            u'Перенос файла <%s> в результирующую папку <%s>' %
                            (scan_filename, self.scan_dir))
                        self.copyToScanDir(scan_filename, self.scan_dir)
                    else:
                        log.warning(
                            u'Не определен результирующий файл сканирования')
            else:
                log.warning(u'Не определена результирующая папка сканирования')

            return True
        except:
            log.fatal(u'Ошибка сканирования в режиме пакетной обработки')

        return False