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