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

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

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

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

Почему нельзя редактировать поле «через точку»?

Разберем ситуацию: вы установили ПутьКДанным для колонки как Объект.Товары.Номенклатура.ВидНоменклатуры. Платформа отобразит значение, но поле будет доступно только для чтения. Это происходит потому, что 1С не может однозначно интерпретировать действие пользователя при попытке изменить это поле. Должна ли программа изменить ВидНоменклатуры у существующего элемента справочника Номенклатура (что повлияет на все документы в базе) или же она должна найти другую номенклатуру с этим видом? Чтобы избежать неявных изменений в базе данных, такие поля блокируются на уровне ядра платформы.

Решение 1: Использование нехранимого реквизита табличной части

Для реализации редактирования нам необходимо создать «промежуточный» реквизит. Рассмотрим этот способ подробнее. Проанализируем алгоритм действий:

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

Шаг 1. Заполнение при открытии формы

Выясним, почему данные могут «обнуляться». В управляемом приложении данные формы и объект БД — это разные сущности. Чтобы колонка заполнилась при открытии, необходимо использовать обработчик ПриЧтенииНаСервере. Посмотрим на пример кода:


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

Важный нюанс: Обращение в цикле «через точку» (СтрокаТЧ.Номенклатура.ВидНоменклатуры) порождает отдельный запрос к базе на каждой итерации. Если в документе сотни строк, это замедлит работу. Рекомендуется использовать запрос для получения всех видов номенклатуры одним пакетом.

Шаг 2. Сохранение данных после записи

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


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    // Повторно заполняем реквизиты формы, так как после записи данные обновились
    ЗаполнитьВидыНоменклатурыНаСервере();
КонецПроцедуры

Шаг 3. Логика редактирования

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

В свойствах поля Номенклатура найдем пункт Связи параметров выбора и добавим новую связь:

Проанализируем результат: теперь при нажатии на кнопку выбора в колонке Номенклатура, система автоматически применит фильтр по тому виду, который пользователь указал в нашей редактируемой «виртуальной» колонке.

Альтернативный подход: Оптимизация через запрос

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


&НаСервере
Процедура ЗаполнитьВидыНоменклатурыНаСервере()
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Товары.НомерСтроки КАК НомерСтроки,
        |   Товары.Номенклатура.ВидНоменклатуры КАК Вид
        |ИЗ
        |   Документ.НашДокумент.Товары КАК Товары
        |ГДЕ
        |   Товары.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
    Результат = Запрос.Выполнить().Выгрузить();
    
    Для Каждого СтрокаДанных Из Результат Цикл
        Объект.Товары[СтрокаДанных.НомерСтроки - 1].ВидНоменклатуры = СтрокаДанных.Вид;
    КонецЦикла;
    
КонецПроцедуры

Резюме

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

  1. Создаем физический или форменный реквизит в структуре таблицы.
  2. Обеспечиваем его наполнение в событии ПриЧтенииНаСервере (для открытия существующих документов).
  3. Синхронизируем данные в ПослеЗаписиНаСервере, чтобы избежать их потери при возврате управления от сервера к клиенту.
  4. Используем событие ПриИзменении на клиенте для оперативной логики (например, очистки номенклатуры при смене вида).

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

← На главную