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

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

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

  1. Мгновенное обновление подчиненной таблицы при быстром перемещении по строкам основной таблицы вызывает микрофризы и сильные зависания интерфейса («лаги») из-за постоянных запросов к серверу.
  2. Случайное добавление пустых строк в конец таблицы при обычном перемещении вниз с помощью клавиш-стрелок на клавиатуре.

В этой статье мы подробно разберем, как элегантно решить обе проблемы с использованием стандартов разработки «1С» и лучших практик оптимизации производительности интерфейса.

---

Часть 1: Оптимизация обновления подчиненной таблицы (Дебаунсинг в 1С)

Выясним причину зависания интерфейса. Когда пользователь зажимает стрелку «Вниз» для быстрого поиска нужного документа в первой таблице, событие ПриАктивизацииСтроки срабатывает для каждого промежуточного документа. Если в этом событии напрямую вызывать обновление второй таблицы, платформа начнет выполнять серверные вызовы десятки раз в секунду. Это перегружает базу данных и блокирует интерфейс клиента.

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

Разберем по шагам реализацию данного механизма на клиенте:

Шаг 1. Обработка события активации строки

В модуле формы для первой (основной) таблицы создадим обработчик события ПриАктивизацииСтроки. В нем мы будем отключать ранее зарегистрированный обработчик ожидания и сразу подключать его заново.


&НаКлиенте
Процедура СписокДокументовПриАктивизацииСтроки(Элемент)
    
    // Сбрасываем таймер, если пользователь продолжает перемещаться по строкам
    ОтключитьОбработчикОжидания("Подключаемый_ОбновитьТаблицуТоваров");
    
    // Запускаем таймер заново с задержкой 0.3 секунды.
    // Обратите внимание: для субсекундных интервалов (менее 1 сек.) 
    // параметр "Однократно" должен быть равен Истина.
    ПодключитьОбработчикОжидания("Подключаемый_ОбновитьТаблицуТоваров", 0.3, Истина);
    
КонецПроцедуры

Шаг 2. Реализация подключаемой процедуры

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


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

Важное предупреждение о производительности:

Ни в коем случае не делайте контекстных вызовов сервера внутри обработчиков событий навигации без крайней необходимости! Передача всего контекста формы туда и обратно сильно бьет по производительности. Рекомендуется использовать директиву &НаСервереБезКонтекста, передавая на сервер только ссылку на документ, получать массив строк и заполнять подчиненную таблицу на клиенте. Посмотрим на пример такой оптимизации:


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

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

Этот подход гарантирует моментальный отклик интерфейса даже при работе через веб-клиент или при медленном интернет-соединении.

---

Часть 2: Отключение автоматического ввода новой строки

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

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

Способ 1. Использование свойства «АвтоВводНовойСтроки» (Рекомендуемый)

Самый простой и правильный способ решить проблему — изменить настройки элемента формы. Рассмотрим, как это сделать:

  1. Откройте форму в конфигураторе.
  2. Выберите нужный элемент формы типа «Таблица» (например, СписокДокументов или Товары).
  3. В панели свойств найдите раздел «Поведение».
  4. Найдите свойство «АвтоВводНовойСтроки» (в некоторых версиях интерфейса — «Авто ввод новой строки») и снимите с него флажок (установите значение Ложь).

Также это свойство можно регулировать программно, например, при создании формы на сервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Элементы.Товары.АвтоВводНовойСтроки = Ложь;
    
КонецПроцедуры

После этого при нажатии стрелки «Вниз» на последней строке фокус просто останется на ней же, а новая пустая строка создаваться не будет.

Способ 2. Ограничение изменения состава строк

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

Для полной блокировки возможности ручного добавления или удаления строк выполните программную настройку:

Элементы.Товары.ИзменятьСоставСтрок = Ложь;

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

Способ 3. Перехват события «ПередНачаломДобавления»

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

Посмотрим на пример кода:


&НаКлиенте
Процедура ТоварыПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, Параметр)
    
    // Блокируем любое интерактивное добавление новых строк
    Отказ = Истина;
    ПоказатьПредупреждение(, "Добавление строк вручную запрещено. Таблица заполняется автоматически!");
    
КонецПроцедуры

Способ 4. Режим «Только просмотр»

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

Элементы.Товары.ТолькоПросмотр = Истина;

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

---

Резюме

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

← На главную