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

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

В разработке на платформе 1С:Предприятие 8.3 механизм подбора через "корзину" является одним из самых удобных способов заполнения табличных частей для пользователя. Однако при его реализации часто возникают вопросы: как не затереть уже добавленные строки, как вызвать дополнительное окно для ввода количества и как правильно работать с динамическими списками. В этой статье мы подробно разберем, как решить эти задачи на примере документа ДанныеДляРасчетаЗарплаты.

Проблема 1: Перезатирание данных при повторном подборе

Рассмотрим типичную ситуацию: разработчик реализовал подбор, но при каждом новом открытии формы подбора и переносе данных в документ старые строки исчезают, заменяясь новыми. Это происходит из-за использования метода Загрузить(). Проанализируем, как правильно организовать перенос данных из временного хранилища.

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


&НаСервере
Процедура ОбработатьПодборНаСервере(АдресВременногоХранилища)
    
    // Получаем данные из корзины (таблицу значений)
    Корзина = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
    
    Для каждого Стр Из Корзина Цикл
        
        // Поиск существующей строки, если нужно объединить объемы
        Отбор = Новый Структура("ВидРабот", Стр.ВидРабот);
        НайденныеСтроки = Объект.ВыполненныеРаботы.НайтиСтроки(Отбор);
        
        Если НайденныеСтроки.Количество() > 0 Тогда
            // Если такая работа уже есть, просто суммируем объем
            НайденнаяСтрока = НайденныеСтроки[0];
            НайденнаяСтрока.ОбъемВыполненныхРабот = НайденнаяСтрока.ОбъемВыполненныхРабот + Стр.ОбъемВыполненныхРабот;
        Иначе
            // Если работы нет, добавляем новую строку
            НовСтр = Объект.ВыполненныеРаботы.Добавить();
            ЗаполнитьЗначенияСвойств(НовСтр, Стр);
            
            // Устанавливаем значения по умолчанию для новых строк
            НовСтр.КоэффициентИсполнения = 1;
            НовСтр.ПроцентИсполнения = 100;
            
            // Вызываем типовые механизмы заполнения, если они предусмотрены в конфигурации
            ЗаполнитьСтрокуВыполненныхРабот(НовСтр, Истина, Ложь);
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Использование метода НайтиСтроки() позволяет нам избежать дублирования позиций. Если бизнес-логика предполагает, что одна и та же работа может встречаться в документе несколько раз разными строками, то условие поиска можно опустить и всегда использовать Добавить().

Проблема 2: Ввод дополнительных параметров (количество, коэффициенты)

Зачастую просто выбрать элемент из списка недостаточно — пользователю нужно сразу указать объем работ или процент выполнения. Для этого логично использовать вспомогательную форму ввода. Разберем по шагам, как это реализовать через ОписаниеОповещения.

Во-первых, в форме подбора при выборе элемента из списка мы должны не сразу добавлять его в корзину, а открывать форму ввода:


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

Во-вторых, в самой вспомогательной форме (например, ФормаКолДетали) при нажатии кнопки "ОК" мы собираем данные в структуру и закрываем форму, передавая результат обратно:


&НаКлиенте
Процедура ОК(Команда)
    
    // Проверка заполнения обязательных полей
    Если ОбъемВыполненныхРабот = 0 Тогда
        Сообщить("Не заполнено количество!");
        Возврат;
    КонецЕсли;

    РезультатВыбора = Новый Структура;
    РезультатВыбора.Вставить("ОбъемВыполненныхРабот", ОбъемВыполненныхРабот);
    РезультатВыбора.Вставить("НомерДетали", НомерДетали);
    РезультатВыбора.Вставить("КоэффициентИсполнения", КоэффициентИсполнения);
    РезультатВыбора.Вставить("ПроцентИсполнения", ПроцентИсполнения);
    
    // Закрываем форму и передаем структуру в процедуру оповещения
    Закрыть(РезультатВыбора);
    
КонецПроцедуры

В-третьих, реализуем процедуру обратного вызова в основной форме подбора, которая добавит данные в корзину:


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

Проблема 3: Получение данных из динамического списка

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

Для корректного получения ссылки на справочник ВидыРаботСотрудников следует обращаться к свойству ТекущиеДанные элемента формы Таблица. Это гарантирует, что вы получите значения всех колонок, присутствующих в строке запроса, включая скрытые.

Важный совет: При переносе данных из корзины в документ всегда используйте Временное хранилище. Это позволяет передавать большие объемы данных между формами без лишней нагрузки на клиент-серверный канал связи, передавая только строковый адрес (УИД) данных в памяти сервера.

Таким образом, мы построили надежную цепочку подбора:

  1. Выбор из динамического списка (с учетом особенностей КлючЗаписи).
  2. Открытие модального (блокирующего) окна для уточнения параметров.
  3. Наполнение локальной таблицы "Корзина" на форме подбора.
  4. Перенос всей корзины в Объект документа с проверкой на дубли и дозаполнением реквизитов.

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

← На главную