Как решить проблему с отображением характеристик при программной загрузке в табличную часть 1С?

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

При разработке обработок импорта данных из внешних файлов (например, Excel или XML) в документы 1С программисты часто сталкиваются с неприятным поведением интерфейса управляемых форм. Данные успешно считываются, номенклатура и характеристики сопоставляются и записываются в документ, однако на форме документа ячейка «Характеристика» выглядит заблокированной или пустой. Пользователю выводится сообщение о том, что характеристики не используются, и только после двойного клика по строке или её перевыбора данные «проявляются» на форме.

В этой статье мы подробно разберем, почему возникает эта проблема на управляемых формах, как работает механизм визуализации характеристик в типовых конфигурациях (таких как УТ 11, ERP, КА 2, Розница) и как правильно реализовать программное заполнение табличной части, чтобы избежать этой ошибки.

Глубинная причина проблемы (Root Cause)

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

Один из таких ключевых служебных реквизитов — ХарактеристикиИспользуются (в зависимости от версии конфигурации он может называться ИспользоватьХарактеристики или ХарактеристикиИспользуютсяВСтроке) с типом Булево.

Этот реквизит управляет поведением ячейки «Характеристика» через механизм Условного оформления формы:

  1. Если в конкретной строке реквизит ХарактеристикиИспользуются равен значению Ложь, то условное оформление делает ячейку «Характеристика» недоступной для редактирования и выводит в неё серый текст-заглушку: <характеристики не используются>.
  2. Если значение реквизита равно Истина — ячейка открывается для редактирования и отображает выбранную характеристику в нормальном режиме.

При стандартном интерактивном вводе номенклатуры пользователем срабатывает клиентское событие ПриИзменении. Оно отправляет запрос на сервер, система проверяет настройки Вида номенклатуры для выбранной позиции и программно заполняет этот скрытый реквизит формы значением Истина или Ложь.

Когда мы выполняем программное заполнение табличной части через методы Объект.Товары.Загрузить() или напрямую заполняем её на сервере без интерактивных действий пользователя:

  1. Данные загружаются напрямую в объектную сущность.
  2. Интерактивные события формы (такие как ПриИзменении) не генерируются и не отрабатывают.
  3. Служебная колонка формы ХарактеристикиИспользуются для всех импортированных строк по умолчанию инициализируется значением Ложь.
  4. Визуально характеристики «пропадают» (блокируются условным оформлением), пока пользователь дважды не кликнет по строке, что принудительно заставляет форму обновить свойства этой строки и пересчитать её видимость.

Проанализируем детально, как решить эту задачу правильно, сохранив производительность системы.

Решение автора: почему оно сработало?

Автор темы нашел элегантное и быстрое решение проблемы непосредственно на стыке передачи данных из обработки в форму документа. На форме внешней обработки он создал реквизит (колонку в таблице значений) с именем ИспользоватьХарактеристики и типом данных Булево.

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

Поскольку на форме документа в коллекции Объект.Товары уже присутствовал точно такой же служебный реквизит формы, метод Загрузить() при копировании данных сопоставил имена колонок по принципу идентичности и автоматически перенес значения из загружаемой таблицы значений в реквизиты формы. Условное оформление мгновенно считало значение Истина и разблокировало ячейки без необходимости производить двойной клик.

Альтернативные и более профессиональные способы решения

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

Способ 1. Получение признака характеристик в едином запросе (Оптимальный по производительности)

Если импортируемый файл содержит сотни или тысячи строк, крайне не рекомендуется проверять признак использования характеристик для каждой номенклатуры по отдельности в цикле (например, обращаясь через точку к реквизитам ссылки Строка.Номенклатура.ВидНоменклатуры.ИспользоватьХарактеристики). Это приведет к лавинообразному росту запросов к базе данных (проблема N+1 запроса) и критическому замедлению работы системы.

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

