При разработке на платформе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда стандартная процедура ЗаполнитьЗначенияСвойств() ведет себя не так, как ожидается. Типичный сценарий: мы пытаемся скопировать данные из одной таблицы значений в другую, поля называются одинаково, данные в источнике есть, но после выполнения кода колонка Ссылка в новой строке остается пустой (содержит Неопределено). Давайте подробно разберем, почему это происходит, как работает механизм типизации в 1С и какими способами можно решить эту задачу.
Проблема кроется не в самой процедуре ЗаполнитьЗначенияСвойств(), а в устройстве объекта ТаблицаЗначений и системы типов платформы. Когда мы создаем колонку в таблице значений и явно указываем ей тип, платформа начинает строго следить за тем, чтобы в эту ячейку не попали данные другого типа. Если в колонку, предназначенную для хранения ссылок на документ «Расходный кассовый ордер», попытаться записать ссылку на документ «Списание с расчетного счета», платформа просто проигнорирует это действие или запишет пустое значение, так как типы несовместимы.
Рассмотрим ситуацию на примере кода, предоставленного автором вопроса:
Для Каждого СтрокаИсходнойТаблицы1 Из ТаблицаРезультатовРасходОрдер Цикл
НоваяСтрока5 = ТаблицаРезультатовРасход.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока5, СтрокаИсходнойТаблицы1);
КонецЦикла;
Если в ТаблицаРезультатовРасход колонка Ссылка была создана с типом ДокументСсылка.РасходныйКассовыйОрдер, а в СтрокаИсходнойТаблицы1.Ссылка лежит другой вид документа, копирования не произойдет. Причем даже прямое присваивание НоваяСтрока5.Ссылка = СтрокаИсходнойТаблицы1.Ссылка; в этом случае не поможет — значение все равно останется пустым.
Проанализируем, как автор создавал таблицу значений:
ТаблицаРезультатовРасход = Новый ТаблицаЗначений();
// ... другие колонки ...
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ДокументСсылка"));
На первый взгляд кажется, что ОписаниеТипов("ДокументСсылка") — это универсальный тип для всех документов. Однако в системе 1С такого базового типа для хранения «любого документа» через строку конструктора не существует в том виде, как мы привыкли. Чтобы колонка принимала ссылки разных видов документов, нужно использовать специальные методы или перечислять типы явно.
Для того чтобы колонка таблицы значений могла принимать абсолютно любую ссылку на документ, существующий в конфигурации, нам необходимо правильно инициализировать ОписаниеТипов. Рассмотрим, как это сделать грамотно. Вместо того чтобы пытаться угадать строку типа, мы можем обратиться к метаданным.
Вариант А: Разрешить все документы
Воспользуемся методом ТипВсеСсылки() менеджера документов. Это создаст описание типов, включающее все возможные ссылки на документы в вашей базе:
ОписаниеВсехДокументов = Документы.ТипВсеСсылки();
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", ОписаниеВсехДокументов);
Вариант Б: Разрешить все справочники
Аналогично можно поступить и со справочниками, если ваша задача требует хранения ссылок на различные справочники в одной колонке:
ОписаниеВсехСправочников = Справочники.ТипВсеСсылки();
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", ОписаниеВсехСправочников);
Часто нам не нужно разрешать «вообще все» документы, а требуется объединить лишь несколько конкретных видов. В этом случае мы создаем составной тип данных. Рассмотрим пример, где в колонку можно записывать и «Поступление товаров», и «Реализацию товаров»:
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ДокументСсылка.ПоступлениеТоваровУслуг"));
МассивТипов.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));
ОписаниеСоставногоТипа = Новый ОписаниеТипов(МассивТипов);
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка", ОписаниеСоставногоТипа);
Теперь процедура ЗаполнитьЗначенияСвойств() без труда определит соответствие типов и заполнит поле, если в источнике находится один из указанных видов документов.
Если таблица значений используется как временный контейнер и вам не важна строгая типизация (например, вы не планируете выводить эту таблицу напрямую в список на форме с автоматическим подбором типов), можно добавить колонку вообще без указания типа. В 1С это означает, что колонка будет иметь тип Произвольный (фактически может хранить любое значение).
Посмотрим на этот простой способ:
// Добавляем колонку без второго параметра
ТаблицаРезультатовРасход.Колонки.Добавить("Ссылка");
В такую колонку можно будет записать и ссылку на документ, и строку, и число, и даже другую таблицу значений. Это самый гибкий вариант, который мгновенно решает проблему с ЗаполнитьЗначенияСвойств().
Выясним еще одну важную деталь. Если ваша таблица-источник получена в результате выполнения запроса (методом РезультатЗапроса.Выгрузить()), то типы ее колонок определяются автоматически на основе выборки. Если в запросе выбиралось только Документ.РасходныйКассовыйОрдер, то и колонка будет иметь только этот тип.
При объединении данных из разных запросов в одну таблицу, убедитесь, что целевая таблица создана с учетом всех возможных типов. Проанализируем пример совмещения двух таблиц с разными типами ссылок:
// Создаем общую таблицу с универсальным типом ссылки
ОбщаяТаблица = Новый ТаблицаЗначений;
ОбщаяТаблица.Колонки.Добавить("Ссылка", Документы.ТипВсеСсылки());
ОбщаяТаблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
// Заполняем из первой таблицы (например, РКО)
Для Каждого Стр Из ТЗ_РКО Цикл
ЗаполнитьЗначенияСвойств(ОбщаяТаблица.Добавить(), Стр);
КонецЦикла;
// Заполняем из второй таблицы (например, СписаниеБезналичных)
Для Каждого Стр Из ТЗ_Безнал Цикл
ЗаполнитьЗначенияСвойств(ОбщаяТаблица.Добавить(), Стр);
КонецЦикла;
Помимо типизации, стоит помнить о нескольких правилах работы этой процедуры, которые могут повлиять на результат:
Ссылка и ДокументСсылка) приведут к тому, что поле будет пропущено.ДокументОбъект, то поле Ссылка у объекта доступно только для чтения, и оно никогда не заполнится таким способом. Однако для строк таблицы значений это ограничение не действует.ЗаполнитьЗначенияСвойств(Приемник, Источник, "Дата, Номер, Ссылка"). Если вы указали список копируемых свойств явно, но забыли включить туда Ссылка, она не заполнится.Если у вас не заполняется поле Ссылка при копировании строк:
Документы.ТипВсеСсылки() для создания универсальной колонки под любые документы.Колонки.Добавить("Ссылка").Null (что часто бывает при левых соединениях в запросах).Использование этих простых правил сделает вашу работу с таблицами значений в 1С более предсказуемой и эффективной, а код — более устойчивым к изменениям в структуре метаданных.