При разработке обработок загрузки данных из внешних источников (например, файлов Microsoft Excel) в документы 1С разработчики нередко сталкиваются с ситуацией: все данные строки табличной части успешно заполняются, но колонка единицы измерения остается пустой. При этом в отладчике обращение к реквизиту номенклатуры возвращает значение, код отрабатывает без исключений, однако после открытия формы документа поле не заполнено.
Разберем детально механизм работы с единицами измерения в типовых конфигурациях 1С, выясним причину такого поведения платформы и рассмотрим правильные варианты заполнения реквизитов.
Посмотрим на типичную строку кода, которая приводит к ошибке:
Результат = ТекущиеДанные["Номенклатура"].БазоваяЕдиницаИзмерения;
СтрокаТЧ.ЕдиницаИзмерения = Результат;
На первый взгляд код выглядит логичным: у позиции номенклатуры считывается единица измерения и записывается в соответствующую колонку строки документа. Однако ключевая ошибка кроется в несовпадении типов данных.
В типовых конфигурациях 1С (таких как «Управление торговлей» редакции 10.3, «Комплексная автоматизация» редакции 1.1, «Управление производственным предприятием» редакции 1.3) учет единиц измерения строится на двух разных справочниках:
КлассификаторЕдиницИзмерения. Именно этот тип имеет реквизит БазоваяЕдиницаИзмерения у справочника Номенклатура. В нем хранятся общие эталоны (штуки, килограммы, метры и т.д.).ЕдиницыИзмерения, владельцем которого выступает конкретный элемент справочника Номенклатура. В табличных частях большинства документов поле ЕдиницаИзмерения имеет тип ссылки именно на этот справочник (СправочникСсылка.ЕдиницыИзмерения), поскольку для одной и той же позиции могут использоваться упаковки с разными коэффициентами пересчета.Проанализируем поведение платформы 1С: когда реквизиту табличной части с типом СправочникСсылка.ЕдиницыИзмерения присваивается значение типа СправочникСсылка.КлассификаторЕдиницИзмерения, платформа не выдает критическую ошибку выполнения. Вместо этого происходит автоматическое приведение к пустому значению несовместимого типа, и в результате колонка документа остается абсолютно пустой.
Если для загружаемой строки документа требуется установить базовую единицу по умолчанию, обратимся к реквизиту номенклатуры ЕдиницаХраненияОстатков или ЕдиницаДляОтчетов. Данные реквизиты изначально хранят правильный ссылочный тип СправочникСсылка.ЕдиницыИзмерения.
Рассмотрим правильный пример заполнения строки табличной части документа:
НоменклатураСсылка = СтрокаТЧ.Номенклатура;
// Устанавливаем единицу измерения правильного типа
СтрокаТЧ.ЕдиницаИзмерения = НоменклатураСсылка.ЕдиницаХраненияОстатков;
// Обязательно заполняем сопутствующий коэффициент
СтрокаТЧ.Коэффициент = СтрокаТЧ.ЕдиницаИзмерения.Коэффициент;
Обратите внимание: в табличных частях документов рядом с полем ЕдиницаИзмерения практически всегда присутствует реквизит Коэффициент. При программной установке единицы измерения необходимо явно заполнять и коэффициент. Для единицы хранения остатков он равен 1, но для произвольных упаковок может отличаться. Если оставить коэффициент равным 0, проведение документа завершится ошибкой либо сформируются некорректные движения по регистрам учета.
Разберем ситуацию, когда из файла Excel загружается конкретное наименование или код единицы измерения, либо требуется найти элемент подчиненного справочника по имеющейся базовой единице из классификатора ОКЕИ.
Так как справочник ЕдиницыИзмерения является подчиненным, поиск необходимо выполнять строго с отбором по владельцу (конкретной номенклатуре):
НоменклатураСсылка = СтрокаТЧ.Номенклатура;
БазоваяЕдиница = НоменклатураСсылка.БазоваяЕдиницаИзмерения;
// Поиск единицы измерения по классификатору с указанием владельца
НайденнаяЕдиница = Справочники.ЕдиницыИзмерения.НайтиПоРеквизиту("ЕдиницаПоКлассификатору", БазоваяЕдиница, , НоменклатураСсылка);
Если ЗначениеЗаполнено(НайденнаяЕдиница) Тогда
СтрокаТЧ.ЕдиницаИзмерения = НайденнаяЕдиница;
СтрокаТЧ.Коэффициент = НайденнаяЕдиница.Коэффициент;
Иначе
// Если по классификатору не найдено, берем единицу хранения по умолчанию
СтрокаТЧ.ЕдиницаИзмерения = НоменклатураСсылка.ЕдиницаХраненияОстатков;
СтрокаТЧ.Коэффициент = 1;
КонецЕсли;
Если алгоритм загрузки не просто заполняет строки документа, но и предварительно создает новые карточки номенклатуры, важно помнить о циклической связи между объектами:
Номенклатура, в котором заполняется БазоваяЕдиницаИзмерения (значение из классификатора ОКЕИ). Записать номенклатуру необходимо для получения ссылки.ЕдиницыИзмерения. В качестве реквизита Владелец указывается записанная ссылка на номенклатуру, в реквизит ЕдиницаПоКлассификатору помещается базовая единица, а в Коэффициент устанавливается значение 1. Объект записывается.ЕдиницаХраненияОстатков подставляется ссылка на созданный подчиненный элемент единицы измерения, и номенклатура записывается повторно.Если пропустить создание подчиненного элемента при программной генерации карточек, реквизит ЕдиницаХраненияОстатков останется незаполненным, и последующая подстановка в табличную часть документа снова приведет к пустой ячейке.