Как в запросе 1С 7.7 дополнить строковую переменную символами по условию?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Разберем типичную задачу: при формировании отчета необходимо выбрать данные справочника (например, Склад.Город) и в зависимости от определенных условий добавить к названию города префикс (например, восклицательные знаки "!!!"), после чего сгруппировать и отсортировать результат. При этом менять метаданные информационной базы нельзя.

Выясним причину, почему это не удается сделать средствами стандартного языка запросов платформы 1С:Предприятие 7.7, и подробно рассмотрим правильные способы реализации такого алгоритма.

Ограничения встроенного языка запросов 1С:Предприятия 7.7

Встроенный механизм Запрос в 1С 7.7 существенно отличается от языка запросов 1С 8.x или классического SQL. Проанализируем ключевые ограничения платформы:

  1. Отсутствие вычисляемых полей и конкатенации: В секции описания переменных запроса нельзя использовать строковые операторы (+), функции работы со строками или логические ветвления (такие как оператор ?() или конструкция CASE WHEN). Переменная может ссылаться только на существующий реквизит базы или предопределенное поле.
  2. Назначение секции «Условие»: Конструкция Условие(...) служит исключительно для фильтрации строк выборки и не позволяет трансформировать значения полей «на лету».

Попытки модифицировать реквизиты объектов в открытой транзакции с последующим откатом (ОтменитьТранзакцию()) крайне опасны. В многопользовательской среде и особенно в распределенных информационных базах (УРИБ) это приводит к блокировкам таблиц и рискам рассинхронизации данных. Рассмотрим штатные и безопасные пути решения.

Способ 1. Постобработка результата через Таблицу Значений (штатный метод)

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

Рассмотрим пошаговую реализацию этого подхода:


// Создаем и выполняем стандартный запрос
ТекстЗапроса = "
|Период с ВыбНачПериода по ВыбКонПериода;
|Склад = Справочник.Склады.ТекущийЭлемент;
|Город = Справочник.Склады.Город;
|Количество = Регистр.ОстаткиТоваров.Количество;
|Функция КонОст = КонОст(Количество);
|Группировка Склад без групп;
|";

Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
    // Выгружаем результат в Таблицу Значений
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    Запрос.Выгрузить(ТЗ);

    // Модифицируем строковое поле по условию
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
        Если ТЗ.Город = "Москва" Тогда
            ТЗ.Город = "!!!" + ТЗ.Город;
        КонецЕсли;
    КонецЦикла;

    // Сворачиваем и сортируем по новым значениям
    ТЗ.Свернуть("Город", "КонОст");
    ТЗ.Сортировать("Город+");

    // Выводим данные в печатную форму
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
        Таб.ВывестиСекцию("Строка");
    КонецЦикла;
КонецЕсли;

Этот вариант гарантирует стабильную работу отчета в любых типах баз (DBF и SQL) без изменения структуры конфигурации.

Способ 2. Формирование префикса на этапе вывода в печатную форму

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

Посмотрим на пример обработки значения непосредственно в цикле обхода группировок запроса:


Пока Запрос.Группировка("Город") = 1 Цикл
    // Формируем строковое представление для отчета
    Если Запрос.Город = "Москва" Тогда
        ГородДляПечати = "!!!" + СокрЛП(Запрос.Город);
    Иначе
        ГородДляПечати = СокрЛП(Запрос.Город);
    КонецЕсли;

    Таб.ВывестиСекцию("СекцияГород");
КонецЦикла;

Способ 3. Использование прямого SQL-запроса (внешняя компонента 1С++)

Если база данных работает под управлением Microsoft SQL Server и требуется высокая скорость обработки без накладных расходов на выгрузку в память клиента, можно использовать прямые запросы через объект ODBCRecordset внешней компоненты 1С++.

В прямом SQL-запросе доступна полная мощь синтаксиса СУБД, включая условные операторы CASE WHEN и вложенные подзапросы:


RS = СоздатьОбъект("ODBCRecordset");
ТекстSQL = "
|SELECT
|    Города.ГородСтрока AS Город,
|    SUM(Города.Остаток) AS ВсегоОстаток
|FROM
|    (
|        SELECT
|            CASE 
|                WHEN $Склады.Город = 'Москва' THEN '!!!' + $Склады.Город
|                ELSE $Склады.Город
|            END AS ГородСтрока,
|            $Остатки.Количество AS Остаток
|        FROM
|            $Справочник.Склады AS Склады
|        INNER JOIN
|            $Регистр.ОстаткиТоваров AS Остатки ON Остатки.$Реквизит.Склад = Склады.ID
|    ) AS Города
|GROUP BY
|    Города.ГородСтрока
|ORDER BY
|    Города.ГородСтрока
|";

ТЗ = RS.ВыполнитьИнструкцию(ТекстSQL);

Такой подход позволяет перенести всю логику сортировки и группировки вычисляемых строк на сторону SQL-сервера, сохраняя исходные структуры метаданных нетронутыми.

← На главную