Разработка и Конфигурация · 11 мин
Как обратиться к элементу документа 1С
Как обратиться к реквизитам, табличным частям и ссылке документа в 1С: синтаксис встроенного языка, работа через объект и запрос, типичные ошибки разработчика.
Обращение к элементу документа — базовая операция при разработке и доработке конфигураций 1С. Под «элементом» обычно понимают реквизит шапки, строку табличной части, ссылку на документ или сам объект документа в памяти. Способ обращения зависит от контекста: код выполняется в модуле объекта, в форме, во внешней обработке или в запросе — и в каждом случае синтаксис отличается.
Главное, что нужно понимать с самого начала: в 1С существуют два принципиально разных представления документа. Ссылка (ДокументСсылка) — это лёгкий идентификатор, через который можно читать реквизиты, но нельзя изменять данные. Объект (ДокументОбъект) — полная структура данных в памяти, которую можно редактировать и записывать. Путаница между ними — причина большинства ошибок новичков.
Ниже разобраны основные сценарии: обращение к реквизитам шапки, перебор табличной части, работа через запрос, обращение из модуля формы и типичные ошибки с методами их диагностики.
Разница между ссылкой и объектом документа
Ссылка на документ — это значение типа ДокументСсылка.ИмяДокумента. Она содержит уникальный идентификатор и позволяет читать реквизиты через точку: при обращении платформа неявно выполняет чтение данных из базы. Однако присвоить значение реквизиту через ссылку нельзя — попытка вызовет ошибку исполнения.
Объект документа получают методом ПолучитьОбъект() от ссылки или методом СоздатьДокумент() у менеджера документа. Объект загружает в память все реквизиты и табличные части, позволяет их менять и записывать методом Записать(). За это приходится платить производительностью: чтение объекта тяжелее чтения отдельных полей через ссылку или запрос.
// Чтение через ссылку
НомерДок = СсылкаНаДокумент.Номер;
// Изменение — только через объект
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокОбъект.Комментарий = "Проверен";
ДокОбъект.Записать();
Как обратиться к реквизитам шапки документа
Реквизиты шапки доступны через точку от ссылки или объекта. Имя реквизита в коде должно точно совпадать с именем, заданным в конфигураторе, — регистр букв значения не имеет, но само имя должно быть идентичным. Стандартные реквизиты (Номер, Дата, Проведен, ПометкаУдаления) доступны всегда, даже если в конфигураторе не добавлен ни один пользовательский реквизит.
Если реквизит ссылочного типа, через точку можно «провалиться» глубже: СсылкаНаДокумент.Контрагент.Наименование. Учтите, что каждое такое разыменование — отдельное обращение к базе. В циклах и при массовой обработке лучше получать нужные поля одним запросом.
Обращение к несуществующему реквизиту вызывает ошибку «Поле объекта не обнаружено». Перед обращением к реквизиту, который может отсутствовать в разных версиях конфигурации, проверяйте его наличие через метаданные.
// Проверка существования реквизита
МетаданныеДок = СсылкаНаДокумент.Метаданные();
Если МетаданныеДок.Реквизиты.Найти("Проект") <> Неопределено Тогда
Проект = СсылкаНаДокумент.Проект;
КонецЕсли;
Работа с табличной частью документа
Табличная часть доступна как коллекция строк через точку от объекта или ссылки: ДокОбъект.Товары. Через ссылку табличную часть можно только читать (перебирать и обращаться к строкам), через объект — также добавлять, удалять и изменять строки.
Типовой перебор строк выполняется циклом Для Каждого. К колонке строки обращаются через точку: Строка.Номенклатура, Строка.Количество. Для добавления строки используется метод Добавить(), для удаления — Удалить(Строка) или Очистить() для всей табличной части.
// Перебор и изменение строк табличной части
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Для Каждого Строка Из ДокОбъект.Товары Цикл
Если Строка.Количество = 0 Тогда
Строка.СтавкаНДС = Неопределено;
КонецЕсли;
КонецЦикла;
// Добавление новой строки
НоваяСтрока = ДокОбъект.Товары.Добавить();
НоваяСтрока.Номенклатура = НайденнаяНоменклатура;
НоваяСтрока.Количество = 1;
ДокОбъект.Записать();
К отдельной строке можно обратиться по индексу: ДокОбъект.Товары[0] — первая строка (индексация с нуля). Поиск строк по значению колонки выполняют методами Найти(Значение, "ИмяКолонки") и НайтиСтроки(ПараметрыОтбора).
- 1Получите объект документа: ДокОбъект = Ссылка.ПолучитьОбъект()
- 2Переберите строки циклом или найдите нужные через НайтиСтроки()
- 3Измените значения колонок или добавьте/удалите строки
- 4Вызовите ДокОбъект.Записать() с нужным режимом проведения
- 5Проверьте результат, открыв документ в пользовательском режиме
Обращение к документу через запрос
Когда нужно прочитать данные многих документов, встроенный запрос — правильный инструмент. В тексте запроса к реквизитам обращаются через точку от имени таблицы документа, а табличная часть доступна как отдельная виртуальная таблица вида Документ.РеализацияТоваровУслуг.Товары.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка КАК Ссылка,
| Реализация.Контрагент КАК Контрагент,
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК Товары
| ПО Реализация.Ссылка = Товары.Ссылка
|ГДЕ
| Реализация.Проведен";
Результат = Запрос.Выполнить().Выбрать();
Результат запроса перебирают методом Следующий() у выборки: Пока Результат.Следующий() Цикл ... КонецЦикла. Обращение к полям выборки — через точку по псевдониму, заданному в секции ВЫБРАТЬ.
Сравнение способов доступа
Подходит для чтения 1–2 реквизитов одного документа; нельзя изменять данные, при массовом чтении медленно.
Единственный способ изменить и записать документ; тяжёлый для больших выборок, блокирует запись другим сеансам.
Оптимален для чтения множества документов и соединения с другими таблицами; только чтение, требует знания языка запросов.
Обращение из модуля объекта и формы документа
В модуле объекта документа (например, в обработчиках ПередЗаписью, ОбработкаПроведения) к реквизитам обращаются напрямую, без префикса: Контрагент, Товары.Итог("Сумма"). Можно также использовать ЭтотОбъект.Контрагент — результат тот же, но явное указание улучшает читаемость при работе со свойствами объекта.
В модуле формы данные документа лежат в реквизите формы, обычно Объект. Обращение выглядит как Объект.Контрагент или Объект.Товары[0].Цена. Важно: на клиенте доступны не все серверные методы, а вызов Записать() у реквизита формы недоступен — для записи используют метод формы Записать() или переносят логику на сервер через директиву &НаСервере.
Как найти документ и проверить результат обращения
Часто обращению к элементу предшествует поиск самого документа. Используются методы менеджера: Документы.РеализацияТоваровУслуг.НайтиПоНомеру(Номер, Дата) или НайтиПоРеквизиту("ИмяРеквизита", Значение). Оба возвращают ссылку; если документ не найден, результат — пустая ссылка, которую проверяют методом Пустая() или функцией ЗначениеЗаполнено().
Обращение к реквизиту пустой ссылки не вызовет исключения, но вернёт неопределённые значения, что приведёт к логическим ошибкам дальше по коду. Поэтому проверка результата поиска — обязательный шаг перед обращением к реквизитам.
НайденныйДок = Документы.ЗаказПокупателя.НайтиПоНомеру("000001", ТекущаяДатаСеанса());
Если НайденныйДок.Пустая() Тогда
Сообщить("Документ не найден");
Возврат;
КонецЕсли;
КонтрагентДокумента = НайденныйДок.Контрагент;
Как проверить результат
Ссылка не пустая, Ссылка.Пустая() = Ложь
Пустая ссылка — обращение к реквизитам даст пустые значения
Возвращается значение ожидаемого типа
Ошибка «Поле объекта не обнаружено» — имя реквизита не совпадает с конфигуратором
Записать() выполняется без исключения, изменения видны в форме
Конфликт блокировок или ошибка проверки заполнения — документ открыт другим сеансом или не заполнены обязательные реквизиты
Типичные ошибки при обращении к элементам документа
Самая частая ошибка — попытка изменить реквизит через ссылку: СсылкаНаДокумент.Комментарий = "текст". Платформа выдаст ошибку, так как ссылка предназначена только для чтения. Вторая по частоте — обращение к табличной части по имени, которое отличается от заданного в конфигураторе (например, Товары вместо Материалы).
Ещё одна группа проблем связана с контекстом: вызов серверных методов на клиенте в управляемой форме, использование ЭтотОбъект в модуле формы (там он недоступен) или обращение к реквизитам формы из модуля объекта. Диагностируйте такие ошибки по тексту исключения и директивам компиляции процедур.
Часто задаваемые вопросы
Как обратиться к реквизиту документа, если известна только строка с его именем?
Используйте квадратные скобки: Значение = СсылкаНаДокумент[ИмяРеквизита], где ИмяРеквизита — строковая переменная. Это удобно в универсальных обработках, когда имя реквизита заранее неизвестно. Для табличных частей такой способ тоже работает: ДокОбъект[ИмяТабличнойЧасти].
Чем отличается ЭтотОбъект от Ссылка в модуле документа?
ЭтотОбъект — сам редактируемый объект документа в памяти, через него доступны все реквизиты и табличные части для чтения и изменения. Ссылка — только идентификатор этого документа в базе; до записи нового документа ссылка может быть пустой. В модуле объекта для работы с данными используйте ЭтотОбъект или обращайтесь к реквизитам напрямую.
Можно ли обратиться к табличной части документа без получения объекта?
Да, через ссылку табличная часть доступна для чтения: СсылкаНаДокумент.Товары вернёт коллекцию строк, которую можно перебрать. Однако каждое такое обращение читает данные из базы, поэтому для массовой обработки лучше использовать запрос к таблице Документ.ИмяДокумента.ИмяТабличнойЧасти.
Почему возникает ошибка «Поле объекта не обнаружено»?
Имя реквизита или табличной части в коде не совпадает с именем в конфигураторе, либо обращение идёт к значению другого типа — например, к ссылке на справочник как к документу. Проверьте точное имя в дереве конфигурации и тип переменной через ТипЗнч() перед обращением.
Как обратиться к движениям документа по регистрам?
Через объект: ДокОбъект.Движения.ИмяРегистра — коллекция записей, доступная в обработке проведения и после записи. Для чтения движений уже проведённого документа правильнее использовать запрос к таблице регистра с отбором по полю Регистратор = СсылкаНаДокумент.
Как узнать, есть ли у документа нужная табличная часть?
Через метаданные: СсылкаНаДокумент.Метаданные().ТабличныеЧасти.Найти("ИмяЧасти") — если результат Неопределено, табличной части нет. Это стандартный приём для универсальных обработок, работающих с разными видами документов.
Что важно запомнить
Ссылка — для чтения, объект — для изменения и записи. Реквизиты читаются через точку, табличная часть перебирается циклом, массовое чтение выполняется запросом. Всегда проверяйте результат поиска документа на пустую ссылку и вызывайте Записать() после изменений объекта.