Как загрузить номенклатуру из Excel и одновременно создать единицы измерения в 1С:Управление торговлей 10?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При работе с системой 1С часто возникает необходимость загрузки большого объема данных из внешних источников, например, из табличных документов Excel. Одной из распространенных задач является загрузка справочника номенклатуры. Однако, помимо самой номенклатуры, требуется корректно создать и связать с ней единицы измерения, которые в 1С хранятся в отдельном справочнике ЕдиницыИзмерения и имеют ссылку на владельца (конкретную номенклатурную позицию).

Рассмотрим ситуацию, когда мы используем универсальную обработку для загрузки данных из табличного документа (например, стандартную обработку "Загрузка данных из табличного документа"), и нам необходимо не просто найти существующую единицу измерения, но и создать новую запись единицы измерения, которая будет принадлежать только что созданной или обновленной позиции номенклатуры. Это ключевой момент, поскольку в 1С:Управление торговлей 10 (и аналогичных конфигурациях) структура единиц измерения достаточно специфична.

Структура единиц измерения в 1С:УТ 10.3

Прежде чем перейти к решению, давайте разберем, как устроены единицы измерения в 1С:УТ 10.3. Это поможет нам понять, почему требуется именно такое решение.

  1. Классификатор единиц измерения (ОКЕИ): В 1С существует глобальный классификатор единиц измерения, который содержит стандартные единицы, такие как "шт" (штука), "кг" (килограмм), "м" (метр) и т.д. Этот справочник не предназначен для создания новых единиц конкретной номенклатуры, а служит источником для выбора базовых измерений.
  2. Базовая единица измерения номенклатуры: Каждая позиция номенклатуры имеет реквизит БазоваяЕдиницаИзмерения, который ссылается на элемент из классификатора. Это основополагающая единица для данной номенклатуры.
  3. Единица хранения остатков: Для номенклатуры также определяется ЕдиницаХраненияОстатков. Именно в этой единице будут учитываться остатки товаров на складах и производиться большинство операций. Она часто совпадает с базовой, но может быть и другой, если номенклатура, например, хранится в упаковках, а базовая единица — штуки.
  4. Справочник "ЕдиницыИзмерения": Это отдельный справочник, который хранит специфические единицы измерения для конкретных позиций номенклатуры. Здесь каждая запись имеет:
    • Владелец: Ссылка на позицию номенклатуры, которой принадлежит данная единица измерения.
    • ЕдиницаПоКлассификатору: Ссылка на элемент из классификатора единиц измерения (например, "шт").
    • Наименование: Наименование этой единицы измерения (может быть "Штука", "Упаковка 10 шт" и т.д.).
    • Коэффициент: Коэффициент пересчета относительно базовой единицы (например, для "Упаковки 10 шт" коэффициент будет 10).

Таким образом, когда мы говорим о создании единицы измерения при загрузке номенклатуры, мы имеем в виду создание новой записи именно в справочнике Справочники.ЕдиницыИзмерения, при этом указывая в качестве владельца новую позицию номенклатуры.

Решение 1: Использование обработчиков событий в универсальной обработке загрузки

Наиболее гибкий и рекомендуемый способ решить эту задачу — это использование встроенных обработчиков событий в универсальной обработке загрузки данных. Большинство таких обработок предоставляют возможность написать собственный код, который будет выполняться на различных этапах работы с объектом, например, перед записью или при записи элемента.

Шаг 1: Настройка обработки загрузки

  1. Выбираем объект загрузки: Откройте вашу универсальную обработку загрузки данных. На вкладке, где вы указываете целевой объект для загрузки, выберите справочник Номенклатура.
  2. Сопоставляем колонки Excel с реквизитами номенклатуры: Обязательно сопоставьте необходимые поля номенклатуры (Наименование, Артикул, Группа и т.д.) с соответствующими колонками в вашем файле Excel. Особое внимание уделите полю, которое будет использоваться для БазоваяЕдиницаИзмерения (например, колонка с наименованием единицы из классификатора, такой как "Штука").
  3. Переходим к обработчикам событий: В универсальной обработке обычно есть вкладка или секция "Настройка", "Обработчики событий" или "Код", где можно написать фрагменты кода для различных событий. Мы будем использовать событие ПриЗаписи объекта. Это событие срабатывает после того, как все основные реквизиты объекта уже заполнены из Excel, но до окончательной записи в базу данных. В этот момент у нас уже будет ссылка на новый (или модифицированный) элемент номенклатуры, и мы сможем создать для него связанную единицу измерения.

Шаг 2: Создание записи единицы измерения в событии "ПриЗаписи"

