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

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

При переходе на платформу 1С 8.3 или при выполнении задач на управляемых формах разработчики нередко сталкиваются с ошибками при попытке перебрать и модифицировать строки таблицы. Разберем типичную ситуацию: в табличной части или таблице значений требуется удалить все строки, где единица измерения равна «Шт», а также рассчитать общую сумму по оставшимся позициям и вывести ее в подвал таблицы.

Проанализируем причины возникновения типичных ошибок начинающих разработчиков и рассмотрим правильные варианты реализации данной задачи на платформе 1С:Предприятие 8.3.

Выясним причину ошибки «Метод объекта не обнаружен (ВыбратьСтроки)»

При попытке использовать код циклического обхода:


ТаблицаЗначений.ВыбратьСтроки();
Пока ТаблицаЗначений.ПолучитьСтроку() = 1 Цикл
    // обработка строк
КонецЦикла;

Платформа выдает исключение: Метод объекта не обнаружен (ВыбратьСтроки). Причина заключается в том, что методы ВыбратьСтроки(), ПолучитьСтроку() и УдалитьСтроку() использовались в устаревшей версии 1С:Предприятие 7.7. В платформе 1С:Предприятие 8.х у табличных объектов таких методов нет.

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

Разберем различия между ТаблицейЗначений и ДанныеФормыКоллекция

Перед написанием алгоритма важно понимать, с каким именно объектом ведется работа:

  1. Таблица значений в оперативной памяти (тип ТаблицаЗначений) — доступна только на сервере и в толстом клиенте. Создается программно конструктором Новый ТаблицаЗначений или получается выгрузкой из базы данных.
  2. Таблица на управляемой форме — если на форме создан реквизит типа «ТаблицаЗначений», то в контексте формы (как на клиенте, так и на сервере) он преобразуется в специализированный объект типа ДанныеФормыКоллекция.

У объекта ДанныеФормыКоллекция нет методов Выгрузить() или Загрузить(), однако для него доступны методы НайтиСтроки(), Удалить() и Итог(), что позволяет выполнять обработку прямо на клиенте без лишних серверных вызовов.

Вариант 1. Удаление строк через метод НайтиСтроки

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

Посмотрим на пример кода, который одинаково успешно работает как с объектом ТаблицаЗначений на сервере, так и с ДанныеФормыКоллекция (реквизитом формы):


// 1. Формируем структуру отбора
ПараметрыОтбора = Новый Структура("ЕдиницаИзмерения", "Шт");

// 2. Получаем массив строк, подходящих под условие
НайденныеСтроки = ТаблицаЗначений.НайтиСтроки(ПараметрыОтбора);

// 3. Удаляем найденные строки в цикле
Для Каждого СтрокаКУдалению Из НайденныеСтроки Цикл
    ТаблицаЗначений.Удалить(СтрокаКУдалению);
КонецЦикла;

// 4. Рассчитываем сумму по оставшимся строкам
ИтоговаяСумма = ТаблицаЗначений.Итог("Сумма");

Важное замечание: метод Удалить() принимает в качестве параметра либо индекс конкретной строки, либо саму ссылку на строку таблицы. Передать массив строк напрямую в метод ТаблицаЗначений.Удалить(НайденныеСтроки) нельзя — синтаксис 1С требует обязательного построчного обхода через цикл Для Каждого.

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

Вариант 2. Удаление строк перебором с конца таблицы

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

Главная ошибка при прямом переборе таблицы и одновременном удалении элементов — смещение индексов, из-за которого часть строк пропускается. Поэтому удаление строк всегда выполняют с конца таблицы к началу.

Обратим внимание на особенность платформы 1С: стандартный цикл Для работает строго с шагом +1, поэтому конструкцию вида Для Индекс = Количество - 1 По 0 использовать нельзя. Обход организуется через цикл Пока:


Индекс = ТаблицаЗначений.Количество() - 1;

Пока Индекс >= 0 Цикл
    ТекущаяСтрока = ТаблицаЗначений[Индекс];
    
    Если ТекущаяСтрока.ЕдиницаИзмерения = "Шт" Тогда
        ТаблицаЗначений.Удалить(Индекс);
    КонецЕсли;
    
    Индекс = Индекс - 1;
КонецЦикла;

ИтоговаяСумма = ТаблицаЗначений.Итог("Сумма");

При таком подходе удаление текущего элемента никак не влияет на нумерацию строк, которые находятся ближе к началу таблицы и еще не были проверены.

Вариант 3. Оптимизация для больших объемов данных через запрос

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


&НаСервере
Процедура ОбработатьТаблицуНаСервере()
    
    // Преобразуем коллекцию формы в объект ТаблицаЗначений
    ТЗ = РеквизитФормыВЗначение("ТаблицаЗначений");
    
    Запрос = Новый Запрос;
    МенеджерВТ = Новый МенеджерВременныхТаблиц;
    Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
    
    // Передаем исходную таблицу в запрос
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Т.Товар КАК Товар,
        |   Т.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
        |   Т.Количество КАК Количество,
        |   Т.Цена КАК Цена,
        |   Т.Сумма КАК Сумма
        |ПОМЕСТИТЬ ВТ_ИсходныеДанные
        |ИЗ
        |   &ТаблицаИсточник КАК Т
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |   Т.Товар,
        |   Т.ЕдиницаИзмерения,
        |   Т.Количество,
        |   Т.Цена,
        |   Т.Сумма
        |ИЗ
        |   ВТ_ИсходныеДанные КАК Т
        |ГДЕ
        |   Т.ЕдиницаИзмерения <> &ИсключаемаяЕдиница";
    
    Запрос.УстановитьПараметр("ТаблицаИсточник", ТЗ);
    Запрос.УстановитьПараметр("ИсключаемаяЕдиница", "Шт");
    
    // Выгружаем отфильтрованные данные
    ТЗПослеФильтрации = Запрос.Выполнить().Выгрузить();
    
    // Рассчитываем сумму средствами таблицы значений
    ИтоговаяСумма = ТЗПослеФильтрации.Итог("Сумма");
    
    // Загружаем результат обратно в данные формы
    ЗначениеВРеквизитФормы(ТЗПослеФильтрации, "ТаблицаЗначений");
    
КонецПроцедуры

Автоматический вывод итога в подвал таблицы без программного кода

Чтобы исключить ошибки при ручном заполнении подвала таблицы формы, платформой 1С предусмотрен встроенный автоматический механизм:

  1. В конфигураторе в свойствах таблицы на форме устанавливаем флаг ОтображатьПодвал.
  2. Выбираем колонку Сумма и в окне ее свойств находим пункт ПутьКДаннымПодвала.
  3. Вместо ручного заполнения текста указываем путь к агрегатной функции: ИмяТаблицы.ИтогСумма (где ИмяТаблицы — имя вашего реквизита формы).

После этой настройки платформа автоматически подсчитывает и выводит корректную сумму всех оставшихся строк при любом добавлении, редактировании или удалении данных.

← На главную