Создание обработок в 1С 8.3: от объекта до внешнего файла
Содержание
Обработку в 1С 8.3 пишут двумя путями: как объект внутри конфигурации или как отдельный внешний файл с расширением .epf. И то и другое создаётся в Конфигураторе (или в 1С:EDT), код — на встроенном языке, интерфейс — на управляемой форме. Писать обработки в 1С имеет смысл тогда, когда нужно выполнить действие, а не хранить данные: пересчитать цены в номенклатуре, разово загрузить остатки
из файла, собрать служебный отчёт по регистру.
Классический случай: бухгалтер просит «поправить во всех договорах одно поле», документов — тысячи, руками нереально. Отчёт тут не поможет (он только показывает), а обработка пройдёт по данным и запишет изменения.
Ниже — весь путь: от выбора типа объекта до упаковки готового .epf, с кодом под управляемое приложение 1С 8.3.
Внешняя или встроенная: выбираем тип и создаём объект
Первое решение — где будет жить обработка.
- 🧩 Встроенная — объект в дереве конфигурации. Ставится вместе с обновлением, доступна через меню, но требует снятия конфигурации с поддержки или своего расширения.
- 📦 Внешняя (
.epf) — отдельный файл. Не трогает конфигурацию, легко передать, подключить и удалить. Для разовых задач и утилит — почти всегда выбор в её пользу.
Для доработок «на живой базе» удобнее внешняя обработка, помещённая в справочник Дополнительные обработки (есть в типовых на БСП): раздел Администрирование → Печатные формы, отчёты и обработки. Так она не ломает поддержку и подключается без Конфигуратора.
Создание внешней обработки
В Конфигураторе: Файл → Новый → Внешняя обработка. Откроется окно объекта — задайте имя (латиницей, без пробелов, например ПересчётЦен) и синоним (это русское название для пользователя).
Чтобы сразу работать с файлом, сохраните его: Файл → Сохранить → имя .epf. Дальше вся правка идёт в этом файле.
Создание встроенной обработки
В дереве конфигурации найдите ветку Обработки, правой кнопкой — Добавить. Остальное идентично внешней: имя, синоним, формы, модуль. Разница только в способе поставки.
Если собираетесь дорабатывать типовую конфигурацию , не меняйте её напрямую — делайте расширение или внешнюю обработку . Иначе обновление затрёт правки или потребует ручного сравнения.
Форма обработки: реквизиты, команды и элементы
Без формы обработка умеет только запускаться по команде из модуля. Чтобы дать пользователю интерфейс, добавьте управляемую форму.
В окне объекта откройте вкладку Формы и нажмите «плюс». Мастер предложит тип — для обработки это форма обработки. Галку «назначить основной» оставьте включённой, иначе форма не откроется двойным кликом.
Форма управляемого приложения состоит из трёх связанных частей:
- Реквизиты (правая верхняя панель) — данные формы: периоды, флажки, ссылки на выбранные объекты, таблицы значений.
- Элементы (левая верхняя панель) — то, что видит пользователь: поля ввода, кнопки, таблицы. Элемент связывается с реквизитом перетаскиванием.
- Команды — действия. Команду перетаскивают на форму, она становится кнопкой.
Пример: поле периода и кнопка запуска
Добавьте реквизит ПериодОтбора типа СтандартныйПериод, перетащите его в дерево элементов — получите готовый выбор периода. Затем создайте команду Выполнить, перетащите на форму — появится кнопка.
Реквизиты формы живут только пока форма открыта. Если данные нужно сохранить между сеансами, пишите их в константу, регистр сведений или настройки хранилища — сама форма ничего не помнит.
Клиент и сервер: как разложить код по директивам
Это ключевая тема управляемого приложения и место, где спотыкаются новички. Код выполняется либо на клиенте (у пользователя), либо на сервере (где база), и перед каждой процедурой стоит директива компиляции.
| Директива | Где работает | Для чего |
|---|---|---|
&НаКлиенте | тонкий клиент | диалоги, вопросы, открытие форм |
&НаСервере | сервер, с контекстом формы | чтение/запись данных, запросы |
&НаСервереБезКонтекста | сервер, без формы | расчёты, не трогающие форму |
&НаКлиентеНаСервереБезКонтекста | обе стороны | общие функции без обращения к БД |
Главное правило: база данных доступна только на сервере. Прочитать справочник, выполнить запрос, записать документ — всё это на сервере.
Типичная связка — команда формы вызывает клиентскую процедуру, та передаёт управление на сервер:
&НаКлиенте
Процедура Выполнить(Команда)
КоличествоОбработанных = ВыполнитьНаСервере(ПериодОтбора.ДатаНачала, ПериодОтбора.ДатаОкончания);
Сообщить("Обработано объектов: " + КоличествоОбработанных);
КонецПроцедуры
&НаСервере
Функция ВыполнитьНаСервере(ДатаС, ДатаПо)
// здесь доступны запросы и запись данных
Возврат ОбработатьДанные(ДатаС, ДатаПо);
КонецФункции
Серверный вызов — это «дорога» между клиентом и сервером. Чем их меньше, тем быстрее работает форма. Не вызывайте сервер в цикле: соберите параметры и сходите на сервер один раз.
Директиву &НаСервереБезКонтекста используйте, когда процедуре не нужны реквизиты формы — такой вызов легче, потому что не тащит на сервер всё содержимое формы.
Длительные операции в фоне
Если обработка перебирает тысячи объектов, прямой серверный вызов заморозит форму: пользователь увидит «зависший» интерфейс и может решить, что программа упала. Чтобы этого избежать, тяжёлую работу запускают в фоновом задании.
В типовых на БСП для этого есть общий модуль ДлительныеОперации: серверная функция стартует фоновое задание и сразу возвращает управление, а клиент показывает индикатор и периодически спрашивает статус. Так форма остаётся живой, а пользователь видит прогресс.
Для разовой утилиты на десяток-другой объектов фон не нужен — он усложняет код. Выносите в фон только то, что реально считается секундами и дольше.
Запросы и работа с данными в обработке
Чтобы выбрать данные для обработки, используют язык запросов. Он похож на SQL, но работает с объектами конфигурации.
Собирать текст запроса вручную не нужно: правой кнопкой в модуле — Конструктор запроса. Он покажет таблицы (справочники, документы, регистры), поможет собрать поля, условия и соединения.
Выполнение запроса в коде
&НаСервере
Функция ПолучитьНоменклатуру(ДатаС, ДатаПо)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Ссылка КАК Ссылка,
| Товары.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Товары
|ГДЕ
| НЕ Товары.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Результат = Новый Массив;
Пока Выборка.Следующий() Цикл
Результат.Добавить(Выборка.Ссылка);
КонецЦикла;
Возврат Результат;
КонецФункции
Параметры в запрос передавайте через Запрос.УстановитьПараметр("ДатаС", ДатаС), а в тексте пишите &ДатаС. Никогда не вставляйте значения прямо в строку запроса — это и медленно, и небезопасно.
Чтение и запись наборов записей
Если обработка правит регистры, работайте через набор записей, а не через отдельные строки:
Набор = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Номенклатура.Установить(ТоварСсылка);
Набор.Прочитать();
// правим строки набора
Набор.Записать();
Для справочников и документов берите объект через .ПолучитьОбъект(), меняйте реквизиты и вызывайте .Записать(). Менять данные напрямую в выборке запроса нельзя — запрос только читает.
Временные таблицы для больших выборок
Когда обработка сопоставляет несколько источников — например, остатки регистра с данными из загруженного файла — не делайте вложенные запросы в цикле. Соберите данные во временные таблицы и соедините их одним запросом.
Для этого в конструкторе запроса на вкладке Пакет запросов первым шагом поместите выборку в ПОМЕСТИТЬ ВременнаяТаблица, а в коде передайте объект МенеджерВременныхТаблиц:
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Это и быстрее, и читается легче, чем десятки отдельных обращений к базе. Любой перебор данных через повторный запрос внутри цикла — первый кандидат на оптимизацию, особенно на больших базах.
Транзакции: безопасная запись изменений
Когда обработка меняет много объектов в цикле, оберните запись в транзакцию. Тогда при сбое на середине не останется половины изменённых данных.
НачатьТранзакцию();
Попытка
Для Каждого Ссылка Из МассивОбъектов Цикл
Объект = Ссылка.ПолучитьОбъект();
Объект.Комментарий = "Обработано";
Объект.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Правила, которые экономят нервы:
- 🔁 На каждый
НачатьТранзакцию()— ровно одинЗафиксироватьТранзакцию()илиОтменитьТранзакцию(). Незакрытая транзакция повесит сеанс. - 🧯 В блоке
ИсключениесначалаОтменитьТранзакцию(), потом уже разбор ошибки. Иначе платформа ругнётся на незавершённую транзакцию. - 📏 Не держите в одной транзакции тысячи записей — это раздувает блокировки. Крупные массивы обрабатывайте порциями по несколько сотен объектов, фиксируя каждую порцию.
Запись внутри транзакции блокирует изменяемые данные для других пользователей. На рабочей базе тяжёлую обработку запускайте в тихое время, а не в разгар рабочего дня, иначе коллеги поймают ожидание на блокировке.
Вывод результата в табличный документ
Если по итогам работы нужно показать результат — список, что сделано, отчёт для проверки — используйте табличный документ.
Самый управляемый способ — макет:
- На вкладке
Макетыобъекта добавьте макет типа Табличный документ. - Нарисуйте области: шапку, строку данных, подвал. Имена областям задайте в свойствах.
- В ячейки с данными впишите
[ИмяПараметра]и пометьте ячейку как параметр. - В коде заполните и выведите области.
&НаСервере
Функция СформироватьОтчёт(Данные)
Макет = Обработки.ПересчётЦен.ПолучитьМакет("Макет");
Таб = Новый ТабличныйДокумент;
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
Таб.Вывести(ОбластьШапка);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого Строка Из Данные Цикл
ОбластьСтрока.Параметры.Наименование = Строка.Наименование;
Таб.Вывести(ОбластьСтрока);
КонецЦикла;
Возврат Таб;
КонецФункции
Готовый табличный документ возвращайте на клиент и показывайте через поле формы типа ТабличныйДокумент либо откройте отдельно. Пользователь сможет распечатать его или выгрузить в Excel стандартными средствами 1С.
Для сложных отчётов с группировками и настройками удобнее не рисовать макет вручную, а взять систему компоновки данных (СКД). Но для «вывести, что обработали» ручного табличного документа достаточно.
Отладка, тестирование и упаковка внешней обработки
Перед передачей обработку надо проверить в отладчике и на тестовых данных.
Отладка
Запустите базу в режиме 1С:Предприятие из Конфигуратора клавишей F5 — отладка включится автоматически. Поставьте точку останова (F9) на нужной строке модуля: когда выполнение дойдёт до неё, оно остановится.
Что помогает на остановке:
- 👁 Табло (
Отладка → Табло) — показывает значения переменных. Выделите переменную и перетащите в табло. - ➡️ Шаг с заходом (
F11) и шаг с обходом (F10) — проход по строкам. - 🧪 Вычисление выражения (
Shift+F9) — посмотреть содержимое структуры, таблицы значений, выборки прямо на паузе.
Если точка останова не срабатывает, проверьте, что в настройках информационной базы (Конфигуратор → Сервис → Параметры → Запуск) включена отладка, а внешняя обработка открыта из той же базы, где идёт отладка.
Тестирование
Прогоните обработку на копии рабочей базы, а не на боевой. Проверьте граничные случаи: пустой отбор, помеченные на удаление объекты, уже обработанные строки (чтобы повторный запуск не ломал данные). Хорошая обработка запускается повторно без вреда — это свойство называют идемпотентностью.
Упаковка и подключение
Готовую внешнюю обработку сохраните как .epf (Файл → Сохранить). Передать можно просто файлом.
Подключение на стороне пользователя:
- Разово:
Файл → Открытьв режиме 1С:Предприятие (нужны права на открытие внешних обработок). - Постоянно: через справочник
Дополнительные обработки— разделАдминистрирование → Печатные формы, отчёты и обработки. Там обработка появится в списке и будет доступна без Конфигуратора.
Открытие внешних обработок — это выполнение чужого кода в вашей базе. Разрешайте его только проверенным файлам и ограничивайте право профилем доступа: вредоносная обработка может удалить или испортить данные.
Чем обработка отличается от отчёта?
Почему код в запросе не видит справочник, а на форме всё работает?
&НаКлиенте, базы она не видит. Перенесите работу с данными в процедуру &НаСервере.Можно ли менять типовую конфигурацию обработкой, не снимая с поддержки?
Как передать результат с сервера на клиент?
ДокументОбъект на клиент не передаются — передавайте ссылки или примитивные данные.Обработка выдаёт «Транзакция не завершена» — в чём дело?
НачатьТранзакцию() не закрыт парным Зафиксировать/Отменить, чаще всего из-за ошибки в цикле. Оберните тело в Попытка…Исключение и в блоке исключения вызовите ОтменитьТранзакцию().