В поле для кода обработчика события ПриЗаписи (или аналогичного, например, ПослеЗагрузкиОбъекта) мы напишем следующий фрагмент. В контексте обработчика, переменная Объект будет представлять собой элемент справочника Номенклатура, который мы загружаем.


// Проверим, существует ли уже единица измерения для данной номенклатуры
// по ее базовой единице измерения. Это помогает избежать дублирования.
// Мы ищем элемент справочника ЕдиницыИзмерения, владельцем которого является
// текущая номенклатура (Объект.Ссылка), и ЕдиницаПоКлассификатору которого
// совпадает с базовой единицей номенклатуры.

// Сначала убедимся, что базовая единица измерения номенклатуры заполнена.
Если Объект.БазоваяЕдиницаИзмерения.Пустая() Тогда
    // Если базовая единица не заполнена, возможно, ее нужно установить
    // из данных Excel или по умолчанию.
    // Пример: Найти по наименованию "Штука" в классификаторе
    ЕдиницаИзКлассификатора = Справочники.КлассификаторЕдиницИзмерения.НайтиПоНаименованию("Штука");
    Если ЕдиницаИзКлассификатора <> Неопределено Тогда
        Объект.БазоваяЕдиницаИзмерения = ЕдиницаИзКлассификатора;
    Иначе
        // Обработка ситуации, если "Штука" не найдена
        Сообщить("Внимание: Единица 'Штука' не найдена в классификаторе. Невозможно установить базовую единицу для " + Объект.Наименование, СтатусСообщения.Важное);
        Возврат; // Или прервать создание единицы измерения
    КонецЕсли;
КонецЕсли;

// Поиск существующей единицы измерения для данной номенклатуры
// по Владельцу и ЕдиницеПоКлассификатору
Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ ПЕРВЫЕ 1
|    ЕдиницыИзмерения.Ссылка
|ИЗ
|    Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
|ГДЕ
|    ЕдиницыИзмерения.Владелец = &Владелец
|    И ЕдиницыИзмерения.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору";

Запрос.УстановитьПараметр("Владелец", Объект.Ссылка);
Запрос.УстановитьПараметр("ЕдиницаПоКлассификатору", Объект.БазоваяЕдиницаИзмерения);

РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    // Единица измерения уже существует, просто присвоим ее в ЕдиницуХраненияОстатков
    Объект.ЕдиницаХраненияОстатков = Выборка.Ссылка;
Иначе
    // Единица измерения не найдена, создаем новую
    НоваяЕдиница = Справочники.ЕдиницыИзмерения.СоздатьЭлемент();
    
    // Заполняем основные реквизиты новой единицы измерения
    // Наименование можно взять из наименования базовой единицы или из Excel
    НоваяЕдиница.Наименование = Объект.БазоваяЕдиницаИзмерения.Наименование;
    
    // Привязываем к элементу классификатора
    НоваяЕдиница.ЕдиницаПоКлассификатору = Объект.БазоваяЕдиницаИзмерения;
    
    // Коэффициент для базовой единицы всегда 1
    НоваяЕдиница.Коэффициент = 1;
    
    // Самое важное: указываем владельца — нашу номенклатуру
    НоваяЕдиница.Владелец = Объект.Ссылка;
    
    // Записываем новую единицу измерения
    Попытка
        НоваяЕдиница.Записать();
        // После успешной записи присваиваем ссылку на созданную единицу
        // в поле ЕдиницаХраненияОстатков объекта номенклатуры
        Объект.ЕдиницаХраненияОстатков = НоваяЕдиница.Ссылка;
    Исключение
        Сообщить("Ошибка при записи единицы измерения для номенклатуры " + Объект.Наименование + ": " + ОписаниеОшибки(), СтатусСообщения.Важное);
    КонецПопытки;
КонецЕсли;

