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