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

В этой статье разберём все способы приведения строк к числовому типу прямо в запросе: от стандартных функций ВАЛ() и ЧИСЛО() до малоизвестных приёмов с ПРЕОБРАЗОВАТЬ() и ЗНАЧ(). Особое внимание уделим типовым ошибкам (например, неявное преобразование строки "123.45" в число 12345 при отсутствии точки как разделителя) и оптимизации запросов для крупных баз.

Почему строку нельзя сравнивать как число напрямую

В 1С:Предприятие 8 строковые и числовые типы данных обрабатываются по-разному даже в условиях ГДЕ. Если попытаться сравнить строку "100" с числом 100 без явного преобразования, система либо выдаст ошибку, либо выполнит неявное приведение — но не всегда так, как вы ожидаете.

Основные проблемы:

  • 🔢 Лексикографическая сортировка: строка "1000" в алфавитном порядке идёт после "200", хотя численно это неверно.
  • Ошибки сравнения: выражение ГДЕ СтрокаПоле = 100 приведёт к исключению, если поле имеет тип Строка.
  • ⚠️ Потеря точности: строка "123,45" может быть интерпретирована как 12345, если разделитель дробной части не учтён.

Пример некорректного запроса:

ВЫБРАТЬ

Номенклатура.Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.Артикул > 1000 // Ошибка, если Артикул - строка!

⚠️ Внимание: В некоторых конфигурациях (например, 1С:УТ 11) артикулы хранятся как строки, даже если визуально выглядят как числа. Всегда проверяйте реальный тип поля в метаданных!

Способы преобразования строки в число в запросе

Существует несколько встроенных функций для явного приведения строк к числовому типу. Их выбор зависит от формата исходных данных и требуемой точности.

1. Функция ВАЛ()

Самый универсальный метод — ВАЛ(Строка). Она преобразует строку в число с учётом региональных настроек (разделитель дробной части, тысячных разрядов). Подходит для большинства случаев:

ВЫБРАТЬ

ВАЛ(Номенклатура.Артикул) КАК АртикулЧисло

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

ВАЛ(Номенклатура.Артикул) > 1000

Особенности ВАЛ():

  • 📌 Преобразует пустую строку в 0.
  • 📌 Игнорирует пробелы в начале и конце строки.
  • ❌ Выдаёт ошибку, если строка содержит недопустимые символы (например, буквы).

2. Функция ЧИСЛО()

ЧИСЛО(Строка) аналогична ВАЛ(), но строже относится к формату. Например, не проигнорирует пробелы:

ВЫБРАТЬ

ЧИСЛО(ЗАМЕНИТЬ(Номенклатура.Артикул, " ", "")) КАК АртикулЧисло

Когда использовать:

  • 🔍 Если нужно гарантированно отсечь строки с "мусором" (например, артикулы вида "A100").
  • 🔢 Когда требуется высокая производительность — ЧИСЛО() работает быстрее ВАЛ() на больших выборках.

3. ПРЕОБРАЗОВАТЬ() и ЗНАЧ()

Для сложных случаев (например, когда строка содержит разделители тысяч) подходит конструкция:

ВЫБРАТЬ

ПРЕОБРАЗОВАТЬ(ЗНАЧ(Номенклатура.Артикул), "Число") КАК АртикулЧисло

Это комбинация приведения к типу (ЗНАЧ()) и явного преобразования (ПРЕОБРАЗОВАТЬ()). Полезно, если строка приходит из внешнего источника с нестандартным форматом.

📊 Какой функцией вы чаще всего преобразуете строки в числа в 1С?
ВАЛ()
ЧИСЛО()
ПРЕОБРАЗОВАТЬ()
Другие способы

Типовые ошибки и как их избежать

Даже опытные разработчики сталкиваются с подводными камнями при работе со строковыми числами. Рассмотрим самые распространённые.

1. Неучёт региональных настроек

Если в строке дробная часть отделена запятой ("123,45"), а в системе установлен разделитель-точка, ВАЛ() вернёт 123 вместо 123.45. Решение:

ВЫБРАТЬ

ВАЛ(СТРЗАМЕНИТЬ(Номенклатура.ЦенаСтрокой, ",", ".")) КАК ЦенаЧисло

