При разработке и модификации конфигураций 1С:Предприятия, особенно при использовании расширений, мы часто сталкиваемся с необходимостью добавления новых реквизитов в существующие документы и их табличные части. Однако, иногда при попытке установить путь к данным для нового элемента формы, который должен отображать наш реквизит, мы можем получить ошибку «Ошибка при установке значения атрибута контекста (ПутьКДанным): Недопустимое значение».
Давайте разберем типичную ситуацию, которая приводит к этой ошибке, и предложим подробное решение, если на форме вместо прямой табличной части документа используется элемент «ТаблицаЗначений».
Наш читатель столкнулся с задачей добавить новый реквизит в табличную часть документа «РаботаВВыходныеИПраздничныеДни» конфигурации «Зарплата и управление персоналом КОРП» с помощью расширения. Он следовал стандартной методике:
ав_ПричинаПривлечения типа Строка.ПриСозданииНаСервере формы документа попытался динамически добавить элемент формы и привязать его к новому реквизиту.Пример кода, который использовал разработчик:
&После("ПриСозданииНаСервере")
Процедура ав_ПриСозданииНаСервере(Форма, ДополнительныеПараметры)
Если Форма.ИмяФормы = "Документ.РаботаВВыходныеИПраздничныеДни.Форма.ФормаДокумента" Тогда
ИмяЭлемента = "ав_ПричинаПривлечения";
Если Форма.Элементы.Найти(ИмяЭлемента) = Неопределено Тогда
ЭлементФормы = Форма.Элементы.Вставить("ав_ПричинаПривлечения", Тип("ПолеФормы"), Форма.Элементы.Сотрудники);
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ПутьКДанным = "ав_ПричинаПривлечения"; // Здесь возникла ошибка
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Ошибка «Недопустимое значение» при установке атрибута контекста ПутьКДанным часто указывает на то, что указанный путь не соответствует существующему реквизиту формы, объекта или колонке в табличном поле.
Изначально, разработчик предполагал, что элемент формы «Сотрудники» напрямую связан с табличной частью документа «Сотрудники». В таком случае корректным путем к данным для нового реквизита был бы Объект.Сотрудники.ав_ПричинаПривлечения. Однако даже после такой корректировки ошибка сохранялась.
Ключевой момент, выясненный в ходе обсуждения, заключается в следующем: элемент на форме, который выглядит как табличная часть документа, на самом деле оказался элементом формы типа «ТаблицаЗначений» (ТЗ). «ТаблицаЗначений» – это временный объект, существующий только в памяти формы и не связанный напрямую со структурой данных объекта базы данных. Если форма оперирует «ТаблицейЗначений» для отображения данных, то изменения в структуре табличной части объекта документа через расширение не будут автоматически отражаться на форме, поскольку форма работает с собственной, независимой структурой данных.
Прежде чем перейти к решению для «ТаблицыЗначений», давайте зафиксируем общие правила для установки ПутьКДанным, которые могли бы помочь, если бы на форме действительно была выведена табличная часть объекта:
ЭлементФормы.ПутьКДанным = "ИмяРеквизитаФормы";ЭлементФормы.ПутьКДанным = "Объект.ИмяРеквизитаОбъекта";ЭлементФормы.ПутьКДанным = "Объект.ИмяТабличнойЧастиОбъекта.ИмяРеквизитаКолонки"; (например, Объект.Сотрудники.ав_ПричинаПривлечения).В нашем случае, проблема не в ошибке синтаксиса пути, а в том, что сам объект, к которому мы пытаемся привязаться, на форме представлен иначе.
Если мы выяснили, что на форме отображается «ТаблицаЗначений», а не прямая табличная часть документа, то подход к добавлению новой колонки кардинально меняется. Мы не можем просто добавить реквизит в табличную часть объекта и ожидать, что он появится в «ТаблицеЗначений» на форме. Нам необходимо:
Разберем это по шагам с примерами кода, которые можно разместить в обработчике ПриСозданииНаСервере или в аналогичной процедуре, вызываемой из него:
Сначала нам нужно получить ссылку на сам объект «ТаблицаЗначений», который является реквизитом формы и связан с табличным полем «Сотрудники».
// В обработчике ПриСозданииНаСервере формы
Если Форма.ИмяФормы = "Документ.РаботаВВыходныеИПраздничныеДни.Форма.ФормаДокумента" Тогда
// Имя элемента формы, который отображает ТаблицуЗначений
ИмяЭлементаТабличноеПоле = "Сотрудники";
Если Форма.Элементы.Найти(ИмяЭлементаТабличноеПоле) <> Неопределено Тогда
// Получаем путь к данным ТабличногоПоля. Он должен указывать на реквизит формы типа ТаблицаЗначений.
ПеременнаяПутьКДаннымТЗ = Форма.Элементы[ИмяЭлементаТабличноеПоле].ПутьКДанным;
Если ЗначениеЗаполнено(ПеременнаяПутьКДаннымТЗ) Тогда
// Получаем саму ТаблицуЗначений как значение реквизита формы
РеквизитФормыТЗ = Форма.РеквизитыФормы.Найти(ПеременнаяПутьКДаннымТЗ);
Если РеквизитФормыТЗ <> Неопределено Тогда
ТаблицаСотрудники = РеквизитФормыТЗ.Значение;
КонецЕсли;
КонецЕсли;
КонецЕсли;
// ...далее код для добавления колонки и элемента формы...
КонецЕсли;
Обратите внимание: мы сначала получаем имя реквизита формы, к которому привязано табличное поле, а затем уже сам объект «ТаблицаЗначений» через этот реквизит.
Используем коллекцию Колонки объекта «ТаблицаЗначений» и метод Добавить() для добавления новой колонки. Важно указать имя колонки и её тип.
// Продолжение кода из Шага 1
Если ТаблицаСотрудники <> Неопределено И ТипЗнч(ТаблицаСотрудники) = Тип("ТаблицаЗначений") Тогда
Если ТаблицаСотрудники.Колонки.Найти("ав_ПричинаПривлечения") = Неопределено Тогда
// Добавляем колонку в ТаблицуЗначений
// Укажите подходящий тип данных, например, "Строка", "Число", "Дата", "Булево"
ТаблицаСотрудники.Колонки.Добавить("ав_ПричинаПривлечения", Новый ОписаниеТипов("Строка", , , Новый КвалификаторыСтроки(250)));
КонецЕсли;
// ...далее код для добавления элемента формы...
КонецЕсли;
Здесь мы добавляем колонку с именем ав_ПричинаПривлечения и типом Строка с длиной 250 символов. Если колонка уже существует, мы её не добавляем повторно.
Теперь, когда колонка добавлена в «ТаблицуЗначений», мы можем добавить элемент формы типа ПолеФормы, который будет отображать данные этой колонки. Важно, чтобы ПутьКДанным указывал на колонку нашей «ТаблицыЗначений» в формате ИмяРеквизитаФормыТаблицаЗначений.ИмяКолонки.
// Продолжение кода из Шага 2
Если ТаблицаСотрудники <> Неопределено И ТипЗнч(ТаблицаСотрудники) = Тип("ТаблицаЗначений") Тогда
// ... код добавления колонки ...
// Добавляем элемент формы для отображения этой колонки
ИмяЭлементаКолонки = "ав_ПричинаПривлечения"; // Имя элемента формы для нашей новой колонки
Если Форма.Элементы.Найти(ИмяЭлементаКолонки) = Неопределено Тогда
ЭлементФормы = Форма.Элементы.Вставить(ИмяЭлементаКолонки, Тип("ПолеФормы"), Форма.Элементы[ИмяЭлементаТабличноеПоле]);
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
// ПутьКДанным теперь указывает на колонку ТаблицыЗначений на форме
ЭлементФормы.ПутьКДанным = ПеременнаяПутьКДаннымТЗ + "." + ИмяЭлементаКолонки;
// Например, "Сотрудники.ав_ПричинаПривлечения" если реквизит формы называется "Сотрудники"
КонецЕсли;
КонецЕсли;
Мы используем Форма.Элементы[ИмяЭлементаТабличноеПоле] в качестве родительского элемента, чтобы наша новая колонка появилась внутри табличного поля «Сотрудники».
Соберем все шаги в единый код, который разместим в общем модуле расширения, например, в обработчике ПриСозданииНаСервере:
&После("ПриСозданииНаСервере")
Процедура ав_ПриСозданииНаСервере(Форма, ДополнительныеПараметры)
Если Форма.ИмяФормы = "Документ.РаботаВВыходныеИПраздничныеДни.Форма.ФормаДокумента" Тогда
ИмяЭлементаТабличноеПоле = "Сотрудники"; // Имя табличного поля на форме, которое отображает ТЗ
ПеременнаяПутьКДаннымТЗ = ""; // Переменная для хранения пути к реквизиту формы типа ТаблицаЗначений
ТаблицаСотрудники = Неопределено; // Переменная для хранения самой ТаблицыЗначений
// Шаг 1: Доступ к ТаблицеЗначений на форме
Если Форма.Элементы.Найти(ИмяЭлементаТабличноеПоле) <> Неопределено Тогда
// Получаем путь к данным ТабличногоПоля
ПеременнаяПутьКДаннымТЗ = Форма.Элементы[ИмяЭлементаТабличноеПоле].ПутьКДанным;
Если ЗначениеЗаполнено(ПеременнаяПутьКДаннымТЗ) Тогда
// Получаем саму ТаблицуЗначений как значение реквизита формы
РеквизитФормыТЗ = Форма.РеквизитыФормы.Найти(ПеременнаяПутьКДаннымТЗ);
Если РеквизитФормыТЗ <> Неопределено Тогда
ТаблицаСотрудники = РеквизитФормыТЗ.Значение;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ТаблицаСотрудники <> Неопределено И ТипЗнч(ТаблицаСотрудники) = Тип("ТаблицаЗначений") Тогда
// Шаг 2: Добавление новой колонки в ТаблицуЗначений
ИмяНовойКолонки = "ав_ПричинаПривлечения";
Если ТаблицаСотрудники.Колонки.Найти(ИмяНовойКолонки) = Неопределено Тогда
// Добавляем колонку в ТаблицуЗначений
ТаблицаСотрудники.Колонки.Добавить(ИмяНовойКолонки, Новый ОписаниеТипов("Строка", , , Новый КвалификаторыСтроки(250)));
КонецЕсли;
// Шаг 3: Добавление элемента формы для отображения новой колонки
Если Форма.Элементы.Найти(ИмяНовойКолонки) = Неопределено Тогда
ЭлементФормы = Форма.Элементы.Вставить(ИмяНовойКолонки, Тип("ПолеФормы"), Форма.Элементы[ИмяЭлементаТабличноеПоле]);
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ПутьКДанным = ПеременнаяПутьКДаннымТЗ + "." + ИмяНовойКолонки;
ЭлементФормы.Заголовок = "Причина привлечения"; // Устанавливаем заголовок для новой колонки
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
После того как мы добавили колонку в «ТаблицуЗначений» на форме, критически важно понять, что данные в этой колонке не будут автоматически сохраняться в базе данных, поскольку «ТаблицаЗначений» – это временный объект. Нам потребуется реализовать дополнительную логику:
ПередЗаписьюНаСервере или ПриЗаписиНаСервере формы документа.Пример (концептуальный) логики для заполнения и сохранения:
// В обработчике ПриЧтенииНаСервере или ПриСозданииНаСервере формы
// (Для чтения данных из объекта в ТаблицуЗначений)
Процедура ав_ЗаполнитьПричинуПривлечения(Форма)
// Предположим, что мы добавили реквизит ав_ПричинаПривлечения
// в табличную часть "Сотрудники" объекта документа через расширение.
// А на форме у нас ТаблицаЗначений, привязанная к реквизиту формы "Сотрудники".
ПутьКДаннымТЗ = "Сотрудники"; // Имя реквизита формы типа ТаблицаЗначений
Если Форма.РеквизитыФормы.Найти(ПутьКДаннымТЗ) <> Неопределено Тогда
ТаблицаСотрудникиФормы = Форма.РеквизитыФормы[ПутьКДаннымТЗ].Значение;
Для Каждого СтрокаТЧОбъекта Из Форма.Объект.Сотрудники Цикл
// Находим соответствующую строку в ТаблицеЗначений формы (например, по уникальному идентификатору сотрудника)
// Здесь мы упрощаем, предполагая, что порядок строк совпадает,
// но в реальных условиях нужно использовать более надежный поиск.
СоответствующаяСтрокаФормы = ТаблицаСотрудникиФормы[СтрокаТЧОбъекта.Индекс];
Если СоответствующаяСтрокаФормы <> Неопределено Тогда
// Заполняем нашу новую колонку ТаблицыЗначений данными из реквизита объекта
СоответствующаяСтрокаФормы.ав_ПричинаПривлечения = СтрокаТЧОбъекта.ав_ПричинаПривлечения;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// В обработчике ПередЗаписьюНаСервере формы
// (Для сохранения данных из ТаблицыЗначений обратно в объект)
Процедура ав_СохранитьПричинуПривлечения(Форма)
ПутьКДаннымТЗ = "Сотрудники"; // Имя реквизита формы типа ТаблицаЗначений
Если Форма.РеквизитыФормы.Найти(ПутьКДаннымТЗ) <> Неопределено Тогда
ТаблицаСотрудникиФормы = Форма.РеквизитыФормы[ПутьКДаннымТЗ].Значение;
Для Каждого СтрокаФормыТЗ Из ТаблицаСотрудникиФормы Цикл
// Находим соответствующую строку в ТабличнойЧасти объекта
// Снова упрощаем поиск
СоответствующаяСтрокаОбъекта = Форма.Объект.Сотрудники[СтрокаФормыТЗ.Индекс];
Если СоответствующаяСтрокаОбъекта <> Неопределено Тогда
// Переносим данные из новой колонки ТаблицыЗначений в реквизит объекта
СоответствующаяСтрокаОбъекта.ав_ПричинаПривлечения = СтрокаФормыТЗ.ав_ПричинаПривлечения;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Эту логику необходимо тщательно продумать и реализовать, учитывая специфику заполнения табличной части в исходной конфигурации. Возможно, потребуется перехватывать или дополнять существующие процедуры заполнения табличного поля на форме.
Если задача заключается исключительно в добавлении дополнительных данных, а прямое изменение табличной части объекта и его отображение на форме через «ТаблицуЗначений» кажется слишком сложным или нежелательным, мы можем рассмотреть следующие подходы для хранения данных через расширение:
Выбор конкретного метода зависит от требований к данным, частоты их использования, необходимости поиска и отчетности, а также от сложности реализации. Если требуется избежать сложного ручного кодирования, можно применить готовое решение для добавления реквизитов в табличные части объектов непосредственно в режиме «1С:Предприятие».
Работая с расширениями и динамическим изменением форм, мы всегда должны помнить о следующих важных аспектах:
ПриСозданииНаСервере или аналогичных процедурах, а не «захватывать» всю форму в расширение. Это повышает совместимость с обновлениями основной конфигурации и уменьшает риски конфликтов.ПутьКДанным: Всегда тщательно проверяйте, чтобы ПутьКДанным точно указывал на существующий реквизит формы, реквизит объекта или колонку «ТаблицыЗначений». Некорректный путь – наиболее частая причина ошибки Недопустимое значение. Используйте отладчик для проверки наличия и типа реквизитов/колонок в момент выполнения.Следуя этим рекомендациям и детально разбираясь в механизмах работы 1С:Предприятия, мы сможем эффективно решать задачи по расширению функционала, минимизируя потенциальные проблемы.