1с ожидается имя формального параметра

Обновлено: 05.07.2024

Передача параметров по ссылке и по значению при вызове процедур и функций

Внимание! Материал данной статьи устарел. Рекомендуется использовать документацию к платформе "1С:Предприятие 8".

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

Передача параметров по ссылке

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

Передача параметров по значению

При передаче параметра вызываемой процедуры или функции по значению, изменение значения формального параметра внутри процедуры или функции никак не влияет на фактический параметр, передаваемый при вызове процедуры или функции. Указание, что параметр нужно передавать по значению, осуществляется с помощью ключевого слова Знач .

Особенности передачи переменных различных типов данных по значению

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

Рассмотрим в качестве примера ситуацию, когда параметром процедуры, передаваемым по значению, является таблица значений. Внутри вызываемой процедуры ОбработатьТаблицу() создается новый экземпляр таблицы значений, в который добавляется три строки. Это никак не влияет на состояние таблицы значений Тз , переданной в качестве фактического параметра при вызове процедуры ОбработатьТаблицу() :

Рассмотрим в качестве примера ситуацию, когда параметром процедуры, передаваемым по значению, является таблица значений. Внутри вызываемой процедуры СвернутьТаблицу() таблица значений, переданная в качестве параметра при вызове процедуры, сворачивается:

Схематично изобразить происходящее при вызове процедуры СвернутьТаблицу(Тз) можно следующим образом:

(1) - вызов процедуры СвернутьТаблицу . В качестве фактического параметра указывается переменная Тз, хранящая ссылку на экземпляр таблицы значений;

(2) - из процедуры вызывается метод Свернуть таблицы значений;

(3) - формальный параметр ссылается на тот же самый экземпляр таблицы значений, что и фактический параметр (переменная Тз) - происходит свертка в экземпляре таблицы значений, на которую ссылается переменная Тз;

(4) - выходим из процедуры. Экземпляр таблицы значений, на которую ссылается переменная Тз, находится в свернутом состоянии.

Таким образом, передача фактического параметра по значению в данном случае не привела к созданию копии таблицы значений. При работе со свойствами и методами таблицы значений мы работаем со свойствами и методами той таблицы значений, которая использовалась при вызове процедуры СвернутьТаблицу() .

Разница для всех типов при передаче параметра процедуры или функции по ссылке или по значению проявляется в присвоении фактическому параметру процедуры или функции нового значения. Вызов свойств и методов контекста фактического параметра, если таковые имеются, влияет на формальный параметр независимо от того, передается ли он по ссылке или по значению.

: Ожидается имя формального параметра
Процедура ПрочестьИз(<<?>>\D:\Work\User\Desktop\postav.xml\) (Проверка: Сервер)
: Ожидается имя формального параметра
Процедура ПрочестьИз(<<?>>\D:\Work\User\Desktop\postav.xml\) (Проверка: Тонкий клиент)

(3) Переменная Contr нигде не определяется.

А вообще, читать XML построителем DOM - суета. Через XDTO читайте.

(25) Можно вытащить на форму реквизит с типом Справочник.Поставщики и выбрать группу там (так надежнее) или сделать так:

Процедуре нужно передавать в параметрах переменные, а вы передаете литерал. В ошибке же написано: ожидается имя формального параметра.

(2)
Я сделал так: Процедура ПрочестьИз(ПутьКФайлу)

пошли такие ошибки, подскажите пожалуйста, где их определять нужно?

: Переменная не определена (Contr)
Название = <<?>>Contr.Атрибуты.ПолучитьИменованныйЭлемент("SNAME"); (Проверка: Сервер)
: Переменная не определена (Contr)
Численность = <<?>>Contr.Атрибуты.ПолучитьИменованныйЭлемент("INN"); (Проверка: Сервер)
: Переменная не определена (Contr)
КПП = <<?>>Contr.Атрибуты.ПолучитьИменованныйЭлемент("KPP"); (Проверка: Сервер)
: Переменная не определена (ИНН)
Если <<?>>ИНН <> Неопределено Тогда (Проверка: Сервер)
: Переменная не определена (ИНН)
Сообщить("INN: " + <<?>>ИНН.Значение); (Проверка: Сервер)

(3) Переменная Contr нигде не определяется.

А вообще, читать XML построителем DOM - суета. Через XDTO читайте.

(4)Так, извиняюсь, я туплю, а Ваш пример создает элемент в справочнике?

(7) А если записать теперь в справочник нужно сделать так?

(10) Сделал так, чтобы можно было не определенный файл читать, а именно выбирать из компа и благодаря Вам получилось. Вы гений!

(12) Ну что вы, я только учусь)

Единственно - этот код не будет работать если клиентский комп и сервер - разные машины.

