Как написать внешнюю обработку в 1с 77
Пример построения программного кода для достижения функционала обратных вызовов (call back) во внешних обработках исключительно штатными средствами. Тестировалось на платформе 1с77 релиз 027. Конфигурация значения не имеет.
Принято считать, что асинхронные вызовы в программном коде – это что-то новое, модное, молодежное. Ряд публикаций на этом ресурсе освещает новый подход к программированию: как правильно открывать форму и получать от нее ответ, как правильно взаимодействовать с пользователем, будь то вопрос или форма выбора файла. Специально для этого в платформу 8х были добавлены новые методы и объекты. А что же с 1с77? Есть ли там эта асинхронность? А если и есть, то в каких задачах она используется?
На самом деле асинхронные вызовы были и в платформе 1с77. Тривиальные задачи: обработка подбора, обработка выбора значения, обработка внешнего события, обработка ожидания. Это все асинхронные вызовы. Основным отличием этих методов является то, что после совершения асинхронного вызова функции выполнение программного кода не останавливается. А результат работы этой функции нужно отлавливать в другой процедуре (как правило предопределенной), которая в свою очередь вызывается тем объектом, к которому мы обратились асинхронным вызовом.
Зачем это все надо? Давайте рассмотрим обработку подбора. Из формы документа мы запускаем форму подбора. Когда на форме подбора мы совершаем выбор элемента, то в форме документа выполняется процедура ОбработкаПодбора. То есть мы смогли вызвать процедуру другой формы, хотя у 1с версии 77 есть ограничение, что из других модулей можно вызывать только экспортные процедуры глобального модуля. При помощи обратного вызова ОбработкаПодбора мы смогли обойти это органичение. А что если мы хотим описать свои процедуры обратного вызова? Что если у нас есть основная форма обработки, в которой собран ключевой функционал бэкэнда нашей разработки. А для взаимодействия с пользователем мы хотим написать отдельные формы плагины, по одной на каждую задачу. Каким образом использовать функционал основной обработки находясь в контексте дополнительной формы? 1с77 не позволяет в обработку добавить дополнительные формы и модуля объекта у внешней обработки тоже нет. Мы хотим обойти и это ограничение. Разделить функциональность нашего проекта на отдельные обработки. По 1-й на каждую задачу. И здесь нам поможет принцип обратного вызова.
Итак, задача состоит в том, чтобы передать из дополнительной формы обработки в основную команду на выполнение процедуры. После выполнения этой процедуры основная форма должна оповестить дополнительную о результате выполнения, иными словами так же передать на выполнение команду в обратную сторону. Как это можно сделать?
- Установить 1С++, написать классы и не морочить уважаемым людям голову)
- Написать внешнюю компоненту, которая генерирует ВнешнееСобытие() и ловить результат Обработчиком внешнего события.
- Использовать обработку предопределенного события формы, путем воздействия на эту форму.
Как вы уже поняли из заголовка публикации, я буду описывать третий метод. Идея не нова. Такой же принцип используют, например, для групповой печати документов. Передают специальный параметр при открытии формы документа, а в процедуре ПриОткрытии() отлавливают этот параметр, выполняют печать, и ставят СтатусВозврата(0), чтобы форма документа не мигала на экране. Кроме того похожим способом можно провести один документ при проведении другого, хотя если написать в лоб, то 1с нам это запретит.
Использовать мы будем событие закрытия формы и предопределенную процедуру ПриЗакрытии(). Чтобы форма не закрывалась при этом, мы установим СтатусВозврата(0). Для обмена информацией между вызовами будем использовать переменную модуля формы основной обработки кэш. В этой переменной хранится общая для всего проекта структура-список значений, наподобие глРасшифровка, которая используется при работе с отчетами в типовых конфигурациях. Прелесть объекта «СписокЗначений» в том, что через переменную всегда передается ссылка на единожды созданный объект, где бы мы не обратились к ней, а также в том, что можно устанавливать и получать значения по текстовому ключу, как в структуре.
Для обращения к переменной кэш на основной форме напишем функцию:
Чтобы обращаться к этой переменной в дополнительной форме мы ее передаем через параметр открытия формы. Поскольку после открытия формы ее параметр изменяет тип на «ГрупповойКонтекст» мы не можем поместить в параметр непосредсвенно саму переменную кэш. Для этого мы создаем список значений, добавляем в него кэш() и передаем этот список как параметр открытия формы.
Процедура для открытия дополнительной формы:
Функция РасположениеОбработки() возвращает путь к папке где лежит текущая форма. Вот ее код:
Для обращения к кэшу в дополнительной форме используется функция
Для корректного описания запроса от одной формы к другой нам нужен список-структура. Я его называю «ПараметрЗакрытия». В нем указывается имя функции которую мы хотим запустить, контекст текущей формы, куда мы хотим передать ответ, данные которые должна обрабатывать эта функция.
Код функции которая возвращает параметр закрытия (в основной и в дополнительной форме):
Через параметр «устПараметр» передается списокзначений. При создании параметра закрытия в нем устанавливается признак «Обработан» = 0, который по факту срабатывания процедуры «ПриЗакрытии()» устанавливается сразу в 1. Это предотвращает ситуацию, когда из-за ошибки форму обработки невозможно закрыть.
Обработка параметра закрытия выполняется в предопределенной процедуре «ПриЗакрытии()». Ниже приведен код этой процедуры (одинаковый для любой формы)
Здесь проверяется, существует ли параметр закрытия в кэше и не обработан ли он уже. Затем получаем имя функции которую надо выполнить и через конструкцию Шаблон() выполняем её. Важно – функция может вернуть только примитивный тип, да и тот через Шаблон() будет преобразован в строку. Если надо передать что-то посложнее, добавьте эти данные в параметр закрытия. Если в параметре закрытия по ключу «КонтФормы» передан контекст формы, то вызываем процедуру ПриЗакрытии() уже этой формы и отправляем команду выполнить процедуру «КБ_Результат()». Естественно, если мы хотим отловить результат обратного вызова на той форме эта процедура должна быть описана. Для определения, по какой функции был получен результат мы копируем имя функции в ключ «Операция». До выполнения обратного вызова обязательно проверяем или до этого мы не отрабатывали результат от другой формы (функцию «КБ_Результат()»).
Код для вызова функции через параметр закрытия:
КонтОсновной() возвращает контекст основной формы, где расположена фукнция «КБ_ДобавитьЗапись()», которую мы хотим выполнить. Он также получается из кэш(), а устанавливается туда при открытии дополнительной формы (см. выше).
Код функции «КБ_ДобавитьЗапись()» из основной формы
тбРезультат – это таблица на основной форме с колонками «Код» и «Наименование». При выполнении этой функции туда будут добавляться записи. Для примера ситуация, когда мы пытаемся добавить существующий код, считается ошибочной и возвращается 0. Чтобы передать вызывающей форме описание ошибки это описание устанавливается в параметре закрытия по ключу «ОписаниеОшибки».
Код функции «КБ_Результат()» на дополнительной форме.
Отдельно стоит остановиться на понятии асинхронности. Когда мы вызываем «контФормы.Форма.Закрыть(0)» код не ожидает завершения выполнения предопределенной процедуры «ПриЗакрытии()» в форме из «контФормы». Эти операции выполняются параллельно. Поэтому, например, нельзя запихнуть такой вызов в цикл. Чтобы выполнить такой вызов в несколько итераций стоит вспомнить, что то, что решается через цикл, можно решить рекурсивно и наоборот. Поэтому используем рекурсию. Данные для отправки загоним в объект который поддерживает интерфейс итератора, т.е. конструкцию Выбрать() и Следующий(). Это может быть таблица значений, база данных дбф, справочник, документ. В процедуре которая совершает асинхронный вызов позиционируемся на следующую запись. Если дошли до конца, то выходим, если нет – совершаем асинхронный вызов. В процедуре обработки результата вызываем описанную выше процедуру.
Для примера код добавления записи в цикле и обработки результата:
Функция НаборЗаписей() создает таблицу значений с данными если она еще не создана и возвращает ее. Приведенный пример показывает, как можно совершать асинхронный вызов в цикле. На самом деле так делать не стоит, поскольку скорость выполнения этого метода очень низкая. Много времени теряется при передаче управления между формами. Плюс интерфейс программы неприятно мигает. Лучше формировать набор данных и передавать его целиком при вызове. Рекомендация примерно, как про запросы в цикле.
В заключение хочется добавить, что скорее всего подобный подход будет воспринят специалистами как баловство. У него действительно есть недостатки перед классами 1С++. В первую очередь это низкая скорость работы, и, наверное, плохая читаемость кода. Но в то же время бывает, что клиенты не хотят использовать внешние компоненты. Да и при разработке тиражных разработок желательно, по возможности, обходиться штатными средствами платформы. Когда даешь обработку пользователю, хочется, чтобы запустил – заработало.
Внешние отчёты и обработки системы «1С:Предприятие» — это отчёты и обработки, которые не входят в состав прикладного решения, а хранятся в отдельных файлах. Такие файлы имеют расширение .ert и находятся, как правило, в папке \ExtForms каталога информационной базы.
Главное преимущество внешних отчётов и обработок заключается в том, что применять их можно в различных прикладных решениях без изменения структуры самих решений. Важным преимуществом является и то, что создавать и отлаживать такие отчёты и обработки можно, не прерывая работы пользователей системы «1С:Предприятие».
Создание нового внешнего отчёта или обработки
Для создания нового отчёта (обработки) открываем программу в режиме конфигуратора и щёлкаем мышкой по кнопке «Новый документ» на панели инструментов, либо в меню « Файл » выбираем пункт « Новый ».
При этом на экран будет выведено диалоговое окно для выбора типа создаваемого файла.
В этом диалоговом окне выбираем пункт «Внешний отчет (обработка)» и щёлкаем по кнопке «ОК», после чего на экране появится окно редактора форм.
Процесс редактирования формы внешней обработки мало чем отличается от редактирования формы любого другого объекта метаданных. Для добавления или изменения элементов формы используются стандартные средства редактора форм, обратиться к которым можно через меню « Действие », « Диалог » или « Вставить ». Основные команды этих меню вынесены на панели инструментов «Редактор диалогов» и «Элементы диалогов».
Примечание: При создании некоторых внешних отчётов и обработок в качестве шаблона можно использовать уже имеющиеся в системе отчёты и обработки. Для сохранения имеющейся в системе обработки во внешний файл необходимо щёлкнуть правой кнопкой мыши по выбранной обработке и в контекстном меню выбрать пункт « Сохранить как внешний отчет (обработку) ».
При написании программных модулей внешних отчётов и обработок необходимо учитывать некоторые особенности функционирования последних. Например, если обработка создаётся для выполнения каких-либо операций с файлами и в ней используется функция ТекКаталог(), следует помнить следующее. Когда обработка открыта пользователем через меню « Сервис −> Дополнительные возможности », текущим каталогом для обработки является рабочий каталог пользователя. Если же пользователь почему-либо открыл обработку через меню « Файл −> Открыть », то текущим каталогом для неё становится тот каталог, в котором находится файл обработки (обычно это папка \ExtForms ). Поэтому в программном коде (на всякий случай!) необходимо предусмотреть оба варианта открытия.
Для сохранения созданной внешней обработки на диске щёлкаем мышкой по кнопке «Сохранить» на панели инструментов «Стандартная» или выбираем в меню « Файл » соответствующую команду. При этом на экран будет выведено стандартное окно «Сохранить как…», в котором необходимо указать имя файла и выбрать директорию для сохранения (по умолчанию внешние обработки сохраняются в папку \ExtForms каталога информационной базы).
Примечание: Любой существующий в конфигурации отчёт или обработка могут быть преобразованы во внешние, и наоборот. Кроме того, внешние отчеты и обработки могут быть добавлены в структуру прикладного решения как новые объекты.
Открытие внешнего отчёта (обработки) в режиме «1С:Предприятие»
Для открытия файла внешнего отчёта (обработки) щёлкаем мышкой по кнопке «Открыть документ» на панели инструментов «Стандартная» или выбираем в меню « Файл » команду « Открыть ».
При этом на экран будет выведено стандартное окно открытия файла.
С помощью данного окна находим файл нужного отчёта и открываем его. Работать такой отчёт будет точно так же, как если бы он входил в состав прикладного решения.
В том случае, если файл внешнего отчёта (обработки) предполагается использовать постоянно, для открытия этого файла лучше всего воспользоваться окном «Дополнительные возможности», которое вызывается через меню « Сервис −> Дополнительные возможности ». Для внесения отчёта (обработки) в имеющийся список отчётов щёлкнем мышью по кнопке «Изменить» (см. рис. ниже) и в появившемся меню выберем пункт « Внести в список «. После этого нам необходимо будет выбрать из предложенного списка имя файла добавляемого отчёта (обработки) и указать его название.
В заключение замечу, что отчёты и обработки в списке отсортированы по их названиям, а внести в данный список можно только файлы, находящиеся в папке \ExtForms .
Открытие внешнего отчёта (обработки) из программного кода
Для открытия формы внешнего отчёта (обработки) из программного кода используется встроенная системная функция ОткрытьФорму() . В качестве первого параметра в функцию передаётся строка "Отчет" , в качестве третьего параметра — строка, содержащая полное имя файла внешнего отчёта или обработки. Например:
Для открытия формы в модальном режиме используется функция ОткрытьФормуМодально() , имеющая аналогичный синтаксис:
В качестве второго (необязательного) параметра функции может использоваться имя переменной, которой можно присвоить значение любого типа для передачи в открываемую форму. Данное значение будет доступно в открытой форме как атрибут Форма.Параметр .
Возвращаемым значением обеих функций будет число 1, если действие выполнено (форма открыта), или 0, если действие не выполнено.
Читая статьи набрёл на "Запуск внешней обработки по расписанию v7.7", стало интересно - чем предложенный способ отличается от того, как сделал я.
В оригинальной статье автор предлагает использовать событие начала работы системы в глобальном модуле и отдельного пользователя.
На мой взгляд решение реальное, однако я бы дополнил его:
При таком подходе стоит выделить отдельную внешнюю обработку и запускать только её.
В коде этой обработки запускать другие необходимые обработки.
Плюс подхода - всё в одной обработке.
Минусы подхода - нет возможности выполнять обработки параллельно; необходимость первоначальной правки глобального модуля каждой конфигурации, где планируется запускать обработку по расписанию.
Другой способ
Мы не будем вообще трогать код конфигурации, в которой планируется запускать внешнюю обработку.
Вместо этого мы создадим vbs-сценарий, который будем создавать COM-объект приложения 7.7.
В нём открывать необходимую обработку.
Внутри обработки опишим необходимые действия в событии "ПриОткрытии".
После всего добавляем запуск этого сценария в планировщик заданий.
совсем примитивный вариант, который демонстрирует идею:
Set v77 = CreateObject("V77.Application")
v77.Initialize v77.RMTrade, "/D""E:\1С77Тестовая\""", "NO_SPLASH_SHOW"
v77.OpenForm "Report", "", "c:\Регламент\Регламент.ert"
Shine bright like a diamond!
Давайте улучшим наше решение.
Что было бы здорово добавить?
1) во-первых, нужно сделать из этого скрипта универсальный механизм.
Неудобно держать 100 однотипных скриптов для разных баз, поэтому сделаем один, но с параметрами.
Добавим такие параметры:
- путь к базе
- логин
- пароль
- путь к внешней обработке
2) во-вторых, нам нужен лог файл.
Желательно лог запуска + лог действий обработки.
Добавляем параметр - лог файл.
Пишим в него самим скриптом, передаём как параметр открываемой обработке. Если будет использовать - хорошо, не будет - и ладно.
3) нужно корректно закрывать 1С
Используем ЗавершитьРаботуСистемы(0), чтобы корректно выйти из 1С, обнуляем ссылку в памяти.
этот вариант уже толще:
В самой обработке
Создаём расписание
Полный путь к скрипту выглядит так: C:\WINDOWS\system32\wscript.exe C:\Регламент\autostart.vbs /Base1C:E:\1С77Тестовая\ /Ert:c:\Регламент\Регламент.ert /Log:c:\Регламент\Регламент.log
C:\WINDOWS\system32\wscript.exe - необходимо указывать наш скрипт как параметр для wscript.exe, иначе он сам не сможет получать параметры
C:\Регламент\autostart.vbs - путь к нашему скрипту
/Base1C:E:\1С77Тестовая\ - путь к базе
/Ert:c:\Регламент\Регламент.ert - путь к обработке
/Log:c:\Регламент\Регламент.log - путь к лог-файлу
/Login. - можно указать пользователя, под которым нужно открывать 1С
/Pass. - и пароль
Важные моменты
При таком подходе возможны ошибки, когда обработка вызывает "ЗавершитьРаботуСистемы" одновременно с прописанным "v77.ExitSystem 0" в скрипте.
Происходит некорректное завершение, которое лечится входом в 1С в монопольном режиме с переиндексацией.
Нужно определится - или обработка закрывает 1С, или скрипт.
Как можно улучшить решение?
первое что приходит на ум - добавить обработку ошибок, прикрутить логирование с проверкой занятости файла
. представляю вашему вниманию простой и достаточно дубовый способ:
1. Создаём в списке пользователей специальное имя, например АвтоEmail, набор прав минимальный – лишь бы хватило открыть общую внешнюю обработку.
2. В Глобальном модуле в процедуре ПриНачалеРаботыСистемы() описываем вызов отработки и завершение работы системы:
Если, например в торговле, обработка будет использовать значения по умолчанию пользователя, то вставку делаем после слов
глПользователь = Спр . ТекущийЭлемент ();
// Вызов и завершение работы
Если ИмяПользователя() = "АвтоEmail" Тогда
СтатусВозврата( 0 );
ОткрытьФорму( "Отчет" , "АвтоEmail" , КаталогИБ() + "ExtForms\ПродажиОстатки.ert" );
Возврат;
КонецЕсли;
3. В самой обработке при открытии выполняем все нужные действия.
4. Далее собираем команду запуска 1С с параметрами:
Пример: "C:\Program Files\1Cv77\BIN\1cv7.exe" ENTERPRISE /D"D:\DataBase\Db\" /N"АвтоEmail" /P"123"
5. Осталось лишь Создать задачу в Планировщике заданий windows, указать команду запуска в действии и расписание.
И раз уж речь была об отправке почтой, то модуль формы обработки может выглядеть примерно так:
Процедура ПриОткрытии ()
// Какой нибудь Запрос
Таб = СоздатьОбъект( "Таблица" );
Таб . ВывестиСекцию ( "Шапка" );
Пока Запрос . Группировка ( 1 ) = 1 Цикл
Таб . ВывестиСекцию ( "Строка" );
КонецЦикла;
Таб . ВывестиСекцию ( "Подвал" );
Таб . Записать (КаталогИБ()+ "ExtForms\Остатки.xls" , 1 );
Компонента ROM-Mail.dll бесплатная и легко пробивается в яндексе.
Возможная проблема или «запишу, чтоб не забыть».
Планировщик Windows 2008 ошибка 2147943645
Планировщику заданий не удается запустить задачу "такую-то" для пользователя "такого-то". Дополнительные сведения: значение ошибки: 2147943645.
Предлагаемое решение – выставить вышеописанную галку и до кучи поставить галку "Выполнить с наивысшими правами", расположенную там же – мне лично сразу помогло.
Для того, чтобы не вносить изменения в конфигурацию можно воспользоваться механизмом внешний обработок. Для примера создадим внешнюю обработку, которая по нажатию на кнопку будет выводить информацию о текущей дате.
Обработку будем создавать для обычного приложения на примере конфигурации 1С. Управление производственным предприятием. После создания поместим обработку в справочник «Внешние обработки».
Создание обработки
Для создания новой обработки в 1С необходимо запустить 1С. в режиме «Конфигуратор».
В Конфигураторе в меню «Файл» необходимо выбрать пункт «Новый», так же можно воспользоваться комбинацией клавиш Ctrl+N или кнопкой на панели быстрого доступа.
В появившемся окне выбираем вариант «Внешняя обработка» и нажимаем «ОК».
В открывшемся окне новой обработки необходимо задать ей имя. Назовём нашу обработку «ИнформацияОТекущемДне», автоматически формируется синоним, который будет виден пользователям.
У внешней обработки могут быть реквизиты и табличные части. Так же можно добавить макеты и формы.
Теперь необходимо создать форму для нашей обработки. Выбираем в списке «Формы» и нажимаем «Добавить».
В появившемся окне формы выбираем параметры для формы нашей обработки. Тип формы установим «Форма обработки», проконтролируем флаг «Назначить форму основной». Можно задать форме имя, но мы оставим стандартное. В данном примере оно не играет никакой роли. Нажимаем «Готово».
Перед нами простейшая обычная форма. Нажимаем правой кнопкой мыши на кнопку «Выполнить» и выбираем пункт «КнопкаВыполнитьНажатие».
Теперь сохраним нашу обработку в файл. Для этого в меню «Файл» выберем пункт «Сохранить»
Указываем каталог для сохранения файла. По умолчанию имя файла заполняется именем, которое мы указали при создании обработки.
Запуск обработки
Для запуска обработки запустим 1С в режиме «Предприятие».
Чтобы запустить обработку в меню «Файл» выберем пункт «Открыть».
Добавление обработки в систему
Пользователям будет неудобно каждый раз для запуска обработки указывать путь к файлу. Так же файл может затеряться или удалиться. Чтобы у наших пользователей всегда был доступ к только что созданной обработке поместим её в справочник «Внешние обработки».
В меню «Операции» выберем пункт «Справочник».
В открывшемся окне выберем справочник «Внешние обработки».
В данном справочнике хранятся все внешние обработки, внешние отчеты и внешние печатные формы добавленные в систему. Нажмём кнопку добавить на панели справочника.
В появившемся окне нового элемента справочника необходимо указать вид элемента. Выбираем значение «Обработка».
Теперь нажимаем на кнопку выбора файла. Система выдаст предупреждение безопасности. Нажимаем «Продолжить».
Выбираем файл нашей обработки. Имя элемента справочника подтянулось автоматически из поля «Синоним» указанного в обработке. Нажимаем «ОК»
Наша обработка появилась в списке. Теперь пользователя достаточно дважды щёлкнуть на неё для запуска.
Как оптимизировать работу с 1С?
Сделать это можно двумя основными способами:
Иметь в штате квалифицированных специалистов, которые имеют достаточную компетенцию для решения основных вопросов.
Обратиться за сопровождением 1С к сторонним специалистам.
Почему клиенты обращаются именно к нам?
Мы предлагаем не только внедрение, настройку и сопровождение, но и разработку под 1С, которая позволит оптимизировать ваши бизнес-процессы.
На вас работает не один человек, а целая команда. Вы не зависите от того, захочет ли специалист пойти в отпуск или взять больничный.
Вам не нужно оплачивать больничные, отпускные и готовить рабочее место для нового сотрудника.
Среди наших сотрудников не только специалисты 1С, но и опытные бухгалтера и юристы, поэтому мы подходим всесторонне к вопросу документооборота и отчетности.
Мы выстраиваем взаимодействие с клиентами так, чтобы вам удобно было оперативно обратиться по любому вопросу.
Позвоните по номеру телефона, указанному на сайте или заполните форму обратной связи, чтобы мы могли сориентировать по стоимости и рассказать, как начать сотрудничество.
Читайте также: