Оператор присваивания во встроенном языке 1С 8.3: переменные, реквизиты, коллекции

· 9 мин

Содержание

Чтобы присвоить значение в 1С, напишите имя переменной, знак =, выражение и точку с запятой: Сумма = 1500;. Отдельного оператора := во встроенном языке 1С:Предприятия нет, сокращений вида += и ++ тоже. Платформа сама понимает по месту в строке, где = означает присваивание, а где сравнение.

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

Синтаксис присваивания: из чего состоит строка

Общая форма одна:

ИмяПеременной = Выражение;

Слева может стоять:

  • 🔹 локальная переменная или переменная модуля;
  • 🔹 свойство объекта: Объект.Комментарий;
  • 🔹 элемент коллекции по индексу: Массив[0], Соответствие["Код"];
  • 🔹 поле строки табличной части: СтрокаТЧ.Количество.

Справа — любое выражение: литерал, другая переменная, вызов функции, арифметика, тернарный оператор ?().

Количество = 10;
Цена = 125.50;
Сумма = Количество * Цена;               // 1255
Текст = "Итого: " + Формат(Сумма, "ЧДЦ=2");
Статус = ?(Сумма > 1000, "Крупный", "Обычный");

Объявлять переменную или нет

Локальную переменную объявлять не обязательно. Она создаётся в момент первого присваивания и живёт до конца процедуры. Явное объявление через Перем нужно в двух случаях:

  1. Переменная модуля, которая должна жить между вызовами процедур. Её объявляют в начале модуля: Перем КэшНастроек;.
  2. Переменная модуля объекта, доступная снаружи: Перем ДополнительныеДанные Экспорт;.
Перем Счетчик; // значение пока Неопределено

Процедура Увеличить()
    Если Счетчик = Неопределено Тогда
        Счетчик = 0;
    КонецЕсли;
    Счетчик = Счетчик + 1;
КонецПроцедуры

Объявленная через Перем переменная до первого присваивания содержит Неопределено. Арифметика с ним вызовет ошибку, поэтому начальное значение задавайте явно.

Ловушка двойного знака равенства

Цепочку А = Б = 0; 1С не понимает как «обнулить обе переменные». Первый = — присваивание, второй — сравнение. В А попадёт Истина или Ложь в зависимости от того, равно ли Б нулю. Сама Б не изменится.

Б = 5;
А = Б = 0;   // А = Ложь, Б по-прежнему 5

Каждой переменной — своя строка.

Как записать значение каждого типа

Литералы примитивных типов пишутся по-разному. Таблица — для быстрой сверки.

ТипПример присваиванияЧто учесть
ЧислоСтавка = 0.2;Разделитель дробной части — точка
СтрокаИмя = "ООО ""Ромашка""";Кавычка внутри строки удваивается
ДатаД = '20261007';Одинарные кавычки, формат ГГГГММДД
Дата и времяД = '20261007153000';ГГГГММДДччммсс
БулевоФлаг = Истина;Также Ложь
Пустое значениеЗ = Неопределено;Null приходит из запросов
СсылкаОрг = Справочники.Организации.ПустаяСсылка();Через менеджер объекта
ПеречислениеВид = Перечисления.ВидыОпераций.Продажа;Значение из конфигурации

Многострочный текст записывают с продолжением строки: каждая следующая строка начинается с вертикальной черты.

ТекстЗапроса = "ВЫБРАТЬ
|    Номенклатура.Ссылка
|ИЗ
|    Справочник.Номенклатура КАК Номенклатура";

Дату из переменных собирают функцией Дата(): Д = Дата(2026, 10, 7); — без времени, Дата(2026, 10, 7, 15, 30, 0) — со временем.

Объекты-коллекции создаются через Новый

Массив, структура, соответствие, таблица значений не имеют литералов. Сначала конструктор, потом заполнение:

Товары = Новый Массив;
Товары.Добавить("Бумага");
Товары[0] = "Бумага А4";              // замена по индексу

Реквизиты = Новый Структура("Код, Наименование", "001", "Склад");
Реквизиты.Наименование = "Основной склад";
Реквизиты.Вставить("Ответственный", "Иванов");

Цены = Новое Соответствие;
Цены["001"] = 125.50;                 // добавит или заменит ключ

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

Присваивание реквизитам объектов базы

Здесь начинаются вопросы. Ссылка на справочник или документ — это только указатель на данные. Через неё значения читают, но не меняют:

