Почему компилятор 1С не видит имя и как это исправить в коде

· 10 мин

Содержание

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

Чаще всего причин три: опечатка в имени, обращение к серверным данным из клиентского кода (или наоборот) и реквизит, который удалили или переименовали в метаданных, а код остался старым. Ниже — как отличить один случай от другого, где искать строку и как писать код, чтобы ошибка не возвращалась.

Как 1С проверяет имена и почему ошибка всплывает до запуска кода

В 1С 8.3 модуль компилируется целиком, прежде чем выполнится хоть одна строка. На этом этапе платформа сверяет каждое имя со списком известных в данном контексте. Не нашла — модуль не компилируется, и вы видите сообщение вида:

{Документ.РеализацияТоваровУслуг.МодульОбъекта(42,15)}: Переменная не определена (СуммаДокумета)

Здесь 42 — номер строки, 15 — позиция в строке. В Конфигураторе двойной щелчок по сообщению открывает модуль на этом месте.

Отсюда важное следствие: ошибка относится ко всему модулю, а не к одной процедуре. Даже если кривая строка стоит в процедуре, которую никто не вызывает, модуль не скомпилируется. Пользователь увидит ошибку при открытии формы, проведении документа или запуске внешней обработки — в тот момент, когда платформе впервые понадобился этот модуль.

Откуда компилятор берёт «известные» имена:

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

В 1С нет режима обязательного объявления переменных. Присваивание Имя = Значение само создаёт локальную переменную. Поэтому ошибку даёт именно ЧТЕНИЕ неизвестного имени: в правой части присваивания, в условии, в параметре вызова.

Типичные ситуации, в которых возникает «Переменная не определена»

Опечатка в имени

Самый частый случай. Переменную объявили под одним именем, а читают под другим:

СуммаДокумента = 0;
Для Каждого СтрокаТЧ Из Товары Цикл
    СуммаДокумента = СуммаДокумета + СтрокаТЧ.Сумма; // пропущена «н»
КонецЦикла;

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

Частая разновидность опечатки — латинская буква в русском слове: Сyмма с латинской «y» или Cчёт с латинской «C». Глазом не отличить. Выручает поиск по модулю (Ctrl+F) по правильному написанию: если строка не находится, внутри имени чужая буква.

Обращение к форме из процедуры без контекста

В модуле управляемой формы процедура с директивой &НаСервереБезКонтекста не видит ни данных формы, ни её реквизитов:

&НаСервереБезКонтекста
Процедура ЗаполнитьКомментарийНаСервере()
    Объект.Комментарий = "Заполнено автоматически"; // Переменная не определена (Объект)
КонецПроцедуры

Варианта исправления два. Первый — сменить директиву на &НаСервере, тогда на сервер уйдут данные формы. Второй, более экономный по трафику, — передать нужное значение параметром и вернуть результат функцией:

&НаКлиенте
Процедура Заполнить(Команда)
    Объект.Комментарий = ТекстКомментария(Объект.Контрагент);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ТекстКомментария(Контрагент)
    Возврат "Контрагент: " + Строка(Контрагент);
КонецФункции

То же касается Элементы и ЭтаФорма — в процедурах без контекста их нет.

Серверные объекты в клиентском коде

На тонком клиенте нет доступа к базе данных. Поэтому в процедуре &НаКлиенте не определены Справочники, Документы, РегистрыСведений, ПараметрыСеанса и другие менеджеры прикладных объектов:

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Валюта = Справочники.Валюты.НайтиПоКоду("643"); // Переменная не определена (Справочники)
КонецПроцедуры

Для предопределённых элементов и пустых ссылок на клиенте есть функция ПредопределенноеЗначение("Справочник.Валюты.ПустаяСсылка"). Всё, что требует запроса к базе, выносят в серверную функцию.

Область видимости переменных: модуль, процедура, клиент и сервер

Локальные переменные и переменные модуля

Локальная переменная живёт, пока выполняется процедура. В соседней процедуре её имени нет. Если два метода должны работать с одним значением, есть три пути:

  1. Передать значение параметром — самый прозрачный вариант.
  2. Вернуть его из функции.
  3. Объявить переменную модуля через Перем в начале модуля, до первой процедуры.

Переменные модуля формы: у клиента и сервера свои

