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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия
← На главную

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

Выясним причину проблемы: почему стандартная сортировка не работает?

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

Это означает, что данные в колонке отображаются «через точку» от справочника Номенклатура (где также могут храниться универсальные аналоги номенклатуры). Для платформы 1С метод Сортировать() работает исключительно с физическими колонками, которые присутствуют в коллекции (в реквизитах табличной части). Поскольку реквизита Артикул в таблице нет, метод выдает ошибку. Чтобы решить эту задачу, нам необходимо временно «материализовать» эти данные для выполнения операции сортировки.

Решение 1: Сортировка через промежуточную таблицу значений на сервере

Самый надежный способ, который подходит для внешних подключаемых обработок и расширений, — это использование временной ТаблицыЗначений. Рассмотрим алгоритм действий:

  1. Выгрузим содержимое табличной части документа в объект ТаблицаЗначений.
  2. Добавим в эту таблицу временную колонку Артикул.
  3. Заполним эту колонку данными из справочника Номенклатура.
  4. Выполним сортировку таблицы по новой колонке.
  5. Очистим исходную табличную часть и загрузим в неё отсортированные данные.

Разберем программную реализацию этого алгоритма. Обратите внимание, что работа с ТаблицейЗначений возможна только на стороне сервера.


&НаСервере
Процедура СортироватьТЧПоАртикулуНаСервере()
    
    // 1. Выгружаем ТЧ в таблицу значений
    ТЗ = Объект.Товары.Выгрузить();
    
    // 2. Добавляем временную колонку для сортировки
    ТЗ.Колонки.Добавить("Артикул", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(25)));
    
    // 3. Заполняем колонку значениями артикула
    Для Каждого СтрокаТЗ Из ТЗ Цикл
        // Обращаемся к реквизиту номенклатуры
        СтрокаТЗ.Артикул = СтрокаТЗ.Номенклатура.Артикул;
    КонецЦикла;
    
    // 4. Сортируем по возрастанию
    ТЗ.Сортировать("Артикул Возр");
    
    // 5. Удаляем временную колонку (необязательно, но желательно для чистоты данных)
    ТЗ.Колонки.Удалить("Артикул");
    
    // 6. Загружаем данные обратно в объект
    Объект.Товары.Очистить();
    Объект.Товары.Загрузить(ТЗ);
    
КонецПроцедуры

Решение 2: Оптимизация процесса с использованием запроса

Проанализируем вышеописанный код. Если в табличной части документа содержится большое количество строк (например, несколько сотен или тысяч), обращение к реквизиту Артикул через точку в цикле Для Каждого может существенно замедлить работу. Это происходит из-за так называемой «проблемы N+1 запроса», когда система вынуждена обращаться к базе данных за артикулом для каждой отдельной строки.

Посмотрим на пример более эффективного решения с использованием объекта Запрос. Мы получим все артикулы одним махом.


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

Решение 3: Нюансы для подключаемых обработок (БСП)

Если вы разрабатываете дополнительную обработку табличной части через механизм Библиотеки стандартных подсистем (БСП), помните, что вы работаете с контекстом формы документа. Рассмотрим важные моменты:

Проанализируем пример вызова из модуля обработки:


Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения) Экспорт
    
    // Получаем форму и объект документа
    ФормаДокумента = ПараметрыВыполнения.ЭтаФорма;
    ДокументОбъект = ФормаДокумента.Объект;
    
    // Выполняем сортировку (логика как в Решении 1)
    // ... (код сортировки) ...
    
    // Важно: так как мы работаем с формой, изменения должны отразиться на экране
    // В некоторых случаях может потребоваться явное уведомление формы
    // КопироватьДанныеФормы(ДокументОбъект, ФормаДокумента.Объект);

КонецПроцедуры

Альтернативный подход: Использование расширений

Если требование сортировки по артикулу является постоянным для пользователей, рассмотрите вариант с использованием расширения конфигурации. Это позволит сделать колонку Артикул реальным реквизитом табличной части Товары.

Преимущества этого метода:

  1. Стандартная сортировка по клику на заголовок колонки заработает автоматически.
  2. Не нужно писать сложный код перебора или запросов при каждом нажатии кнопки.
  3. Пользователь сможет использовать стандартные средства поиска и фильтрации платформы по этой колонке.

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

Важное замечание по типам данных: Помните, что Артикул — это строка. Сортировка строковых данных в 1С происходит посимвольно. Если ваши артикулы состоят из цифр разной длины (например, "1", "2", "10"), то при сортировке по возрастанию "10" может оказаться между "1" и "2". Чтобы избежать этого, артикулы должны иметь фиксированную длину с ведущими нулями или приводиться к числовому типу в промежуточной ТаблицеЗначений.

← На главную