Разберем типичную задачу: при формировании отчета необходимо выбрать данные справочника (например, Склад.Город) и в зависимости от определенных условий добавить к названию города префикс (например, восклицательные знаки "!!!"), после чего сгруппировать и отсортировать результат. При этом менять метаданные информационной базы нельзя.
Выясним причину, почему это не удается сделать средствами стандартного языка запросов платформы 1С:Предприятие 7.7, и подробно рассмотрим правильные способы реализации такого алгоритма.
Встроенный механизм Запрос в 1С 7.7 существенно отличается от языка запросов 1С 8.x или классического SQL. Проанализируем ключевые ограничения платформы:
+), функции работы со строками или логические ветвления (такие как оператор ?() или конструкция CASE WHEN). Переменная может ссылаться только на существующий реквизит базы или предопределенное поле.Условие(...) служит исключительно для фильтрации строк выборки и не позволяет трансформировать значения полей «на лету».Попытки модифицировать реквизиты объектов в открытой транзакции с последующим откатом (ОтменитьТранзакцию()) крайне опасны. В многопользовательской среде и особенно в распределенных информационных базах (УРИБ) это приводит к блокировкам таблиц и рискам рассинхронизации данных. Рассмотрим штатные и безопасные пути решения.
Самый простой, надежный и переносимый способ, не требующий сторонних библиотек и изменения конфигурации, — выгрузить результат работы штатного запроса в объект ТаблицаЗначений, модифицировать строки в цикле, а затем выполнить группировку и сортировку.
Рассмотрим пошаговую реализацию этого подхода:
// Создаем и выполняем стандартный запрос
ТекстЗапроса = "
|Период с ВыбНачПериода по ВыбКонПериода;
|Склад = Справочник.Склады.ТекущийЭлемент;
|Город = Справочник.Склады.Город;
|Количество = Регистр.ОстаткиТоваров.Количество;
|Функция КонОст = КонОст(Количество);
|Группировка Склад без групп;
|";
Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
// Выгружаем результат в Таблицу Значений
ТЗ = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТЗ);
// Модифицируем строковое поле по условию
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
Если ТЗ.Город = "Москва" Тогда
ТЗ.Город = "!!!" + ТЗ.Город;
КонецЕсли;
КонецЦикла;
// Сворачиваем и сортируем по новым значениям
ТЗ.Свернуть("Город", "КонОст");
ТЗ.Сортировать("Город+");
// Выводим данные в печатную форму
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
Таб.ВывестиСекцию("Строка");
КонецЦикла;
КонецЕсли;
Этот вариант гарантирует стабильную работу отчета в любых типах баз (DBF и 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-сервера, сохраняя исходные структуры метаданных нетронутыми.