Как программно заполнить табличную часть при множественном выборе сотрудников без записи объекта в 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При работе с обычными формами в 1С программисты часто сталкиваются с задачей множественного подбора элементов в табличную часть (ТЧ). Типичная ошибка — попытка записать объект в базу данных прямо внутри обработчика выбора, чтобы данные «появились» на экране. Это приводит к тому, что пользователь теряет возможность отменить изменения, нажав кнопку «Закрыть». Другая проблема — появление лишней пустой строки. Рассмотрим подробнее, как правильно реализовать этот механизм, сохранив интерактивность и чистоту данных.

Анализ проблемы: почему появляется пустая строка и зачем нужна запись?

Давайте разберем ситуацию, описанную в исходном вопросе. Автор пытался получить объект по ссылке через ПолучитьОбъект(), добавить в него строки, вызвать Записать(), а затем обновить форму через Прочитать(). Это в корне неверный подход для интерактивной формы по нескольким причинам:

Шаг 1: Правильная работа с контекстом формы

Первым делом выясним: если мы находимся в модуле формы, нам не нужно получать объект по ссылке. Мы работаем напрямую с данными формы. Вместо Объект = Ссылка.ПолучитьОбъект() следует использовать ЭтотОбъект (в обычных формах) или напрямую обращаться к имени табличной части.

Для того чтобы избежать появления лишней пустой строки, необходимо в начале процедуры установить параметр СтандартнаяОбработка = Ложь. Это скажет платформе, что мы берем управление процессом заполнения на себя и стандартный механизм завершения выбора в текущую ячейку выполнять не нужно.

Шаг 2: Оптимизация получения данных сотрудников

Проанализируем запрос из примера. Выбирать все данные из регистра сведений ДанныеСотрудников без фильтра — плохая практика. Если сотрудников в базе тысячи, система будет «тормозить». Давайте модернизируем запрос, используя параметр В.

Посмотрим на пример правильной подготовки данных:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ДанныеСотрудников.Подразделение,
    |	ДанныеСотрудников.Должность,
    |	ДанныеСотрудников.Сотрудник
    |ИЗ
    |	РегистрСведений.ДанныеСотрудников КАК ДанныеСотрудников
    |ГДЕ
    |	ДанныеСотрудников.Сотрудник В (&МассивВыбранных)";

Запрос.УстановитьПараметр("МассивВыбранных", ВыбранноеЗначение);
ТаблицаДанных = Запрос.Выполнить().Выгрузить();

Шаг 3: Алгоритм заполнения ТЧ без лишних строк

Теперь реализуем основной цикл заполнения. Важный нюанс: если мы хотим, чтобы выбранные сотрудники добавились корректно, мы просто обходим массив ВыбранноеЗначение и добавляем новые строки в ЭтотОбъект.СписокСотрудников.

Проанализируем итоговый код обработчика:


Процедура ТабличноеПоле1СотрудникОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь; // Отключаем стандартное заполнение текущей ячейки
    
    // Если выбрано пустое значение или отмена - ничего не делаем
    Если ВыбранноеЗначение = Неопределено Тогда 
        Возврат;
    КонецЕсли;

    // Подготавливаем данные запросом (как в Шаге 2)
    Запрос = Новый Запрос("ВЫБРАТЬ Подразделение, Должность, Сотрудник 
                          |ИЗ РегистрСведений.ДанныеСотрудников 
                          |ГДЕ Сотрудник В (&Массив)");
    Запрос.УстановитьПараметр("Массив", ВыбранноеЗначение);
    Выгрузка = Запрос.Выполнить().Выгрузить();

    Для Каждого ВыбранныйОбъект Из ВыбранноеЗначение Цикл
        
        // Ищем данные сотрудника в выгрузке
        СтрокаДанных = Выгрузка.Найти(ВыбранныйОбъект, "Сотрудник");
        
        // Добавляем новую строку в табличную часть объекта
        НоваяСтрока = ЭтотОбъект.СписокСотрудников.Добавить();
        НоваяСтрока.Сотрудник = ВыбранныйОбъект;
        
        Если СтрокаДанных <> Неопределено Тогда
            НоваяСтрока.Должность = СтрокаДанных.Должность;
            НоваяСтрока.Подразделение = СтрокаДанных.Подразделение;
        КонецЕсли;
        
    КонецЦикла;

    // Сообщаем форме, что данные изменены
    ЭтаФорма.Модифицированность = Истина;
    
    // Принудительно обновляем визуальное отображение строк
    ЭлементыФормы.СписокСотрудников.ОбновитьСтроки();

КонецПроцедуры

Шаг 4: Визуальное обновление и модифицированность

Чтобы пользователь увидел изменения мгновенно и система поняла, что объект изменен, мы используем два важных инструмента:

  1. Модифицированность: Установка ЭтаФорма.Модифицированность = Истина активирует кнопку «Записать» и заставит 1С спросить «Сохранить изменения?» при попытке закрыть форму. Это заменяет небезопасный метод Записать().
  2. ОбновитьСтроки(): В обычных формах иногда возникает визуальный лаг, когда данные в памяти объекта уже есть, а табличное поле на экране их еще не отобразило. Метод ЭлементыФормы.ИмяТЧ.ОбновитьСтроки() синхронизирует состояние памяти и экрана без обращения к базе данных.

Альтернативный вариант: Полное перезаполнение

Если ваша задача состоит не в добавлении новых строк к существующим, а в полном обновлении списка, используйте метод Загрузить(). Это работает значительно быстрее циклов.

Разберем пример:


// Сначала очищаем старые данные
ЭтотОбъект.СписокСотрудников.Очистить();

// Загружаем всю таблицу из результата запроса одной командой
ЭтотОбъект.СписокСотрудников.Загрузить(ТаблицаДанных);

ЭтаФорма.Модифицированность = Истина;

Важно: Метод Загрузить() требует, чтобы имена колонок в таблице значений полностью совпадали с именами колонок в табличной части объекта. Это самый эффективный способ обновления больших объемов данных в оперативной памяти формы.

Таким образом, комбинируя отключение стандартной обработки, оптимизированные запросы и правильные методы обновления интерфейса, мы получаем отзывчивое и корректно работающее приложение, которое ведет себя предсказуемо для пользователя.

← На главную