При работе с системой 1С часто возникает необходимость загрузки большого объема данных из внешних источников, например, из табличных документов Excel. Одной из распространенных задач является загрузка справочника номенклатуры. Однако, помимо самой номенклатуры, требуется корректно создать и связать с ней единицы измерения, которые в 1С хранятся в отдельном справочнике ЕдиницыИзмерения и имеют ссылку на владельца (конкретную номенклатурную позицию).
Рассмотрим ситуацию, когда мы используем универсальную обработку для загрузки данных из табличного документа (например, стандартную обработку "Загрузка данных из табличного документа"), и нам необходимо не просто найти существующую единицу измерения, но и создать новую запись единицы измерения, которая будет принадлежать только что созданной или обновленной позиции номенклатуры. Это ключевой момент, поскольку в 1С:Управление торговлей 10 (и аналогичных конфигурациях) структура единиц измерения достаточно специфична.
Прежде чем перейти к решению, давайте разберем, как устроены единицы измерения в 1С:УТ 10.3. Это поможет нам понять, почему требуется именно такое решение.
БазоваяЕдиницаИзмерения, который ссылается на элемент из классификатора. Это основополагающая единица для данной номенклатуры.ЕдиницаХраненияОстатков. Именно в этой единице будут учитываться остатки товаров на складах и производиться большинство операций. Она часто совпадает с базовой, но может быть и другой, если номенклатура, например, хранится в упаковках, а базовая единица — штуки.Владелец: Ссылка на позицию номенклатуры, которой принадлежит данная единица измерения.ЕдиницаПоКлассификатору: Ссылка на элемент из классификатора единиц измерения (например, "шт").Наименование: Наименование этой единицы измерения (может быть "Штука", "Упаковка 10 шт" и т.д.).Коэффициент: Коэффициент пересчета относительно базовой единицы (например, для "Упаковки 10 шт" коэффициент будет 10).Таким образом, когда мы говорим о создании единицы измерения при загрузке номенклатуры, мы имеем в виду создание новой записи именно в справочнике Справочники.ЕдиницыИзмерения, при этом указывая в качестве владельца новую позицию номенклатуры.
Наиболее гибкий и рекомендуемый способ решить эту задачу — это использование встроенных обработчиков событий в универсальной обработке загрузки данных. Большинство таких обработок предоставляют возможность написать собственный код, который будет выполняться на различных этапах работы с объектом, например, перед записью или при записи элемента.
Номенклатура.БазоваяЕдиницаИзмерения (например, колонка с наименованием единицы из классификатора, такой как "Штука").ПриЗаписи объекта. Это событие срабатывает после того, как все основные реквизиты объекта уже заполнены из Excel, но до окончательной записи в базу данных. В этот момент у нас уже будет ссылка на новый (или модифицированный) элемент номенклатуры, и мы сможем создать для него связанную единицу измерения.В поле для кода обработчика события ПриЗаписи (или аналогичного, например, ПослеЗагрузкиОбъекта) мы напишем следующий фрагмент. В контексте обработчика, переменная Объект будет представлять собой элемент справочника Номенклатура, который мы загружаем.
// Проверим, существует ли уже единица измерения для данной номенклатуры
// по ее базовой единице измерения. Это помогает избежать дублирования.
// Мы ищем элемент справочника ЕдиницыИзмерения, владельцем которого является
// текущая номенклатура (Объект.Ссылка), и ЕдиницаПоКлассификатору которого
// совпадает с базовой единицей номенклатуры.
// Сначала убедимся, что базовая единица измерения номенклатуры заполнена.
Если Объект.БазоваяЕдиницаИзмерения.Пустая() Тогда
// Если базовая единица не заполнена, возможно, ее нужно установить
// из данных Excel или по умолчанию.
// Пример: Найти по наименованию "Штука" в классификаторе
ЕдиницаИзКлассификатора = Справочники.КлассификаторЕдиницИзмерения.НайтиПоНаименованию("Штука");
Если ЕдиницаИзКлассификатора <> Неопределено Тогда
Объект.БазоваяЕдиницаИзмерения = ЕдиницаИзКлассификатора;
Иначе
// Обработка ситуации, если "Штука" не найдена
Сообщить("Внимание: Единица 'Штука' не найдена в классификаторе. Невозможно установить базовую единицу для " + Объект.Наименование, СтатусСообщения.Важное);
Возврат; // Или прервать создание единицы измерения
КонецЕсли;
КонецЕсли;
// Поиск существующей единицы измерения для данной номенклатуры
// по Владельцу и ЕдиницеПоКлассификатору
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ЕдиницыИзмерения.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
|ГДЕ
| ЕдиницыИзмерения.Владелец = &Владелец
| И ЕдиницыИзмерения.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору";
Запрос.УстановитьПараметр("Владелец", Объект.Ссылка);
Запрос.УстановитьПараметр("ЕдиницаПоКлассификатору", Объект.БазоваяЕдиницаИзмерения);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
// Единица измерения уже существует, просто присвоим ее в ЕдиницуХраненияОстатков
Объект.ЕдиницаХраненияОстатков = Выборка.Ссылка;
Иначе
// Единица измерения не найдена, создаем новую
НоваяЕдиница = Справочники.ЕдиницыИзмерения.СоздатьЭлемент();
// Заполняем основные реквизиты новой единицы измерения
// Наименование можно взять из наименования базовой единицы или из Excel
НоваяЕдиница.Наименование = Объект.БазоваяЕдиницаИзмерения.Наименование;
// Привязываем к элементу классификатора
НоваяЕдиница.ЕдиницаПоКлассификатору = Объект.БазоваяЕдиницаИзмерения;
// Коэффициент для базовой единицы всегда 1
НоваяЕдиница.Коэффициент = 1;
// Самое важное: указываем владельца — нашу номенклатуру
НоваяЕдиница.Владелец = Объект.Ссылка;
// Записываем новую единицу измерения
Попытка
НоваяЕдиница.Записать();
// После успешной записи присваиваем ссылку на созданную единицу
// в поле ЕдиницаХраненияОстатков объекта номенклатуры
Объект.ЕдиницаХраненияОстатков = НоваяЕдиница.Ссылка;
Исключение
Сообщить("Ошибка при записи единицы измерения для номенклатуры " + Объект.Наименование + ": " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
КонецЕсли;
БазоваяЕдиницаИзмерения для текущего объекта номенклатуры. Если нет, мы пытаемся найти стандартную единицу "Штука" в классификаторе и установить ее. Это часто бывает полезно, если в Excel нет явного указания базовой единицы, и по умолчанию мы хотим использовать "шт".ЕдиницыИзмерения, чтобы найти запись по Владельцу (ссылке на текущую номенклатуру Объект.Ссылка) и ЕдиницаПоКлассификатору.ЕдиницыИзмерения с помощью метода Справочники.ЕдиницыИзмерения.СоздатьЭлемент().НоваяЕдиница.Наименование = Объект.БазоваяЕдиницаИзмерения.Наименование; Мы присваиваем наименование, которое берем из наименования базовой единицы номенклатуры. Можно также взять его из отдельной колонки Excel, если это предусмотрено.НоваяЕдиница.ЕдиницаПоКлассификатору = Объект.БазоваяЕдиницаИзмерения; Устанавливаем ссылку на элемент из глобального классификатора единиц измерения, который мы уже сопоставили с базовой единицей номенклатуры.НоваяЕдиница.Коэффициент = 1; Для базовой единицы коэффициент всегда равен 1. Если вам нужно создавать дополнительные единицы (упаковки) с другими коэффициентами, вам потребуется дополнительная логика и данные из Excel.НоваяЕдиница.Владелец = Объект.Ссылка; Это самый важный шаг – мы устанавливаем владельца этой единицы измерения, привязывая ее к только что загруженной номенклатуре. Объект.Ссылка будет содержать ссылку на текущий элемент номенклатуры.НоваяЕдиница.Записать(); Сохраняем новую единицу измерения в базу данных. Мы оборачиваем этот шаг в конструкцию Попытка...Исключение для корректной обработки возможных ошибок.Объект.ЕдиницаХраненияОстатков = НоваяЕдиница.Ссылка; После успешной записи, мы присваиваем ссылку на созданную единицу измерения в реквизит ЕдиницаХраненияОстатков загружаемого объекта номенклатуры. Это гарантирует, что номенклатура будет корректно использовать эту единицу для учета.Обработчики событий, такие как ПриЗаписи, предоставляют огромную гибкость. Вы можете выполнять в них практически любые действия с объектами 1С:
ЕдиницыИзмерения).Другой подход, который может быть проще для понимания и отладки в некоторых случаях, — это двухэтапная загрузка.
Справочники.ЕдиницыИзмерения. Если в вашем файле Excel есть отдельный список уникальных единиц измерения, вы можете сначала загрузить их как отдельный справочник, а затем уже использовать ссылки на них. Однако, если каждая единица уникальна для каждой номенклатуры и имеет владельца, это решение становится менее эффективным, чем использование обработчиков событий.ЕдиницаХраненияОстатков (и других полей, ссылающихся на справочник ЕдиницыИзмерения), мы указываем, что нужно найти существующий элемент по наименованию, коду или по комбинации полей (например, по наименованию и владельцу).Этот подход может быть полезен, если логика создания единиц измерения очень сложна, или если единицы измерения используются множеством номенклатурных позиций и не имеют уникального владельца (хотя в УТ 10 Справочник.ЕдиницыИзмерения почти всегда привязан к владельцу).
Мы предлагаем рассмотреть дополнительные рекомендации, которые помогут при работе с загрузкой данных:
КлассификатореЕдиницИзмерения 1С, если вы планируете искать их по наименованию.Попытка...Исключение и логирование сообщений пользователю. Это поможет понять, почему та или иная запись не была создана или обработана.ЕдиницыИзмерения являются подчиненным справочником с владельцем, является ключевым для решения данной задачи.Таким образом, использование обработчиков событий в универсальной обработке загрузки является мощным инструментом для решения сложных задач по интеграции данных, позволяя нам гибко управлять созданием связанных объектов, таких как записи единиц измерения для новой номенклатуры, в рамках одной операции загрузки.