Глобальная переменная 1С

Ошибка Переменная не определена в 1С 8.3 указывает на то, что программа не может получить нужную информацию в исполняемом программном коде. Это может быть связано с обновлением или доработкой программы. Если стандартный набор действий при исправлении ошибок не помог:

  • чистка кеша;
  • тестирование и исправление информационной базы;
  • просмотр зарегистрированных ошибок на сайте 1С,

придется разбираться с местом возникновения ошибки в 1С самостоятельно.

БухЭксперт8 подготовил 3 примера получения и исправления ошибки:

  • в доработанном программном коде;
  • при выводе печатной формы;
  • при исполнении кода на Клиенте.

Ошибка в доработанном программном коде

В форму типового отчета Движение товаров программист добавил поле Склад. Список выбора значений в это поле ограничен. При открытии отчета появляется ошибка:

В сообщении об ошибке указано место возникновения ошибки — строка 919 в модуле формы. Для исправления ошибки необходимо выполнить следующие действия:

  1. Нажмите кнопку Подробно в форме сообщения об ошибке.
    В окне Обнаружены ошибки программа укажет:
    • номер неправильной строки кода;
    • исполняемую команду, которая привела к ошибке. Иногда подробной информации в окне Обнаружены ошибки достаточно для понимания причин ее возникновения, но не всегда. В большинстве случаев требуется перейти в место возникновения ошибки и проанализировать используемые в команде данные.
  2. Для перехода в место ошибки нажмите кнопку Конфигуратор.
    В Конфирураторе курсор автоматически установится на строке программного кода с ошибкой. Необходимо проверить используемые командой данные. В данном примере ошибка сигнализирует, что переменной ОсновнойСклад не задано значение: при добавлении в список складов программа не понимает, какой склад требуется добавить.
  3. Исправьте ошибку.
    Укажите нужное значение переменной в программном коде, например:
    • ОсновнойСклад = Справочники.Склады.НайтиПоНаименованию(«Основной склад»);
    • ОсновнойСклад = Справочники.Склады.ОсновнойСклад.
      Синтаксис Справочники.Склады.ОсновнойСклад используется только для предопределенного склада с именем ОсновнойСклад:
  4. Сохраните изменения и обновите информационную базу.
  5. Проверьте работу 1С после исправления ошибки.

После исправления отчет открывается без ошибки, а при выборе складов устанавливается нужное значение Основной склад.

Ошибка вывода печатной формы

Для вывода в печатную форму накладной данных об ответственном менеджере, оформившем документ поступления, программист внес изменения в макет ПФ_MXL_Накладная и программный код.

В макет документа добавлена область Подвал:

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

После доработки программы при попытке вывода накладной на печать 1С выдает ошибку:

Информация в окне сообщения об ошибке указывает, что в Модуле менеджера документа ПоступлениеТоваровУслуг не определено значение переменной Ответственный. Для исправления ошибки:

  1. Перейдите в Конфигуратор. В Модуле менеджера документа ПоступлениеТоваровУслуг перейдите на строку 4804.
  2. Укажите для вывода в печатную форму поля Ответственный — текущего пользователя, используя специальную команду 1С:
    • Пользователи.ТекущийПользователь().
  3. Сохраните изменения и обновите информационную базу.
  4. Перейдите в пользовательский режим для проверки выполненных изменений.

После исправления программного кода накладная сформируется без ошибки.

Ошибка исполнения кода на Клиенте

С переходом на управляемые формы в Бухгалтерия 3.0 работы программистам прибавилось.

Язык программирования стал сложнее. Часть команд теперь могут выполняться только на стороне клиента — это, условно говоря, компьютер пользователя, который посылает запросы на исполнение операций серверу. Сервер обрабатывает все поступившие запросы и отсылает обратно клиенту результат обработки данных.

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

  • &НаКлиенте — переменные существуют только на время клиентского вызова;
  • &НаСервере— переменные существуют только на время серверного вызова.

Разделение команд в программном коде не зависит от того, используете ли вы файловую или клиент-серверную 1С. Разграничение должно четко исполняться, иначе будут возникать ошибки, одну из которых БухЭксперт8 разберет на примере.

При доработке программного кода программист использовал операцию получения данных склада &НаКлиенте в процедуре ПриОткрытии.

При сохранении изменений 1С сообщила об ошибке Переменная не определена (Справочники) при определении значения склада:

  • «?»Справочники.Склады.НайтиПоКоду(«»00-000002»).

Ошибка связана с тем, что данная операция исполняется только на сервере, т. е. &НаСервере. И несмотря на то, что сама команда исполнения корректна, ошибка будет формироваться до тех пор, пока ее не перенесут в область команд исполнения &НаСервере, например так:

