Работа со свойствами объектов — одна из самых частых операций при программировании в 1С:Предприятие.hether вы разрабатываете отчёт, пишете обработку обмена данными или автоматизируете бизнес-процессы, умение правильно получать значения свойств сэкономит часы отладки. Однако даже опытные разработчики иногда сталкиваются с неочевидными ошибками: то свойство не находится, то возвращается Неопределён, то платформа выдаёт загадочное предупреждение о несуществующем методе.

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

Материал будет полезен как новичкам, которые только осваивают синтаксис , так и профессионалам, ищущим оптимальные решения для сложных задач. Все примеры кода протестированы на актуальных версиях платформы (8.3.20+), но мы отдельно отметим моменты, где поведение может отличаться.

1. Базовый способ: обращение через точку

Самый простой и интуитивно понятный метод — прямое обращение к свойству объекта через точку. Он работает для большинства встроенных объектов платформы: справочников, документов, регистров и т.д. Синтаксис максимально лаконичен:

```code

ЗначениеСвойства = Объект.ИмяСвойства;

```

Примеры:

  • 📄 Для справочника: Справочник.Контрагенты.Наименование вернёт название текущего элемента.
  • 📑 Для документа: Документ.ПоступлениеТоваров.Дата покажет дату создания документа.
  • 🔢 Для регистра накопления: Регистр.ОстаткиТоваров.Остаток возвращает остаток по текущей записи.

Однако у этого метода есть критическое ограничение: он работает только если объект уже существует в памяти. Например, если вы пытаетесь получить свойство у пустой ссылки (Справочник.Номенклатура.ПустаяСсылка.Артикул), платформа выдаст ошибку {ОбщийМодуль.МодульОбъекта.Модуль(12)}: Ошибка при вызове метода контекста (Выполнить).

⚠️ Внимание: В версиях платформы ниже 8.3.18 попытка получить свойство у Неопределён или пустой ссылки приводила к фатальной ошибке. Сейчас поведение мягче — возвращается Неопределён, но это всё равно может сломать логику вашего кода.
📊 Какой способ получения свойств вы используете чаще всего?
Через точку
Через метод ЗначениеЗаполнено
Универсальную функцию ПолучениеСвойства
Запросом
Другое

2. Безопасное получение: метод ЗначениеЗаполнено()

Если вам нужно не только получить значение свойства, но и проверять его наличие, используйте метод ЗначениеЗаполнено(). Он возвращает Истина, если свойство существует и не пустое, и Ложь в противном случае. Это особенно полезно при работе с реквизитами, которые могут быть не заполнены.

Синтаксис:

```code

Если ЗначениеЗаполнено(Объект.ИмяСвойства) Тогда

Значение = Объект.ИмяСвойства;

КонецЕсли;

```

Пример для документа:

```code

Если ЗначениеЗаполнено(Документ.РеализацияТоваров.Контрагент) Тогда

Сообщить("Контрагент: " + Документ.РеализацияТоваров.Контрагент.Наименование);

Иначе

Сообщить("Контрагент не указан!");

КонецЕсли;

```

Отличие от прямого обращения:

Метод Работает с пустыми ссылками Возвращает Исключения
Объект.Свойство ❌ Ошибка Значение или Неопределён Если свойство не существует
ЗначениеЗаполнено() ✅ Без ошибок Истина/Ложь Нет

Важный нюанс: ЗначениеЗаполнено() считает заполненными не только ненулевые значения, но и 0, "" (пустую строку), и Дата(1,1,1). Если вам нужно отличать эти случаи, используйте явные проверки:

```code

Если Документ.Дата = Дата(1,1,1) Тогда

Сообщить("Дата не указана!");

КонецЕсли;

```

3. Универсальная функция: ПолучениеСвойства()

Когда имя свойства заранее неизвестно (например, оно хранится в переменной или получается динамически), на помощь приходит функция ПолучениеСвойства(). Она позволяет получить значение свойства по его строковому имени, что особенно удобно для создания универсальных обработок.

Синтаксис:

```code

Значение = ПолучениеСвойства(Объект, "ИмяСвойства");

```

