Обнуление реквизитов в 1С 8.3: от кнопки «X» до обработки на тысячи объектов

· 9 мин

Содержание

Очистить поле в 1С — значит присвоить реквизиту пустое значение его типа: "" для строки, 0 для числа, Дата(1, 1, 1) для даты, Ложь для булева и ПустаяСсылка() для ссылки. Вручную поле очищают кнопкой с крестиком справа от поля или сочетанием Shift+F4. Программно — одной строкой присваивания, но правильное «пустое» зависит от типа и от того, где выполняется код: на клиенте или на сервере.

Ниже — примеры для каждого случая: одиночный реквизит, поле управляемой формы, табличная часть, составной тип и массовая очистка по базе. Код рассчитан на платформу 8.3 и управляемые формы.

Что считается пустым значением: таблица по типам

Платформа не хранит «ничего» в типизированном реквизите. У каждого типа есть своё значение по умолчанию, и именно его функция ЗначениеЗаполнено() считает незаполненным.

Тип реквизитаПустое значениеПример присваивания
Строкапустая строкаОбъект.Комментарий = "";
ЧислонольОбъект.Скидка = 0;
Дата1 января 0001 годаОбъект.ДатаОплаты = Дата(1, 1, 1);
БулевоЛожьОбъект.Согласовано = Ложь;
Ссылка на справочникпустая ссылкаОбъект.Контрагент = Справочники.Контрагенты.ПустаяСсылка();
Ссылка на документпустая ссылкаОбъект.Основание = Документы.СчетНаОплату.ПустаяСсылка();
Перечислениепустая ссылкаОбъект.ВидОперации = Перечисления.ВидыОпераций.ПустаяСсылка();
Составной типНеопределеноОбъект.Субконто1 = Неопределено;
Хранилище значенияхранилище без данныхОбъект.Файл = Новый ХранилищеЗначения(Неопределено);

💡 Литерал '00010101' и выражение Дата(1, 1, 1) дают одно и то же. Второй вариант проще читать в чужом коде.

Универсальный способ через описание типов

Если тип заранее неизвестен (обработка проходит по произвольным реквизитам), пустое значение берут у метаданных:

ОписаниеРеквизита = Метаданные.Справочники.Контрагенты.Реквизиты.ОсновнойДоговор;
Объект.ОсновнойДоговор = ОписаниеРеквизита.Тип.ПривестиЗначение(Неопределено);

Метод ПривестиЗначение() у объекта ОписаниеТипов возвращает значение по умолчанию для одиночного типа. Для составного типа результатом будет Неопределено. Этот приём работает только на сервере: объект Метаданные на тонком клиенте недоступен.

Программное обнуление реквизитов объекта

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

Через объект и запись

&НаСервереБезКонтекста
Процедура ОчиститьКомментарий(СсылкаНаДокумент)

    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    ДокументОбъект.Комментарий = "";
    ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

КонецПроцедуры

Пока не вызван Записать(), изменение живёт только в памяти. Ссылку напрямую менять нельзя: СсылкаНаДокумент.Комментарий = "" вызовет ошибку, потому что ссылка доступна только для чтения.

Проверка перед очисткой

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

Если ЗначениеЗаполнено(ДокументОбъект.Комментарий) Тогда
    ДокументОбъект.Комментарий = "";
    ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;

Режим РежимЗаписиДокумента.Запись не перепроводит документ: движения в регистрах остаются прежними. Если очищаемый реквизит участвует в движениях (склад, договор, статья затрат), записывайте в режиме РежимЗаписиДокумента.Проведение, иначе регистры разойдутся с шапкой документа.

Несколько реквизитов за один раз

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

ПустыеЗначения = Новый Структура;
ПустыеЗначения.Вставить("Комментарий", "");
ПустыеЗначения.Вставить("ДатаОплаты", Дата(1, 1, 1));
ПустыеЗначения.Вставить("СуммаАванса", 0);
ПустыеЗначения.Вставить("Ответственный", Справочники.Пользователи.ПустаяСсылка());

ЗаполнитьЗначенияСвойств(ДокументОбъект, ПустыеЗначения);

ЗаполнитьЗначенияСвойств() копирует только те свойства, имена которых совпадают. Опечатка в имени ключа ошибки не вызовет: поле просто не очистится. Поэтому после такого кода полезно один раз проверить результат в отладчике.

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

Как очистить поле в управляемой форме

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

Кнопка очистки и Shift+F4