Рассмотрим пример реализации такого запроса:


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

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ТаблицаТоваров.Номенклатура КАК Номенклатура
    |ПОМЕСТИТЬ ВТ_Товары
    |ИЗ
    |	&ТаблицаТоваров КАК ТаблицаТоваров
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	ВТ_Товары.Номенклатура КАК Номенклатура,
    |	ВЫБОР
    |		КОГДА Номенклатура.ИспользоватьХарактеристики ТОГДА ИСТИНА
    |		ИНАЧЕ ЛОЖЬ
    |	КОНЕЦ КАК ХарактеристикиИспользуются
    |ИЗ
    |	ВТ_Товары КАК ВТ_Товары
    |	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
    |		ПО ВТ_Товары.Номенклатура = Номенклатура.Ссылка";

// Примечание: В зависимости от конфигурации (ERP, УТ 11) признак может лежать 
// в самой Номенклатуре или в её Виде номенклатуры: Номенклатура.ВидНоменклатуры.ИспользоватьХарактеристики.

Запрос.УстановитьПараметр("ТаблицаТоваров", ТаблицаТоваров);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

// Быстро заполним признак в нашей исходной таблице через Соответствие
СоответствиеПризнаков = Новый Соответствие;
Для Каждого СтрокаПризнака Из РезультатЗапроса Цикл
    СоответствиеПризнаков.Вставить(СтрокаПризнака.Номенклатура, СтрокаПризнака.ХарактеристикиИспользуются);
КонецЦикла;

Для Каждого СтрокаТЗ Из ТаблицаТоваров Цикл
    НайденныйПризнак = СоответствиеПризнаков.Получить(СтрокаТЗ.Номенклатура);
    СтрокаТЗ.ХарактеристикиИспользуются = ?(НайденныйПризнак = Неопределено, Ложь, НайденныйПризнак);
КонецЦикла;

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

Способ 2. Вызов штатных процедур пересчета формы (Стандартный путь для ERP/УТ/КА)

В крупных типовых конфигурациях 1С ручное прописывание логики заполнения всех служебных колонок не всегда является лучшим решением. Дело в том, что помимо характеристик на форме присутствуют и другие скрытые реквизиты, завязанные на номенклатуру: ставки НДС, упаковки, склады, типы номенклатуры (товар, услуга, работа) и т.д.

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

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


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

КонецПроцедуры

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

Способ 3. Прямой обход коллекции на форме (для небольших документов)

Если объем загружаемых данных невелик (до 50-100 строк) и загрузка выполняется непосредственно в модуле формы документа без промежуточных сложных запросов, мы можем быстро обойти коллекцию строк программно сразу после вызова метода Загрузить.

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


&НаСервере
Процедура ЗагрузитьТабличнуюЧастьНаСервере(АдресХранилища)

    Объект.Товары.Загрузить(ПолучитьИзВременногоХранилища(АдресХранилища));
    
    // Быстро обходим загруженные строки и напрямую проставляем значение в реквизит формы
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        // Обратите внимание: прямое обращение через точку к реквизитам ссылки 
        // допустимо только при небольшом объеме данных!
        Если ЗначениеЗаполнено(СтрокаТЧ.Номенклатура) Тогда
            СтрокаТЧ.ХарактеристикиИспользуются = СтрокаТЧ.Номенклатура.ИспользоватьХарактеристики;
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Важное примечание: Чтобы избежать снижения производительности при таком подходе на больших файлах, рекомендуется заменить прямое обращение СтрокаТЧ.Номенклатура.ИспользоватьХарактеристики на предварительно подготовленное Соответствие или кэш на сервере, как это было показано в Способе 1.

Способ 4. Нюансы для отраслевых конфигураций (на примере решений от Рарус, таких как Альфа-Авто)

Если вы работаете в специализированных или отраслевых конфигурациях, логика управления характеристиками может существенно отличаться от стандартных библиотек 1С (БСП). Например, в решениях линейки «Альфа-Авто» на форме табличной части часто присутствует скрытый реквизит с именем ВладелецХарактеристики.

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

Решением в данном случае является обязательное программное заполнение этого скрытого реквизита при импорте:


// Пример заполнения для отраслевых конфигураций типа Альфа-Авто
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    СтрокаТЧ.ВладелецХарактеристики = СтрокаТЧ.Номенклатура;
КонецЦикла;

Резюме и рекомендации

Проанализировав проблему, мы можем сделать следующие выводы:

← На главную