Почему аварийно завершается платформа 1С при установке отбора в табличном поле и как скрыть пустые строки контактной информации?

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

При сопровождении типовых конфигураций на обычных формах (например, «1С:Управление торговлей 10.3») разработчики нередко сталкиваются с необходимостью кастомизации интерфейса справочника Контрагенты. Одной из частых задач является скрытие незаполненных строк на вкладке «Контакты» в табличном поле КонтактнаяИнформация. Однако попытка динамической фильтрации этих строк через свойства элемента управления может приводить к аварийному закрытию толстого клиента платформы «1С:Предприятие 8.3».

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

Анализ причин сбоя и падения платформы

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


ЭлементыФормы.КонтактнаяИнформация.ОтборСтрок.Представление.Значение = ""; 
ЭлементыФормы.КонтактнаяИнформация.ОтборСтрок.Представление.ВидСравнения = ВидСравнения.Содержит;
ЭлементыФормы.КонтактнаяИнформация.ОтборСтрок.Представление.Использование = Истина;

Выясним причину, по которой данная конструкция приводит к падению платформы в операционных системах Windows 10 и Windows Server при работе на платформе 8.3. Здесь действуют сразу два критических фактора:

  1. Некорректный контекст вызова (рекурсивная перерисовка): событие ПриПолученииДанных предназначено исключительно для визуального оформления уже выбранных строк. Изменение свойства ОтборСтрок внутри этого события инициирует немедленное обновление состава отображаемых данных и повторный вызов графической подсистемы. Возникает бесконечная рекурсия, которая за доли секунды переполняет стек вызовов интерфейсного потока.
  2. Особенности поиска по строкам неограниченной длины: колонка Представление в типовой подсистеме контактной информации имеет тип «Строка неограниченной длины». Применение вида сравнения ВидСравнения.Содержит со значением пустой строки "" к строкам переменной структуры на уровне ядра платформы вызывает ошибку обращения к памяти (Access Violation), что мгновенно завершает рабочий процесс.

Способ 1. Исключение пустых строк в запросе чтения контактной информации (Рекомендуемый)

Проанализируем типовой механизм заполнения контактной информации в конфигурациях на обычных формах. В типовой УТ 10.3 табличное поле заполняется данными из регистра сведений КонтактнаяИнформация с добавлением пустых шаблонов для всех доступных видов контактной информации из справочника ВидыКонтактнойИнформации. Это сделано для того, чтобы пользователь мог сразу ввести телефон или адрес без ручного добавления новой строки.

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

  1. Откроем конфигуратор и перейдем в общий модуль УправлениеКонтактнойИнформацией.
  2. Найдем процедуру ПрочитатьКонтактнуюИнформацию.
  3. В тексте запроса найдем первую ветку подзапроса, которая выбирает все виды контактной информации из справочника и дополняет их пустыми полями.
  4. Установим жесткое условие ЛОЖЬ И в секции ГДЕ этой ветки объединения.