// Так НЕЛЬЗЯ — ошибка «Поле объекта недоступно для записи»
Ссылка.Комментарий = "Проверено";

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

Объект = Ссылка.ПолучитьОбъект();
Объект.Комментарий = "Проверено";
Объект.Ответственный = Пользователи.ТекущийПользователь();
Объект.Записать();

Для нового элемента вместо ПолучитьОбъект() вызывают конструктор менеджера: Справочники.Номенклатура.СоздатьЭлемент(), Документы.РеализацияТоваровУслуг.СоздатьДокумент(). Если документ проводится, запись делают с режимом: Объект.Записать(РежимЗаписиДокумента.Проведение);.

Методы ПолучитьОбъект() и Записать() работают только на сервере. В клиентском модуле формы их вызов приведёт к ошибке: вынесите код в процедуру с директивой &НаСервере или в общий серверный модуль.

Табличная часть

Строку сначала добавляют, потом заполняют поля:

НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Номенклатура = Номенклатура;
НоваяСтрока.Количество   = 3;
НоваяСтрока.Цена         = 250;
НоваяСтрока.Сумма        = НоваяСтрока.Количество * НоваяСтрока.Цена; // 750

Константы и регистры сведений

У них свой способ записи:

  • 🔹 константа: Константы.ИмяКонстанты.Установить(Значение);, чтение — Константы.ИмяКонстанты.Получить();
  • 🔹 регистр сведений : менеджер записи РегистрыСведений.ИмяРегистра.СоздатьМенеджерЗаписи(), заполнение измерений и ресурсов, затем Записать().

Реквизиты формы

На форме объекта данные лежат в основном реквизите Объект. Значение присваивают ему, а не элементу формы:

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

Элементы.Комментарий — это поле на экране со свойствами вроде Видимость и ТолькоПросмотр. Присвоить ему значение реквизита нельзя.

💡 Строка Модифицированность = Истина; нужна, чтобы форма предложила сохранить изменения при закрытии. Без неё пользователь может закрыть окно, и программное изменение пропадёт.

Если на сервере формы нужен полноценный объект с его методами, используйте пару РеквизитФормыВЗначение("Объект") и ЗначениеВРеквизитФормы(ОбъектДанных, "Объект").

Значения для запроса присваивают параметрами

В тексте запроса переменные модуля не видны. Значение передают через параметр с ампersand-именем в тексте и методом УстановитьПараметр():

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг
               |ГДЕ Дата МЕЖДУ &Начало И &Конец";
Запрос.УстановитьПараметр("Начало", НачалоМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Конец", КонецМесяца(ТекущаяДатаСеанса()));

Склеивать значение прямо в текст запроса через + не нужно: так ломаются даты и строки с кавычками, а сам запрос хуже кешируется.

Динамическая типизация: что происходит с типом

Переменная во встроенном языке не привязана к типу. Одна и та же переменная может хранить число, потом строку, потом ссылку:

Значение = 10;          // Число
Значение = "десять";    // Строка
Значение = Неопределено;

Удобно, но порождает две ловушки.

Сложение разных типов

Тип результата определяет левый операнд. Строка плюс число склеивается в строку, число плюс строка пытается превратить строку в число.

А = "Сумма: " + 1500;   // "Сумма: 1 500" — с пробелом-разделителем разрядов
Б = 5 + "3";            // 8
В = 5 + "три";          // ошибка преобразования

Пробел в «1 500» ломает коды, номера и имена файлов. Число к строке приводите явно: Формат(1500, "ЧГ=0") вернёт 1500 без разделителей. Тот же приём нужен для номеров строк и кодов в сообщениях.

Дата плюс число сдвигает дату на секунды: ТекущаяДатаСеанса() + 86400 — сутки вперёд. Разность двух дат — число секунд.

Присваивание типизированному реквизиту

У реквизита в конфигураторе тип задан. Значение другого типа платформа приведёт к типу реквизита, и результат может отличаться от ожидаемого: несовместимое значение превратится в пустое значение типа, лишние символы строки отрежутся по длине, дробная часть подстроится под точность числа. Ошибки при этом не будет, вы просто потеряете данные.

Проверяйте тип перед присваиванием:

Если ТипЗнч(Значение) = Тип("Число") Тогда
    Объект.Количество = Значение;
Иначе
    ВызватьИсключение "Ожидалось число, получено: " + ТипЗнч(Значение);
КонецЕсли;

Для составного типа проверку делают через описание типа: Метаданные.Справочники.Номенклатура.Реквизиты.Вес.Тип.СодержитТип(Тип("Число")).

Значение или ссылка: копирование коллекций

Примитивные типы (число, строка, дата, булево) копируются по значению. Объекты — массив, структура, таблица значений, объект справочника — по ссылке. Присваивание не создаёт копию, а даёт второе имя тому же объекту:

Исходный = Новый Массив;
Исходный.Добавить(1);
Копия = Исходный;
Копия.Добавить(2);
// Исходный.Количество() = 2 — изменился и исходный массив

Как получить настоящую копию:

Что копируемСпособ
Таблица значенийКопия = Таблица.Скопировать();
Структура (без вложенных)Цикл Для Каждого КлючИЗначение Из Исходная с Копия.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение)
МассивЦикл с Добавить()
Любая вложенная коллекцияВ конфигурациях на БСП — ОбщегоНазначения.СкопироватьРекурсивно(Исходная)

