При программном заполнении регистра сведений из таблицы значений или табличной части на форме программисты часто сталкиваются с парадоксальной ситуацией: в отладчике мы видим, что переменная заполнена, но метод Записать() выбрасывает исключение: «Запись не верна! Значение поля не может быть пустым!». Рассмотрим детально, почему это происходит, как работает механизм типизации в 1С и какими способами можно гарантированно избежать этой ошибки.
В языке 1С:Предприятие используется динамическая типизация для переменных, но строгая типизация для свойств объектов метаданных. Проанализируем ситуацию: когда мы создаем новую запись в наборе записей через метод Добавить(), мы получаем объект типа РегистрСведенийМенеджерЗаписи или РегистрСведенийВыборка (в контексте набора — строку набора). Поля этого объекта жестко привязаны к типам данных, определенным в конфигураторе для данного регистра.
Выясним причину ошибки на примере кода из обсуждения:
НаборЗаписей = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
Для Каждого ТекСтрока из Таблица Цикл
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Владелец = ТекСтрока.Номенклатура;
НоваяЗапись.Штрихкод = ТекСтрока.Штрихкод;
НоваяЗапись.ТипШтрихкода = ТекСтрока.ТипШтрихкода;
КонецЦикла;
НаборЗаписей.Записать();
Если в ТекСтрока.ТипШтрихкода содержится значение, тип которого не совпадает с типом измерения ТипШтрихкода в метаданных регистра, 1С не выдаст ошибку в момент присваивания. Вместо этого сработает внутренний механизм платформы: система попытается привести значение к нужному типу. Если прямое приведение невозможно (например, мы пытаемся записать строку в поле типа ПланВидовХарактеристикСсылка или ссылку одного перечисления в другое), свойству просто присвоится пустое значение данного типа.
Важный момент: в отладчике до строки присваивания вы видите значение в ТекСтрока, но сразу после строки НоваяЗапись.ТипШтрихкода = ... значение в НоваяЗапись становится пустым. Именно поэтому при вызове метода Записать() система сообщает о незаполненном обязательном поле.
Для того чтобы убедиться в наличии проблемы типизации, рекомендуем проверять значения не в исходной таблице, а в самом объекте записи. Посмотрим на алгоритм проверки:
НаборЗаписей.Записать().НаборЗаписей[0].ТипШтрихкода.Неопределено, значит, в цикле произошло некорректное присваивание.ТипЗнч(ТекСтрока.ТипШтрихкода) и сравните его с ожидаемым типом через Тип("ПланВидовХарактеристикСсылка.ТипыШтрихкодов") (или соответствующим вашему регистру типом).Существует несколько подходов к исправлению этой ошибки, в зависимости от того, откуда берутся данные.
Если вы точно знаете, какой тип должен быть у измерения, и данные в таблице могут быть «сырыми» (например, после загрузки из Excel), можно использовать принудительное назначение типа. Рассмотрим пример:
Если ТекСтрока.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.ПустаяСсылка() Тогда
// Если в таблице пусто, ставим значение по умолчанию
НоваяЗапись.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
Иначе
// Если значение есть, проверяем, того ли оно типа
// В некоторых случаях помогает поиск по наименованию или коду, если типы не совпадают
НоваяЗапись.ТипШтрихкода = ТекСтрока.ТипШтрихкода;
КонецЕсли;
Если записей немного, попробуем заменить НаборЗаписей на МенеджерЗаписи. Это позволит нам отловить ошибку на конкретной строке таблицы и понять, на каких именно данных спотыкается система. Посмотрим на пример кода:
Для Каждого ТекСтрока из Таблица Цикл
МенеджерЗаписи = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, ТекСтрока);
Попытка
МенеджерЗаписи.Записать();
Исключение
Сообщить("Ошибка в строке с номенклатурой " + ТекСтрока.Номенклатура + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Важное предупреждение: метод с МенеджеромЗаписи работает медленнее и не подходит для массовой перезаписи тысяч строк. Также помните, что НаборЗаписей без установленного отбора при записи полностью очищает регистр перед записью новых данных. Всегда устанавливайте фильтры через НаборЗаписей.Отбор.
Если ваша Таблица является реквизитом формы (ДанныеФормыКоллекция), проанализируем, как она была создана. Если колонки создавались программно без указания типов или были получены из запроса, где типы могут быть составными, платформа может передавать на сервер объект, который визуально похож на нужную ссылку, но программно ей не является.
Убедитесь, что в колонке ТипШтрихкода вашей таблицы на форме жестко задан тип, совпадающий с типом измерения в регистре сведений. Это исключит возможность попадания в таблицу данных «чужого» типа.
Часто в типовых конфигурациях (УТ 11, ERP) тип штрихкода может быть либо элементом Плана видов характеристик, либо Перечислением. Если ваша обработка была написана для одной конфигурации, а вы пытаетесь запустить её в другой, названия объектов могут совпадать (например, «EAN13»), но их внутренняя природа будет разной. Проверьте через конфигуратор:
Перечисления.ТипыШтрихкодов.EAN13.ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13.Использование неправильного метаобъекта — самая частая причина «невидимой» пустоты в полях записи регистра.
Подводя итог, при возникновении ошибки «Значение не может быть пустым» при записи регистра, всегда проверяйте не то, что вы передаете, а то, что принимает объект 1С. Используйте отладчик непосредственно на объекте НоваяЗапись и следите за строгим соответствием типов данных между источником (таблицей) и приемником (регистром).