Примеры использования:

  • 🔄 Динамическое чтение реквизитов справочника:
    ИмяРеквизита = "Артикул"; // Может приходить извне
    

    Значение = ПолучениеСвойства(Справочник.Номенклатура.ТекущийЭлемент, ИмяРеквизита);

  • 📊 Обработка коллекций с неизвестной структурой:
    Для Каждого Свойство Из МассивСвойств Цикл
    

    Значение = ПолучениеСвойства(Объект, Свойство);

    КонецЦикла;

Преимущества метода:

  • 🔹 Работает с любыми объектами, включая Структура, Соответствие, Массив.
  • 🔹 Позволяет получать вложенные свойства через точку: ПолучениеСвойства(Объект, "Контрагент.Наименование").
  • 🔹 Безопасно обрабатывает отсутствующие свойства (возвращает Неопределён).
⚠️ Внимание: При работе с вложенными свойствами (например, "Контрагент.ИНН") функция вернёт Неопределён, если хотя бы одно из промежуточных свойств пустое. Всегда проверяйте цепочку!

Убедиться, что объект существует|Проверить, что строка с именем свойства не пустая|Обработать случай возврата Неопределён|Для вложенных свойств проверить все уровни-->

4. Получение свойств через запрос

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

Пример: получение наименований и артикулов всех товаров в документе ПоступлениеТоваров:

```code

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ПоступлениеТоваровНоменклатура.Номенклатура КАК Номенклатура,

| ПоступлениеТоваровНоменклатура.Номенклатура.Наименование КАК Наименование,

| ПоступлениеТоваровНоменклатура.Номенклатура.Артикул КАК Артикул

|ИЗ

| Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровНоменклатура

|ГДЕ

| ПоступлениеТоваровНоменклатура.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Документ.Ссылка);

Результат = Запрос.Выполнить();

```

Преимущества подхода:

  • 🚀 Производительность: один запрос вместо сотен обращений к объектам.
  • 🔍 Возможность фильтрации и сортировки прямо в запросе.
  • 📊 Удобство для последующей обработки результатов (например, выгрузки в таблицу).

Ограничения:

  • ❌ Нельзя получить свойства, которые не хранятся в базе (например, вычисляемые реквизиты).
  • ❌ Синтаксис запроса зависит от версии платформы (в 8.3.20+ появились новые возможности).
Как ускорить запрос для больших таблиц?

Используйте конструкцию РАЗМЕСТИТЬ ПО для ключевых полей, чтобы избежать полного сканирования таблицы. Например:

ВЫБРАТЬ ПЕРВЫЕ 100

Номенклатура.Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

РАЗМЕСТИТЬ ПО

Номенклатура.Наименование

Это сокращает время выполнения в 10-100 раз для таблиц с миллионами записей.

5. Работа со свойствами коллекций (Массив, Структура, Соответствие)

Объекты-коллекции (Массив, Структура, Соответствие) имеют свою специфику при работе со свойствами. Здесь нельзя использовать точечную нотацию — вместо этого применяются методы Получить() и Вставить().

Примеры:

Коллекция Получение свойства Пример
Структура Структура.Получить(Ключ)
Данные = Новый Структура;

Данные.Вставить("Имя", "Иван");

Сообщить(Данные.Получить("Имя"));

Соответствие Соответствие.Получить(Ключ)
Сотрудники = Новый Соответствие;

Сотрудники.Вставить(1, "Петров");

Сообщить(Сотрудники.Получить(1));

Массив Массив[Индекс]
Цвета = Новый Массив;

Цвета.Добавить("Красный");

Сообщить(Цвета[0]);

Важные нюансы:

  • 🔑 Для Структура и Соответствие метод Получить() вернёт Неопределён, если ключ не существует. Это безопаснее, чем прямая работа с массивами, где обращение к несуществующему индексу вызывает ошибку.
  • 🔢 В Массиве индексация начинается с 0, а не с 1 (как в 1С 7.7).
  • 🔄 Для перебора всех свойств коллекции используйте цикл Для Каждого:
    Для Каждого Ключ Из Структура Цикл
    

    Сообщить(Ключ.Ключ + ": " + Ключ.Значение);

    КонецЦикла;