Посмотрим на итоговый пример сформированного текста запроса:


Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
               |    ВложенныйЗапрос.Вид КАК Вид,
               |    ВложенныйЗапрос.Тип КАК Тип,
               |    ВложенныйЗапрос.Объект КАК Объект,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле1) КАК Поле1,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле2) КАК Поле2,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле3) КАК Поле3,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле4) КАК Поле4,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле5) КАК Поле5,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле6) КАК Поле6,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле7) КАК Поле7,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле8) КАК Поле8,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле9) КАК Поле9,
               |    МАКСИМУМ(ВложенныйЗапрос.Поле10) КАК Поле10,
               |    МАКСИМУМ(ВложенныйЗапрос.Представление) КАК Представление,
               |    МАКСИМУМ(ВложенныйЗапрос.Комментарий) КАК Комментарий,
               |    МАКСИМУМ(ВложенныйЗапрос.ЗначениеПоУмолчанию) КАК ЗначениеПоУмолчанию,
               |    МАКСИМУМ(ВложенныйЗапрос.ТипДома) КАК ТипДома,
               |    МАКСИМУМ(ВложенныйЗапрос.ТипКорпуса) КАК ТипКорпуса,
               |    МАКСИМУМ(ВложенныйЗапрос.ТипКвартиры) КАК ТипКвартиры
               |ИЗ
               |    (ВЫБРАТЬ
               |        &Объект КАК Объект,
               |        ВидыКонтактнойИнформации.Тип КАК Тип,
               |        ВидыКонтактнойИнформации.Ссылка КАК Вид,
               |        """" КАК Представление,
               |        """" КАК Поле1,
               |        """" КАК Поле2,
               |        """" КАК Поле3,
               |        """" КАК Поле4,
               |        """" КАК Поле5,
               |        """" КАК Поле6,
               |        """" КАК Поле7,
               |        """" КАК Поле8,
               |        """" КАК Поле9,
               |        """" КАК Поле10,
               |        """" КАК Комментарий,
               |        ЛОЖЬ КАК ЗначениеПоУмолчанию,
               |        ЗНАЧЕНИЕ(Перечисление.ТипыДомов.ПустаяСсылка) КАК ТипДома,
               |        ЗНАЧЕНИЕ(Перечисление.ТипыКорпусов.ПустаяСсылка) КАК ТипКорпуса,
               |        ЗНАЧЕНИЕ(Перечисление.ТипыКвартир.ПустаяСсылка) КАК ТипКвартиры
               |    ИЗ
               |        Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации
               |    ГДЕ
               |        ЛОЖЬ И 
               |        (НЕ ВидыКонтактнойИнформации.ПометкаУдаления)
               |        И ВидыКонтактнойИнформации.ВидОбъектаКонтактнойИнформации = &ВидОбъектаКонтактнойИнформации
               |    
               |    ОБЪЕДИНИТЬ
               |    
               |    ВЫБРАТЬ
               |        РегистрСведенийКонтактнаяИнформация.Объект,
               |        РегистрСведенийКонтактнаяИнформация.Тип,
               |        РегистрСведенийКонтактнаяИнформация.Вид,
               |        ВЫРАЗИТЬ(РегистрСведенийКонтактнаяИнформация.Представление КАК СТРОКА(1000)),
               |        РегистрСведенийКонтактнаяИнформация.Поле1,
               |        РегистрСведенийКонтактнаяИнформация.Поле2,
               |        РегистрСведенийКонтактнаяИнформация.Поле3,
               |        РегистрСведенийКонтактнаяИнформация.Поле4,
               |        РегистрСведенийКонтактнаяИнформация.Поле5,
               |        РегистрСведенийКонтактнаяИнформация.Поле6,
               |        РегистрСведенийКонтактнаяИнформация.Поле7,
               |        РегистрСведенийКонтактнаяИнформация.Поле8,
               |        РегистрСведенийКонтактнаяИнформация.Поле9,
               |        РегистрСведенийКонтактнаяИнформация.Поле10,
               |        ВЫРАЗИТЬ(РегистрСведенийКонтактнаяИнформация.Комментарий КАК СТРОКА(1000)),
               |        РегистрСведенийКонтактнаяИнформация.ЗначениеПоУмолчанию,
               |        РегистрСведенийКонтактнаяИнформация.ТипДома,
               |        РегистрСведенийКонтактнаяИнформация.ТипКорпуса,
               |        РегистрСведенийКонтактнаяИнформация.ТипКвартиры
               |    ИЗ
               |        РегистрСведений.КонтактнаяИнформация КАК РегистрСведенийКонтактнаяИнформация
               |    ГДЕ
               |        РегистрСведенийКонтактнаяИнформация.Объект = &Объект) КАК ВложенныйЗапрос
               |
               |СГРУППИРОВАТЬ ПО
               |    ВложенныйЗапрос.Вид,
               |    ВложенныйЗапрос.Тип,
               |    ВложенныйЗапрос.Объект
               |
               |УПОРЯДОЧИТЬ ПО
               |    Представление УБЫВ,
               |    ВложенныйЗапрос.Тип.Порядок,
               |    Вид";

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

Способ 2. Корректная установка фильтра в событиях инициализации формы

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

Рассмотрим правила корректной работы со свойством ОтборСтрок:

  1. Перенос кода в события инициализации: настройка отбора должна выполняться однократно при открытии формы — в обработчиках ПередОткрытием или ПриОткрытии, либо сразу после вызова процедуры считывания контактных данных.
  2. Отказ от вида сравнения «Содержит» по пустой строке: вместо поиска подстроки следует использовать проверку на неравенство (ВидСравнения.НеРавно) либо специализированные проверки заполненности.
  3. Явное приведение типов: для предотвращения сбоев платформы убедимся, что строковое поле ограничено по длине с помощью функции ВЫРАЗИТЬ(... КАК СТРОКА(1000)) на уровне формирования источника данных.

Посмотрим на пример корректной установки отбора в процедуре формы:


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    // Устанавливаем отбор однократно до вывода элементов на экран
    ОтборПредставление = ЭлементыФормы.КонтактнаяИнформация.ОтборСтрок.Представление;
    ОтборПредставление.ВидСравнения = ВидСравнения.НеРавно;
    ОтборПредставление.Значение     = "";
    ОтборПредставление.Использование = Истина;
КонецПроцедуры

Сводные правила безопасной работы с табличными полями

Чтобы избежать аварийных падений платформы «1С:Предприятие» при работе со сложными элементами управления в обычных формах, зафиксируем основные правила:

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