Как правильно загрузить данные из Таблицы Значений в Табличную Часть документа с поиском по коду?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Типичная постановка задачи

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

Рассмотрим стандартный, но не всегда работающий «в лоб» код:


Для каждого ТекСтрока из МояТЗ Цикл
    нСтр = Объект.ТЧ.Добавить();
    ЗаполнитьЗначенияСвойств(нСтр, ТекСтрока);
    // Попытка найти ссылку по коду из ТЗ
    нСтр.Номенклатура = Справочники.Номенклатура.НайтиПоКоду(ТекСтрока.Код);
КонецЦикла;

Почему данные могут не загружаться?

Проанализируем ситуацию, когда после выполнения кода поле справочника в документе остается пустым. Основная причина кроется в несоответствии типов данных. Метод НайтиПоКоду ожидает на вход значение того же типа, который задан для кода в самом справочнике (обычно это Строка или Число).

Разберем по шагам, на что нужно обратить внимание:

  1. Тип кода в конфигураторе: Откройте свойства справочника и посмотрите, какой тип имеет стандартный реквизит Код. Если это Строка, а вы передаете в поиск Число, система ничего не найдет.
  2. Лидирующие нули: Если код в 1С имеет строковый тип и длину, например, 9 символов (000000123), а из Excel приходит строка "123", поиск вернет пустую ссылку.
  3. Лишние пробелы: Часто при чтении из Excel в строке могут оказаться невидимые символы или пробелы. Всегда используйте функцию СокрЛП() при получении значения.
  4. Определение типов в ТЗ: Если при создании колонок таблицы значений вы жестко указали тип СправочникСсылка, но пытаетесь записать туда строку из Excel, возникнет конфликт типов еще на этапе заполнения ТЗ.

Алгоритм правильной загрузки из внешнего источника

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


// 1. Подготовка Таблицы Значений
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("КодИзФайла", Новый ОписаниеТипов("Строка")); // Специально для кода
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));

// ... цикл загрузки из Excel в ТЗ ...
НовСтрока = ТЗ.Добавить();
НовСтрока.КодИзФайла = СокрЛП(ExcelЛист.Cells(Row, 2).Text); 

// 2. Загрузка в Табличную Часть документа
Для каждого ТекСтрока из ТЗ Цикл
    нСтр = Объект.ТЧ.Добавить();
    // Заполняем простые реквизиты (Количество, Цена и т.д.)
    ЗаполнитьЗначенияСвойств(нСтр, ТекСтрока);
    
    // Ищем ссылку в справочнике по строковому коду
    СсылкаНаОбъект = Справочники.МойСправочник.НайтиПоКоду(ТекСтрока.КодИзФайла);
    
    Если СсылкаНаОбъект.Пустая() Тогда
        Сообщить("Не найден объект с кодом: " + ТекСтрока.КодИзФайла);
    Иначе
        нСтр.ОбъектСправочника = СсылкаНаОбъект;
    КонецЕсли;
КонецЦикла;

Оптимизация: Использование метода Загрузить()

Проанализируем более профессиональный подход. Если ваша таблица значений содержит тысячи строк, поиск НайтиПоКоду внутри цикла создаст огромную нагрузку на базу данных (будет выполнено столько отдельных запросов, сколько строк в таблице). В таких случаях лучше использовать механизм запросов.

Рассмотрим последовательность действий для оптимизации:

  1. Поместите вашу ТЗ во временную таблицу в запросе.
  2. Выполните Левое Соединение временной таблицы со справочником по полю Код.
  3. Получите результат запроса, в котором уже будут готовые ссылки СправочникСсылка.
  4. Выгрузите результат в новую ТЗ.
  5. Используйте метод Объект.ТЧ.Загрузить(РезультатЗапросаТЗ).

Метод Загрузить() работает значительно быстрее, чем добавление строк в цикле через Добавить(), так как платформа выполняет запись данных в память пакетом.

Важные нюансы работы с типами при создании ТЗ

Как выяснилось в обсуждении, одной из ошибок была попытка сразу присвоить колонке ТЗ тип СправочникСсылка и записывать туда код. Если вы планируете использовать ЗаполнитьЗначенияСвойств, имена колонок в ТЗ и реквизитов в ТЧ должны совпадать, а типы должны быть идентичными.

Посмотрим на пример правильной типизации:


ТЗ = Новый ТаблицаЗначений;
// Если реквизит в ТЧ называется "Товар" и имеет тип СправочникСсылка.Номенклатура
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

// При заполнении ТЗ мы СНАЧАЛА находим ссылку, а потом кладем ее в колонку
НовСтр = ТЗ.Добавить();
НовСтр.Товар = Справочники.Номенклатура.НайтиПоКоду(КодИзЭкскселя);
НовСтр.Количество = ЧислоИзЭкскселя;

// Теперь ЗаполнитьЗначенияСвойств отработает идеально
Для каждого СтрТЗ Из ТЗ Цикл
    НоваяСтрокаТЧ = Объект.ТЧ.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрокаТЧ, СтрТЗ);
КонецЦикла;

Резюме

Для успешной загрузки данных из ТЗ в ТЧ документа придерживайтесь следующих правил: проверяйте соответствие типов (строка или число в коде), очищайте входные данные от лишних пробелов с помощью СокрЛП и старайтесь подготавливать ссылки до момента окончательного заполнения табличной части. Если данных много — используйте запросы для сопоставления ссылок, чтобы избежать замедления работы системы.

← На главную