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