Как запретить интерактивное добавление некорректной строки в список регистра сведений

Программист 1С v8.3 (Обычные формы)
← На главную

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

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

Разбор механики события ПередОкончаниемРедактирования

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

  1. Элемент — ссылка на само табличное поле. Через него мы можем получить доступ к ТекущиеДанные.
  2. НоваяСтрока — булево значение. Принимает Истина, если строка была только что создана (через кнопку «Добавить» или «Копировать»), и Ложь, если редактируется уже существующая запись.
  3. ОтменаРедактирования — важнейший флаг. Он становится Истина, если пользователь сам инициировал отмену изменений (например, нажал клавишу Esc).
  4. Отказ — если мы установим этот параметр в значение Истина, платформа заблокирует попытку завершить редактирование и оставить фокус на строке.

Рассмотрим ситуацию, с которой столкнулся автор темы: если просто ставить Отказ = Истина при некорректных данных, пользователь попадает в «ловушку». Он не может сохранить плохие данные, но и не может просто закрыть строку, если передумал вводить запись. Система требует от него либо ввести правильные данные, либо... а «либо» не срабатывает, если логика написана неверно.

Правильное решение: использование флага ОтменаРедактирования

Чтобы предоставить пользователю возможность выйти из режима редактирования без сохранения ошибочной строки (например, нажатием Esc), мы должны игнорировать проверку данных, если платформа уже пометила это действие как отмену. Выясним причину: если ОтменаРедактирования уже равна Истина, система и так не собирается записывать данные в базу. Если же мы в этот момент установим Отказ = Истина, мы заблокируем саму отмену!

Рассмотрим пример правильного кода:


Процедура РегистрСведенийСписокПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
    
    // 1. Если пользователь сам нажал Esc (ОтменаРедактирования = Истина), 
    // нам не нужно проверять данные и мешать ему выйти.
    Если ОтменаРедактирования Тогда
        Возврат;
    КонецЕсли;

    // 2. Проверяем наши условия валидности данных.
    // Допустим, мы вызываем функцию ЗапрещеноКорректироватьСменуПоВремени.
    Если ЗапрещеноКорректироватьСменуПоВремени(Элемент.ТекущиеДанные.ДатаЛитья) Тогда
        
        // Сообщаем пользователю, что не так
        Сообщить("Указанная дата слишком стара для редактирования!", СтатусСообщения.Внимание);
        
        // 3. Устанавливаем Отказ, чтобы не дать строке записаться.
        Отказ = Истина;
        
        // Если это была новая строка, и мы хотим дать возможность пользователю 
        // просто нажать Esc для ее удаления из списка:
        // Никаких дополнительных действий не требуется, просто Отказ = Истина 
        // при ОтменаРедактирования = Ложь.
    КонецЕсли;

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

Важный нюанс: Обратите внимание, что в коде выше мы не используем ОтменаРедактирования = Истина программно. Этот параметр предназначен для чтения состояния системы. Установка Отказ = Истина — единственный надежный способ прервать запись в этом событии.

Альтернативные способы контроля (на уровне модели данных)

Хотя решение в форме (интерфейсное) работает отлично для удобства пользователя, опытные разработчики знают, что проверку стоит дублировать или переносить на уровень модуля набора записей. Проанализируем ситуацию: если данные в регистр попадут не через форму, а через программный код или обмен данными, ваша проверка в форме не сработает.

Рассмотрим, как реализовать жесткий запрет в модуле набора записей регистра сведений:


// В модуле набора записей регистра
Процедура ПередЗаписью(Отказ, Замещение)
    
    Для Каждого Запись Из ЭтотОбъект Цикл
        Если Запись.ДатаЛитья < '20200101' Тогда
            Сообщить("Запись данных за прошлые периоды запрещена на уровне сервера.");
            Отказ = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Такой подход гарантирует целостность базы данных, однако с точки зрения UX (User Experience) он менее приятен: пользователь узнает об ошибке только после нажатия «ОК» или Enter, и строка может просто «вылететь» с системной ошибкой.

Использование события ПриИзменении для мгновенной реакции

Чтобы сделать интерфейс еще более дружелюбным, мы можем проверять данные не в момент закрытия всей строки, а сразу после заполнения конкретного поля (например, даты). Разберем по шагам:

  1. Откроем форму списка регистра.
  2. Выберем колонку «Дата».
  3. Создадим обработчик события ПриИзменении.

Процедура РегистрСведенийСписокДатаЛитьяПриИзменении(Элемент)
    
    ТекущиеДанные = ЭлементыФормы.РегистрСведенийСписок.ТекущиеДанные;
    
    Если ТекущиеДанные <> Неопределено Тогда
        Если ТекущиеДанные.ДатаЛитья < НачалоГода(ТекущаяДата()) Тогда
            Предупреждение("Вы ввели дату прошлого года. Пожалуйста, исправьте значение.");
            // Можно даже очистить поле или вернуть старое значение, если оно было сохранено
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Комбинирование методов ПриИзменении (для оперативного информирования) и ПередОкончаниемРедактирования (для окончательного запрета записи) является «золотым стандартом» разработки в 1С.

Резюме и рекомендации

Подводя итог нашему исследованию, выделим основные правила работы с интерактивным вводом в списках:

Рассмотренные нами приемы позволяют создавать надежные и понятные интерфейсы, которые не вводят пользователя в ступор и сохраняют данные в консистентном состоянии.

← На главную