(14) тогда на клиентском компе выбрать его не получится - надо будет как-то по-другому указывать путь. Если все-таки выбирать на клиенте - можно или передавать на сервер текст, содержащийся в xml-файле, там через текстовый документ сохранять его во временный файл и его открывать или класть двоичные данные файла во временное хранилище, вытаскивать их из него на сервере и опять-таки сохранять во временный файл. (15) а зачем для фабрики нужен файл? Оно принимает ЧтениеXML, которому можно сказауть Установитьстроку(). (17)Добавил условие если значение заполнено, а как правильно добавить условие если элемент уже есть в справочнике, то есть сравнивая по ИНН?

(19)Это я сделал так

А сделать если Contr.INN = с тем что есть в справочнике, то его не добавлять.

(19)Последнее, тут при экспорте код работает все нормально, но даже при работе просто так выдает ошибку

А вот ошибка:
: Переменная не определена (Справочники)
Выборка = <<?>>Справочники.Поставщики.Выбрать(); (Проверка: Тонкий клиент)
: Переменная не определена (Справочники)
Выборка = <<?>>Справочники.Поставщики.Выбрать(); (Проверка: Тонкий клиент)

(23) Справочники недоступны на клиенте. Запись надо формировать на сервере, ну так примерно. (6) не создает, как и код в (1). Он просто показывает, как достучаться до значений в файле XML. А "не читает" - это что значит? Файл XML с текстом из (1) прочитался на ура. (8)И снова привет, слушай, а если нужно это все записать в определенную группу "Главные" в справочнике "Поставщики", я уже все перепробовал, вообще не получается.

(25) Можно вытащить на форму реквизит с типом Справочник.Поставщики и выбрать группу там (так надежнее) или сделать так:

(26) Оказывается так все просто, а я огромные коды смотрю, где всякие поиски по коду и тд, вообще жесть. (26) А ты сталкивался с таким, что 2 файла xml в одном файле содержатся поставщики, которые должны относиться к Группе "Главные" а во втором файле содержатся поставщики, которые относятся к группе "Второстепенные"?. Если выбран файлик Главные, то в группу "Главные", а если Второстепенные, то в группу "Второстепенные"? (29) Я вообще с загрузкой сталкивался постольку-поскольку. Значит, тебе стопудово надо вешать на форму реквизит, в котором выбирается группа, в которую нужно писать поставщиков. К тому, чтобы поиск группы прописывать в коде, я (и не только я) отношусь очень отрицательно, потому что завтра-послезавтра этих групп могут нашлепать еще тридцать штук. В общем, вешаешь на форму реквизит, выбираешь группу - грузишь файл. Выбираешь другую группу - грузишь другой файл.

(30) Просто напиши возможно ли такое вообще, задача жесткая.

Представим есть файл счета.xml в котором хранятся все данные о контрагентах поставщики и номер счета. добавляем в справочник "Счета", в котором табличная часть - ссылается на справочник "Поставщики", при этом идет функция считывания данных о поставщиках в справочнике "поставщики" и если в файле будет например, Наименование - заполнено, ИНН - заполнено, а в справочнике 1с будет тот же поставщик, но Наименование - заполнено, ИНН - не заполнено, то в справочнике не создается новый элемент, а реквизит ИНН добавляется в уже созданный элемент.

Сколько же всего сложного и таинственного нас окружает.

Черные дыры и сновидения. Темная материя и подсознание. Корпускулярно-волновой дуализм и 1С.

И ведь думаешь, что знаешь эту "1Ску" как свои пять пальцев, но стоит случайно копнуть глубже. И очередная багофича. Да ешё и какая!

В этой статье рассмотрим секретный оператор ?

О нём мало кто знает, хоть он и существует как минимум с версии 8.0.


В последнее время я публикую на своём телеграм-канале разные хитрые задачки с подвохом для программистов 1С. Какие-то беру "по памяти", а какие-то "рождаю" в результате экспериментов. Об этом скоро выйдет отдельная статья. И вот в очередном тесте адекватности платформы случайно натыкаюсь на такую конструкцию:

Синтаксис-проверка прошла успешно. Никаких ошибок не высветилось. И, казалось бы, ошибка тогда должна произойти в момент выполнения.


Код успешно выполнился. Удивительно, но сработало! И тут меня понесло.


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

Мы создаём новую переменную и назначаем ей значение - ?. И в переменной находится Неопределенно. И, казалось бы, это и есть ответ на вопрос. Знак ? означает Неопределено.

Но что же тогда это:


В данном коде сначала идёт объявление переменной "А". И в А установлено числовое значение "1". А далее идёт наше сравнение с ?. Если бы под знаком вопроса скрывалось Неопределено, то мы бы не попали внутрь условия. А по скрину видно, что попали.


Очень странная ошибка. "Переменная не определена (Сообщить)". Ну допустим. Добавим тогда такую переменную:

Данный код компилируется без ошибок. И при выполнении в 1С сообщает "ТЕСТ". То есть значение переменной Сообщить

