При разработке и использовании обработок загрузки данных из внешних файлов Excel разработчики часто сталкиваются с ситуацией, когда числовые данные (артикулы, коды товаров, штрихкоды) считываются с пробелами между разрядами. Например, вместо значения "123456" получается строка "123 456". При этом стандартная функция СтрЗаменить(Результат, " ", "") не дает никакого эффекта, и пробел остается на месте, из-за чего метод Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", Артикул) возвращает пустую ссылку.
Разберем природу возникновения этой ошибки и рассмотрим практические способы ее решения как в коде конфигурации, так и на уровне подготовки файлов.
Проанализируем процесс загрузки данных через COM-объект Excel.Application. При выгрузке диапазона листа с помощью свойства WS.UsedRange.Value ячейки, содержащие числовые данные, попадают в 1С не как строки, а со своим «родным» типом Число.
Когда мы передаем числовое значение в строковые функции (например, СокрЛП() или Строка()), платформа 1С выполняет неявное приведение типа. Согласно региональным установкам русской локализации, числа форматируются с разделением триад (групп разрядов). При этом в качестве разделителя используется не стандартный символ пробела с кодом ASCII 32, а неразрывный пробел (код символа 160 / Символы.НПП).
Так как функция СтрЗаменить(Результат, " ", "") ищет символ пробела с кодом 32, неразрывный пробел с кодом 160 просто игнорируется и остается в результирующей строке.
Рассмотрим прямое решение проблемы при помощи удаления спецсимволов. Для гарантированной очистки строки от любых пробельных символов заменим как обычный пробел, так и неразрывный пробел:
// Очистка строки от обычных и неразрывных пробелов
Артикул = СокрЛП(Результат);
Артикул = СтрЗаменить(Артикул, " ", "");
Артикул = СтрЗаменить(Артикул, Символ(160), "");
В платформе 1С:Предприятие также доступна предопределенная системная константа Символы.НПП, которую удобно использовать вместо явного указания кода:
Артикул = СтрЗаменить(СтрЗаменить(СокрЛП(Результат), Символы.НПП, ""), " ", "");
Если артикул изначально является числовым значением, наиболее правильным подходом с точки зрения платформы 1С является явное форматирование без разделения групп разрядов. Посмотрим на пример вызова функции Формат() с параметром ЧГ=0 (Числовая Группировка = 0):
// Если значение еще является числом:
ЧисловоеЗначение = МассивКолонок.Получить(0).Получить(строкаТП);
Артикул = Формат(ЧисловоеЗначение, "ЧГ=0");
// Если значение уже приведено к строке:
Артикул = Формат(Число(Результат), "ЧГ=0");
Обратите внимание: преобразование через Число() сработает только в том случае, если в артикуле нет буквенных символов. Если в файле могут встретиться составные артикулы (например, "АБВ123"), разберем универсальный вариант обработки.
Рассмотрим надежный алгоритм, который корректно обрабатывает как чисто числовые артикулы, так и строки со смешанными символами:
ЗначениеЯчейки = МассивКолонок.Получить(0).Получить(строкаТП);
Если ТипЗнч(ЗначениеЯчейки) = Тип("Число") Тогда
Артикул = Формат(ЗначениеЯчейки, "ЧГ=0");
Иначе
// Если это строка, удаляем возможные неразрывные и стандартные пробелы
Артикул = СокрЛП(ЗначениеЯчейки);
Артикул = СтрЗаменить(Артикул, Символы.НПП, "");
Артикул = СтрЗаменить(Артикул, " ", "");
КонецЕсли;
// Поиск номенклатуры по очищенному артикулу
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", Артикул);
Если в рабочей базе активно работают пользователи и нет возможности выполнить монопольное обновление конфигурации, рассмотрим альтернативные варианты решения задачи:
.epf): скопируем типовую обработку или форму документа во внешнюю обработку, внесем исправление по замене неразрывного пробела и откроем ее через меню Файл → Открыть либо подключим в справочник дополнительных обработок.="'" & A2, скопируем результат и вставим обратно как значения. Лидирующий апостроф заставит COM-объект возвращать значение строго в виде текста, не преобразуя его в числовой формат.