В процессе доработки конфигураций 1С с помощью механизма расширений разработчики часто сталкиваются с неочевидной на первый взгляд проблемой. Вы добавляете новый реквизит и выводите его на управляемую форму, но при открытии формы пользователем этого реквизита нет. Он появляется только после того, как пользователь вручную сбрасывает настройки формы к стандартным. Однако при следующем входе проблема повторяется. Давайте разберемся, почему так происходит и как этого избежать.
Проанализируем ситуацию: мы имеем дело не с ошибкой в коде и не с проблемами кэша, а с фундаментальной особенностью работы платформы 1С:Предприятие, связанной с сохранением пользовательских настроек.
Чтобы понять корень проблемы, рассмотрим, как платформа работает с формами. Когда пользователь впервые открывает какую-либо форму и как-то взаимодействует с ней (например, меняет ширину колонок, перемещает элементы), платформа сохраняет текущее состояние этой формы в базе данных. Эти настройки привязаны к конкретному пользователю и конкретной форме.
Что происходит, когда мы добавляем расширение с новым элементом на уже существующую форму?
Когда мы нажимаем кнопку "Еще" -> "Изменить форму" -> "Еще" -> "Установить стандартные настройки", мы фактически удаляем сохраненные пользовательские настройки для данной формы. В этот момент платформа вынуждена заново строить форму на основе ее текущей структуры в метаданных, которая уже включает изменения из нашего расширения. Именно поэтому новый реквизит появляется.
Важный момент: эта проблема не связана с кэшем конфигурации, который хранится в файлах на компьютере пользователя (например, в папке C:\Users\ИмяПользователя\AppData\Local\1C\1cv8). Очистка этих папок не поможет, так как настройки формы хранятся непосредственно в таблицах информационной базы, а не в локальных файлах. Поэтому совет "почистить кэш", хоть и является универсальным первым шагом при многих проблемах, в данном случае оказывается неэффективным.
Самым надежным и правильным способом гарантировать отображение элементов из расширения является их программное создание. Вместо того чтобы перетаскивать реквизит на форму в конфигураторе, мы напишем код, который будет добавлять нужный элемент при каждом открытии формы. Этот код размещается в модуле расширяемой формы в процедуре-обработчике события ПриСозданииНаСервере.
Этот подход имеет ключевое преимущество: код исполняется каждый раз при формировании формы на сервере, до того, как к ней будут применены сохраненные пользовательские настройки. Таким образом, наш элемент будет добавлен в структуру формы гарантированно.
Рассмотрим по шагам, как это сделать:
ПриСозданииНаСервере с помощью директивы &НаСервере и &После (чтобы наш код выполнился после основного кода формы).Посмотрим на пример. Допустим, мы добавили в расширении реквизит МойНовыйРеквизит в объект (например, в документ "РеализацияТоваровУслуг") и хотим вывести его на форму документа.
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расширение_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверим, существует ли уже такой элемент, чтобы не дублировать
// при возможных повторных вызовах или других доработках.
Если ЭтаФорма.Элементы.Найти("МойНовыйРеквизитПоле") = Неопределено Тогда
// Создаем новый элемент формы типа "ПолеФормы"
НовыйЭлемент = ЭтаФорма.Элементы.Добавить("МойНовыйРеквизитПоле", Тип("ПолеФормы"), ЭтаФорма.Элементы.Товары);
// Связываем элемент с данными (с нашим новым реквизитом объекта)
НовыйЭлемент.ПутьКДанным = "Объект.МойНовыйРеквизит";
// Настраиваем внешний вид
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.Заголовок = "Мой дополнительный реквизит:";
КонецЕсли;
КонецПроцедуры
Разберем код подробнее:
ЭтаФорма.Элементы.Добавить(Имя, Тип, Родитель): это основной метод, который создает новый элемент управления.
"МойНовыйРеквизитПоле" – уникальное имя нового элемента на форме.Тип("ПолеФормы") – тип создаваемого элемента.ЭтаФорма.Элементы.Товары – родительская группа, куда будет помещен наш элемент. Нужно указать имя существующей на форме группы (в данном примере — таблица "Товары").НовыйЭлемент.ПутьКДанным = "Объект.МойНовыйРеквизит": самая важная строка. Она связывает визуальный элемент на форме с реквизитом данных (Объект – это основной реквизит формы).Такой подход полностью решает исходную проблему и является лучшей практикой при модификации форм через расширения.
Существует и другой, более "грубый" способ — программно очистить сохраненные настройки формы для пользователей. Этот метод не рекомендуется для постоянного использования, так как он лишает пользователей их персональных настроек интерфейса (ширины колонок, отборов, сортировок), что может вызвать недовольство.
Однако он может быть полезен как разовая административная мера после установки крупного обновления, затрагивающего интерфейс.
Для этого можно использовать объект ХранилищеОбщихНастроек или ХранилищеНастроекПользователя. Например, можно создать обработку, которая выполнит следующий код для нужных пользователей:
// Ключ формы обычно имеет вид /Форма/ИмяОбъектаМетаданных.ИмяФормы
КлючНастроек = "/Форма/Документ.РеализацияТоваровУслуг.ФормаДокумента";
// Получаем массив пользователей
МассивПользователей = ПользователиИнформационнойБазы.ПолучитьПользователей();
Для Каждого Пользователь Из МассивПользователей Цикл
// Удаляем настройку для конкретного пользователя
ХранилищеОбщихНастроек.Удалить(КлючНастроек, "", Пользователь.Имя);
КонецЦикла;
Повторимся: используйте этот метод с осторожностью, понимая, что он приведет к сбросу всех пользовательских кастомизаций для указанной формы.
В итоге, проанализировав ситуацию, мы приходим к выводу, что "пропадание" реквизитов из расширений — это не баг, а следствие архитектуры платформы. Лучшее решение — не бороться с этим механизмом, а работать в его рамках, используя программное добавление элементов для обеспечения их гарантированного отображения.