При обмене данными между различными конфигурациями 1С, особенно когда источником является стандартная конфигурация, а приемником – специфическая или доработанная, мы часто сталкиваемся с необходимостью преобразования типов данных. Одна из типичных задач – это конвертация строкового кода в числовой. Однако сложности возникают, когда исходный строковый код содержит не только цифры, но и буквы или другие нечисловые символы.
Рассмотрим подробнее ситуацию, описанную на форуме: нам требуется перегрузить данные из справочника "ФизическиеЛица" в 1С:ЗУП в справочник "Картотека" в базе "Поликлиника". Основная проблема заключается в преобразовании реквизита "Код", который в источнике имеет тип "Строка" (например, Строка(Ф10)), а в приемнике ожидается тип "Число" (например, Число (15)). При этом исходный строковый код содержит буквы.
Выясним, почему прямое преобразование строкового кода с буквами в числовой тип может вызвать проблемы, и какие существуют методы решения этой задачи.
Прежде всего, давайте разберемся, как работает встроенная функция Число() в 1С. Эта функция предназначена для явного преобразования строки в число. Она успешно справляется со строками, которые содержат исключительно цифры, десятичные разделители (точку или запятую) и, опционально, знак минуса в начале. Например, строки "123", "45.67", "-89" будут без проблем преобразованы в соответствующие числовые значения.
Однако, если в строке встречаются любые другие символы, такие как буквы, пробелы (кроме неразрывных пробелов, которые функция может иногда игнорировать) или специальные знаки, функция Число() не сможет выполнить преобразование и вызовет ошибку времени выполнения. В версиях 1С 8.x и выше система строго контролирует тип параметра, и если он не является корректным числовым представлением, будет выдана ошибка.
Таким образом, прямое использование конструкции вида Число(СтроковыйКодСБуквами) приведет к сбою при обмене данными.
На основе обсуждений на форуме и дополнительной информации, мы можем выделить несколько подходов к решению этой задачи. Выбор конкретного метода будет зависеть от требований к данным в базе-приемнике и их семантики.
Это, пожалуй, самое простое и логичное решение, если исходный код содержит буквы, и эти буквы являются значимой частью кода, которую мы не можем отбросить. Форумчане также пришли к этому выводу в ходе обсуждения.
Суть метода: Вместо того чтобы пытаться преобразовать строковое значение, содержащее буквы, в число, мы просто изменяем тип реквизита "Код" в базе-приемнике (в нашем случае, в базе "Поликлиника") со "Число" на "Строка".
Преимущества:
Число(), так как преобразование типа не требуется.Когда применять: Этот подход идеален, когда уникальность записи в приемнике не обязательно должна быть выражена чисто числовым кодом, и когда буквы в коде источника имеют смысл и должны быть сохранены.
Если нам критически важно, чтобы код в базе-приемнике был именно числовым, и мы можем пожертвовать буквенными символами, то необходимо предварительно очистить исходную строку от всех нечисловых символов. После такой очистки строку уже можно будет безопасно преобразовать в число.
Суть метода: Создаем собственную функцию или алгоритм, который будет итеративно проверять каждый символ в исходной строке. Мы будем оставлять только те символы, которые допустимы для числового представления (цифры от 0 до 9, знак минуса '-' и десятичный разделитель '.' или ',').
Пример реализации функции очистки (концептуальный):
// Функция для очистки строки от нечисловых символов, оставляя только цифры, минус и десятичный разделитель
Функция ОчиститьСтрокуДляЧисла(ИсходнаяСтрока)
ПеременнаяСимволыДляЧисла = "0123456789.,-"; // Допустимые символы для числа
ОчищеннаяСтрока = "";
Для Каждого Символ Из ИсходнаяСтрока Цикл
Если Найти(ПеременнаяСимволыДляЧисла, Символ) > 0 Тогда
ОчищеннаяСтрока = ОчищеннаяСтрока + Символ;
КонецЕсли;
КонецЦикла;
Возврат ОчищеннаяСтрока;
КонецФункции
// Пример использования в правилах конвертации данных
// Предположим, что ИсходноеЗначение это строковый код из ЗУП
СтрокаДляПреобразования = ОчиститьСтрокуДляЧисла(ИсходноеЗначение);
Попытка
ЧисловоеЗначение = Число(СтрокаДляПреобразования);
Исключение
// Обработка ситуации, если даже после очистки строка не стала числом
// (например, была пустой или содержала несколько минусов/разделителей)
ЧисловоеЗначение = 0; // Или Неопределено, или другое значение по умолчанию
КонецПопытки;
Важные моменты при очистке:
СтрокаСЗапятой.Заменить(",", ".").СтрЗаменить(Строка, Символы.НПП, "") для удаления неразрывных пробелов, которые могут присутствовать в строке.Число() в конструкцию Попытка...Исключение. Это позволит gracefully обработать ситуации, когда даже после очистки строка не может быть преобразована в число, и избежать аварийного завершения обмена данными. В блоке Исключение вы можете присвоить числовой переменной значение 0, Неопределено или зарегистрировать ошибку в журнале.
Попытка
ЧисловоеЗначение = Число(ОчищеннаяСтрока);
Исключение
Сообщить("Ошибка преобразования строки '" + ОчищеннаяСтрока + "' в число. Присвоено значение 0.");
ЧисловоеЗначение = 0;
КонецПопытки;
Когда применять: Этот метод подходит, если буквенная часть кода является "мусором" или служебной информацией, которая не нужна в конечном числовом коде, а основная идентификация осуществляется именно по числовой части.
Этот подход является радикальным, но очень эффективным, если исходный код из ЗУП вообще не играет роли для уникальной идентификации объекта в базе "Поликлиника".
Суть метода: Мы полностью отказываемся от передачи исходного значения "Код" из базы-источника. Вместо этого, при создании нового элемента справочника "Картотека" в базе "Поликлиника", система автоматически генерирует для него новый уникальный числовой код. Это часто реализуется стандартными механизмами 1С, например, при записи нового элемента справочника, когда устанавливается новый номер (УстановитьНовыйКод() или аналогичная логика).
Преимущества:
Когда применять: Этот метод наиболее уместен, когда синхронизация данных происходит по другим уникальным полям, таким как ФИО и ДатаРождения (как было упомянуто на форуме), или по внутреннему уникальному идентификатору (ГУИД), а поле "Код" в приемнике является лишь техническим идентификатором, не связанным напрямую с кодом источника.
Независимо от выбранного метода (очистка строки или изменение логики), реализовывать его удобнее всего через обработчики событий в Правилах Конвертации Данных (ПКД) или Правилах Обмена Данными (ПОД). Это мощный инструмент, который позволяет нам программно вмешиваться в процесс обмена.
Доступные обработчики:
Перед выгрузкой и При выгрузке: Эти обработчики выполняются в базе-источнике перед или во время выгрузки данных. Здесь мы можем подготовить строковое значение, например, очистить его, если хотим передавать только числовую часть.Перед загрузкой и При загрузке: Эти обработчики выполняются в базе-приемнике перед или во время загрузки данных. Здесь мы можем применить нашу логику преобразования или принятия решения о новом коде.Пример использования в обработчике "Перед загрузкой" для ПКС "Код":
Предположим, у нас есть свой алгоритм очистки, и мы хотим применить его при загрузке.
// Обработчик "Перед загрузкой" для свойства "Код"
// Параметры: Источник, Приемник, ВходящиеДанные, СвойствоКонвертации
Если ВходящиеДанные.Значение.ТипЗнч() = Тип("Строка") Тогда
// Вызываем нашу функцию очистки
ОчищеннаяСтрока = ОчиститьСтрокуДляЧисла(ВходящиеДанные.Значение);
Попытка
Приемник.Код = Число(ОчищеннаяСтрока);
Исключение
Приемник.Код = 0; // Значение по умолчанию в случае ошибки
ЗаписатьЖурналРегистрации("ПреобразованиеКода", УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось преобразовать код '" + ВходящиеДанные.Значение +
"' в число после очистки. Установлено 0.");
КонецПопытки;
Отказ = Истина; // Отключаем стандартную загрузку, так как мы установили значение вручную
КонецЕсли;
Такой подход дает нам максимальную гибкость в управлении процессом преобразования данных.
Разберем также некоторые сопутствующие вопросы, которые могут возникнуть при работе с преобразованием типов в 1С:
Формат() с соответствующими параметрами, например, ЧГ=0 для удаления разделителей групп разрядов. При обратном преобразовании (строка в число) функция Число() обычно достаточно умна, чтобы распознать оба разделителя (точку и запятую), но стандартизация всегда снижает риск ошибок.
CAST или CONVERT в SQL. Функция ВЫРАЗИТЬ() не позволяет преобразовать строковое поле в числовое, если строка содержит нечисловые символы, и выдаст ошибку несовместимости типов. В таких случаях приходится придумывать индивидуальные решения, например, работать со строками одинаковой длины с ведущими нулями для корректного сравнения, если это требуется в логике запроса. Однако в контексте обмена данными и ПКД мы работаем с объектами 1С в модулях, где доступны все вышеописанные программные средства.
В заключение, задача конвертации строкового кода, содержащего буквы, в числовой тип при обмене данными 1С имеет несколько решений. Выбор оптимального метода зависит от специфики данных и требований к их хранению в базе-приемнике. Мы можем либо сохранить строковый тип, либо очистить строку перед преобразованием, либо полностью отказаться от использования исходного кода, позволяя приемнику генерировать свой собственный. Использование обработчиков событий в ПКД предоставляет гибкий инструментарий для реализации любого из этих подходов.