В модуле управляемой формы переменная модуля объявляется с директивой и существует только в своём контексте:

&НаКлиенте
Перем КэшЦен;

Такую переменную видят только клиентские процедуры. Серверная процедура этой формы прочитать КэшЦен не может — получите Переменная не определена (КэшЦен). Переменная модуля с директивой &НаСервере тоже не спасает: серверный контекст формы между вызовами не сохраняется, и значение каждый раз начинается заново.

Если данные нужны и клиенту, и серверу формы, создайте реквизит формы. Он передаётся между контекстами и доступен с обеих сторон.

Глобальные переменные

В общих модулях раздела переменных нет совсем — объявить там Перем нельзя. «Глобальную» переменную для клиента объявляют в модуле управляемого приложения со словом Экспорт. На сервере она недоступна.

Где нужна переменнаяЧем заменить
В нескольких процедурах одного модуляПеременная модуля (Перем в начале модуля)
На клиенте и на сервере формыРеквизит формы
Во всех клиентских модулях сеансаЭкспортная переменная модуля управляемого приложения
На сервере в течение сеансаПараметр сеанса (объект метаданных «Параметры сеанса»)
Повторно вычисляемое значениеОбщий модуль с повторным использованием возвращаемых значений

Реквизиты объектов и форм: почему имя реквизита «не видно»

Модуль объекта и модуль формы обращаются к реквизитам по-разному

В модуле объекта реквизиты доступны напрямую по имени: Если СуммаДокумента = 0 Тогда. В модуле управляемой формы прямого доступа нет. Реквизиты объекта лежат внутри основного реквизита формы, обычно он называется Объект:

// модуль объекта — так можно
Если Не ЗначениеЗаполнено(Контрагент) Тогда

// модуль управляемой формы — нужно через Объект
Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда

Код, перенесённый из модуля объекта в форму без правки, даёт ошибку на каждом реквизите. Обратный перенос — тоже: в модуле объекта имени Объект нет, там используют ЭтотОбъект.

Реквизит удалили или переименовали

Ещё одна частая причина — изменение метаданных. Разработчик переименовал реквизит, а в одном из модулей осталось старое имя. Поведение при этом разное:

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

Переименование через свойства объекта в Конфигураторе не правит код автоматически. Перед переименованием найдите все упоминания через глобальный поиск Ctrl+Shift+F по всей конфигурации.

Похожие ошибки, которые путают с этой

Текст ошибкиКогда возникаетЧто означает
Переменная не определена (Х)При компиляции модуляИмя без точки не известно в этом контексте
Процедура или функция с указанным именем не определена (Х)При компиляцииВызван метод, которого нет или который недоступен из этого контекста
Тип не определен (Х)При выполнении Новый ХТип не существует или недоступен в контексте, например Новый Запрос на клиенте
Поле объекта не обнаружено (Х)При выполненииЧерез точку запрошено свойство, которого у объекта нет
Метод объекта не обнаружен (Х)При выполненииЧерез точку вызван несуществующий метод
Значение не является значением объектного типа (Х)При выполненииПеременная есть, но в ней Неопределено или примитивное значение
Диагностика: выберите симптом

Диагностика: как найти строку с ошибкой и проверить все модули

Проверка синтаксиса одного модуля

Откройте модуль в Конфигураторе и нажмите Ctrl+F7. Платформа проверит синтаксис и выведет ошибки в окно сообщений. Двойной щелчок по строке сообщения ставит курсор на место ошибки.

Проверка учитывает директивы компиляции, поэтому обращение к Справочники в клиентской процедуре будет поймано сразу.

Проверка всей конфигурации

Если ошибка всплыла после доработки или объединения конфигураций, проверять модули по одному долго. Откройте Конфигурация → Проверка конфигурации:

  1. Отметьте флажок логической целостности и проверку модулей.
  2. Выберите режимы, в которых работают пользователи: тонкий клиент, веб-клиент, сервер, внешнее соединение.
  3. Нажмите «Выполнить» и пройдите по списку сообщений.

Проверка по каждому режиму отдельно важна: модуль может нормально компилироваться на сервере и падать в тонком клиенте.

Отладчик для ошибок при выполнении

