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

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

При разработке интерфейсов в 1С:Предприятии часто возникает задача разделения визуального представления данных для удобства пользователя. Типичный пример: в документе есть одна табличная часть (например, СдельнаяОплата), содержащая разнородные данные, отличающиеся реквизитом ТипВремени (явка, ремонт, простой). Пользователь просит распределить эти строки по разным вкладкам на форме: на первой вкладке показывать только «Явку», а на второй — все остальные виды времени («Ремонт» и «Простой»).

Самое простое решение, которое сразу приходит на ум — использовать одну и ту же табличную часть на обеих вкладках, применив к каждой из них соответствующий визуальный отбор. Однако здесь разработчик сталкивается с неприятной особенностью платформы 1С: стандартное поле НомерСтроки жестко привязано к физическому индексу строки в базе данных. В результате на первой вкладке пользователь увидит строки с номерами 1, 2, 5, 7, а на второй — 3, 4, 6. Такая «рваная» нумерация путает пользователей и выглядит неэстетично.

В этой статье мы подробно разберем, почему так происходит, и рассмотрим три эффективных практических способа реализации независимой сквозной нумерации (1, 2, 3...) на каждой из вкладок.

Почему стандартный НомерСтроки не подходит для фильтруемых таблиц?

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

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

Решение 1. Разделение данных через временные реквизиты формы (Лучшая практика для управляемых форм)

Этот метод является наиболее архитектурно правильным и гибким для управляемого интерфейса 1С. Мы полностью отказываемся от непосредственного вывода реальной табличной части документа на форму. Вместо этого мы создаем два независимых реквизита формы с типом ТаблицаЗначений. Пользователь работает именно с ними, а перед записью документа данные программно объединяются обратно в реальную табличную часть.

Давайте пошагово разберем этот процесс:

  1. В редакторе формы перейдем на вкладку Реквизиты и создадим два новых реквизита формы с типом ТаблицаЗначений. Назовем их, например, ТЗ_Явка и ТЗ_РемонтПростой.
  2. Для обеих таблиц добавим точно такой же набор колонок, который присутствует в исходной табличной части документа СдельнаяОплата.
  3. Разместим эти таблицы на соответствующих вкладках формы. Поскольку это независимые таблицы значений, стандартное поле НомерСтроки (или индекс строки + 1) на каждой вкладке будет автоматически начинаться с единицы и идти строго по порядку (1, 2, 3...).

Теперь нам необходимо написать программный код для распределения данных при открытии формы и их слияния перед записью.

В модуле формы реализуем процедуру заполнения наших таблиц значений на сервере при создании формы:


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

После того как пользователь отредактировал данные, добавил новые строки или удалил ненужные, нам необходимо собрать эти данные обратно в единую табличную часть документа перед записью на сервере:


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

Преимущества данного подхода:

Решение 2. Использование расчетной колонки (Без разделения таблиц)

Если по каким-то причинам вы не хотите создавать дублирующие реквизиты на форме и желаете работать напрямую с объектом Объект.СдельнаяОплата, можно использовать программный пересчет номеров строк «на лету».

Для реализации этого способа выполним следующие шаги:

  1. Добавим в табличную часть документа новый реквизит с именем ВизуальныйНомер (тип Число, длина 5, точность 0).
  2. На форме для обеих табличных частей снимем флажок видимости у стандартного поля НомерСтроки.
  3. Выведем на форму колонку ВизуальныйНомер и установим для нее свойство ТолькоПросмотр = Истина.
  4. Напишем процедуру, которая будет динамически рассчитывать и заполнять это поле при любых изменениях в табличной части.

Рассмотрим пример кода такой процедуры пересчета:


&НаКлиенте
Процедура ПересчитатьВизуальныеНомера()
    
    СчетчикЯвка = 0;
    СчетчикПрочие = 0;
    
    Для Каждого СтрокаТЧ Из Объект.СдельнаяОплата Цикл
        
        Если СтрокаТЧ.ТипВремени = ПредопределенноеЗначение("Перечисление.ТипыВремени.Явка") Тогда
            СчетчикЯвка = СчетчикЯвка + 1;
            СтрокаТЧ.ВизуальныйНомер = СчетчикЯвка;
        Иначе
            СчетчикПрочие = СчетчикПрочие + 1;
            СтрокаТЧ.ВизуальныйНомер = СчетчикПрочие;
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

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

Например, обработчик изменения типа времени будет выглядеть следующим образом:


&НаКлиенте
Процедура СдельнаяОплатаТипВремениПриИзменении(Элемент)
    
    // Пересчитываем визуальные номера для обновления интерфейса
    ПересчитатьВизуальныеНомера();
    
КонецПроцедуры

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

Решение 3. Самый простой и быстрый вариант — Скрытие нумерации

Давайте проанализируем ситуацию с практической точки зрения. Часто ли пользователю действительно критически необходим порядковый номер строки на экране? В большинстве случаев нумерация строк носит исключительно декоративный характер и не несет в себе важной бизнес-логики.

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

При этом:

Резюме

Мы подробно разобрали проблему «рваной» нумерации при отображении одной табличной части на разных закладках формы и рассмотрели эффективные методы борьбы с ней.

Для простых задач, где нумерация не имеет значения, смело применяйте Решение 3 (скрытие колонки). Если же нумерация критически важна для пользователя, то для управляемых форм наилучшим выбором станет Решение 1 с разделением данных на уровне реквизитов формы. Оно гарантирует стабильное поведение интерфейса и сохраняет привычный функционал платформы 1С.

← На главную