Очистка реквизитов и полей на управляемой форме в 1С

· 9 мин

Содержание

Чтобы очистить поле формы в 1С, присвойте реквизиту пустое значение его типа: строке — "", числу — 0, ссылке — Справочники.Имя.ПустаяСсылка(), дате — '00010101'. Пользователь делает то же вручную — выделяет значение в поле и жмёт Del либо крестик очистки в правом крае поля ввода.

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

Пустое значение реквизита: базовый приём

Любой реквизит управляемой формы — это переменная конкретного типа. «Очистить» его — значит записать туда пустое значение этого же типа. Для одного реквизита объекта это одна строка кода:

Объект.Комментарий   = "";                                     // строка
Объект.Количество    = 0;                                      // число
Объект.ДатаОтгрузки  = '00010101';                             // дата
Объект.Проведён      = Ложь;                                   // булево
Объект.Контрагент    = Справочники.Контрагенты.ПустаяСсылка(); // ссылка

Если реквизит объявлен прямо на форме (не внутри Объект), обращайтесь к нему по имени без префикса: КомментарийФормы = "";. Техника очистки от этого не меняется — отличается только путь к реквизиту. Собственные реквизиты формы живут, пока открыта форма, и в базу сами по себе не попадают, поэтому их чистят так же свободно, как временные переменные.

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

Тип реквизитаПустое значение
Строка""
Число0
Дата'00010101'
БулевоЛожь
СправочникСсылка.ИмяСправочники.Имя.ПустаяСсылка()
ДокументСсылка.ИмяДокументы.Имя.ПустаяСсылка()
ПеречислениеСсылка.ИмяПеречисления.Имя.ПустаяСсылка()
Составной типНеопределено

Крестик очистки в поле ввода делает ровно это же — подставляет пустое значение типа. Показать или скрыть крестик можно в свойствах самого поля на форме, кодом его дёргать не нужно.

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

Ссылки, перечисления и составные типы

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

Объект.Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
Объект.СтавкаНДС     = Перечисления.СтавкиНДС.ПустаяСсылка();
Объект.Основание     = Документы.ЗаказКлиента.ПустаяСсылка();

С составным типом (когда реквизит хранит, например, и контрагента, и физлицо) правило другое. Составной реквизит очищается присвоением Неопределено — пустая ссылка конкретного вида тут не подойдёт.

// реквизит составного типа
Объект.Плательщик = Неопределено;

Не присваивайте Неопределено реквизиту с единственным ссылочным типом — платформа попытается привести Неопределено к типу поля и может выдать ошибку. Для однозначной ссылки — только ПустаяСсылка().

Проверить, пуст ли реквизит, тоже надо по-разному. У ссылки есть метод Пустая(), который возвращает булево:

Если Объект.Контрагент.Пустая() Тогда
    Сообщить("Контрагент не заполнен");
КонецЕсли;

Для составного реквизита сравнивайте напрямую с Неопределено:

Если Объект.Плательщик = Неопределено Тогда
    // поле пустое
КонецЕсли;

Такое разделение — частый источник ошибок: на составном поле вызов .Пустая() до заполнения приведёт к ошибке, потому что у Неопределено этого метода нет.

Когда тип реквизита заранее неизвестен (универсальная обработка полей), проверяйте заполненность глобальной функцией ЗначениеЗаполнено(). Она возвращает Ложь для любого пустого значения — пустой ссылки, нуля, пустой строки, '00010101' и Неопределено — и не зависит от типа:

Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда
    Сообщить("Заполните контрагента");
КонецЕсли;

Табличная часть: очистить всю или выборочно

Удалить все строки табличной части — один метод Очистить():

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

Он убирает строки целиком, безопасен и не требует цикла. Это же решение подходит, когда нужно перезаполнить таблицу: сначала Очистить(), затем добавление строк заново.

Если строки надо оставить, а обнулить только одну колонку — пройдите таблицу циклом и запишите пустое значение в нужный реквизит строки:

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

Удаление строк, которые пользователь выделил в таблице на форме, работает через идентификаторы выделенных строк. Коллекцию выделенных строк даёт элемент формы, а строку по идентификатору ищем в данных:

&НаКлиенте
Процедура УдалитьВыделенные(Команда)
    Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
        СтрокаТаблицы = Объект.Товары.НайтиПоИдентификатору(Ид);
        Если СтрокаТаблицы <> Неопределено Тогда
            Объект.Товары.Удалить(СтрокаТаблицы);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Здесь цикл идёт по массиву идентификаторов (ВыделенныеСтроки), а не по самой таблице, поэтому удаление строк внутри цикла не ломает перебор. Данные формы доступны на клиенте, так что серверный вызов не нужен.

Если нужно удалить строки по условию (например, все позиции с нулевым количеством), собирайте их в отдельный массив, а удаляйте вторым проходом — тогда перебор и удаление не мешают друг другу:

КСтрокам = Новый Массив;
Для Каждого СтрокаТовара Из Объект.Товары Цикл
    Если СтрокаТовара.Количество = 0 Тогда
        КСтрокам.Добавить(СтрокаТовара);
    КонецЕсли;
