При разработке печатных форм, отчетов или обработок во встроенном языке 1С часто требуется объединить несколько строковых полей в одну строку — например, сформировать полное ФИО из отдельных полей: фамилии, имени и отчества. Однако при выполнении стандартной операции сложения через плюс разработчики нередко сталкиваются с ошибкой «Преобразование значения к типу Число не может быть выполнено» (в разговорной речи — «Нельзя приравнять к числу»), хотя все исходные реквизиты в конфигураторе объявлены как строковые.
Проанализируем механику работы платформы 1С, выясним первопричину этой ошибки и подробно разберем все способы её устранения.
Во встроенном языке 1С:Предприятия оператор + перегружен: он используется для арифметического сложения чисел, сдвига дат и конкатенации строк. Вычисление выражения происходит последовательно слева направо, а тип предполагаемой операции определяется по типу первого (левого) операнда.
Рассмотрим проблемную строку кода:
ОбластьПодвал.Параметры.Поле1 = ВыборкаДетальныеЗаписи.Фамилия + " " + ВыборкаДетальныеЗаписи.Имя + " " + ВыборкаДетальныеЗаписи.Отчество;
Если в результате выполнения запроса в поле ВыборкаДетальныеЗаписи.Фамилия вернулось значение типа NULL, платформа не может распознать операцию как строковую конкатенацию. По умолчанию при наличии неопределенного типа или NULL в начале выражения платформа пытается выполнить арифметическое сложение. Встретив следующий операнд — строковый пробел " ", 1С пытается преобразовать строку к числу, что завершается аварийным падением с ошибкой типов.
Разберем основные сценарии, при которых в выборку попадает значение NULL, даже если реквизиты объектов имеют строковый тип:
ЛЕВОЕ СОЕДИНЕНИЕ, ПРАВОЕ СОЕДИНЕНИЕ или ПОЛНОЕ СОЕДИНЕНИЕ в правой таблице отсутствует соответствующая запись по условию связи, все поля этой таблицы заполняются значением NULL.Документ.Контрагент.Фамилия, когда контрагент не выбран) запрос возвращает NULL.ОБЪЕДИНИТЬ ВСЕ): когда в одной из объединяемых веток поле отсутствует и вместо него явно подставлен литерал NULL.Наиболее надежный и профессиональный подход — не допускать появления значений NULL в результатах запроса. Для этого используем встроенную функцию языка запросов ЕСТЬNULL(), которая заменяет NULL на пустую строку.
Посмотрим на пример правильного оформления выборки полей:
ВЫБРАТЬ
ЕСТЬNULL(СпрФизЛица.Фамилия, "") КАК Фамилия,
ЕСТЬNULL(СпрФизЛица.Имя, "") КАК Имя,
ЕСТЬNULL(СпрФизЛица.Отчество, "") КАК Отчество
ИЗ
Документ.ПриемНаРаботу КАК Документ
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК СпрФизЛица
ПО Документ.Сотрудник = СпрФизЛица.Ссылка
Также конкатенацию можно выполнить непосредственно на стороне СУБД в самом тексте запроса:
ВЫБРАТЬ
ЕСТЬNULL(СпрФизЛица.Фамилия, "") + " " + ЕСТЬNULL(СпрФизЛица.Имя, "") + " " + ЕСТЬNULL(СпрФизЛица.Отчество, "") КАК ФИО
ИЗ
Справочник.Сотрудники КАК Сотрудники
Если изменить исходный запрос невозможно или требуется быстрое решение, можно явно указать платформе, что первым операндом является строка. Для этого достаточно начать выражение с пустой строки "":
ОбластьПодвал.Параметры.Поле1 = "" + ВыборкаДетальныеЗаписи.Фамилия + " " + ВыборкаДетальныеЗаписи.Имя + " " + ВыборкаДетальныеЗаписи.Отчество;
В этом случае платформа с самого начала переходит в режим работы со строками. При конкатенации со строкой значение NULL неявно преобразуется в пустое строковое представление, и ошибка не возникает.
Для предотвращения ошибок несовместимости типов в коде рекомендуется использовать специализированные строковые функции, которые безопасно приводят любые типы к строке:
СтрШаблон(): автоматически форматирует переданные аргументы и подставляет пустые значения вместо NULL:
ОбластьПодвал.Параметры.Поле1 = СокрЛП(СтрШаблон("%1 %2 %3",
ВыборкаДетальныеЗаписи.Фамилия,
ВыборкаДетальныеЗаписи.Имя,
ВыборкаДетальныеЗаписи.Отчество));
Строка():
ОбластьПодвал.Параметры.Поле1 = СокрЛП(Строка(ВыборкаДетальныеЗаписи.Фамилия) + " "
+ Строка(ВыборкаДетальныеЗаписи.Имя) + " "
+ Строка(ВыборкаДетальныеЗаписи.Отчество));
При простой конкатенации строк, если у физического лица отсутствует отчество или имя, между словами могут появиться двойные пробелы или лишние пробелы по краям. Разберем по шагам, как собрать строку без дефектов форматирования:
ЧастиФИО = Новый Массив;
Если ЗначениеЗаполнено(ВыборкаДетальныеЗаписи.Фамилия) Тогда
ЧастиФИО.Добавить(СокрЛП(ВыборкаДетальныеЗаписи.Фамилия));
КонецЕсли;
Если ЗначениеЗаполнено(ВыборкаДетальныеЗаписи.Имя) Тогда
ЧастиФИО.Добавить(СокрЛП(ВыборкаДетальныеЗаписи.Имя));
КонецЕсли;
Если ЗначениеЗаполнено(ВыборкаДетальныеЗаписи.Отчество) Тогда
ЧастиФИО.Добавить(СокрЛП(ВыборкаДетальныеЗаписи.Отчество));
КонецЕсли;
ОбластьПодвал.Параметры.Поле1 = СтрСоединить(ЧастиФИО, " ");
Если конфигурация разработана на базе Библиотеки Стандартных Подсистем (БСП), для работы с ФИО и склеивания строк рекомендуется использовать готовые библиотечные методы:
СтроковыеФункцииКлиентСервер.СоединитьСтрокиВМассив() — объединяет переданную коллекцию строк с разделителем, автоматически пропуская пустые и некорректные элементы.ФизическиеЛицаКлиентСервер.ФамилияИнициалы() — специализированная функция для корректного формирования фамилии и инициалов физлица.