Разработка внешних обработок — это одна из наиболее частых задач для начинающего программиста 1С. В данной статье мы подробно разберем, как создать инструмент, который анализирует документ ПоступлениеНаРасчетныйСчет, извлекает из него договор контрагента и определяет, из какой именно части документа (шапки, табличной части или связанного счета) этот договор был взят. Мы пройдем путь от создания формы до написания серверного кода, учитывая типичные ошибки новичков.
Прежде чем приступать к написанию кода, проанализируем структуру нашей будущей обработки. Нам необходимо создать внешнюю обработку, на форме которой будут располагаться следующие элементы:
ПоступлениеНаРасчетныйСчет.РезультатыПоиска, в которой будут две колонки: Договор (тип СправочникСсылка.ДоговорыКонтрагентов) и Источник (тип Строка).Рассмотрим важный нюанс: при создании реквизита на форме для выбора документа, убедитесь, что его тип установлен как ДокументСсылка.ПоступлениеНаРасчетныйСчет. Это позволит платформе сразу понимать, с каким типом данных мы работаем.
Для правильного решения задачи нам нужно понимать, где в типовых конфигурациях (например, 1С:Бухгалтерия 3.0) может храниться договор. Проанализируем три основных места:
ДоговорКонтрагента. Он используется, если платеж идет по одному основанию.РасшифровкаПлатежа.СчетНаОплату. В этом случае договор может быть «подтянут» из самого счета.Перейдем к программированию. Основная работа должна происходить на сервере, так как на клиенте мы не имеем прямого доступа к данным базы. Разберем по шагам создание процедуры, которая будет вызываться при нажатии кнопки на форме.
Многие начинающие разработчики сталкиваются с ошибкой «Переменная не задана» при попытке обратиться к документу. Выясним причину: если вы создали реквизит на форме с именем ВыбранныйДокумент, то обращаться к нему в коде модуля формы нужно именно по этому имени. Если же реквизит является частью основного объекта обработки, то путь будет выглядеть как Объект.ВыбранныйДокумент.
Рассмотрим пример кода, реализующий базовую проверку:
&НаСервере
Процедура СгенерироватьНаСервере()
// Очищаем таблицу перед новым заполнением
Объект.РезультатыПоиска.Очистить();
// Проверяем, выбран ли документ на форме
Если Объект.ВыбранныйДокумент.Пустая() Тогда
Возврат;
КонецЕсли;
// Получаем объект документа для анализа его структуры
ДокОбъект = Объект.ВыбранныйДокумент.ПолучитьОбъект();
// 1. Проверяем табличную часть "Расшифровка платежа"
Если ДокОбъект.РасшифровкаПлатежа.Количество() > 0 Тогда
Для Каждого СтрокаТЧ Из ДокОбъект.РасшифровкаПлатежа Цикл
Если ЗначениеЗаполнено(СтрокаТЧ.ДоговорКонтрагента) Тогда
НоваяСтрока = Объект.РезультатыПоиска.Добавить();
НоваяСтрока.Договор = СтрокаТЧ.ДоговорКонтрагента;
НоваяСтрока.Источник = "Из табличной части документа";
КонецЕсли;
КонецЦикла;
КонецЕсли;
// 2. Если таблица пуста, проверяем шапку документа
Если Объект.РезультатыПоиска.Количество() = 0 Тогда
Если ЗначениеЗаполнено(ДокОбъект.ДоговорКонтрагента) Тогда
НоваяСтрока = Объект.РезультатыПоиска.Добавить();
НоваяСтрока.Договор = ДокОбъект.ДоговорКонтрагента;
// Проверяем, не из счета ли взят договор
Если ЗначениеЗаполнено(ДокОбъект.СчетНаОплату) Тогда
НоваяСтрока.Источник = "Из счета на оплату";
Иначе
НоваяСтрока.Источник = "Из реквизитов шапки";
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В процессе обсуждения на форумах часто возникает спор: использовать ли обращение «через точку» (как в примере выше) или писать SQL-подобный запрос. Разберем ситуацию подробнее. Когда мы пишем ДокументОбъект.ДоговорКонтрагента, система считывает из базы данных весь документ со всеми его полями и всеми строками всех табличных частей. Если ваша обработка будет обрабатывать тысячи документов, это приведет к серьезному замедлению работы (так называемые «тормоза» системы).
Посмотрим на пример того, как получить те же данные более эффективно через объект Запрос. Это позволит нам извлечь только нужные поля, не нагружая память сервера лишними данными:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Поступление.ДоговорКонтрагента КАК ДоговорШапка,
| Поступление.СчетНаОплату КАК Счет,
| Поступление.РасшифровкаПлатежа.(
| ДоговорКонтрагента КАК ДоговорТЧ
| ) КАК Расшифровка
|ИЗ
| Документ.ПоступлениеНаРасчетныйСчет КАК Поступление
|ГДЕ
| Поступление.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Объект.ВыбранныйДокумент);
РезультатЗапроса = Запрос.Выполнить();
Проанализируем этот подход: запрос выполняется на уровне СУБД и возвращает структурированный результат. Даже если вы только начинаете изучать 1С, привычка использовать запросы вместо прямого обращения к объектам в циклах сделает вас востребованным специалистом значительно быстрее.
Рассмотрим ситуацию, когда при нажатии кнопки «Сгенерировать» ничего не происходит или вылетает ошибка. Выясним возможные причины:
&НаСервере, программа не сможет получить доступ к данным документа.РеквизитамиФормы. Чтобы изменить данные, которые хранятся в объекте обработки, всегда используйте префикс Объект. (например, Объект.МояТаблица.Добавить()).ЗначениеЗаполнено(). Если вы попытаетесь вывести пустую ссылку в таблицу, пользователь увидит пустую строку, что может быть воспринято как ошибка работы программы.Мы разобрали основы создания внешней обработки для анализа структуры документа. Главный вывод: для успешного решения задачи в 1С важно не только знать синтаксис языка, но и понимать внутреннее устройство метаданных конфигурации. Сочетание правильного контекста выполнения (Клиент/Сервер) и грамотного обращения к реквизитам формы позволяет создавать надежные и быстрые инструменты автоматизации.
Помните, что путь программиста 1С состоит из постоянной практики. Сегодня вы научились выводить договор из шапки документа, а завтра сможете строить сложные аналитические отчеты, объединяющие данные из десятков различных источников.