Та же логика у параметров процедур. По умолчанию параметр передаётся по ссылке, и присваивание внутри процедуры меняет переменную вызывающего кода. Чтобы защитить исходник, объявите параметр с ключевым словом Знач:

Процедура Обработать(Знач Количество)
    Количество = Количество * 2; // снаружи значение не изменится
КонецПроцедуры

Ошибки при присваивании и как их ловить

Большинство сбоев выдают узнаваемый текст. Сверьтесь с диагностикой:

Диагностика: выберите симптом

Ввод из внешних источников — файлов, обменов, HTTP-сервисов — оборачивайте в Попытка:

Попытка
    Количество = Число(СтрЗаменить(СтрокаИзФайла, " ", ""));
Исключение
    Количество = 0;
    ЗаписьЖурналаРегистрации("Загрузка",
        УровеньЖурналаРегистрации.Ошибка, , ,
        ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

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

Как присваивать быстро и без сюрпризов

Несколько приёмов, которые отличают аккуратный код от «рабочего на моей базе».

Заполняйте свойства пачкой

ЗаполнитьЗначенияСвойств(Приемник, Источник) переносит все одноимённые свойства за один вызов. Вместо десяти строк присваивания — одна:

НоваяСтрока = Объект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ВыборкаИзЗапроса);

Третий параметр ограничит список свойств, четвёртый — исключит лишние: ЗаполнитьЗначенияСвойств(Приемник, Источник, , "Ссылка, Код").

Не получайте объект ради чтения

Ссылка.ПолучитьОбъект() читает из базы весь объект с табличными частями. Если нужно одно поле, хватит запроса или функции БСП ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "ИНН"). В цикле по тысяче документов разница заметна в разы.

Записывайте один раз

Каждый вызов Записать() — это транзакция, проверки и подписки на события. Присвойте все реквизиты и вызовите запись в конце, а не после каждого поля.

Проверяйте заполненность, а не пустоту по типу

ЗначениеЗаполнено(Значение) одинаково работает для нуля, пустой строки, пустой даты, пустой ссылки и Неопределено. Это надёжнее, чем сравнение Значение = "" или Значение = 0, которое ломается при смене типа.

Если Не ЗначениеЗаполнено(Объект.Договор) Тогда
    Объект.Договор = ДоговорПоУмолчанию;
КонецЕсли;

Давайте переменным понятные имена

Сумма, СуммаНДС, СтрокаТовара читаются годами. А1, Тмп, Ч превращают сопровождение в расследование. Имена на русском в стиле СуммаСНДС — норма для встроенного языка и общепринятых стандартов разработки.

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

Есть ли в 1С оператор `+=` или инкремент `++`?
Нет. Пишите полную форму: Счетчик = Счетчик + 1;. Для строк — Текст = Текст + Символы.ПС + НоваяСтрока;.
Как присвоить значение сразу нескольким переменным?
Только отдельными строками. Запись А = Б = 0; сравнит Б с нулём и запишет в А результат сравнения.
Чем отличаются Неопределено и Null?
Неопределено — значение по умолчанию у пустых переменных и составных реквизитов. Null приходит из запроса при левом соединении, когда связанной записи нет. В запросе от него избавляются функцией ЕСТЬNULL().
Можно ли присвоить значение реквизиту через ссылку без записи объекта?
Нет. Ссылка доступна только для чтения. Значение попадёт в базу после Записать() у объекта, полученного через ПолучитьОбъект().
Почему присвоенное на форме значение не сохраняется?
Чаще всего значение присвоили элементу формы, а не реквизиту Объект, или не выставили Модифицированность = Истина, и пользователь закрыл форму без записи.