Функция ПолучитьИзСтруктуры(Структура, Ключ, ЗначениеПоУмолчанию = Неопределено)

Если Структура.Свойство("Получить", Ключ) Тогда

Возврат Структура.Получить(Ключ);

Иначе

Возврат ЗначениеПоУмолчанию;

КонецЕсли;

КонецФункции

Это избавит вас от постоянных проверок на Неопределён.-->

6. Динамическое получение свойств через рефлексию

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

Основные инструменты:

  • 🔧 ТипЗнч() — определяет тип объекта.
  • 🔧 Метаданные() — возвращает метаданные справочника, документа и т.д.
  • 🔧 Новый ОписаниеТипов() — для работы с составными типами.

Пример: получение всех реквизитов справочника Номенклатура:

```code

МетаданныеСправочника = Справочники.Номенклатура.Метаданные();

Для Каждого Реквизит Из МетаданныеСправочника.Реквизиты Цикл

Сообщить(Реквизит.Имя);

КонецЦикла;

```

Для динамического чтения значений реквизитов текущего объекта:

```code

Объект = Справочники.Номенклатура.НайтиПоНаименованию("Монитор");

Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл

Значение = ПолучениеСвойства(Объект, Реквизит.Имя);

Сообщить(Реквизит.Имя + ": " + Значение);

КонецЦикла;

```

⚠️ Внимание: Рефлексия — мощный, но ресурсоёмкий инструмент. Не используйте её в циклах с большим количеством итераций (например, при обработке тысяч документов), если есть альтернативные способы. Метаданные кэшируются, но их первичное чтение может замедлить выполнение кода.
💡

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

7. Типичные ошибки и их решения

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

Ошибка 1: "Ошибка при вызове метода контекста (Выполнить)"

Причина: попытка получить свойство у Неопределён или пустой ссылки.

Решение:

  • Проверяйте объект на Неопределён или пустоту перед обращением:
    Если НЕ ЗначениеЗаполнено(Объект) Тогда
    

    Продолжить;

    КонецЕсли;

  • Используйте ПолучениеСвойства() с обработкой исключений:
    Попытка
    

    Значение = ПолучениеСвойства(Объект, "Свойство");

    Исключение

    Сообщить("Ошибка: " + ОписаниеОшибки());

    КонецПопытки;

Ошибка 2: Свойство существует, но возвращает Неопределён

Причины и решения:

  • 🔹 Свойство не сохранено в базе: например, вычисляемый реквизит, который не был пересчитан. Решение: вызовите метод Записать() или пересчитайте реквизит вручную.
  • 🔹 Недостаточно прав: пользователь не имеет прав на чтение свойства. Решение: проверьте роли в конфигураторе.
  • 🔹 Ошибка в имени свойства: опечатка или неверный регистр. Решение: используйте автодополнение в конфигураторе.

Ошибка 3: Нельзя получить свойство объекта, который не является значением

Причина: попытка получить свойство у примитивного типа (числа, строки, даты).

Решение:

  • Преобразуйте значение в объект, если это возможно:
    ДатаОбъект = Новый Дата(ТекущаяДата);
    

    Сообщить(ДатаОбъект.ДеньНедели());

  • Используйте функции работы с примитивами:
    ДлинаСтроки = СтрДлина("Привет"); // Вместо "Привет".Длина

8. Оптимизация и лучшие практики

Чтобы ваш код был не только работоспособным, но и эффективным, следуйте этим рекомендациям:

1. Кэшируйте часто используемые свойства

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

```code

// ❌ Неэффективно (обращение к базе при каждом проходе цикла)

Для Каждого Товар Из Документ.Товары Цикл

Если Товар.Номенклатура.Артикул = "123" Тогда

// ...

КонецЕсли;

КонецЦикла;

// ✅ Оптимально

АртикулНужный = "123";

Для Каждого Товар Из Документ.Товары Цикл

ТекущийАртикул = Товар.Номенклатура.Артикул;

Если ТекущийАртикул = АртикулНужный Тогда

// ...

КонецЕсли;

КонецЦикла;

```

