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