Как добавить нетиповую табличную часть в справочник и избежать конфликта данных при записи?

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

При доработке типовых конфигураций на базе БСП (Библиотека стандартных подсистем) программисты часто сталкиваются с задачей расширения функционала стандартных справочников (например, «Номенклатура» или «Контрагенты»). Популярный сценарий: добавить новую табличную часть и дать пользователю возможность её заполнять. Однако попытка реализовать это через отдельную форму часто приводит к ошибке "Данные были изменены или удалены другим пользователем". Рассмотрим, почему это происходит и как правильно реализовать задачу несколькими способами.

Почему возникает ошибка конфликта данных?

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

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

Способ 1. Программное добавление элементов на типовую форму

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

Для реализации этого метода воспользуемся механизмом расширений. Проанализируем шаги:

  1. Создаем расширение и добавляем в него нужный справочник и его новую табличную часть.
  2. В расширении создаем модуль для формы элемента справочника.
  3. Используем обработчик события ПриСозданииНаСервере с аннотацией &После.

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


&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    // Создаем элемент формы - Таблица
    НоваяТаблица = Элементы.Добавить("МояНетиповаяТЧ", Тип("ТаблицаФормы"), ЭтаФорма);
    НоваяТаблица.ПутьКДанным = "Объект.МояНетиповаяТЧ";
    
    // Добавляем колонки в таблицу
    НоваяКолонка = Элементы.Добавить("МояТЧ_Номенклатура", Тип("ПолеФормы"), НоваяТаблица);
    НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
    НоваяКолонка.ПутьКДанным = "Объект.МояНетиповаяТЧ.Номенклатура";
    
    НоваяКолонкаЦена = Элементы.Добавить("МояТЧ_Цена", Тип("ПолеФормы"), НоваяТаблица);
    НоваяКолонкаЦена.Вид = ВидПоляФормы.ПолеВвода;
    НоваяКолонкаЦена.ПутьКДанным = "Объект.МояНетиповаяТЧ.Цена";
    
КонецПроцедуры

Преимущества: Данные редактируются в рамках одного контекста формы. Объект один, версия одна, конфликтов при записи не возникнет.

Способ 2. Использование механизма оповещений и обновления формы

Если по каким-то причинам (например, слишком громоздкий интерфейс) вам необходимо использовать именно отдельную форму для редактирования табличной части, нужно научить основную форму «узнавать» об изменениях. Выясним, как это сделать правильно.

В вашей дополнительной форме после записи объекта необходимо вызвать процедуру оповещения. Посмотрим на пример кода в модуле вашей нетиповой формы:


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    // Оповещаем систему о том, что объект изменен
    Оповестить("ИзмененыДанныеНоменклатуры", ПараметрыЗаписи, Объект.Ссылка);
КонецПроцедуры

Теперь самое важное: в основной (типовой) форме нужно перехватить это событие. Так как мы не хотим менять типовой код, мы снова используем расширение для формы элемента и добавляем обработчик ОбработкаОповещения.


&НаКлиенте
Процедура Расш1_ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ИзмененыДанныеНоменклатуры" И Источник = Объект.Ref Тогда
        // Метод Прочитать() обновляет данные объекта в форме напрямую из БД
        ЭтаФорма.Прочитать(); 
    КонецЕсли;
КонецПроцедуры

Метод Прочитать() — ключевой момент. Он перечитывает данные из базы, обновляет версию объекта в памяти текущей формы и актуализирует все реквизиты. Теперь при нажатии «Записать» в основной форме ошибки не будет.

Способ 3. Программное создание команд (кнопок) без изменения формы

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

Если мы хотим добавить кнопку «Открыть мою форму» программно через расширение, сделаем это следующим образом:


&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    // 1. Создаем команду
    ИмяКоманды = "КомандаОткрытьМоюТЧ";
    МояКоманда = ЭтаФорма.Команды.Добавить(ИмяКоманды);
    МояКоманда.Действие = "ПодключеннаяКоманда_ОткрытьМоюТЧ"; // Процедура должна быть в модуле формы
    МояКоманда.Заголовок = "Редактировать спец. данные";
    
    // 2. Добавляем кнопку на командную панель
    НоваяКнопка = Элементы.Добавить("КнопкаОткрытьМоюТЧ", Тип("КнопкаФормы"), Элементы.ФормаКоманднаяПанель);
    НоваяКнопка.ИмяКоманды = ИмяКоманды;
    
КонецПроцедуры

&НаКлиенте
Процедура ПодключеннаяКоманда_ОткрытьМоюТЧ(Команда)
    ПараметрыФормы = Новый Структура("Ключ", Объект.Ссылка);
    ОткрытьФорму("Справочник.Номенклатура.Форма.МояНетиповаяФорма", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры

Обратите внимание на третий параметр в ОткрытьФорму — ЭтаФорма. Указывая владельца, мы связываем формы и упрощаем системе работу с оповещениями.

Рекомендации по использованию БСП

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

Резюмируем:

  1. Если нужно просто добавить поля — используйте программное добавление элементов в расширении (Способ 1). Это исключит любые конфликты версий.
  2. Если нужна отдельная форма — обязательно вызывайте ЭтаФорма.Прочитать() в основной форме через ОбработкаОповещения (Способ 2).
  3. Для добавления кнопок используйте расширение формы и помните, что обработчик команды обязан находиться в модуле формы.

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

← На главную