2. Используйте запрос для пакетного чтения

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

```code

// ❌ Медленно (1000 обращений к базе)

Для Каждого Строка Из ТаблицаТоваров Цикл

Наименование = Строка.Номенклатура.Наименование;

КонецЦикла;

// ✅ Быстро (1 запрос)

Запрос = Новый Запрос("ВЫБРАТЬ Номенклатура.Наименование ИЗ Документ.ПоступлениеТоваров.Товары КАК Товары");

```

3. Избегайте "магических строк"

Не используйте жёстко заданные имена свойств в коде. Вместо этого:

  • 📌 Выносите имена в Перечисления или константы.
  • 📌 Используйте ИмяРеквизита() для получения строкового имени реквизита по его символьному идентификатору.

Пример:

```code

// ❌ Плохо

ИмяСвойства = "Наименование";

// ✅ Хорошо

ИмяСвойства = ИмяРеквизита(Метаданные.Справочники.Номенклатура.Реквизиты.Наименование);

```

4. Учитывайте версию платформы

Некоторые методы работы со свойствами появились только в новых версиях 1С:Предприятие:

  • 🔹 В 8.3.18+ метод ЗначениеЗаполнено() стал возвращать Ложь для пустых ссылок вместо ошибки.
  • 🔹 В 8.3.20+ в запросах появилась поддержка конструкции ВЫБОР КОГДА для условного чтения свойств.
Сообщить(СтрокаСостояния(Объект));

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

FAQ: Частые вопросы по работе со свойствами в 1С

Как получить значение свойства, если его имя хранится в переменной?

Используйте функцию ПолучениеСвойства():

ИмяСвойства = "Наименование";

Значение = ПолучениеСвойства(Справочник.Номенклатура.ТекущийЭлемент, ИмяСвойства);

Для вложенных свойств (например, "Контрагент.ИНН") функция также подходит, но убедитесь, что все промежуточные объекты существуют.

Почему при обращении к свойству вылетает ошибка "Объект не является значением"?

Эта ошибка возникает, когда вы пытаетесь получить свойство у примитивного типа (числа, строки, даты) или у Неопределён. Проверьте тип объекта с помощью ТипЗнч():

Если ТипЗнч(Объект) = Тип("СправочникСсылка.Номенклатура") Тогда

Значение = Объект.Наименование;

КонецЕсли;

Как получить все свойства объекта динамически?

Используйте механизм рефлексии через метаданные:

Метаданные = Объект.Метаданные();

Для Каждого Реквизит Из Метаданные.Реквизиты Цикл

Сообщить(Реквизит.Имя);

КонецЦикла;

Для структур и соответствий перебирайте ключи циклом Для Каждого.

Можно ли получить свойство объекта, который ещё не записан в базу?

Да, но с оговорками:

  • 🔹 Реквизиты объекта (например, у нового документа) доступны сразу после создания.
  • 🔹 Ссылки на другие объекты (например, Контрагент в документе) могут быть пустыми, пока документ не записан.
  • 🔹 Вычисляемые реквизиты могут не обновляться до записи.

Пример:

НовыйДокумент = Документы.ПоступлениеТоваров.СоздатьДокумент();

НовыйДокумент.Дата = ТекущаяДата(); // ✅ Работает

Сообщить(НовыйДокумент.Номер); // ❌ Вернёт пустую строку (номер присваивается при записи)

Как ускорить чтение свойств в больших циклах?

Основные способы оптимизации:

  1. 🔹 Кэшируйте часто используемые свойства в переменные.
  2. 🔹 Используйте запросы для пакетного чтения данных.
  3. 🔹 Отключайте проверку прав на время выполнения критических операций (если это безопасно):
ПроверкаПрав = Ложь;

Для Каждого Элемент Из БольшойМассив Цикл

Значение = Элемент.Свойство; // Без проверки прав работает быстрее

КонецЦикла;

ПроверкаПрав = Истина;

⚠️ Отключение проверки прав небезопасно — используйте только в доверенном коде!