У поля ввода есть свойство КнопкаОчистки. Если оно включено, справа появляется крестик. Включить можно в конфигураторе, в палитре свойств элемента формы, или кодом:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Элементы.Договор.КнопкаОчистки = Истина;
КонецПроцедуры

Сочетание Shift+F4 очищает активное поле и без кнопки, если поле доступно для редактирования.

Очистка на клиенте

Менеджеры Справочники и Документы на клиенте недоступны. Пустую ссылку там получают через ПредопределенноеЗначение():

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

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

Очистка реквизита формы, а не объекта

Если поле привязано не к Объект.Реквизит, а к реквизиту самой формы (например, ОтборПоСкладу), обращение идёт без префикса:

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

Событие «Очистка»

У поля формы есть событие Очистка. Оно срабатывает, когда пользователь нажимает крестик или Shift+F4. В обработчике можно запретить очистку или выполнить дополнительные действия:

&НаКлиенте
Процедура ОрганизацияОчистка(Элемент, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    ПоказатьПредупреждение(, "Организацию нельзя оставить пустой.");
КонецПроцедуры

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

Учтите разницу между ручной и программной очисткой. Когда поле очищает пользователь, после Очистка срабатывает и ПриИзменении. Когда поле обнуляет код, ни одно из этих событий не вызывается. Если в ПриИзменении есть пересчёт, вызовите эту процедуру явно после присваивания.

Очистка табличной части: строки, колонки, массово

Табличную часть можно очистить целиком, по колонке или выборочно по строкам.

Удалить все строки

Объект.Товары.Очистить();

Метод одинаково работает в форме (на клиенте и на сервере) и в объекте. После него табличная часть пуста, нумерация строк начнётся заново.

Обнулить одну колонку

Строки остаются, очищается только одно поле, например скидка:

Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    СтрокаТЧ.ПроцентСкидки = 0;
    СтрокаТЧ.СуммаСкидки = 0;
КонецЦикла;

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

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

ТаблицаТоваров = Объект.Товары.Выгрузить();
ТаблицаТоваров.ЗаполнитьЗначения(0, "ПроцентСкидки, СуммаСкидки");
Объект.Товары.Загрузить(ТаблицаТоваров);

Этот вариант — только на сервере: Выгрузить() и Загрузить() у табличной части формы на клиенте недоступны.

Удалить строки по условию

Удалять строки внутри прямого цикла Для Каждого нельзя — пропустятся соседние строки. Идите с конца коллекции:

Для Сч = 1 По Объект.Товары.Количество() Цикл
    СтрокаТЧ = Объект.Товары[Объект.Товары.Количество() - Сч];
    Если СтрокаТЧ.Количество = 0 Тогда
        Объект.Товары.Удалить(СтрокаТЧ);
    КонецЕсли;
КонецЦикла;

Граница цикла вычисляется один раз в начале. При удалении строк индекс Количество() - Сч по-прежнему указывает на ещё не проверенную строку: удалены только строки ниже неё.

Пустые значения сложных типов: составной тип, хранилище, ссылки

Здесь ошибаются чаще всего.

  • 🔹 Составной тип. Значение Неопределено — это и есть пусто. Если присвоить пустую ссылку конкретного справочника, поле станет «пустым, но с типом»: ЗначениеЗаполнено() вернёт Ложь, а ТипЗнч() покажет справочник. Для отборов по типу это разные вещи.
  • 🔹 Субконто в бухгалтерских регистрах. Обычно составной тип, поэтому чистим через Неопределено.
  • 🔹 Строка неограниченной длины. Очищается так же, "", но в запросах сравнивать её с пустой строкой напрямую нельзя — используйте ПОДСТРОКА(Поле, 1, 1) = "" или выражение с ВЫРАЗИТЬ.
  • 🔹 Хранилище значения. Присваивайте Новый ХранилищеЗначения(Неопределено). Двоичные данные внутри исчезнут после записи объекта.
  • 🔹 Число с ограничением «Неотрицательное». Ноль допустим, но если у реквизита стоит проверка заполнения, ноль тоже считается незаполненным.
  • 🔹 Перечисление. Пустая ссылка Перечисления.Имя.ПустаяСсылка(); на клиенте — ПредопределенноеЗначение("Перечисление.Имя.ПустаяСсылка").

💡 Однотипному реквизиту можно присвоить и Неопределено: платформа приведёт его к пустому значению типа. Но в коде такой приём читается как «здесь составной тип», поэтому для однотипных полей лучше писать явное пустое значение.

Очистка при копировании, заполнении и записи

Иногда поле надо очищать не по кнопке, а автоматически — в событиях модуля объекта.

При копировании

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

Процедура ПриКопировании(ОбъектКопирования)
    Комментарий = "";
    НомерВходящегоДокумента = "";
    ДатаВходящегоДокумента = Дата(1, 1, 1);
КонецПроцедуры

Процедура пишется в модуле объекта. Номер и дату самого документа платформа очищает при копировании сама.

При заполнении

Обработчик ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка) вызывается при вводе на основании и при создании нового объекта. Если документ вводится на основании другого, а часть полей переносить не нужно, присвойте им пустые значения в конце процедуры, после основного заполнения.

