Почему в 1С 7.7 не выводятся данные при конкатенации в процедуре Сообщить?

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

При разработке отчетов и обработок в платформе 1С:Предприятие 7.7 начинающие разработчики часто сталкиваются с ситуацией, когда попытка вывести несколько полей выборки запроса в одну строку через оператор сложения + приводит к неожиданным результатам. Например, выводится только первое значение, а второе полностью пропадает из окна сообщений, либо возвращается ошибка несовпадения типов.

Проанализируем конкретный пример кода, в котором возникла подобная проблема:


Процедура Расходные()
    ВыбНачПериода = ТекущаяДата() - 29;
    ВыбКонПериода = ТекущаяДата() + 2;
    
    Запрос = СоздатьОбъект("Запрос");
    ТекстЗапроса = "
    |Период с ВыбНачПериода по ВыбКонПериода;
    |РасходнаяНакладная = Документ.РасходнаяНакладная.ТекущийДокумент;
    |Товар = Документ.РасходнаяНакладная.Товар;
    |НомерСтроки = Документ.РасходнаяНакладная.НомерСтроки;
    |Группировка РасходнаяНакладная;
    |Группировка НомерСтроки;
    |Функция Колво = Счётчик();
    |"; 
    
    Запрос.Выполнить(ТекстЗапроса);
    Пока Запрос.Группировка(1) = 1 Цикл 
        Сообщить(Запрос.РасходнаяНакладная + Запрос.Колво); // Количество не выводится
        Пока Запрос.Группировка(2) = 1 Цикл 
            Сообщить(Запрос.Товар.Наименование + Запрос.НомерСтроки); // Номер строки не виден
        КонецЦикла;
    КонецЦикла; 
КонецПроцедуры

Причины возникновения проблемы

Выясним причину, почему данные отображаются некорректно. В платформе 1С 7.7 такое поведение обусловлено двумя независимыми механизмами:

  1. Правило левосторонней типизации оператора сложения: при вычислении выражения в скобках тип результата определяется исключительно типом левого (первого) операнда. Если левым операндом выступает объектная ссылка (например, Запрос.РасходнаяНакладная типа «Документ»), платформа пытается применить операцию сложения к объекту и числу Запрос.Колво. Поскольку операция сложения документа с числом не определена, выражение не может быть корректно приведено к строке без явного указания строкового контекста.
  2. Фиксированная длина строковых реквизитов: реквизиты справочников и документов строкового типа (например, Наименование) в 1С 7.7 имеют строго фиксированную длину в метаданных (например, 50, 100 или 150 символов). Если наименование товара короче максимальной длины, платформа дополняет его пробелами справа. При сложении Запрос.Товар.Наименование + Запрос.НомерСтроки число приводится к строке и дописывается в самый конец после десятков хвостовых пробелов. В результате номер строки физически присутствует, но уходит далеко за пределы видимой области окна сообщений.

Способ 1. Неявное приведение к строке через пустую строку

Разберем самый простой способ решения проблемы типизации. Чтобы платформа интерпретировала оператор + как конкатенацию строк, первым операндом необходимо поставить строковый литерал (хотя бы пустую строку ""). В этом случае все последующие операнды автоматически преобразуются в их строковое представление:


// Добавляем пустую строку или строковый разделитель первым операндом:
Сообщить("" + Запрос.РасходнаяНакладная + " : " + Запрос.Колво);

Способ 2. Удаление концевых пробелов с помощью функции СокрЛП

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


// Очищаем наименование от хвостовых пробелов:
Сообщить("Товар: " + СокрЛП(Запрос.Товар.Наименование) + ", строка: " + Запрос.НомерСтроки);

Способ 3. Формирование строк через функцию Шаблон()

Рассмотрим более надежный и читаемый способ форматирования сложных строк в 1С 7.7 — использование встроенной функции Шаблон(). Внутри строки-шаблона выражения помещаются в квадратные скобки [...], автоматически вычисляются и преобразуются к строковому типу без необходимости ручной расстановки операторов сложения:


Сообщить(Шаблон("[Запрос.РасходнаяНакладная] (Всего строк: [Запрос.Колво])"));
Сообщить(Шаблон("Товар: [СокрЛП(Запрос.Товар.Наименование)], строка №[Запрос.НомерСтроки]"));

Способ 4. Явное преобразование типов через функцию Строка()

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

Сообщить(Строка(Запрос.РасходнаяНакладная) + " - " + Строка(Запрос.Колво));

Оптимизация выборки данных в запросе 1С 7.7

Обратим внимание на важную деталь производительности: обращение через точку к реквизитам объектов внутри цикла обхода (Запрос.Товар.Наименование) заставляет платформу выполнять дополнительное чтение объекта из базы данных на каждом шаге цикла. Чтобы ускорить выполнение кода, строковые поля следует выносить непосредственно в тело запроса:


Процедура РасходныеОптимизированная()
    ВыбНачПериода = ТекущаяДата() - 29;
    ВыбКонПериода = ТекущаяДата() + 2;
    
    Запрос = СоздатьОбъект("Запрос");
    ТекстЗапроса = "
    |Период с ВыбНачПериода по ВыбКонПериода;
    |РасходнаяНакладная = Документ.РасходнаяНакладная.ТекущийДокумент;
    |Товар = Документ.РасходнаяНакладная.Товар;
    |ТоварНаименование = Документ.РасходнаяНакладная.Товар.Наименование;
    |НомерСтроки = Документ.РасходнаяНакладная.НомерСтроки;
    |Группировка РасходнаяНакладная;
    |Группировка НомерСтроки;
    |Функция Колво = Счётчик();
    |"; 
    
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
        Возврат;
    КонецЕсли;
    
    Пока Запрос.Группировка(1) = 1 Цикл 
        Сообщить(Шаблон("[Запрос.РасходнаяНакладная] (Количество строк: [Запрос.Колво])"));
        Пока Запрос.Группировка(2) = 1 Цикл 
            Сообщить(Шаблон("Товар: [СокрЛП(Запрос.ТоварНаименование)], строка №[Запрос.НомерСтроки]"));
        КонецЦикла;
    КонецЦикла; 
КонецПроцедуры
← На главную