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

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

1. Прямое обращение через ссылку на документ

Самый очевидный и простой способ — получить ссылку на документ и обратиться к его реквизиту напрямую. Этот метод работает, если у вас уже есть ссылка (например, из поля СсылкаНаДокумент в текущем объекте) или вы можете её получить через стандартные механизмы платформы.

Пример кода для получения номера документа "Заказ покупателя" по его ссылке:

СсылкаНаЗаказ = Документы.ЗаказПокупателя.НайтиПоНомеру("000000001", Дата);

Если Не СсылкаНаЗаказ.Пустая() Тогда

НомерЗаказа = СсылкаНаЗаказ.Номер;

Сообщить("Номер заказа: " + НомерЗаказа);

КонецЕсли;

  • Плюсы: максимальная простота, минимальный код.
  • ⚠️ Минусы: требует загрузки объекта в память (может быть медленно для больших документов).
  • 🔄 Когда использовать: для разовых операций с небольшим количеством документов.
⚠️ Внимание: Если документ ещё не проведён или удалён, прямое обращение вызовет ошибку. Всегда проверяйте существование объекта через метод Пустая() или ЭтоГруппа() (для справочников).
📊 Какой способ обращения к чужим документам вы используете чаще?
Прямое обращение через ссылку
Запросы
Менеджер значений
Объектные методы (ПолучитьОбъект и т.п.)

2. Использование метода ПолучитьОбъект()

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

Пример для работы с УникальнымИдентификатором:

УидДокумента = "a1b2c3d4-5678-90ef-1234-567890abcdef";

ДокументОбъект = Документы.РеализацияТоваровУслуг.ПолучитьОбъект(УидДокумента);

Если ДокументОбъект <> Неопределён Тогда

ДатаДокумента = ДокументОбъект.Дата;

КонецЕсли;

Этот метод удобен при интеграции с внешними системами, где передаются именно идентификаторы, а не ссылки. Однако он имеет ограничения:

  • 🔍 Работает только для существующих документов (иначе вернёт Неопределён).
  • 🚫 Не подходит для удалённых или помеченных на удаление документов.
  • ⚡ Может быть медленнее, чем работа со ссылками, из-за внутренних проверок.
💡

Для ускорения работы с ПолучитьОбъект() предварительно проверьте наличие документа через запрос к базе — это сэкономит ресурсы, если объект не существует.

3. Работа через запросы (SELECT)

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

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

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

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

"ВЫБРАТЬ

| ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,

| ПоступлениеТоваровУслуг.Дата КАК Дата,

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

|ИЗ

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

|ГДЕ

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

Запрос.УстановитьПараметр("Номер", "000000005");

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

Выборка = Результат.Выбрать();

Если Выборка.Следующий() Тогда

Сообщить("Дата: " + Выборка.Дата + ", Сумма: " + Выборка.Сумма);

КонецЕсли;

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

  • 📊 Можно получить данные многих документов за один запрос.
  • 🔒 Безопасно для удалённых или непроведённых документов (не вызовет ошибку).
  • ⚡ Оптимизировано для работы с большими базами (не грузит объекты в память).
⚠️ Внимание: В запросах нельзя напрямую обращаться к реквизитам объектов, которые не включены в выборку. Например, если вы выбрали только Ссылка, то Выборка.Ссылка.Номер работать не будет — нужно явно указывать все нужные поля в ВЫБРАТЬ.
Метод Скорость Безопасность Когда использовать
Прямое обращение ⚡ Быстро (для 1 документа) ❌ Риск ошибок Разовые операции
ПолучитьОбъект() 🐢 Медленно ⚠️ Требует проверок Интеграция по UID
Запросы ⚡⚡ Очень быстро ✅ Максимальная Массовая обработка

4. Обращение к реквизитам через МенеджерЗначений

Если вам нужно получить значение реквизита без загрузки всего документа, можно использовать МенеджерЗначений. Этот метод полезен, когда документ большой, а нужен только один реквизит.

Пример для получения контрагента из документа "Счёт на оплату":

СсылкаНаСчёт = Документы.СчётНаОплату.НайтиПоНомеру("СЧ-0001", ТекущаяДата());

Менеджер = Новый МенеджерЗначения(СсылкаНаСчёт);

Контрагент = Менеджер.Получить("Контрагент");

Сообщить("Контрагент: " + Контрагент.Наименование);

МенеджерЗначений удобен в следующих случаях:

  • 📄 Нужно получить один-два реквизита из большого документа.
  • 🔄 Документ часто изменяется, и вы не хотите блокировать его на чтение.
  • 🛠️ Работаете с динамическими реквизитами (которые могут отсутствовать).
Что делать, если МенеджерЗначений возвращает Неопределён?

Это означает, что реквизит не существует в документе или документ не найден. Проверьте:

1. Правильность ссылки на документ.

2. Наличие реквизита в метаданных (возможно, опечатка в имени).

