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