Как реализовать заполнение табличной части с отбором и защитой от дублей в 1С 8.1

Программист 1С v8.3 (Обычные формы) Управленческий учет
← На главную

В разработке на платформе 1С:Предприятие 8.1 (Обычные формы) часто возникает задача автоматического заполнения табличной части документа или обработки данными из справочников. Основные сложности, с которыми сталкиваются начинающие разработчики, — это попадание в список «папок» (групп справочника) и многократное добавление одних и тех же элементов при повторном нажатии кнопки. Рассмотрим подробно, как решить эти задачи эффективно и профессионально.

Исключение групп справочника при простом переборе

Разберем ситуацию, когда мы используем прямой перебор элементов справочника Контрагенты. В исходном коде автора в табличную часть попадают все записи, включая группы. Это происходит потому, что метод Выбрать() возвращает и элементы, и иерархические папки. Чтобы этого избежать, нам нужно добавить проверку логического свойства ЭтоГруппа.

Проанализируем обновленный код процедуры:


Процедура Кнопка1Нажатие(Элемент)
    Выборка = Справочники.Контрагенты.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Проверяем, является ли текущая запись группой
        Если Выборка.ЭтоГруппа Тогда
            Продолжить; // Пропускаем итерацию и переходим к следующему элементу
        КонецЕсли;
        
        СтрТч = Долги.Добавить();
        СтрТч.Контрагент = Выборка.Ссылка;
        СтрТч.МесячныйЛимит = Выборка.МесячныйЛимитГотовый;
        СтрТч.Вид = Перечисления.ВидыДолгов.ДолгПоставщика;
        СтрТч.Валюта = Константы.БазоваяВалюта.Получить();
    КонецЦикла;
КонецПроцедуры

Использование оператора Продолжить внутри цикла Пока позволяет нам игнорировать любые записи, которые не являются конечными элементами. Это самый простой способ «отсеять» лишнее, не меняя структуру алгоритма.

Решение проблемы дублирования строк

Если пользователь нажмет на кнопку заполнения несколько раз, в табличной части Долги появятся одинаковые контрагенты. Рассмотрим два подхода к решению этой проблемы: полную очистку перед заполнением и точечную проверку наличия записи.

Способ 1: Очистка таблицы. Если задача состоит в том, чтобы таблица всегда отражала актуальное состояние справочника «с нуля», мы можем просто очистить ее перед циклом.


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

Способ 2: Поиск существующих записей. Если нам нужно сохранить уже введенные пользователем данные и добавить только тех контрагентов, которых в таблице еще нет, воспользуемся методом НайтиСтроки().

Проанализируем алгоритм проверки:


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

Метод НайтиСтроки работает быстрее, чем ручной перебор табличной части в поисках дубля, так как использует внутренние механизмы платформы.

Оптимизация заполнения через Запросы

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

Разберем пример реализации через запрос:


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

Обратим внимание на условие ГДЕ Контрагенты.ЭтоГруппа = ЛОЖЬ. Это позволяет нам вообще не получать папки из базы данных, что экономит память и время работы скрипта.

Реализация механизма «Подбора»

Если пользователю нужно не просто заполнить таблицу «всеми сразу», а выбирать конкретных контрагентов из списка, в Обычных формах используется механизм Подбора. Это открывает форму выбора справочника, при клике в которой данные передаются в документ.

  1. В процедуре нажатия кнопки вызываем форму выбора: ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", , Элемент); Здесь Элемент — это сама кнопка или табличное поле, которое станет «владельцем» формы выбора.
  2. В форме документа создаем предопределенную процедуру ОбработкаВыбора:
    
    Процедура ДолгиОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
        СтандартнаяОбработка = Ложь; // Отключаем стандартное поведение
        
        // Проверяем, не выбран ли этот контрагент ранее
        ПараметрыПоиска = Новый Структура("Контрагент", ВыбранноеЗначение);
        Если Долги.НайтиСтроки(ПараметрыПоиска).Количество() = 0 Тогда
            НоваяСтрока = Долги.Добавить();
            НоваяСтрока.Контрагент = ВыбранноеЗначение;
            // Дозаполняем данные из объекта
            НоваяСтрока.МесячныйЛимит = ВыбранноеЗначение.МесячныйЛимитГотовый;
            // ...
        КонецЕсли;
    КонецПроцедуры
    

Использование программных отборов

Для того чтобы в форме выбора пользователь видел только тех контрагентов, которые соответствуют определенным критериям (например, только работающие поставщики), мы можем настроить Отбор перед открытием формы.

Рассмотрим по шагам, как это сделать:


ФормаВыбора = Справочники.Контрагенты.ПолучитьФормуВыбора();
// Устанавливаем отбор по папкам
ФормаВыбора.Отбор.ЭтоГруппа.Использование = Истина;
ФормаВыбора.Отбор.ЭтоГруппа.Значение = Ложь;

// Устанавливаем режим выбора только элементов
ФормаВыбора.ЭлементыФормы.СправочникСписок.НастройкаОтбора.ЭтоГруппа.Доступность = Ложь;

ФормаВыбора.Открыть();

Выясним причину, по которой это удобно: пользователь избавляется от необходимости вручную переходить по папкам и не может ошибиться, выбрав группу вместо конкретного контрагента. Это значительно повышает эргономику интерфейса 1С 8.1.

Таким образом, комбинируя использование запросов для автоматического заполнения и механизм подбора для интерактивной работы, мы получаем надежный инструмент управления табличными частями. Не забывайте использовать проверку на дубли через НайтиСтроки(), чтобы поддерживать чистоту данных в ваших документах.

← На главную