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