Выходит, что символ ? указывает на предыдущее слово в коде. В данном случае, перед ? было слово Сообщить. И поэтому 1С изначально поругалась, что такая переменная не определена. А когда мы добавили переменную Сообщить, то всё стало на свои места.

То есть наш код для 1С выглядит так:

А теперь вернемся к нашим предыдущим примерам и разберём что и как сработало.

В данном коде предыдущее слово перед ? - Если. Но оно является ключевым для 1С. Как "Цикл", "Процедура" и так далее. Поэтому, его оператор ? не учитывает и берет в качестве источника значения переменную А.

Скорректируем же этот код так, как его видит 1С:

Теперь всё логично. А = А и поэтому условие выполняется.

А что с нашим самым первым примером?

На самом деле всё так же. Просто заменяем знак вопроса на предыдущее слово.

Да, такой код тоже странный, но в рамках 1С всё логично. Сначала объявляется переменная и в ней Неопределено. А затем происходит присвоение переменной значения из её самой. То есть опять же Неопределено. Можете проверить такой код - это хоть и выглядит странно, но работает. А почитать чуть подробнее можно в статье на ИТС: МояПеременная = 0; МояПеременная = ? + 1; //1 МояПеременная = ? + 1; //2 МояПеременная = ? * 5; //10 МояПеременная = ? / 2; //5 МояПеременная = ? - 6; //-1

А самое интересное, что такая возможность существовала как минимум ещё с версии 8.0 . Специально скачал старую платформу и проверил.

На самом деле такой код можно ещё упросить:

Но такой вариант становится менее надежным. Ведь всё работает до тех пор, пока перед ? находится МояПеременная. Если же вставить после этого какое-то другое "слово", то всё порушится.

Но вот ещё пример:

Мы же помним, что знак ? берет предыдущее слово. Так вот в нашей строке кода это слово "А". Именно так - без "Структура".

Поэтому 1С в таком коде вместо знака вопроса вставит "А"

Но зато появляется новая возможность применения:

В данном коде мы создали структуру и наполнили её объявленными ранее переменными. Тоже бывает удобно, когда нужно передать какой-то набор переменных метода в другой метод через структуру.

А вот ещё пример. Можно передать в какой-то метод или конструктор одно значение несколько раз:

Передавать знак ? можно даже в условный тернарный оператор. Например, этот код приводит отрицательные числа к 0:

А этот приводит отрицательные числа к положительным:

Подобным образом можно присваивать дефолтные значения необязательным параметрам:

Главное помнить, что знак ? берет именно предыдущее слово, поэтому вот так работать НЕ будет:

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

Но что если использовать символ ? в параметрах?

Сделаем процедуру с параметром ? :

Такую процедуру действительно возможно создать. И можно вызывать. Причем 1С понимает, что параметр обязательный и его необходимо передать.

Но мы можем сделать его необязательным:

И параметр не обязан быть единственным. Можно делать разными способами:

А можно использовать Знач

Но вот незадача, ? в параметре метода не использует предыдущее слово (как во всех других случаях). Как обратиться к этому параметру - неизвестно.

В стеке вызовов он отображается:


А попробуем добавить второй параметр ?

1С ругается так:

Формальный параметр с указанным именем уже определен (?)

Опираясь на текст ошибки, мы можем предположить, что 1С объявляет параметр с именем "?"

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

Как обратиться к параметру с именем "?" - неизвестно. Методы Вычислить() и Выполнить() не помогли.

Но, возможно, это всё те вопросы, которые нам ещё предстоит разгадать. Секреты и загадки этой таинственной платформы под кодовым названием 1С.


Понравилась статья?

Поставьте лайк плюс. Пишите свои идеи и комментарии по теме. Статья будет дополняться.


Начиная с версии платформы 8.3.15 в расширениях можно использовать аннотацию &ИзменениеИКонтроль. При этом важна именно версия платформы, а не режим совместимости. То есть, если у Вас платформа 8.3.15, а режим совместимости установлен 8.3.12, то аннотация &ИзменениеИКонтроль будет работать.


Для примера использования создадим простую обработку с одной командой на форме и со следующим программным кодом в модуле:



Расширение не применилось, так как отличается текст процедуры в исходной конфигурации и в расширении.

Это позволит избежать ошибок, когда после обновления конфигурации был изменен модуль, для которого в расширении была использована аннотация &Вместо.

Автоматическое обновление модуля в расширении можно выполнить только если настроено сравнение/объединение с помощью внешних программ.

В любом случае использование аннотации &ИзменениеИКонтроль позволит избежать ручного сравнения всех процедур и функций, где была использована аннотация &Вместо. Теперь сравнивать нужно будет только те процедуры и функции, где код в исходной конфигурации был изменен в результате обновления.

Но если бы наша процедура была клиентской, то расширение бы все равно применилось, несмотря на то что отличается текст процедуры.

Читайте также: