Почему в 1С 7.7 возникает ошибка «Не выбран документ!» и зачем использовать метод НайтиДокумент()

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

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

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

Рассмотрим по шагам два примера кода, которые вызывают у начинающих разработчиков массу вопросов.

Пример 1 (нерабочий вариант):


Док43 = СоздатьОбъект("Документ");
Док43 = Оп.Документ;
Док43.СделатьНеПроведенным();

Пример 2 (рабочий вариант):


Док43 = СоздатьОбъект("Документ");
Док43.НайтиДокумент(Оп.Документ);
Док43.СделатьНеПроведенным();

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

Однако на второй строчке Док43 = Оп.Документ; происходит критическая ошибка. Вместо того чтобы передать ссылку внутрь ранее созданного объекта, мы полностью перезаписываем значение переменной Док43. Теперь в этой переменной хранится обычное значение типа «Документ» — то есть простая ссылка на запись в базе данных. Выделенный ранее объектный контекст безвозвратно теряется в памяти (уничтожается сборщиком мусора).

Поскольку у простой ссылки нет контекста для модификации данных в СУБД, попытка вызвать метод СделатьНеПроведенным() на третьей строчке приводит к закономерной системной ошибке «Не выбран документ!».

В чем разница между Ссылкой и Объектом в 1С 7.7

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

Давайте структурируем различия между этими понятиями в 1С 7.7:

  1. Ссылка на документ (значение типа «Документ»). Это всего лишь указатель на запись в таблице базы данных. Ссылку можно получить из реквизитов других объектов (например, Оп.Документ), передать в качестве параметра в процедуры и функции, использовать для сравнения или вывести в печатную форму. Ссылка предназначена исключительно для чтения базовых свойств и идентификации записи. Изменить документ через ссылку невозможно.
  2. Объект документа (контекст, созданный через СоздатьОбъект). Это полноценный программный инструмент, предоставляющий интерфейс для изменения данных. Чтобы объект понял, с какой именно записью в базе данных ему предстоит работать, его необходимо позиционировать.

Именно для позиционирования объекта и связывания его с конкретной ссылкой служит метод НайтиДокумент(), который мы видим в рабочем примере №2. Этот метод загружает данные конкретного документа из базы данных в оперативный объектный контекст, подготавливая его к редактированию или проведению.

Альтернативные методы позиционирования объекта

Помимо метода НайтиДокумент(), в платформе 1С 7.7 существуют и другие способы спозиционировать созданный объект на нужную запись в базе данных:

Если объект не был спозиционирован ни одним из этих методов, то даже попытка прочитать его реквизиты (например, написать Сообщить(Док43.НомерДок);) вернет пустое значение.

Особенности работы метода СделатьНеПроведенным()

Разберем важный нюанс работы с методом СделатьНеПроведенным(), который часто становится причиной рассинхронизации данных в 1С 7.7.

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

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

Влияние типизации при создании объектов на производительность системы

Обратим внимание на то, как именно создается объект в примерах:

Док43 = СоздатьОбъект("Документ");

Такой вызов создает объект неопределенного вида. С точки зрения архитектуры СУБД (неважно, используется ли файловая версия DBF или клиент-серверная MS SQL), это заставляет платформу обращаться к общей таблице журнала документов — 1SJOURN. При поиске конкретного документа системе приходится тратить дополнительные ресурсы на анализ метаданных всех существующих в системе видов документов.

Если вам заранее известен вид обрабатываемого документа, мы настоятельно рекомендуем использовать строгую типизацию при создании объекта:

Док43 = СоздатьОбъект("Документ.РасходнаяНакладная");

Рассмотрим, какие преимущества дает такой подход:

  1. Повышение скорости работы базы данных. Объект сразу связывается со специализированными физическими таблицами шапки (DH*) и табличной части (DT*) конкретного вида документа, минуя лишние запросы к общему журналу.
  2. Доступ к специфическим реквизитам. В процессе написания кода вам сразу становятся доступны уникальные реквизиты шапки и табличной части этого вида документа (которых нет у обобщенного объекта «Документ»).

Резюме и правила хорошего тона в коде 1С 7.7

Подводя итог нашему разбору, зафиксируем основные правила работы с документами в 1С 7.7, которые уберегут вас от ошибок:

← На главную