Мы рассмотрим важную и часто встречающуюся задачу при разработке собственных обработок или расширений в 1С:Предприятии 8.3 — это программная проверка заполнения реквизитов формы. Особую сложность представляют реквизиты типа "Таблица Значений" (ТЗ), для которых требуется специфический подход к определению их типа и проверке содержимого. Разберем, как это можно реализовать, используя встроенные механизмы платформы.
Когда мы обходим список обязательных реквизитов формы и нам необходимо выполнить различную логику проверки в зависимости от их типа, ключевым шагом является корректное определение этого типа. В частности, для табличных данных, которые на форме представлены как ДанныеФормыКоллекция, нам нужно отличить их от примитивных типов.
Для определения типа значения реквизита, а не типа его описания, мы используем функцию ТипЗНЧ(). Эта функция возвращает тип того значения, которое содержится в переменной или реквизите в текущий момент. Это критически важно, поскольку прямое сравнение, например, ЭтаФорма[Реквизит] = Тип("ДанныеФормыКоллекция"), не будет работать. В данном случае мы пытаемся сравнить само значение реквизита (т.е. объект коллекции) с объектом, который представляет собой системный тип. Это как сравнить конкретный автомобиль с абстрактным понятием "автомобиль" – это разные вещи.
Правильный подход выглядит следующим образом:
Если ТипЗНЧ(ЭтаФорма[Реквизит]) = Тип("ДанныеФормыКоллекция") Тогда
// Здесь мы знаем, что реквизит является коллекцией (например, таблицей значений)
// Можем выполнять специфичную логику для коллекций
КонецЕсли;
В этом примере ЭтаФорма[Реквизит] обращается к значению реквизита формы по его имени, хранящемуся в переменной Реквизит. Функция ТипЗНЧ() возвращает тип этого значения, который затем сравнивается с системным типом Тип("ДанныеФормыКоллекция"). Таким образом, мы корректно определяем, имеем ли мы дело с табличной частью или произвольной таблицей значений.
ДанныеФормыКоллекция — это специализированный тип данных, который активно используется в управляемых формах 1С:Предприятия для представления различных коллекций информации. Понимание этого типа данных является фундаментальным для корректной работы с табличными данными на форме. Чаще всего этот тип встречается при работе с:
ДанныеФормыКоллекция.ДанныеФормыКоллекция.Понимание того, что реквизит на форме является ДанныеФормыКоллекция, позволяет нам применять к нему специфичные свойства и методы, например, для проверки его заполненности или для перебора строк.
После того как мы успешно определили, что наш реквизит имеет тип ДанныеФормыКоллекция, следующим логичным шагом является проверка, содержит ли эта коллекция какие-либо данные, то есть не пуста ли она. Для этого у объектов типа ДанныеФормыКоллекция существует полезное свойство .Количество(), которое возвращает число строк в коллекции.
Если ЭтаФорма[Реквизит].Количество() = 0, это означает, что таблица или коллекция полностью пуста. Теперь мы можем добавить эту проверку в нашу общую логику обхода обязательных реквизитов формы:
Перем Отказ; // Предполагается, что переменная Отказ объявлена ранее и управляет отменой действия
// Мы создадим фиктивный массив обязательных реквизитов для примера.
// В реальной ситуации он будет заполнен именами реквизитов вашей формы.
МассивОбязательныхРеквизитов = Новый Массив;
МассивОбязательныхРеквизитов.Добавить("ТабличнаяЧасть"); // Пример имени табличной части
МассивОбязательныхРеквизитов.Добавить("МойРеквизитСтрока"); // Пример имени строкового реквизита
МассивОбязательныхРеквизитов.Добавить("МойРеквизитЧисло"); // Пример имени числового реквизита
// Инициализируем Отказ
Отказ = Ложь;
// Цикл по обязательным реквизитам
Для Каждого Реквизит Из МассивОбязательныхРеквизитов Цикл
// Шаг 1: Определяем тип реквизита
Если ТипЗНЧ(ЭтаФорма[Реквизит]) = Тип("ДанныеФормыКоллекция") Тогда
// Реквизит является табличной коллекцией (например, табличной частью или ТЗ)
Если ЭтаФорма[Реквизит].Количество() = 0 Тогда
Сообщить("Таблица '" + Реквизит + "' должна быть заполнена! Добавьте хотя бы одну строку.", СтатусСообщения.Внимание, Реквизит);
Отказ = Истина;
Прервать; // Если нужно остановить проверку после первого найденного незаполненного реквизита
КонецЕсли;
Иначе
// Реквизит является примитивным типом или другим типом данных
// Здесь мы можем добавить свою логику проверки для других типов,
// например, проверку на пустую строку, Неопределено, 0 для чисел и т.д.
// Универсальная функция ЗначениеЗаполнено() очень удобна для большинства случаев.
Если ЗначениеЗаполнено(ЭтаФорма[Реквизит]) = Ложь Тогда
Сообщить("Поле '" + Реквизит + "' не заполнено! Заполните его, пожалуйста.", СтатусСообщения.Внимание, Реквизит);
Отказ = Истина;
Прервать; // Если нужно остановить проверку
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если Отказ Тогда
// Здесь можно выполнить дополнительные действия, если проверка не пройдена
// Например, отменить запись или проведение документа.
Сообщить("Заполнение формы не завершено. Исправьте ошибки перед продолжением.", СтатусСообщения.Ошибка);
КонецЕсли;
В этом примере мы видим, как можно комбинировать проверку типа с проверкой заполнения для разных видов реквизитов. Функция ЗначениеЗаполнено() является универсальным способом проверки заполнения для большинства примитивных типов данных (строк, чисел, дат, ссылок).
Важно отметить, что параметр СтатусСообщения.Внимание или СтатусСообщения.Ошибка и третий параметр (имя реквизита) в функции Сообщить() позволяют платформе более интеллектуально отображать сообщения пользователю, например, подсвечивать соответствующий элемент формы.
При работе с ДанныеФормыКоллекция важно учитывать особенности клиент-серверного взаимодействия в 1С. Платформа оптимизирует передачу данных, передавая коллекции порциями, чтобы уменьшить объем сетевого трафика и ускорить взаимодействие. Это означает, что при обходе большого количества строк или частом обращении к свойствам коллекции на клиенте может происходить множество неявных серверных вызовов, что снижает производительность.
Рекомендация по оптимизации: Если ваша коллекция потенциально может содержать значительное количество строк (например, более 20-30), или вы планируете выполнять сложную фильтрацию (например, с помощью метода НайтиСтроки) или интенсивный обход строк, рекомендуется выполнять эти операции на сервере. Для этого мы можем передать коллекцию на сервер и там уже работать с ней, или использовать серверные обработчики формы, где она будет доступна полностью в контексте сервера. Это позволит избежать лишних клиент-серверных обменов и значительно повысит производительность.
Платформа 1С:Предприятие предоставляет ряд мощных встроенных механизмов, которые позволяют значительно упростить и стандартизировать проверку заполнения реквизитов, дополняя или даже заменяя часть нашей программной логики:
Это самый простой и часто используемый механизм для базовой проверки обязательности заполнения. Для каждого реквизита формы (и, что еще важнее, реквизита объекта метаданных) в конфигураторе можно установить свойство "Проверка заполнения" в значение "Выдавать ошибку". В этом случае:
Количество() > 0).Мы настоятельно рекомендуем использовать этот механизм для всех реквизитов, которые должны быть заполнены всегда. Это значительно снижает объем необходимого кода, обеспечивает единообразное поведение для пользователя и упрощает поддержку конфигурации.
ОбработкаПроверкиЗаполненияНаСервере и ОбработкаПроверкиЗаполнения:
Для более сложной или специфичной логики проверки заполнения, которая не укладывается в рамки простого свойства "Проверка заполнения", мы можем использовать специализированные события, предоставляемые платформой:
ОбработкаПроверкиЗаполненияНаСервере: Это событие формы, которое вызывается на сервере перед записью или проведением объекта. Оно предназначено для проверки реквизитов формы, которые не относятся к основному объекту (т.е. являются произвольными реквизитами самой формы, как в нашем случае с ЭтаФорма[Реквизит]).ОбработкаПроверкиЗаполнения: Это событие основного объекта формы (например, ДокументОбъект или СправочникОбъект). Оно вызывается на сервере перед записью или проведением самого объекта и предназначено для проверки его реквизитов. Это событие обычно используется в модулях объектов.В обработчиках этих событий нам передается параметр Отказ (тип Булево, который мы устанавливаем в Истина при обнаружении ошибок) и ПроверяемыеРеквизиты (массив имен реквизитов, которые платформа будет проверять по умолчанию, если для них установлено свойство "Проверка заполнения"). Мы можем:
ПроверяемыеРеквизиты.Отказ = Истина, если обнаружили незаполненные или некорректные данные, чтобы отменить запись или проведение объекта.Сообщить(), предоставляя пользователю максимально информативную обратную связь.Пример использования ОбработкаПроверкиЗаполненияНаСервере (для модуля формы):
&НаСервере
Процедура ОбработкаПроверкиЗаполненияНаСервере(Отказ, ПроверяемыеРеквизиты)
// Предположим, у нас есть реквизит формы "МояТаблица",
// который не является частью основного объекта, но должен быть заполнен.
Если МояТаблица.Количество() = 0 Тогда
Сообщить("Таблица 'МояТаблица' должна быть заполнена! Добавьте хотя бы одну строку.", СтатусСообщения.Внимание, "МояТаблица");
Отказ = Истина;
КонецЕсли;
// Если для "МояТаблица" в конфигураторе установлено свойство "Проверка заполнения",
// и мы уже проверили ее здесь, то можно удалить ее имя из списка ПроверяемыеРеквизиты.
// Это предотвратит повторную стандартную проверку платформы.
Если ПроверяемыеРеквизиты.Найти("МояТаблица") <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(ПроверяемыеРеквизиты.Найти("МояТаблица"));
КонецЕсли;
// Дополнительные проверки других реквизитов формы по нашей сложной логике...
// Например, проверка значения другого реквизита "Комментарий"
Если ТипЗНЧ(Комментарий) = Тип("Строка") И Строка(Комментарий) = "" Тогда
Сообщить("Комментарий не может быть пустым!", СтатусСообщения.Внимание, "Комментарий");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Такой подход дает максимальную гибкость в управлении процессом проверки заполнения, позволяя сочетать стандартные механизмы с собственной бизнес-логикой.
В контексте управляемых форм 1С:Предприятия у начинающих разработчиков часто возникает вопрос о том, когда использовать ЭтаФорма, а когда ЭтотОбъект (или просто Объект). Давайте разберемся, чтобы избежать путаницы:
ЭтаФорма:
Обращение ЭтаФорма всегда относится непосредственно к самой форме, ее элементам управления и реквизитам. Если мы хотим обратиться к реквизиту, который является произвольным реквизитом самой формы (т.е. вы добавили его на форму вручную через конфигуратор в разделе "Реквизиты" формы), то корректно обращаться к нему через ЭтаФорма.ИмяРеквизита или ЭтаФорма[ИмяРеквизита]. В модуле формы часто можно просто использовать ИмяРеквизита без префикса ЭтаФорма, но для ясности и однозначности явное указание ЭтаФорма предпочтительнее.
Важный момент: Информация о том, что ЭтаФорма устарела или будет отменена, не является общепринятой и актуальной. ЭтаФорма остается основным и правильным способом обращения к самой форме и ее реквизитам. Разговоры о "старении" часто возникают из-за путаницы с контекстом или устаревших практик.
ЭтотОбъект (или Объект):
В контексте формы ЭтотОбъект (или чаще просто переменная Объект, которая создается автоматически, если основной реквизит формы называется "Объект") представляет собой основной реквизит формы. Этот реквизит содержит данные редактируемого прикладного объекта, например, экземпляр ДокументОбъект (для форм документов), СправочникОбъект (для форм элементов справочников) или РегистрНаборЗаписей (для форм записей регистров). Если ваш реквизит (например, табличная часть документа, или обычный реквизит типа "Наименование") является частью этого основного объекта, то к нему следует обращаться через основной реквизит: Объект.ИмяТабличнойЧасти или Объект.ИмяРеквизитаОбъекта.
Например, если на форме документа "Реализация" основной реквизит называется "Объект" и имеет тип "ДокументОбъект.РеализацияТоваровУслуг", а нам нужна его табличная часть "Товары", мы обратимся к ней как Объект.Товары.
Таким образом, выбор между ЭтаФорма и Объект зависит от того, является ли реквизит произвольным реквизитом самой формы (для управления интерфейсом, временных данных) или же частью основного прикладного объекта, данные которого мы редактируем на форме.
Мы подробно рассмотрели, как программно определить тип реквизита формы, в частности, типа ДанныеФормыКоллекция, и как проверить его заполнение в 1С:Предприятии 8.3. Мы выяснили, что функция ТипЗНЧ() является ключевым инструментом для этой задачи, позволяя нам различать типы данных и применять специфическую логику проверки.
Кроме того, мы проанализировали дополнительные, более мощные встроенные механизмы проверки заполнения, такие как свойство "Проверка заполнения" в конфигураторе и события формы и объекта ОбработкаПроверкиЗаполненияНаСервере и ОбработкаПроверкиЗаполнения. Эти механизмы предоставляют гибкие возможности для создания надежных и удобных систем контроля данных.
Наконец, мы разобрались с различиями в использовании ЭтаФорма и Объект, что является важным аспектом при написании корректного и поддерживаемого кода для управляемых форм. Применяя все эти знания, мы можем создавать надежные и эффективные механизмы контроля данных в наших обработках и конфигурациях, обеспечивая высокое качество вводимой информации.