Компиляционная ошибка ловится проверкой синтаксиса. Но если имя собирается строкой и выполняется через Выполнить() или Вычислить(), компилятор его заранее не видит:

ТекстКода = "Результат = Цена * Количество";
Выполнить(ТекстКода); // Переменная не определена (Количество), если её нет в процедуре

Здесь поможет отладчик. Поставьте точку останова (F9) перед вызовом, запустите отладку (F5) и посмотрите в табло, какие переменные существуют на этот момент. Строку, переданную в Выполнить(), выводите в окно сообщений перед вызовом — так видно, какое имя на самом деле пришло.

В 1С:EDT неизвестные имена подсвечиваются прямо при наборе, без отдельной проверки. Для больших доработок это экономит много проходов «изменил — проверил».

Ошибка появилась у пользователя: что делать без программиста

Бухгалтер обычно видит это сообщение не в коде, а при открытии документа, отчёта или внешней обработки. Что можно сделать самостоятельно:

  • 🔍 Ошибка при открытии внешней обработки или отчёта (файл .epf/.erf). Обработка написана под другую конфигурацию или старый релиз. Запросите у автора версию под ваш релиз.
  • 🔍 Ошибка сразу после обновления типовой конфигурации. Скорее всего, в базе есть доработки или расширения, которые ссылаются на старые имена. Посмотрите список расширений в Администрирование → Печатные формы, отчеты и обработки → Расширения и попробуйте временно отключить подозрительное расширение — только по согласованию с тем, кто отвечает за базу.
  • 🔍 Ошибка в типовой базе без доработок. Проверьте, что обновление прошло до конца, а не прервалось на середине. Скопируйте полный текст ошибки с именем модуля и номером строки — без этого программисту придётся искать вслепую.

Не открывайте модули в Конфигураторе рабочей базы «посмотреть и поправить». Любая правка снимает типовую конфигурацию с полной поддержки или требует включения возможности изменений. Сначала — резервная копия базы и согласование с ответственным за конфигурацию.

Как писать код, чтобы ошибка не повторялась

Несколько привычек, которые почти исключают «Переменная не определена»:

  1. Объявляйте переменные явно. Строка Перем Итог; в начале процедуры или стартовое присваивание Итог = 0; делают намерение очевидным.
  2. Используйте контекстную подсказку. Начните имя и нажмите Ctrl+Пробел — Конфигуратор подставит имя без опечаток и предложит только то, что доступно в этом месте.
  3. Ставьте директиву каждой процедуре формы. Процедура без директивы в форме считается серверной. Явная директива сразу показывает, к чему здесь есть доступ.
  4. По умолчанию берите &НаСервереБезКонтекста, а данные передавайте параметрами. Ошибку про Объект вы увидите при первой проверке синтаксиса, а не у пользователя.
  5. Не храните общее состояние в переменных модуля формы. Для обмена между клиентом и сервером есть реквизиты формы.
  6. Переименовывайте через поиск. Перед сменой имени реквизита ищите упоминания по всей конфигурации, включая расширения и внешние обработки.
  7. Запускайте Проверку конфигурации перед выпуском. Особенно после объединения конфигураций и обновления на новый релиз.
  8. Пишите одним алфавитом. Держите раскладку под контролем при наборе русских имён.

Частые вопросы

Почему ошибка показывает строку, которая никогда не выполняется?
Модуль компилируется целиком до запуска. Неизвестное имя в любой процедуре, даже неиспользуемой, ломает весь модуль.
Можно ли включить обязательное объявление переменных, как Option Explicit?
Встроенного режима нет. Присваивание всегда создаёт локальную переменную. Опечатки в левой части ловят внимательная проверка, контекстная подсказка и средства EDT.
Почему код работает в толстом клиенте, а в тонком падает?
В толстом клиенте доступны объекты базы данных, в тонком — нет. Проверяйте конфигурацию в режиме тонкого клиента и выносите обращения к базе на сервер.
Что значит текст в фигурных скобках перед ошибкой?
Это адрес: имя модуля, номер строки и позиция в строке. По нему программист открывает точное место в Конфигураторе.
Помогут ли очистка кэша или перезапуск 1С?
Нет. Это ошибка в тексте модуля, а не сбой среды. Нужна правка кода, обновление обработки или отключение несовместимого расширения.