2. Пустые строки и NULL

ВАЛ(NULL) и ВАЛ("") возвращают 0, что может исказить результаты. Чтобы исключить такие записи:

ВЫБРАТЬ

ВАЛ(Номенклатура.Артикул) КАК АртикулЧисло

ГДЕ

НЕ Номенклатура.Артикул ЕСТЬ NULL

И НЕ Номенклатура.Артикул = ""

3. Переполнение числового типа

Если строка содержит число больше 2^31-1 (для типа Число(10,0)), произойдёт ошибка. Для больших значений используйте:

ВЫБРАЗТЬ

ПРЕОБРАЗОВАТЬ(ЗНАЧ(Номенклатура.Код), "Число(15,0)") КАК КодЧисло

⚠️ Внимание: В конфигурациях с включённым режимом совместимости 1С:Предприятие 7.7 функция ВАЛ() может вести себя иначе — всегда проверяйте поведение на тестовой базе!

Убедиться, что поле действительно содержит числовые символы|Проверить региональные настройки (разделители)|Исключить NULL и пустые строки|Оценить диапазон значений (не превышает лимиты типа)

-->

Оптимизация производительности

Преобразование строк в числа в запросе может значительно замедлить выполнение на больших таблицах. Рассмотрим способы оптимизации.

1. Предварительная обработка данных

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

2. Использование индексов

Создайте вычисляемое поле с числовым значением и проиндексируйте его:

// В модуле объекта

Процедура ПриЗаписи()

Если НЕ ЗначениеЗаполнено(АртикулЧисло) Тогда

АртикулЧисло = ВАЛ(Артикул);

КонецЕсли;

КонецПроцедуры

Затем в запросе используйте уже числовое поле:

ВЫБРАТЬ

Номенклатура.Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.АртикулЧисло > 1000

3. Альтернативные подходы для фильтрации

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

ВЫБРАТЬ

Номенклатура.Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

НАЧИНАЕТСЯС(Номенклатура.Артикул, "1") // Отсекаем заведомо нечисловые строки

И ВАЛ(Номенклатура.Артикул) > 1000

Метод преобразования Производительность Надёжность Когда использовать
ВАЛ() Средняя Высокая Универсальный случай
ЧИСЛО() Высокая Средняя Чистые числовые строки
ПРЕОБРАЗОВАТЬ(ЗНАЧ(), "Число") Низкая Высокая Сложные форматы
Предварительное вычисляемое поле Максимальная Максимальная Критичные по скорости запросы
💡

Для ускорения запросов с преобразованием строк в числа используйте вычисляемые поля с индексами или предварительную фильтрацию по строковым шаблонам.

Работа с дробными числами

Особую сложность представляют строки, содержащие дробные числа (например, цены или веса). Здесь важно учитывать:

  • 📏 Разделитель дробной части: запятая или точка.
  • 🔢 Количество знаков после запятой.
  • ⚠️ Локальные настройки пользователя, под которым выполняется запрос.

Пример обработки цены в формате "1 234,56":

ВЫБРАТЬ

ВАЛ(СТРЗАМЕНИТЬ(СТРЗАМЕНИТЬ(Документ.СуммаСтрокой, " ", ""), ",", ".")) КАК СуммаЧисло

Для гарантированно корректного преобразования используйте функцию Формат() с явным указанием формата:

ВЫБРАТЬ

ЧИСЛО(Формат(Документ.СуммаСтрокой, "ЧДЦ=.; ЧРД= ")) КАК СуммаЧисло

💡

Если в базе хранятся строковые цены с разными разделителями, создайте обработку, которая приведёт их к единому формату при загрузке данных. Это избавит от проблем с преобразованием в будущем.

Примеры реальных запросов

Разберём практические случаи, где преобразование строк в числа необходимо.

1. Фильтрация номенклатуры по артикулу

Задача: выбрать товары с артикулами в диапазоне 1000–2000 (артикулы хранятся как строки).

ВЫБРАТЬ

Номенклатура.Наименование,

Номенклатура.Артикул

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

ВАЛ(Номенклатура.Артикул) МЕЖДУ 1000 И 2000

УПОРЯДОЧИТЬ ПО

ВАЛ(Номенклатура.Артикул)

2. Сортировка по строковому коду

