Как обработать ввод новой строки в табличной части обычной формы 1С без прерывания работы пользователя?

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

Приветствуем, коллеги! Сегодня мы детально разберем одну из классических и в то же время коварных проблем, с которой часто сталкиваются разработчики при работе с обычными формами в 1С. Представьте ситуацию: в документе (например, «Корректировка реализации») пользователю необходимо корректировать строки табличной части. При этом бизнес-логика требует, чтобы при изменении или добавлении строки фиксировались дополнительные сведения (например, причина изменения количества или номенклатуры) и записывались в независимый регистр сведений.

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

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

Анализ стандартного поведения событий табличного поля

Для начала разберем, почему стандартные события часто не подходят для решения нашей задачи напрямую:

  1. Событие ПриОкончанииРедактирования: вызывается, когда фокус покидает строку, которая редактировалась. Параметр НоваяСтрока имеет тип Булево и возвращает Истина, если строка действительно была только что добавлена. Проблема в том, что это событие срабатывает после того, как строка уже добавлена и пользователь завершил её редактирование. Если мы открываем здесь модальную форму для заполнения причины изменения, это происходит прямо в момент окончания ввода. Пользователь заполнил строку, хочет перейти к следующей, но тут "бабах" — всплывающее окно. Это прерывает фокус ввода и мешает быстрой работе.
  2. Событие ПередНачаломДобавления: в этом событии строка еще физически не добавлена в табличную часть, у нас нет данных по номенклатуре и количеству. Мы не можем открыть форму ввода причины, так как пользователь еще ничего не выбрал.

Ниже мы подробно рассмотрим четыре решения, которые сделают интерфейс удобным и логичным.

---

Решение 1. Групповой ввод причин перед записью (Паттерн «ПередЗаписью») — Рекомендуемый UX-подход

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

Алгоритм работы:

  1. Пользователь добавляет и редактирует строки в табличной части без каких-либо всплывающих окон.
  2. При нажатии кнопки «Записать» или «Провести» срабатывает событие формы ПередЗаписью.
  3. В этом событии программно проверяется табличная часть: сравниваются текущие строки документа с исходными (или проверяется наличие записей в регистре сведений для добавленных строк).
  4. Если обнаружены новые или измененные строки, по которым еще не зафиксирована причина в регистре, открывается одна общая форма.
  5. В этой форме в виде таблицы выводятся только те строки, которые требуют заполнения причин. Пользователь заполняет причины для всех строк разом в одном окне и нажимает «ОК».
  6. Данные записываются в регистр, после чего документ успешно сохраняется. Если пользователь закрыл форму без сохранения — устанавливается параметр Отказ = Истина.

Проанализируем пример реализации данного подхода в модуле формы документа:


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

Плюсы: Идеальный UX. Пользователь вводит данные массово и не отвлекается на постоянные модальные окна при редактировании каждой отдельной строки.

---

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

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

Алгоритм работы:

  1. В событии табличного поля ПередНачаломДобавления мы прописываем Отказ = Истина. Это отменит стандартное создание пустой строки.
  2. Сразу после этого открываем свою кастомную вспомогательную форму ввода.
  3. В этой форме пользователь выбирает номенклатуру, указывает количество (было/стало) и сразу пишет причину.
  4. При нажатии «ОК» в вашей форме:
    • Происходит запись в регистр сведений.
    • Данные возвращаются в основную форму документа.
    • В табличную часть документа программно добавляется строка через метод Добавить() и заполняется возвращенными значениями.

Давайте посмотрим на пример кода для обработчика события табличного поля:


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

Плюсы: В документе никогда не появится «мусорных» незаполненных строк, по которым забыли указать причину. Всё строго контролируется в момент создания.

---

Решение 3. Точечная реакция через событие «ПриИзменении» конкретных колонок

Если вы хотите оставить ввод в самой табличной части, но реагировать точечно, используйте событие ПриИзменении не для всей таблицы, а для конкретного элемента управления в колонке (например, у поля ввода колонки «Количество» или «Номенклатура»).

Алгоритм работы:

  1. Когда пользователь заполняет или меняет колонку «Количество», срабатывает событие ПриИзменении этого элемента управления.
  2. В обработчике проверяется, новая ли это строка (например, по отсутствию связи с регистром или через скрытый реквизит ТЧ ЭтоНоваяСтрока).
  3. Если строка новая или измененная и ключевые данные заполнены, открывается форма ввода причины.

Посмотрим на пример кода:


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

Плюсы: Форма открывается ровно в тот момент, когда введены ключевые данные (количество), а не когда пользователь решил переключить фокус на другую строку (как это происходит в ПриОкончанииРедактирования).

---

Решение 4. Использование стандартного режима редактирования в диалоге

Мало кто помнит, но в обычных формах 1С у элемента управления ТабличноеПоле есть встроенное свойство РежимРедактирования. По умолчанию оно установлено в значение «В списке».

Если переключить его в значение «В списке и диалоге» или «В диалоге»:

  1. При попытке добавить новую строку (или отредактировать старую) платформа автоматически не будет давать вводить данные прямо в строке табличной части.
  2. Вместо этого откроется отдельное окно (которое настраивается в свойствах табличного поля как «Форма редактирования строки»).
  3. В этой форме вы сможете удобно расположить все необходимые поля (включая причину изменения, количество "было/стало", выбор номенклатуры) и прописать логику записи в регистр при нажатии кнопки сохранения этой строки.

Плюсы: Использование штатного функционала платформы без сложных программных обходов и перехвата событий.

---

Резюме

Мы рассмотрели четыре отличных способа решения проблемы ввода новой строки на обычных формах 1С. Выбор конкретного варианта зависит от ваших требований к интерфейсу:

← На главную