Почему не заполняется Ссылка при использовании процедуры ЗаполнитьЗначенияСвойств?

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

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

В чем суть проблемы?

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

Рассмотрим ситуацию на примере кода, предоставленного автором вопроса:


Для Каждого СтрокаИсходнойТаблицы1 Из ТаблицаРезультатовРасходОрдер Цикл
    НоваяСтрока5 = ТаблицаРезультатовРасход.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока5, СтрокаИсходнойТаблицы1);
КонецЦикла;

Если в ТаблицаРезультатовРасход колонка Ссылка была создана с типом ДокументСсылка.РасходныйКассовыйОрдер, а в СтрокаИсходнойТаблицы1.Ссылка лежит другой вид документа, копирования не произойдет. Причем даже прямое присваивание НоваяСтрока5.Ссылка = СтрокаИсходнойТаблицы1.Ссылка; в этом случае не поможет — значение все равно останется пустым.

Причина 1: Жесткая типизация колонок

Проанализируем, как автор создавал таблицу значений:


ТаблицаРезультатовРасход = Новый ТаблицаЗначений();
// ... другие колонки ...
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ДокументСсылка"));

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

Решение 1: Использование универсальных ссылочных типов

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

Вариант А: Разрешить все документы

Воспользуемся методом ТипВсеСсылки() менеджера документов. Это создаст описание типов, включающее все возможные ссылки на документы в вашей базе:


ОписаниеВсехДокументов = Документы.ТипВсеСсылки();
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", ОписаниеВсехДокументов);

Вариант Б: Разрешить все справочники

Аналогично можно поступить и со справочниками, если ваша задача требует хранения ссылок на различные справочники в одной колонке:


ОписаниеВсехСправочников = Справочники.ТипВсеСсылки();
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", ОписаниеВсехСправочников);

Решение 2: Составной тип данных

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


МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ДокументСсылка.ПоступлениеТоваровУслуг"));
МассивТипов.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));

ОписаниеСоставногоТипа = Новый ОписаниеТипов(МассивТипов);
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", ОписаниеСоставногоТипа);

Теперь процедура ЗаполнитьЗначенияСвойств() без труда определит соответствие типов и заполнит поле, если в источнике находится один из указанных видов документов.

Решение 3: Отказ от типизации (тип «Любая ссылка»)

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

Посмотрим на этот простой способ:


// Добавляем колонку без второго параметра
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка"); 

В такую колонку можно будет записать и ссылку на документ, и строку, и число, и даже другую таблицу значений. Это самый гибкий вариант, который мгновенно решает проблему с ЗаполнитьЗначенияСвойств().

Решение 4: Типизация через запрос

Выясним еще одну важную деталь. Если ваша таблица-источник получена в результате выполнения запроса (методом РезультатЗапроса.Выгрузить()), то типы ее колонок определяются автоматически на основе выборки. Если в запросе выбиралось только Документ.РасходныйКассовыйОрдер, то и колонка будет иметь только этот тип.

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


// Создаем общую таблицу с универсальным типом ссылки
ОбщаяТаблица = Новый ТаблицаЗначений;
ОбщаяТаблица.Колонки.Добавить("Ссылка", Документы.ТипВсеСсылки());
ОбщаяТаблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));

// Заполняем из первой таблицы (например, РКО)
Для Каждого Стр Из ТЗ_РКО Цикл
    ЗаполнитьЗначенияСвойств(ОбщаяТаблица.Добавить(), Стр);
КонецЦикла;

// Заполняем из второй таблицы (например, СписаниеБезналичных)
Для Каждого Стр Из ТЗ_Безнал Цикл
    ЗаполнитьЗначенияСвойств(ОбщаяТаблица.Добавить(), Стр);
КонецЦикла;

Важные нюансы работы ЗаполнитьЗначенияСвойств()

Помимо типизации, стоит помнить о нескольких правилах работы этой процедуры, которые могут повлиять на результат:

  1. Совпадение имен: Поля в источнике и приемнике должны называться идентично. Регистр букв обычно не важен, но наличие лишних пробелов или отличия в именовании (например, Ссылка и ДокументСсылка) приведут к тому, что поле будет пропущено.
  2. Доступность для записи: Процедура копирует только те свойства, которые доступны для записи. Если вы используете её для копирования данных в ДокументОбъект, то поле Ссылка у объекта доступно только для чтения, и оно никогда не заполнится таким способом. Однако для строк таблицы значений это ограничение не действует.
  3. Использование фильтров: Помните, что у процедуры есть дополнительные параметры. Например, ЗаполнитьЗначенияСвойств(Приемник, Источник, "Дата, Номер, Ссылка"). Если вы указали список копируемых свойств явно, но забыли включить туда Ссылка, она не заполнится.

Подведем итоги

Если у вас не заполняется поле Ссылка при копировании строк:

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

← На главную