Почему при форматировании числа в таблице значений остается только первый символ?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Анализ исходной ситуации

Представим стандартный сценарий: у нас есть объект ТаблицаЗначений, полученный в результате выполнения запроса. В одной из колонок хранятся числа, например, 145 254. Нам необходимо убрать неразрывный пробел, чтобы получить строку "145254". Разработчик использует привычный цикл обхода:


Для каждого СтрокаИзТЗ из ТаблицаДанных Цикл
    СтрокаИзТЗ.МоеЧисло = Формат(СтрокаИзТЗ.МоеЧисло, "ЧГ=0");
КонецЦикла;

При пошаговой отладке выясняется странная деталь: выражение Формат(СтрокаИзТЗ.МоеЧисло, "ЧГ=0") вычисляет верную строку "145254", но как только управление переходит к следующей строке кода, значение в СтрокаИзТЗ.МоеЧисло превращается в "1". Проанализируем причины этого явления.

Выясняем причину: коварство типизации

Основная причина такого поведения кроется в том, как 1С работает с типами данных в колонках таблицы значений. В отличие от простых переменных, колонки таблицы могут иметь жесткую типизацию. Выясним, как именно устанавливаются эти правила:

  1. Программное создание без типа: Если вы создаете колонку методом Колонки.Добавить("Имя") без параметров, она получает тип Произвольный. В такую колонку можно записывать данные любого типа и любой длины.
  2. Выгрузка из запроса: Это самый частый случай. Метод Выгрузить() создает таблицу, структура которой в точности соответствует метаданным запроса. Если в запросе поле имело тип Число(10, 0) или было ограничено конструкцией ВЫРАЗИТЬ("" КАК СТРОКА(1)), то и колонка в таблице значений получит именно такие ограничения.

В рассматриваемой ситуации колонка МоеЧисло была типизирована как Строка с длиной 1. Это могло произойти, если в исходном запросе к этому полю применялись преобразования или если запрос объединял данные, где в одной из частей была пустая строка единичной длины. Когда мы пытаемся записать строку "145254" в ячейку, которая "готова" принять только один символ, платформа 1С не выдает ошибку, а просто отсекает лишнее, оставляя первый символ. Именно поэтому мы видим "1" вместо ожидаемого результата.

Как проверить тип и длину колонки?

Чтобы убедиться в наших догадках, рассмотрим способ программной проверки ограничений колонки. Для этого мы можем обратиться к свойству ТипЗначения колонки таблицы:


ОписаниеТипа = ТаблицаДанных.Колонки.МоеЧисло.ТипЗначения;
Для каждого Тип Из ОписаниеТипа.Типы() Цикл
    Сообщить("Допустимый тип: " + Тип);
КонецЦикла;
// Проверка квалификаторов строки
Квалификатор = ОписаниеТипа.КвалификаторыСтроки;
Сообщить("Длина строки в колонке: " + Квалификатор.Длина);

Если в окне сообщений вы увидите Длина строки в колонке: 1, причина подтверждена. Теперь разберем по шагам, как это исправить.

Способ 1: Изменение типа в запросе

Самый правильный метод — исправить источник данных. Если вы понимаете, что число в дальнейшем должно стать строкой, можно подготовить поле прямо в тексте запроса, задав ему достаточную длину. Однако помните, что возможности форматирования (удаление пробелов) внутри SQL-запроса в 1С ограничены. Тем не менее, можно гарантировать длину:


"ВЫБРАТЬ
|   ВЫРАЗИТЬ("""" КАК СТРОКА(20)) КАК МоеЧислоСтрокой,
|   ... "

Способ 2: Программная типизация колонки при создании

Если таблица создается вручную, разберем, как правильно задать описание типа с неограниченной длиной. Для этого используются КвалификаторыСтроки. Значение 0 в параметре длины означает "неограниченно":


КвалификаторСтр = Новый КвалификаторыСтроки(0); // 0 - любая длина
ОписаниеТипаСтр = Новый ОписаниеТипов("Строка", , КвалификаторСтр);
ТаблицаДанных.Колонки.Добавить("МоеЧисло", ОписаниеТипаСтр);

Способ 3: Пересоздание колонки "на лету"

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

  1. Добавляем новую колонку с временным именем и нужным типом (неограниченная строка).
  2. В цикле копируем данные из старой колонки в новую, применяя функцию Формат().
  3. Удаляем старую колонку.
  4. Переименовываем новую колонку в исходное имя.

ТаблицаДанных.Колонки.Добавить("ВременнаяКолонка", Новый ОписаниеТипов("Строка"));
Для каждого Стр Из ТаблицаДанных Цикл
    Стр.ВременнаяКолонка = Формат(Стр.МоеЧисло, "ЧГ=0");
КонецЦикла;
ТаблицаДанных.Колонки.Удалить("МоеЧисло");
ТаблицаДанных.Колонки.ВременнаяКолонка.Имя = "МоеЧисло";

Важный нюанс: Разделители и функция СтрЗаменить

Часто разработчики пытаются использовать СтрЗаменить(Строка, " ", ""). Проанализируем ситуацию: почему это может не сработать? В 1С при форматировании чисел по умолчанию используется неразрывный пробел (код символа 160), а не обычный (код 32). Обычный поиск пробела в кавычках его не найдет. Поэтому использование функции Формат(Число, "ЧГ=0") — это максимально надежный способ, так как он управляет выводом на уровне ядра системы.

Рекомендация по архитектуре решения

Рассмотрим подробнее, действительно ли вам нужно менять само значение в таблице? Если ваша цель — просто красиво отобразить число без пробелов в списке на форме, то превращать число в строку — плохая практика. Выясним почему:

Вместо изменения данных в ТаблицаЗначений, лучше настроить формат отображения в элементе формы (Табличное поле или Таблица формы). В свойствах колонки на форме найдите поле "Формат" и введите туда ЧГ=0. Данные останутся числами, но пользователь увидит их без пробелов.

Резюме

Если при записи в таблицу значений данные обрезаются — всегда проверяйте КвалификаторыСтроки в ОписаниеТипов соответствующей колонки. Помните, что таблицы, полученные из запросов, наследуют жесткую типизацию, и для работы с длинными строками вам может потребоваться либо корректировка запроса, либо программное переопределение типов колонок.

← На главную