Теперь сохранение изменений пройдет без ошибки.

Усложнение языка программирования 1С требует от разработчика более глубокого подхода к вносимым изменениям в программу. Недостаточно просто знать синтаксис команды, важно еще правильно задать область исполнения команды в режиме управляемых форм.

См. также:

  • Большое количество забивается решеткой
  • Печатная форма недоступна 1С 8.3 при вызове внешней печатной формы
  • Значение поля номер не уникально 1С 8.3: как исправить
  • У пользователя недостаточно прав на исполнение операции

Если Вы еще не подписаны:

Активировать демо-доступ бесплатно →

или

Оформить подписку на Рубрикатор →

После оформления подписки вам станут доступны все материалы по 1С Бухгалтерия, записи поддерживающих эфиров и вы сможете задавать любые вопросы по 1С.

Помогла статья?

Получите еще секретный бонус и полный доступ к справочной системе БухЭксперт8 на 14 дней бесплатно

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

Чтобы иметь к глобальной переменной 1С из другого модуля — необходимо объявить ее экспортной (слово ЭКСПОРТ после имени переменной 1С). Чтобы обратиться к такой переменной 1С необходимо написать имя модуля, точка, имя экспортной переменной 1С.

Далее — подробнее про переменные 1С, с примерами.

Создание переменной 1С в модуле, например:
ПЕРЕМ Переменная1;

Начальное значение у такой переменной 1С будет Неопределено (см. далее), пока далее в коде не будет присвоено явно другое значение.

ПЕРЕМ можно использовать только в начале модуля или в начале процедуры/функции. Нельзя использовать в общих модулях.

Так как переменную 1С гораздо проще создать, когда она нужна, просто назначив ей значение, например:
Переменная1 = 22;
, то ПЕРЕМ обычно используют для создания глобальных (экспортных) переменных 1С.

Простая переменная 1С доступна («видна») в том модуле (в той процедуре/функции), где она создана. Если же переменная 1С глобальная, то она будет видна из других модулей.

Особенностью является то, что переменные 1С объявленные внутри цикла, условия Если — видны во всей функции/процедуре, а не только в объявленной части модуля. Если при выполнении в данное «Если» захода не было, то значение переменной НЕОПРЕДЕЛЕНО.

Пример создания экспортной переменной 1С:

Только зарегистрированные пользователи VIP группы могут видеть этот контент.

Пример доступа к экспортной переменной 1С, созданной в модуле объекта справочника Номенклатура:

Только зарегистрированные пользователи VIP группы могут видеть этот контент.

Пример доступа к экспортной переменной 1С, созданной в модуле формы элемента справочника Номенклатура:

Только зарегистрированные пользователи VIP группы могут видеть этот контент.

Циклы применяются для выполнения каких либо повторяющихся действий, возможные варианты перебора в цикле:

Перебираем строки с помощью цикла Для каждого

Код 1C v 8.3 Для каждого ТекСтрока Из КоллекцияСтрок Цикл
// код обработки
КонецЦикла;

Перебираем строки с помощью цикла Пока

Код 1C v 8.3 Пока л < КолСтрок Цикл
// код обработки, например л=л+1;
КонецЦикла;

Перебираем строки с помощью цикла Для

Код 1C v 8.3 Для л=0 по КолСтрок Цикл
// код обработки, например л=л+1;
КонецЦикла

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

Код 1C v 8.3 ~НачалоЦикла:
Если л <> КоличествоИтераций Тогда
// код обработки, например л=л+1;
Перейти ~НачалоЦикла;
КонецЕсли;

Примеры циклов

Код 1C v 8.2 УП &НаКлиенте
Процедура ВыполнитьКод(Команда)
/// Как организовать цикл в 1с 8.3, 8.2
// Для Цикл
Для Счетчик = 1 По 5 Цикл
Сообщить(Счетчик); // 1 2 3 4 5
КонецЦикла;
// Для Каждого Цикл
Дни = Новый Массив();
Дни.Добавить(«Понедельник»);
Дни.Добавить(«Вторник»);
Дни.Добавить(«Среда»);
Для Каждого Элемент Из Дни Цикл
Сообщить(Элемент); // Понедельник Вторник Среда
КонецЦикла;
// Пока Цикл
Счетчик = 0;
Пока Счетчик < Дни.Количество() Цикл
Сообщить(Дни); // Понедельник Вторник Среда