Если коды контрагентов хранятся как строки ("001", "002", ..., "010"), стандартная сортировка даст порядок: 001, 010, 002. Исправляем:

ВЫБРАТЬ

Контрагенты.Наименование

ИЗ

Справочник.Контрагенты КАК Контрагенты

УПОРЯДОЧИТЬ ПО

ВАЛ(Контрагенты.Код)

3. Агрегация по числовым значениям в строках

Задача: посчитать количество документов, где номер (строка) начинается с цифры 5.

ВЫБРАТЬ

КОЛИЧЕСТВО(*) КАК Количество

ИЗ

Документ.ЗаказПокупателя КАК Заказ

ГДЕ

ЛЕВ(Заказ.Номер, 1) = "5"

И ВАЛ(Заказ.Номер) > 5000

Что делать, если строка содержит не только цифры?

Если в строке есть префиксы (например, "ART-100"), используйте комбинацию ПРАВ() и НАЙТИ() для извлечения числовой части:

ВАЛ(СРЕД(Номенклатура.Артикул, НАЙТИ(Номенклатура.Артикул, "-") + 1))

Обработка ошибок преобразования

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

1. Использование ВЫРАЗИТЬ

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

ВЫБРАТЬ

ВЫРАЗИТЬ(ВАЛ(Номенклатура.Артикул) КАК Число(10,0)) КАК АртикулЧисло

Если преобразование не удалось, вернётся NULL.

2. Фильтрация "плохих" строк

Исключите записи, которые заведомо не могут быть числами:

ВЫБРАТЬ

Номенклатура.Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

НЕ Номенклатура.Артикул ПОДОБНО "%[^0-9]%" // Исключаем строки с нецифровыми символами

И ВАЛ(Номенклатура.Артикул) > 100

3. Логгирование ошибок

Для отладки полезно выводить строки, которые не удалось преобразовать:

ВЫБРАТЬ РАЗЛИЧНЫЕ

Номенклатура.Артикул КАК НекорректныйАртикул

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

НЕ ПРЕДСТАВЛЯЕТСОБОЙЧИСЛО(Номенклатура.Артикул) // Функция проверяет, можно ли строку преобразовать в число

⚠️ Внимание: Функция ПРЕДСТАВЛЯЕТСОБОЙЧИСЛО() появилась в платформе 1С:Предприятие 8.3.14. В более ранних версиях используйте ПОПЫТКА ... ИСКЛЮЧЕНИЕ в программном коде.

FAQ: Частые вопросы

Можно ли сравнивать строку с числом напрямую, без преобразования?

Нет, это приведёт к ошибке. Система не выполняет неявное преобразование строк в числа в условиях ГДЕ. Всегда используйте явные функции (ВАЛ(), ЧИСЛО()).

Почему запрос с ВАЛ() работает медленно на большой таблице?

Функция ВАЛ() требует полного сканирования строк и их преобразования. Для ускорения:

  1. Создайте вычисляемое поле с числовым значением и проиндексируйте его.
  2. Используйте предварительную фильтрацию по строковым шаблонам (например, НАЧИНАЕТСЯС).
Как преобразовать строку "1 234,56 руб." в число 1234.56?

Удалите все нецифровые символы (кроме разделителя дробной части) и замените разделители:

ВАЛ(СТРЗАМЕНИТЬ(

СТРЗАМЕНИТЬ(

СТРЗАМЕНИТЬ(Строка, " ", ""),

"руб.",

""

),

",",

"."

))

Что делать, если в строке есть буквенные префиксы (например, "PR-100")?

Извлеките числовую часть с помощью СРЕД() и НАЙТИ():

ВАЛ(СРЕД(

Артикул,

НАЙТИ(Артикул, "-") + 1

))

Или используйте регулярные выражения (в новых версиях платформы).

Как узнать, какие артикулы не преобразовались в числа?

Выполните запрос с проверкой:

ВЫБРАТЬ

Номенклатура.Артикул КАК НекорректныйАртикул

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

НЕ ПРЕДСТАВЛЯЕТСОБОЙЧИСЛО(Номенклатура.Артикул)

Или используйте конструкцию ПОПЫТКА ... ИСКЛЮЧЕНИЕ в программном коде.