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

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

При разработке отчетов или динамических списков программисты часто сталкиваются с необходимостью сформировать красивое текстовое представление документа или записи непосредственно в запросе. Типичная задача: объединить статичный текст, номер документа и его дату. Однако простая попытка использовать оператор + часто приводит к ошибке «Неверные параметры "+"». Разберем детально, почему это происходит и какими способами можно решить эту задачу в современных реалиях платформы «1С:Предприятие».

Анализируем причину ошибки: несовместимость типов

Прежде всего, давайте проанализируем ситуацию, описанную в теме. Автор пытается выполнить следующую операцию:


ВЫБОР
    КОГДА КОЛИЧЕСТВО(ВложенныйЗапрос.СчетФактура) >= 1
        ТОГДА ВложенныйЗапрос.СчетФактура
    ИНАЧЕ "Счет-фактура (УПД) №" + ПриобретениеТоваровУслуг.НомерВходящегоДокумента + " от " + ПриобретениеТоваровУслуг.ДатаВходящегоДокумента
КОНЕЦ

Проблема здесь заключается в том, что язык запросов 1С — это строго типизированный механизм, который транслирует команды в SQL-запрос. В классическом языке запросов 1С оператор + предназначен исключительно для работы с числами (сложение) или строками (конкатенация). Но он не умеет автоматически приводить дату или ссылку к строке.

Когда вы пытаетесь прибавить к строке " от " поле с типом Дата, система выдает ошибку, так как не знает, в каком формате эту дату нужно превратить в текст. Аналогичная проблема возникнет, если попытаться прибавить число или ссылку на объект (документ или справочник).

Решение 1: Современный подход с функцией СТРОКА()

Если вы работаете на платформе версии 8.3.20 и выше, нам доступно штатное решение. Разработчики добавили в язык запросов функцию СТРОКА(), которая позволяет преобразовывать примитивные типы данных прямо в теле запроса.

Рассмотрим, как изменится наш код с использованием этой функции:


"Счет-фактура (УПД) №" + ПриобретениеТоваровУслуг.НомерВходящегоДокумента + " от " + СТРОКА(ПриобретениеТоваровУслуг.ДатаВходящегоДокумента)

Важные нюансы использования функции СТРОКА():

  1. Она работает только с примитивными типами: Число, Дата, Булево.
  2. Если вам нужно получить строку из ссылки (например, из ссылки на контрагента), вам все равно придется обращаться к реквизиту Наименование или использовать другие методы.
  3. Результат преобразования даты будет зависеть от региональных настроек сервера, что не всегда удобно для формирования строго регламентированных печатных форм.

Решение 2: Использование Системы компоновки данных (СКД)

Если ваша задача — вывести данные в отчет, то лучше всего перенести логику формирования строки из запроса в Вычисляемые поля СКД. Это наиболее гибкий и «правильный» метод с точки зрения архитектуры 1С.

Разберем по шагам, как это сделать:

  1. В схеме компоновки данных оставьте в запросе поля НомерВходящегоДокумента и ДатаВходящегоДокумента как отдельные поля.
  2. Перейдите на закладку «Вычисляемые поля».
  3. Добавьте новое поле, например, ПредставлениеДокумента.
  4. В колонке «Выражение» напишите: "Счет-фактура (УПД) №" + НомерВходящегоДокумента + " от " + Формат(ДатаВходящегоДокумента, "ДФ=dd.MM.yyyy").

В чем преимущество этого метода? СКД при обработке выражений использует не язык запросов, а язык выражений СКД, который гораздо ближе к объектному языку 1С. Здесь нам доступна функция Формат(), которая позволяет задать любой вид даты без сложных манипуляций в запросе.

Решение 3: Постобработка результатов запроса

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

Проанализируем пример кода:


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

Для Каждого СтрокаТЗ Из Результат Цикл
    СтрокаТЗ.Представление = СтрШаблон("Счет-фактура №%1 от %2", СтрокаТЗ.Номер, Формат(СтрокаТЗ.Дата, "ДЛФ=D"));
КонецЦикла;

Здесь мы используем функцию СтрШаблон(), которая делает код читаемым и избавляет от нагромождения плюсов. Этот метод идеален, если данных не миллионы строк, так как цикл обхода коллекции в памяти 1С-сервера работает очень быстро.

Решение 4: Старый «хакерский» способ (для старых платформ)

Бывают ситуации, когда мы ограничены старой версией платформы (ниже 8.3.20) и не можем использовать СКД (например, в динамическом списке). В этом случае программисты используют сложную конструкцию из функций ДЕНЬ(), МЕСЯЦ() и ГОД() в сочетании с ВЫБОР.

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


ВЫБОР 
    КОГДА ДЕНЬ(ДатаДок) = 1 ТОГДА "01"
    КОГДА ДЕНЬ(ДатаДок) = 2 ТОГДА "02"
    ...
    ИНАЧЕ СТРОКА(ДЕНЬ(ДатаДок)) // Если версия позволяет хотя бы это
КОНЕЦ + "." + ...

Внимание: Мы крайне не рекомендуем использовать этот метод, так как текст запроса раздувается до огромных размеров, его становится невозможно поддерживать, а производительность значительно падает. Если вы столкнулись с такой необходимостью — это верный признак того, что логику нужно выносить в СКД или программный код.

Ограничение длины строки: Лимит в 1024 символа

Проанализируем еще один важный технический момент. При сложении строк в запросе (конкатенации) существует ограничение: результат не может превышать 1024 символа.

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

Подведем итоги

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

  1. Если версия платформы 8.3.20+ — используйте функцию СТРОКА().
  2. Если строите отчет — используйте вычисляемые поля СКД и функцию Формат().
  3. Если нужно просто получить Представление() ссылки — помните, что его нельзя складывать с другими строками внутри запроса через +, так как оно формируется уже на стороне клиента.
  4. Старайтесь передавать на сторону SQL-сервера только получение данных, а «украшательство» и сборку итоговых строк оставляйте для уровня приложения.
← На главную