Разберем код по шагам:

  1. Проверка заполнения базовой единицы: Первым делом мы проверяем, заполнена ли БазоваяЕдиницаИзмерения для текущего объекта номенклатуры. Если нет, мы пытаемся найти стандартную единицу "Штука" в классификаторе и установить ее. Это часто бывает полезно, если в Excel нет явного указания базовой единицы, и по умолчанию мы хотим использовать "шт".
  2. Поиск существующей записи: Перед тем как создавать новую запись, критически важно проверить, не существует ли уже единица измерения для данной номенклатуры с такой же базовой единицей из классификатора. Это помогает избежать дублирования. Мы используем запрос к справочнику ЕдиницыИзмерения, чтобы найти запись по Владельцу (ссылке на текущую номенклатуру Объект.Ссылка) и ЕдиницаПоКлассификатору.
  3. Создание новой единицы: Если существующая запись не найдена, мы создаем новый элемент справочника ЕдиницыИзмерения с помощью метода Справочники.ЕдиницыИзмерения.СоздатьЭлемент().
  4. Заполнение реквизитов:
    • НоваяЕдиница.Наименование = Объект.БазоваяЕдиницаИзмерения.Наименование; Мы присваиваем наименование, которое берем из наименования базовой единицы номенклатуры. Можно также взять его из отдельной колонки Excel, если это предусмотрено.
    • НоваяЕдиница.ЕдиницаПоКлассификатору = Объект.БазоваяЕдиницаИзмерения; Устанавливаем ссылку на элемент из глобального классификатора единиц измерения, который мы уже сопоставили с базовой единицей номенклатуры.
    • НоваяЕдиница.Коэффициент = 1; Для базовой единицы коэффициент всегда равен 1. Если вам нужно создавать дополнительные единицы (упаковки) с другими коэффициентами, вам потребуется дополнительная логика и данные из Excel.
    • НоваяЕдиница.Владелец = Объект.Ссылка; Это самый важный шаг – мы устанавливаем владельца этой единицы измерения, привязывая ее к только что загруженной номенклатуре. Объект.Ссылка будет содержать ссылку на текущий элемент номенклатуры.
  5. Запись и привязка:
    • НоваяЕдиница.Записать(); Сохраняем новую единицу измерения в базу данных. Мы оборачиваем этот шаг в конструкцию Попытка...Исключение для корректной обработки возможных ошибок.
    • Объект.ЕдиницаХраненияОстатков = НоваяЕдиница.Ссылка; После успешной записи, мы присваиваем ссылку на созданную единицу измерения в реквизит ЕдиницаХраненияОстатков загружаемого объекта номенклатуры. Это гарантирует, что номенклатура будет корректно использовать эту единицу для учета.

Гибкость обработчиков событий

Обработчики событий, такие как ПриЗаписи, предоставляют огромную гибкость. Вы можете выполнять в них практически любые действия с объектами 1С:

Решение 2: Двухэтапная загрузка

Другой подход, который может быть проще для понимания и отладки в некоторых случаях, — это двухэтапная загрузка.

  1. Этап 1: Загрузка (или проверка) единиц измерения. Сначала мы загружаем или убеждаемся в наличии всех необходимых единиц измерения в справочнике Справочники.ЕдиницыИзмерения. Если в вашем файле Excel есть отдельный список уникальных единиц измерения, вы можете сначала загрузить их как отдельный справочник, а затем уже использовать ссылки на них. Однако, если каждая единица уникальна для каждой номенклатуры и имеет владельца, это решение становится менее эффективным, чем использование обработчиков событий.
  2. Этап 2: Загрузка номенклатуры. После того как единицы измерения существуют (или будут созданы на первом этапе), мы загружаем номенклатуру. В этом случае, в настройках обработки загрузки для поля ЕдиницаХраненияОстатков (и других полей, ссылающихся на справочник ЕдиницыИзмерения), мы указываем, что нужно найти существующий элемент по наименованию, коду или по комбинации полей (например, по наименованию и владельцу).

Этот подход может быть полезен, если логика создания единиц измерения очень сложна, или если единицы измерения используются множеством номенклатурных позиций и не имеют уникального владельца (хотя в УТ 10 Справочник.ЕдиницыИзмерения почти всегда привязан к владельцу).

Дополнительные рекомендации

Мы предлагаем рассмотреть дополнительные рекомендации, которые помогут при работе с загрузкой данных:

  1. Контроль заполнения: Всегда используйте функцию "Контроль заполнения" в вашей обработке загрузки перед окончательной записью данных. Это позволит выявить потенциальные ошибки и несоответствия данных до их фактического попадания в базу 1С.
  2. Подготовка данных в Excel: Максимально подготовьте данные в Excel. Убедитесь, что наименования единиц измерения в Excel точно соответствуют наименованиям в КлассификатореЕдиницИзмерения 1С, если вы планируете искать их по наименованию.
  3. Обработка ошибок: В коде обработчиков всегда предусматривайте обработку возможных ошибок с помощью конструкций Попытка...Исключение и логирование сообщений пользователю. Это поможет понять, почему та или иная запись не была создана или обработана.
  4. Понимание структуры 1С: Глубокое понимание того, как устроены объекты и справочники в 1С, является залогом успешной загрузки данных. Знание о том, что ЕдиницыИзмерения являются подчиненным справочником с владельцем, является ключевым для решения данной задачи.

Таким образом, использование обработчиков событий в универсальной обработке загрузки является мощным инструментом для решения сложных задач по интеграции данных, позволяя нам гибко управлять созданием связанных объектов, таких как записи единиц измерения для новой номенклатуры, в рамках одной операции загрузки.

← На главную