При разработке внешних обработок для конфигурации «Управление торговлей 11» программисты часто сталкиваются со следующей проблемой: при заполнении табличной части документа из внешнего файла (например, Excel) численные и строковые реквизиты записываются без проблем, а ссылка на справочник в составной реквизит (например, Контрагент) не проставляется вовсе или сбрасывается сразу после выполнения кода.
В этой статье мы разберем причины такого поведения платформы 1С и типовых конфигураций, а также рассмотрим правильный алгоритм программного заполнения составных реквизитов.
Проанализируем основные причины, по которым ссылка на контрагента не записывается в строку табличной части:
Объект на клиенте представляет собой структуру данных формы (ДанныеФормыСтруктура), а не сам объект базы данных (ДокументОбъект). Программная установка значений на клиенте напрямую в коллекцию формы не вызывает типовые обработчики событий и может приводить к некорректному сбросу данных.Контрагент, оставив реквизит Партнер пустым, механизмы конфигурации автоматически очистят несогласованное значение.СправочникСсылка.Контрагенты.ПустаяСсылка()), то при попытке присвоить ее в реквизит составного типа платформа 1С преобразует данное значение в Неопределено.Часто разработчики пытаются решить проблему ограничениями типов на уровне элементов формы или принудительным приведением типа. Рассмотрим, почему эти способы не работают:
Использование свойства ОграничениеТипа применяется к элементам формы (например, Элементы.ИмяПоля.ОграничениеТипа) и влияет исключительно на интерактивный выбор значения пользователем в интерфейсе. Оно не меняет тип данных в реквизитах табличной части и не помогает при программной установке значения.
Также не требуется создавать объект ОписаниеТипов или использовать метод ПривестиЗначение(). Если в реквизит составного типа записывается реальная (непустая) ссылка на объект, платформа 1С автоматически определяет и фиксирует нужный тип.
Для корректного заполнения табличной части документа необходимо выполнить следующие шаги:
РеквизитФормыВЗначение().Контрагент и Партнер.ЗначениеВРеквизитФормы().Рассмотрим практическую реализацию загрузки строк в табличную часть РасчетыСПартнерами документа на сервере:
&НаКлиенте
Процедура ЗагрузитьДанныеИзФайлаНаКлиенте()
// Формируем массив структур с примитивными типами данных
МассивСтрок = Новый Массив;
Для НС = 10 По ФайлСтрок Цикл
СтрокаДанных = Новый Структура;
СтрокаДанных.Вставить("ИНН", СокрЛП(Excel.Cells(НС, 1).Text));
СтрокаДанных.Вставить("Сумма", Число(Excel.Cells(НС, 7).Text));
МассивСтрок.Добавить(СтрокаДанных);
КонецЦикла;
// Передаем данные на сервер для обработки
ЗаполнитьТабличнуюЧастьНаСервере(МассивСтрок);
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьТабличнуюЧастьНаСервере(МассивСтрок)
// Получаем прикладной объект из данных формы
ДокументОбъект = РеквизитФормыВЗначение("Объект");
ДокументОбъект.РасчетыСПартнерами.Очистить();
Для Каждого СтрИзФайла Из МассивСтрок Цикл
// Ищем контрагента по ИНН
НайденныйКонтрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", СтрИзФайла.ИНН);
Если НЕ ЗначениеЗаполнено(НайденныйКонтрагент) Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = ДокументОбъект.РасчетыСПартнерами.Добавить();
// Устанавливаем ссылку в составной реквизит
НоваяСтрока.Контрагент = НайденныйКонтрагент;
// Обязательно заполняем связанного партнера для УТ 11
НоваяСтрока.Партнер = НайденныйКонтрагент.Партнер;
НоваяСтрока.Сумма = СтрИзФайла.Сумма;
КонецЦикла;
// Возвращаем измененный объект обратно в данные формы
ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры
Выполнение операции на сервере с параллельным заполнением реквизита Партнер гарантирует, что платформа 1С корректно сохранит ссылку составного типа и данные не сбросятся при обновлении формы.