Обнуление реквизитов в 1С 8.3: от кнопки «X» до обработки на тысячи объектов
Содержание
Очистить поле в 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, 1) <> """"";
Выборка = Запрос.Выполнить().Выбрать();
Обработано = 0;
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.Комментарий = "";
Объект.Записать();
Обработано = Обработано + 1;
КонецЦикла;
Сообщить(СтрШаблон("Очищено элементов: %1", Формат(Обработано, "ЧГ=0")));
КонецПроцедуры
Отбор в запросе сразу отсекает объекты, где поле уже пустое, — лишних записей не будет.
Перед массовой очисткой сделайте резервную копию базы: выгрузку .dt или копию средствами СУБД. Отменить групповую запись нельзя. Первый запуск делайте на копии базы и на небольшом отборе.
Свойство Объект.ОбменДанными.Загрузка = Истина перед записью сообщает объекту, что идёт загрузка данных. Типовой код в обработчиках ПередЗаписью и ПриЗаписи в этом режиме обычно сразу выходит, проверка заполнения не выполняется. Обработка ускоряется, но вместе с ней пропускается и логика, которая держит данные согласованными: пересчёт зависимых полей, заполнение служебных реквизитов. Включайте режим загрузки, только если прочитали обработчики объекта и знаете, что они делают.