КонецЦикла;

Для Каждого СтрокаТовара Из КСтрокам Цикл
    Объект.Товары.Удалить(СтрокаТовара);
КонецЦикла;

Не удаляйте строки, перебирая саму табличную часть в прямом цикле Для Сч = 0 По ... Цикл: после каждого удаления индексы смещаются и часть строк проскочит. Либо Очистить(), либо перебор массива идентификаторов, как выше.

Динамический список: сброс отбора и настроек

Динамический список очистить «как таблицу» нельзя — он показывает результат запроса к базе, а не хранимые на форме данные. У него нет метода Очистить(). «Очистка» динамического списка почти всегда означает одно из двух: сбросить программный отбор или сбросить то, что пользователь настроил сам.

Программный отбор живёт в свойстве Отбор реквизита-списка. Снять все условия — очистить коллекцию его элементов:

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

Добавить отбор обратно — так же через коллекцию элементов:

НовыйОтбор = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Организация");
НовыйОтбор.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
НовыйОтбор.ПравоеЗначение = ВыбраннаяОрганизация;
НовыйОтбор.Использование  = Истина;

После изменения Отбор список перечитывает данные сам — ручного обновления не требуется.

Сортировку и группировку динамического списка сбрасывают теми же коллекциями:

Список.Порядок.Элементы.Очистить();      // снять заданную сортировку
Список.Группировка.Элементы.Очистить();  // снять группировку

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

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

Программный Отбор и пользовательские настройки независимы. Если после сброса в коде условие осталось — значит, его задал пользователь через панель настроек, и чистить надо именно её, а не Список.Отбор.

Разделять эти два слоя важно при разборе жалоб вида «список пустой, хотя данные есть». Чаще виноват не код, а сохранённый пользовательский отбор: команда стандартных настроек возвращает список к рабочему виду, а программный Отбор при этом остаётся нетронутым — он и должен действовать всегда.

Как очистить поле при изменении другого реквизита

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

Логику вешают на событие ПриИзменении управляющего поля. Обработчик создаётся из свойств элемента формы и срабатывает, как только пользователь выбрал новое значение:

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

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

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

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

Особенности очистки на управляемой форме

Главный вопрос управляемой формы — в каком контексте выполнять очистку. Реквизиты объекта (Объект.*) и реквизиты формы доступны на клиенте, поэтому очищать их можно прямо в клиентской процедуре, без обращения к серверу:

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

На клиенте нет прямого доступа к менеджерам (Справочники.Контрагенты), поэтому для пустой ссылки используйте ПредопределённоеЗначение(...) либо получайте значение в серверной процедуре. А вот изменение свойств динамического списка (Отбор, компоновщик) делайте в серверном контексте.

После программной очистки форма считается изменённой, и при закрытии 1С спросит про сохранение. Управляйте этим флагом осознанно:

Модифицированность = Ложь; // если очистка — не повод сохранять форму

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

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

Интерфейс 1С 8.3 — «Такси», на платформе 8.3.2x и новее. Вызовов из старых обычных форм (ЭлементыФормы.Поле.Значение) здесь нет: в управляемой форме к значению обращаются через реквизит, а к поведению поля — через Элементы.ИмяПоля.

Частые ошибки при очистке полей

Диагностика по симптому — что именно пошло не так и как поправить.

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

Отдельно держите в голове дату: пустая дата в 1С — это '00010101', а не пустая строка и не 0. Присвоение строки или числа дате даст ошибку типа.

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

Как очистить все поля формы разом?
Отдельной команды «очистить всю форму» нет. Напишите процедуру, которая присваивает пустые значения нужным реквизитам: ссылки через ПустаяСсылка(), строки через "", табличные части через Очистить(). Для нового документа обычно хватает создать его заново.
Чем отличается очистка реквизита формы от реквизита объекта?
Ничем по технике — и там, и там присваивается пустое значение типа. Разница в обращении: к реквизиту объекта — через Объект.Имя, к реквизиту формы — по имени напрямую.
Почему `Неопределено` не очищает поле контрагента?
Если у поля единственный тип (например, только СправочникСсылка.Контрагенты), платформа пытается привести Неопределено к этому типу и падает. Пустую ссылку берите у менеджера: Справочники.Контрагенты.ПустаяСсылка(). Неопределено очищает только составной тип.
Как проверить, что поле пустое, перед записью?
Для ссылки — метод Пустая(): Если Объект.Контрагент.Пустая() Тогда. Для составного типа — сравнение Если Объект.Поле = Неопределено Тогда. Для числа и строки — сравнение с 0 и "".
Как сбросить фильтр динамического списка кодом?
Очистите элементы отбора: Список.Отбор.Элементы.Очистить() в серверной процедуре. Это снимает программные условия; настройки, заданные пользователем вручную, сбрасываются через команду стандартных настроек в меню списка.
Надо ли обновлять форму после очистки реквизита?
Нет. Реквизиты объекта и формы живут в данных формы на клиенте — после присвоения пустого значения поле на экране обновляется само. Отдельного обновления требует только динамический список, но он перечитывает данные автоматически после изменения отбора.