3. Права доступа текущего пользователя к документу.

5. Работа с реквизитами в транзакциях

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

Пример проблемного кода:

НачатьТранзакцию();

Док = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

Док.Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");

Док.Записать();

// ❌ ОШИБКА: пытаемся прочитать несохранённый документ

Сумма = Док.СуммаДокумента; // Может вернуть 0 или неактуальное значение

ЗафиксироватьТранзакцию();

Как правильно:

  1. 🔄 Читать реквизиты ДО начала транзакции (если они не меняются).
  2. 🔒 Использовать уровни изоляции транзакций (например, УстановитьУровеньИзоляции(УровеньИзоляцииТранзакций.ПовторяемоеЧтение)).
  3. 📊 Для критичных операций — читать данные через запрос с указанием ДЛЯ ИЗМЕНЕНИЯ.
⚠️ Внимание: В 1С:Предприятие 8.3.20+ изменилось поведение транзакций при работе с реквизитами документов. Если вы используете старые версии, тестируйте код на блокировки в многопользовательском режиме.

Убедиться, что документ существует (не Пустая())

Проверить права доступа текущего пользователя

Оценить необходимость транзакции

Подумать о производительности (запрос vs прямое обращение)-->

6. Особенности работы с удалёнными и непроведёнными документами

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

Как обращаться к реквизитам в зависимости от состояния:

Состояние документа Метод обращения Риски
Проведённый Любой (прямое обращение, запросы, менеджер) ✅ Без рисков
Непроведённый Прямое обращение или менеджер ⚠️ Движения не сформированы
Помечен на удаление Только через запросы с ПометкаУдаления = Ложь ❌ Ошибка при прямом обращении
Удалённый Только архивные запросы ❌ Данные могут быть неполными

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

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

"ВЫБРАТЬ

| ЗаказПокупателя.Ссылка КАК Ссылка,

| ЗаказПокупателя.Дата КАК Дата

|ИЗ

| Документ.ЗаказПокупателя КАК ЗаказПокупателя

|ГДЕ

| ЗаказПокупателя.ПометкаУдаления = Ложь

| И ЗаказПокупателя.Номер = &Номер";

💡

Всегда проверяйте состояние документа перед работой с его реквизитами. Для помеченных на удаление документов используйте фильтр ПометкаУдаления = Ложь в запросах.

7. Оптимизация производительности при массовой обработке

Если вам нужно обработать реквизиты тысяч документов, прямой перебор через ПолучитьОбъект() или Ссылка.Реквизит приведёт к тормозам. В таких случаях используйте:

  • 📊 Пакетные запросы с ограничением по 100–500 документов за раз.
  • 🔄 Временные таблицы для промежуточных данных.
  • Асинхронные операции (для фоновых задач).
  • 🗃️ Кэширование часто используемых реквизитов (например, в Соответствие).

Пример оптимизированного запроса для массового чтения:

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

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

"ВЫБРАТЬ ПЕРВЫЕ 500

| Реализация.Ссылка КАК Ссылка,

| Реализация.Контрагент КАК Контрагент,

| Реализация.СуммаДокумента КАК Сумма

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания";

Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("ДатаОкончания", КонецМесяца(ТекущаяДата()));

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

Для ещё большей производительности можно использовать планы обмена или регламентные задания, если обработка не требует мгновенного результата.

FAQ: Частые вопросы по работе с реквизитами документов

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

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

Как получить реквизит документа из другой базы (распределённой информационной системы)?

Для этого используйте планы обмена или веб-сервисы. Пример через план обмена:

УзелОбмена = ПланыОбмена.ОсновнойПланОбмена.НайтиУзелПоИмени("Склад");

Данные = УзелОбмена.ПолучитьДанные();

Документ = Данные.ПолучитьДокумент("РеализацияТоваровУслуг", УидДокумента);

Убедитесь, что у вас настроены права доступа и синхронизация между базами.

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

Причины могут быть следующие:

  1. Документ удалён или помечен на удаление.
  2. Не хватает прав доступа у текущего пользователя.
  3. Ссылка на документ некорректна (например, из другой базы).
  4. Реквизит удален из конфигурации или переименован.

Проверьте существование документа через Ссылка.Пустая() и права пользователя.

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

Используйте метод НайтиПоНомеру():

Ссылка = Документы.ЗаказПокупателя.НайтиПоНомеру("000000010", ТекущаяДата());

Если Не Ссылка.Пустая() Тогда

Контрагент = Ссылка.Контрагент;

КонецЕсли;

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

Можно ли изменить реквизит чужого документа напрямую?

Технически — да, но это крайне не рекомендуется. Изменение документов в обход бизнес-логики может привести к:

  • 🔄 Нарушению последовательности проводок.
  • 📊 Рассинхронизации итогов и регистров.
  • 🚫 Ошибкам при проверке связей документов.

Используйте стандартные методы Записать() и Провести() или создавайте отдельные документы корректировки.