Как проверить регистр букв в запросе или в системе компоновки данных (СКД)?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в 1С программисты часто сталкиваются с задачей проверки регистра строк. Например, нужно найти номенклатуру, записанную только заглавными буквами, или выявить некорректное заполнение имен. Однако стандартный язык запросов 1С преподносит сюрприз: условие ГДЕ Поле1 = "ТЕКСТ" возвращает те же результаты, что и ГДЕ Поле1 = "текст". В этой статье мы разберем, почему так происходит, и какими способами можно обойти это ограничение в СКД и программном коде.

Причина ограничения: Особенности SQL и Collation

Прежде чем искать решение, давайте проанализируем причину проблемы. Основная причина, по которой в запросе нельзя напрямую проверить регистр, заключается в настройках сравнения (collation) базы данных на стороне SQL-сервера. По умолчанию при установке 1С используется параметр Cyrillic_General_CI_AS, где аббревиатура CI (Case Insensitive) означает нечувствительность к регистру.

Даже если бы в языке запросов существовала функция ВРег(), на уровне СУБД сравнение все равно игнорировало бы разницу между строчными и прописными буквами. Язык запросов 1С не поддерживает оператор COLLATE, который позволил бы изменить правила сравнения «на лету» в конкретном запросе. Поэтому нам приходится искать обходные пути на уровне прикладного решения.

Способ 1. Использование вычисляемых полей в СКД

Рассмотрим ситуацию, когда отчет строится на Системе компоновки данных. Хотя в тексте самого запроса функции преобразования регистра бесполезны для сравнения, вкладка «Вычисляемые поля» предоставляет больше возможностей. В отличие от запроса, выражения вычисляемых полей выполняются уже после получения данных из БД, непосредственно в процессоре компоновки.

Чтобы проверить регистр в СКД, выполним следующие шаги:

  1. Перейдем на закладку «Вычисляемые поля».
  2. Добавим новое поле, например, ЭтоВерхнийРегистр.
  3. В колонке «Выражение» напишем проверку: ВРег(Наименование) = Наименование

Если это выражение возвращает Истина, значит, исходная строка в базе данных уже была записана в верхнем регистре. Этот метод работает медленнее, чем чистый запрос, так как вычисления происходят в памяти, но для большинства отчетов это наиболее простое и эффективное решение.

Способ 2. Вызов экспортных функций (внешние функции)

Если логика проверки сложнее, чем просто ВРег(), мы можем использовать экспортные функции. Проанализируем нюанс: функции из модуля самого отчета СКД «не видит». Чтобы вызвать функцию в выражении СКД, она должна находиться либо в Общем модуле (с флагами «Клиент», «Сервер», «Внешнее соединение»), либо в Модуле менеджера объекта (если отчет встроен в конфигурацию).

Пример функции в общем модуле:


Функция ПроверитьРегистр(Строка) Экспорт
    Возврат ВРег(Строка) = Строка;
КонецФункции

В СКД вызов будет выглядеть так: ИмяОбщегоМодуля.ПроверитьРегистр(Номенклатура.Наименование).

Важный момент: Для того чтобы СКД разрешила вызов внешних функций, при программном формировании отчета необходимо инициализировать процессор компоновки с соответствующим параметром:


ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);

Здесь последний параметр Истина разрешает использование внешних функций (возможность вызова методов из модулей 1С).

Способ 3. Набор данных — объект (Таблица значений)

Рассмотрим еще один надежный вариант: подготовить данные заранее в программном коде и передать их в СКД через «Набор данных - Объект». Выясним преимущества этого метода: в обычном коде 1С (не в запросе) функции работы со строками работают безупречно.

Посмотрим на пример подготовки данных:


Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Наименование ИЗ Справочник.Номенклатура");
ТЗ = Запрос.Выполнить().Выгрузить();
ТЗ.Колонки.Добавить("ТолькоЗаглавные", Новый ОписаниеТипов("Булево"));

Для Каждого Стр Из ТЗ Цикл
    // Используем бинарное сравнение или проверку через ВРег
    Стр.ТолькоЗаглавные = (ВРег(Стр.Наименование) = Стр.Наименование);
КонецЦикла;

ВнешниеНаборыДанных = Новый Структура("МояТаблица", ТЗ);
// Далее передаем ВнешниеНаборыДанных в ПроцессорКомпоновки

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

Способ 4. Бинарное сравнение (СтрСравнить)

Начиная с версии платформы 8.3.10, в языке 1С появилась мощная функция СтрСравнить(). Она позволяет выполнять сравнение строк с учетом регистра без лишних преобразований в ВРег или НРег.

Разберем, как это работает в коде:


Результат = СтрСравнить(Строка1, Строка2, СпособСравнения.Бинарно);
Если Результат = 0 Тогда
    // Строки полностью идентичны, включая регистр
КонецЕсли;

Параметр СпособСравнения.Бинарно заставляет систему сравнивать коды символов напрямую. Это самый современный и производительный способ программной проверки регистра в 1С.

Нюанс с группировками в СКД

Проанализируем важную особенность поведения самой системы компоновки. Даже если вы вычислили поле регистра или вывели строки с разным написанием («Мама» и «МАМА»), СКД при использовании Группировок может «схлопнуть» эти записи в одну строку. По умолчанию процессор вывода считает их одинаковыми для целей группировки.

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

Резюме

Подведем итоги нашего исследования. В языке запросов проверить регистр невозможно из-за особенностей SQL Collation. Однако мы можем решить задачу следующими методами:

  1. Использовать Вычисляемые поля в СКД с функциями ВРег()/НРег().
  2. Вызывать экспортные функции из модулей менеджера или общих модулей.
  3. Использовать СтрСравнить с бинарным режимом в программном коде.
  4. Формировать данные через Таблицу значений (Набор данных - Объект) для максимального контроля над процессом.

Выбор конкретного метода зависит от архитектуры вашего отчета и требований к производительности.

← На главную