Очистка реквизитов и полей на управляемой форме в 1С
Содержание
Чтобы очистить поле формы в 1С, присвойте реквизиту пустое значение его типа: строке — "", числу — 0, ссылке — Справочники.Имя.ПустаяСсылка(), дате — '00010101'. Пользователь делает то же вручную — выделяет значение в поле и жмёт Del либо крестик очистки в правом крае поля ввода.
Программная очистка сводится к одному действию: записать в реквизит значение, которое платформа считает пустым для данного типа. Ниже — пустые значения для всех типов, очистка ссылок и составных реквизитов, удаление строк табличной части, сброс отбора динамического списка и нюансы управляемых форм.
Пустое значение реквизита: базовый приём
Любой реквизит управляемой формы — это переменная конкретного типа. «Очистить» его — значит записать туда пустое значение этого же типа. Для одного реквизита объекта это одна строка кода:
Объект.Комментарий = ""; // строка
Объект.Количество = 0; // число
Объект.ДатаОтгрузки = '00010101'; // дата
Объект.Проведён = Ложь; // булево
Объект.Контрагент = Справочники.Контрагенты.ПустаяСсылка(); // ссылка
Если реквизит объявлен прямо на форме (не внутри Объект), обращайтесь к нему по имени без префикса: КомментарийФормы = "";. Техника очистки от этого не меняется — отличается только путь к реквизиту. Собственные реквизиты формы живут, пока открыта форма, и в базу сами по себе не попадают, поэтому их чистят так же свободно, как временные переменные.
Пустые значения по типам удобно держать перед глазами:
| Тип реквизита | Пустое значение |
|---|---|
| Строка | "" |
| Число | 0 |
| Дата | '00010101' |
| Булево | Ложь |
| СправочникСсылка.Имя | Справочники.Имя.ПустаяСсылка() |
| ДокументСсылка.Имя | Документы.Имя.ПустаяСсылка() |
| ПеречислениеСсылка.Имя | Перечисления.Имя.ПустаяСсылка() |
| Составной тип | Неопределено |
Крестик очистки в поле ввода делает ровно это же — подставляет пустое значение типа. Показать или скрыть крестик можно в свойствах самого поля на форме, кодом его дёргать не нужно.
Записывать пустые значения логично в обработчике ПриСозданииНаСервере (инициализация новой формы) или в отдельной команде «Очистить», которую вешаете на кнопку.
Ссылки, перечисления и составные типы
Для однозначного ссылочного типа всегда берите пустую ссылку у менеджера объекта. Это работает для справочников, документов, перечислений, планов видов характеристик и прочих:
Объект.Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
Объект.СтавкаНДС = Перечисления.СтавкиНДС.ПустаяСсылка();
Объект.Основание = Документы.ЗаказКлиента.ПустаяСсылка();
С составным типом (когда реквизит хранит, например, и контрагента, и физлицо) правило другое. Составной реквизит очищается присвоением Неопределено — пустая ссылка конкретного вида тут не подойдёт.
// реквизит составного типа
Объект.Плательщик = Неопределено;
Не присваивайте Неопределено реквизиту с единственным ссылочным типом — платформа попытается привести Неопределено к типу поля и может выдать ошибку. Для однозначной ссылки — только ПустаяСсылка().
Проверить, пуст ли реквизит, тоже надо по-разному. У ссылки есть метод Пустая(), который возвращает булево:
Если Объект.Контрагент.Пустая() Тогда
Сообщить("Контрагент не заполнен");
КонецЕсли;
Для составного реквизита сравнивайте напрямую с Неопределено:
Если Объект.Плательщик = Неопределено Тогда
// поле пустое
КонецЕсли;
Такое разделение — частый источник ошибок: на составном поле вызов .Пустая() до заполнения приведёт к ошибке, потому что у Неопределено этого метода нет.
Когда тип реквизита заранее неизвестен (универсальная обработка полей), проверяйте заполненность глобальной функцией ЗначениеЗаполнено(). Она возвращает Ложь для любого пустого значения — пустой ссылки, нуля, пустой строки, '00010101' и Неопределено — и не зависит от типа:
Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда
Сообщить("Заполните контрагента");
КонецЕсли;
Табличная часть: очистить всю или выборочно
Удалить все строки табличной части — один метод Очистить():
Объект.Товары.Очистить();
Он убирает строки целиком, безопасен и не требует цикла. Это же решение подходит, когда нужно перезаполнить таблицу: сначала Очистить(), затем добавление строк заново.
Если строки надо оставить, а обнулить только одну колонку — пройдите таблицу циклом и запишите пустое значение в нужный реквизит строки:
Для Каждого СтрокаТовара Из Объект.Товары Цикл
СтрокаТовара.Цена = 0;
СтрокаТовара.Сумма = 0;
КонецЦикла;
Удаление строк, которые пользователь выделил в таблице на форме, работает через идентификаторы выделенных строк. Коллекцию выделенных строк даёт элемент формы, а строку по идентификатору ищем в данных:
&НаКлиенте
Процедура УдалитьВыделенные(Команда)
Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
СтрокаТаблицы = Объект.Товары.НайтиПоИдентификатору(Ид);
Если СтрокаТаблицы <> Неопределено Тогда
Объект.Товары.Удалить(СтрокаТаблицы);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Здесь цикл идёт по массиву идентификаторов (ВыделенныеСтроки), а не по самой таблице, поэтому удаление строк внутри цикла не ломает перебор. Данные формы доступны на клиенте, так что серверный вызов не нужен.
Если нужно удалить строки по условию (например, все позиции с нулевым количеством), собирайте их в отдельный массив, а удаляйте вторым проходом — тогда перебор и удаление не мешают друг другу:
КСтрокам = Новый Массив;
Для Каждого СтрокаТовара Из Объект.Товары Цикл
Если СтрокаТовара.Количество = 0 Тогда
КСтрокам.Добавить(СтрокаТовара);
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаТовара Из КСтрокам Цикл
Объект.Товары.Удалить(СтрокаТовара);
КонецЦикла;
Не удаляйте строки, перебирая саму табличную часть в прямом цикле Для Сч = 0 По ... Цикл: после каждого удаления индексы смещаются и часть строк проскочит. Либо Очистить(), либо перебор массива идентификаторов, как выше.
Динамический список: сброс отбора и настроек
Динамический список очистить «как таблицу» нельзя — он показывает результат запроса к базе, а не хранимые на форме данные. У него нет метода Очистить(). «Очистка» динамического списка почти всегда означает одно из двух: сбросить программный отбор или сбросить то, что пользователь настроил сам.
Программный отбор живёт в свойстве Отбор реквизита-списка. Снять все условия — очистить коллекцию его элементов:
&НаСервере
Процедура СброситьОтборНаСервере()
Список.Отбор.Элементы.Очистить();
КонецПроцедуры
Добавить отбор обратно — так же через коллекцию элементов:
НовыйОтбор = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйОтбор.ПравоеЗначение = ВыбраннаяОрганизация;
НовыйОтбор.Использование = Истина;
После изменения Отбор список перечитывает данные сам — ручного обновления не требуется.
Сортировку и группировку динамического списка сбрасывают теми же коллекциями:
Список.Порядок.Элементы.Очистить(); // снять заданную сортировку
Список.Группировка.Элементы.Очистить(); // снять группировку
Это полезно, когда список настраивался кодом под конкретную задачу, а потом его нужно вернуть к «плоскому» виду без условий.
Отбор, который пользователь навесил вручную через панель настроек списка, хранится в компоновщике настроек, а не в Отбор. Самый надёжный способ сбросить его для пользователя — команда восстановления стандартных настроек в меню Ещё над списком (в вашей конфигурации подпись пункта может отличаться). Она возвращает отбор, сортировку и колонки к исходному виду без кода.
Программный Отбор и пользовательские настройки независимы. Если после сброса в коде условие осталось — значит, его задал пользователь через панель настроек, и чистить надо именно её, а не Список.Отбор.
Разделять эти два слоя важно при разборе жалоб вида «список пустой, хотя данные есть». Чаще виноват не код, а сохранённый пользовательский отбор: команда стандартных настроек возвращает список к рабочему виду, а программный Отбор при этом остаётся нетронутым — он и должен действовать всегда.
Как очистить поле при изменении другого реквизита
Самый частый повод очистить поле программно — не кнопка «Очистить», а зависимость между реквизитами. Поменяли организацию в документе — подразделение и склад от старой организации больше не годятся, их нужно обнулить автоматически. Иначе в базу попадут несовместимые данные.
Логику вешают на событие ПриИзменении управляющего поля. Обработчик создаётся из свойств элемента формы и срабатывает, как только пользователь выбрал новое значение:
&НаКлиенте
Процедура ОрганизацияПриИзменении(Элемент)
// прежние подразделение и склад относились к другой организации — чистим
Объект.Подразделение = ПредопределённоеЗначение("Справочник.ПодразделенияОрганизаций.ПустаяСсылка");
Объект.Склад = ПредопределённоеЗначение("Справочник.Склады.ПустаяСсылка");
КонецПроцедуры
На клиенте нет прямого обращения к менеджерам справочников, поэтому пустую ссылку берут через ПредопределённоеЗначение(...). Если пустое значение надо вычислить (например, подставить склад по умолчанию новой организации), вынесите логику в серверную процедуру и вызовите её из клиентского обработчика.
Очищайте зависимые поля сразу при смене управляющего, а не при записи. Так пользователь видит, что набор значений обновился, и не выберет подразделение, которого в новой организации нет.
Тот же приём работает для табличных частей: при смене шапки документа иногда нужно очистить строки, которые пересчитываются по новым условиям, — вызовом Объект.Товары.Очистить() в обработчике ПриИзменении.
Особенности очистки на управляемой форме
Главный вопрос управляемой формы — в каком контексте выполнять очистку. Реквизиты объекта (Объект.*) и реквизиты формы доступны на клиенте, поэтому очищать их можно прямо в клиентской процедуре, без обращения к серверу:
&НаКлиенте
Процедура ОчиститьШапку(Команда)
Объект.Контрагент = ПредопределённоеЗначение("Справочник.Контрагенты.ПустаяСсылка");
Объект.Комментарий = "";
Объект.Товары.Очистить();
КонецПроцедуры
На клиенте нет прямого доступа к менеджерам (Справочники.Контрагенты), поэтому для пустой ссылки используйте ПредопределённоеЗначение(...) либо получайте значение в серверной процедуре. А вот изменение свойств динамического списка (Отбор, компоновщик) делайте в серверном контексте.
После программной очистки форма считается изменённой, и при закрытии 1С спросит про сохранение. Управляйте этим флагом осознанно:
Модифицированность = Ложь; // если очистка — не повод сохранять форму
Снимайте Модифицированность только когда очистка действительно не должна записываться. Если вы очистили реальные данные документа и ждёте сохранения — флаг не трогайте, иначе пользователь потеряет изменения молча.
Начальные пустые значения для новой формы удобно задавать в ПриСозданииНаСервере — этот обработчик отрабатывает один раз при открытии. Логику, которая должна выполниться при каждом открытии, ставьте в ПриОткрытии. Не путайте их: инициализацию полей нового документа место в создании формы, а не в открытии.
Интерфейс 1С 8.3 — «Такси», на платформе 8.3.2x и новее. Вызовов из старых обычных форм (ЭлементыФормы.Поле.Значение) здесь нет: в управляемой форме к значению обращаются через реквизит, а к поведению поля — через Элементы.ИмяПоля.
Частые ошибки при очистке полей
Диагностика по симптому — что именно пошло не так и как поправить.
Неопределено. Замените на Справочники.Имя.ПустаяСсылка(). Неопределено — только для составного типа..Пустая() на реквизите составного типа, где лежит Неопределено. Проверяйте такое поле сравнением = Неопределено, а не методом ссылки.Список.Отбор.Элементы.Очистить() или настройки пользователя.Очистить() или перебор массива ВыделенныеСтроки.Отдельно держите в голове дату: пустая дата в 1С — это '00010101', а не пустая строка и не 0. Присвоение строки или числа дате даст ошибку типа.
Частые вопросы
Как очистить все поля формы разом?
ПустаяСсылка(), строки через "", табличные части через Очистить(). Для нового документа обычно хватает создать его заново.Чем отличается очистка реквизита формы от реквизита объекта?
Объект.Имя, к реквизиту формы — по имени напрямую.Почему `Неопределено` не очищает поле контрагента?
СправочникСсылка.Контрагенты), платформа пытается привести Неопределено к этому типу и падает. Пустую ссылку берите у менеджера: Справочники.Контрагенты.ПустаяСсылка(). Неопределено очищает только составной тип.Как проверить, что поле пустое, перед записью?
Пустая(): Если Объект.Контрагент.Пустая() Тогда. Для составного типа — сравнение Если Объект.Поле = Неопределено Тогда. Для числа и строки — сравнение с 0 и "".Как сбросить фильтр динамического списка кодом?
Список.Отбор.Элементы.Очистить() в серверной процедуре. Это снимает программные условия; настройки, заданные пользователем вручную, сбрасываются через команду стандартных настроек в меню списка.