Счетчик = Счетчик + 1;
КонецЦикла;
/// Как организовать обратный цикл в 1с 8.3, 8.2
Счетчик = Дни.Количество() — 1;
Пока Счетчик >= 0 Цикл
Сообщить(Дни); // Среда Вторник Понедельник
Счетчик = Счетчик — 1;
КонецЦикла;
/// Как прервать цикл в 1с 8.3, 8.2
Для Счетчик = 1 По 5 Цикл
Если Счетчик > 2 Тогда
Прервать;
КонецЕсли;
Сообщить(Счетчик); // 1 2
КонецЦикла;
/// Как принудительно продолжить цикл в 1с 8.3, 8.2
Для Счетчик = 1 По 5 Цикл
Если Счетчик <> 3 Тогда
Продолжить;
КонецЕсли;
Сообщить(Счетчик); // 3
КонецЦикла;
КонецПроцедуры

А какой цикл работает быстрее?

Итак, я нашел пять способов, как можно организовать цикл средствами 1С.

Первый вид цикла, назовем его условно «Для По» выглядит так:

Код 1C v 8.х Для н = 0 по КоличествоИтераций Цикл
КакиеТоДействия();
КонецЦикла;

Второй вид «Для Каждого»:

Код 1C v 8.х Для Каждого ЭлементКоллекции из Коллекция Цикл
КакиеТоДействия();
КонецЦикла;

Третий «Пока»:

Код 1C v 8.х Пока н <> КоличествоИтераций Цикл
КакиеТоДействия();
н = н + 1;
КонецЦикла;

Далее вспомнил ассемблерную молодость & цикл «Если»:

Код 1C v 8.х ~НачалоЦикла:
Если н <> КоличествоИтераций Тогда
КакиеТоДействия();
н = н + 1;
Перейти ~НачалоЦикла;
КонецЕсли;

Ну и напоследок «Рекурсия»

Код 1C v 8.х Процедура РекурсивныйЦикл(н, КоличествоИтераций)
КакиеТоДействия();
Если н <> КоличествоИтераций Тогда
РекурсивныйЦикл(н+1, КоличествоИтераций);
КонецЕсли;
КонецПроцедуры

Естественно, что относить рекурсию к циклам не совсем корректно, но тем ни менее с её помощью можно добиться похожих результатов. Сразу оговорюсь, что в дальнейшем тестировании рекурсия не участвовала. Во первых все тесты проводились при 1 000 000 итераций, а рекурсия выпадает уже при 2 000. Во вторых скорость рекурсии в десятки раз меньше, чем скорость остальных циклов.

Последнее отступление. Одним из условий было выполнение в цикле каких-либо действий. Во первых пустой цикл используется очень редко. Во вторых цикл «ДляКаждого» используется для какой-либо коллекции, а значит и остальные циклы должны работать с коллекцией, чтобы тестирование проходило в одинаковых условиях.

Ну что ж, поехали. В качестве тела цикла использовалось чтение из заранее заполненного массива.

Код 1C v 8.х ПриемникТестовогоЗначения = ТестовыйМассив.Получить(н);

или, при использовании цикла «Для Каждого»

Код 1C v 8.х ПриемникТестовогоЗначения = Элем;

Тестирование проводилось на платформе 8.3.5.1231 для трех видов интерфейса (Обычное приложение, Управляемое приложение и Такси).

Результаты для 8.3.5.1231

Интерфейс ДляПо ДляКаждого Пока Если
Обычное приложение 5734,2 4680,4 7235,4 7263,0
Управляемое приложение 5962,4 4882,6 7497,4 7553,6
Такси 5937,2 4854,6 7500,8 7513,0

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

Казалось бы и все, но & тестировать так тестировать!

Результаты для 8.2.19.106

Интерфейс ДляПо ДляКаждого Пока Если
Обычное приложение 4411,8 3497,2 5432,0 5454,0
Управляемое приложение 4470,8 3584,8 5522,6 5541,0

В среднем платформа 8.2 на 25% быстрее, чем 8.3. Я немножко не ожидал такой разницы и решил провести тест на другой машине. Скажу только, что там 8.2 была быстрее процентов на 20.

Почему? Не знаю, дезасемблировать ядро в мои планы не входило, но в замер производительности я все же заглянул. Оказалось, что сами циклические операции в 8.3 проходят несколько быстрее, чем в 8.2. Но на строке

Код 1C v 8.х ПриемникТестовогоЗначения = ТестовыйМассив.Получить(н);

то есть при считывании элемента коллекции в переменную происходит значительное снижение производительность.

Для себя я сделал несколько выводов:

1. Если есть возможность использовать специализированный цикл & «Для Каждого», то лучше использовать его. Кстати, сам по себе он отрабатывает дольше чем другие циклы, но скорость доступа к элементу коллекции у него на много выше.

2. Если заранее знаешь количество итераций & используй «Для По». «Пока» отработает медленнее.

3. Если использовать цикл «Если» & другие программисты тебя явно не поймут.

В статье использованы материалы с хабра и хелпме