Как обойти реквизиты объекта на управляемой форме и как работают логические операторы в 1С?

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

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

Анализ проблемы: почему возникает ошибка «Получение элемента по индексу для значения не определено»?

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

Попытка реализовать это через следующий код приводит к ошибке:


&НаСервере
Функция ПроверочнаяСумма()
    Для Каждого Рек из Элементы Цикл
        Сообщить(рек.Имя + " - " + Строка(рек.Вид) + " - " + Объект[Рек]);
    КонецЦикла;
КонецФункции

Проанализируем причины сбоя:

  1. Неверная индексация: В выражении Объект[Рек] переменная Рек является объектом встроенного языка (тип ПолеФормы, ГруппаФормы или кнопка), а не строкой. Платформа 1С не умеет обращаться к свойствам структуры данных по ссылке на визуальный элемент управления, поэтому возвращает ошибку «Получение элемента по индексу для значения не определено».
  2. Несоответствие имен элементов и реквизитов: Попытка исправить код на Объект[Рек.Имя] также может завершиться ошибкой «Поле объекта не обнаружено». Имя визуального элемента на форме далеко не всегда совпадает с именем реквизита данных, к которому он привязан. Кроме того, на форме могут присутствовать декорации, группы или кнопки, у которых вообще нет связанных данных.

Решение №1: Обход реквизитов через метаданные объекта

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

На управляемой форме объект представлен типом данных ДанныеФормыСтруктура. Чтобы получить доступ к его метаданным, нам необходимо временно преобразовать его в прикладной объект на сервере. Для этого воспользуемся методом РеквизитФормыВЗначение().

Рассмотрим рабочий программный код:


&НаСервере
Функция ПроверочнаяСумма()
    
    // Преобразуем данные формы в реальный объект обработки
    ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
    КоличествоОтмеченных = 0;
    
    // Обходим коллекцию реквизитов из метаданных объекта
    Для Каждого Реквизит Из ОбработкаОбъект.Метаданные().Реквизиты Цикл
        
        // Получаем значение реквизита по его имени
        Значение = ОбработкаОбъект[Реквизит.Имя];
        
        // Проверяем тип данных и значение флажка
        Если ТипЗнч(Значение) = Тип("Булево") И Значение Тогда
            КоличествоОтмеченных = КоличествоОтмеченных + 1;
        КонецЕсли;
        
        Сообщить(Реквизит.Имя + " - " + Реквизит.Тип + " - " + Значение);
    КонецЦикла;
    
    Возврат КоличествоОтмеченных;
    
КонецФункции

Преимущества этого подхода: Мы полностью застрахованы от ошибок, связанных с элементами оформления формы. Код анализирует только реальные данные объекта, независимо от того, выведены ли они на экран и как именно называются элементы интерфейса.

Решение №2: Использование свойства «ПутьКДанным»

Если реквизиты добавлены непосредственно на форму (а не в объект обработки) или нам нужно работать именно с элементами интерфейса, мы должны использовать свойство ПутьКДанным элементов формы.

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


&НаСервере
Функция ПроверочнаяСуммаПоЭлементам()
    
    Сумма = 0;
    
    Для Каждого Элемент Из Элементы Цикл
        
        // Нам интересны только поля формы, у которых есть связь с данными
        Если ТипЗнч(Элемент) = Тип("ПолеФормы") И Элемент.Вид = ВидПоляФормы.ПолеФлажка Тогда
            
            ПутьКДанным = Элемент.ПутьКДанным;
            
            // Проверяем, что путь ведет к реквизиту объекта (например, "Объект.ИмяФлажка")
            Если СтрНачинаетсяС(ПутьКДанным, "Объект.") Тогда
                
                // Извлекаем чистое имя реквизита
                ИмяРеквизита = Сред(ПутьКДанным, 8); // отсекаем "Объект."
                
                // Безопасно получаем значение из структуры Объект
                Если Объект[ИмяРеквизита] = Истина Тогда
                    Сумма = Сумма + 1;
                КонецЕсли;
                
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЦикла;
    
    Возврат Сумма;
    
КонецФункции

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

Особенности логических операций: «Ленивые вычисления» в 1С

В процессе обсуждения на форуме возник важный вопрос: как именно работают логические операторы И и ИЛИ в 1С? Проверяется ли вся цепочка условий или вычисления прекращаются при первом несоответствии?

В платформе 1С:Предприятие 8 реализован механизм «ленивых» (коротких) вычислений. Это означает, что логическое выражение вычисляется строго слева направо и только до тех пор, пока результат не станет однозначно ясен.

Рассмотрим, как это работает на практике:

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


Если СсылкаНаДокумент <> Неопределено И СсылкаНаДокумент.Проведен Тогда
    // Выполняем действия с проведенным документом
КонецЕсли;

Если бы ленивых вычислений не существовало, то в случае, когда переменная СсылкаНаДокумент равна Неопределено, программа попыталась бы обратиться к свойству Проведен и выдала бы критическую ошибку «Значение не является значением объектного типа». Благодаря короткому вычислению в 1С 8.х, как только первая часть условия возвращает Ложь, система мгновенно прекращает дальнейшие проверки, предотвращая аварийное завершение работы.

Историческая справка: В старой платформе 1С:Предприятие 7.7 ленивых вычислений не было. Программистам приходилось конструировать громоздкие вложенные условия, чтобы избежать падения программы:


// Так приходилось писать в 1С 7.7
Если ПустоеЗначение(СсылкаНаДокумент) = 0 Тогда
    Если СсылкаНаДокумент.Проведен = 1 Тогда
        // Код обработки
    КонецЕсли;
КонецЕсли;

Современный синтаксис 1С v8.3 позволяет писать этот код лаконично, безопасно и в одну строку.

Кратко о работе с JSON в 1С:Предприятие 8

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

Для быстрой работы с JSON-строками используются методы ПрочитатьJSON() и ЗаписатьJSON(). Они позволяют преобразовывать коллекции 1С (такие как Структура, Массив, Соответствие) в JSON-строку и обратно буквально в несколько строк кода:


// Пример записи структуры в JSON
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ДанныеДляЗаписи = Новый Структура("Имя, Статус", "Масянька", Истина);
ЗаписатьJSON(Запись, ДанныеДляЗаписи);
РезультатСтрока = Запись.Закрыть();
Сообщить(РезультатСтрока); // Выведет {"Имя":"Масянька","Статус":true}

Для работы с большими файлами JSON рекомендуется использовать потоковые объекты ЧтениеJSON и ЗаписьJSON, которые позволяют читать и записывать данные порциями, минимизируя нагрузку на оперативную память сервера.

← На главную