Перед записью

Когда значение поля теряет смысл при определённом условии, его стоит чистить в ПередЗаписью, чтобы в базу не попадали противоречивые данные:

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если Не ЕстьОтсрочка Тогда
        ДатаОплаты = Дата(1, 1, 1);
    КонецЕсли;
КонецПроцедуры

Так очистка сработает при любой записи: из формы, из обработки, из обмена (если он не пишет в режиме загрузки).

Массовая очистка реквизитов в базе

Задача «очистить поле у всех контрагентов» или «стереть комментарий в документах за год» решается двумя путями.

СпособКогда подходитРиски
Обработка «Групповое изменение реквизитов»типовая конфигурация на БСП, нужен простой отборзапись идёт с обработчиками, долго на больших объёмах
Своя обработка или код во внешней обработкесложный отбор, табличные части, десятки тысяч объектовошибка в коде портит данные сразу у всех объектов

Через групповое изменение

В БП 3.0 обработка открывается из раздела Администрирование → Обслуживание → Корректировка данных → Групповое изменение реквизитов. В других конфигурациях на БСП её проще найти через Все функции → Обработки.

  1. Выберите тип объектов, например справочник «Контрагенты».
  2. Задайте отбор: какие элементы менять.
  3. В списке реквизитов отметьте нужный и оставьте значение пустым — для ссылок выберите пустое значение, для строк сотрите текст.
  4. Нажмите кнопку изменения и дождитесь протокола.

Программно, запросом и выборкой

&НаСервереБезКонтекста
Процедура ОчиститьКомментарииКонтрагентов()

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    Контрагенты.Ссылка КАК Ссылка
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |ГДЕ
    |    НЕ Контрагенты.ЭтоГруппа
    |    И ПОДСТРОКА(Контрагенты.Комментарий, 1, 1) <> """"";

    Выборка = Запрос.Выполнить().Выбрать();
    Обработано = 0;

    Пока Выборка.Следующий() Цикл
        Объект = Выборка.Ссылка.ПолучитьОбъект();
        Объект.Комментарий = "";
        Объект.Записать();
        Обработано = Обработано + 1;
    КонецЦикла;

    Сообщить(СтрШаблон("Очищено элементов: %1", Формат(Обработано, "ЧГ=0")));

КонецПроцедуры

Отбор в запросе сразу отсекает объекты, где поле уже пустое, — лишних записей не будет.

Перед массовой очисткой сделайте резервную копию базы: выгрузку .dt или копию средствами СУБД. Отменить групповую запись нельзя. Первый запуск делайте на копии базы и на небольшом отборе.

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

Почему поле не очищается: ошибки и что с ними делать

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

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

Чем Неопределено отличается от пустой ссылки?
Неопределено — пустое значение без типа, применяется для составных реквизитов. Пустая ссылка имеет конкретный тип справочника или документа.
Как очистить поле в типовой конфигурации, не меняя её?
Для разовой задачи — обработкой «Групповое изменение реквизитов» или внешней обработкой. Для постоянной логики — расширением конфигурации, чтобы не снимать типовую с поддержки.
Можно ли очистить реквизит запросом?
Нет. Язык запросов 1С только читает данные. Запросом находят объекты, а меняют их через объект и запись.
Как очистить поле сразу у нескольких выделенных элементов списка?
В конфигурациях на БСП выделите строки в списке и найдите в меню «Ещё» команду изменения выделенных. Откроется групповое изменение уже с отбором по выделенным объектам.
Как очистить реквизит у предопределённого элемента?
Так же, как у обычного: получить объект, присвоить пустое значение, записать. Ограничение касается только самой привязки к предопределённым данным, обычные реквизиты меняются свободно.