В практике разработки на платформе 1С:Предприятие часто возникает задача преобразования числовых данных в строковый формат. Например, это требуется для удаления разделителей групп разрядов (пробелов) перед выводом в текстовый файл, формирования артикулов или уникальных идентификаторов. Однако иногда разработчики сталкиваются с необъяснимым поведением системы: код кажется верным, отладчик показывает правильное значение в момент вычисления, но после записи в ячейку таблицы значений от строки остается лишь первый символ. Рассмотрим, почему так происходит, и разберем способы решения этой проблемы.
Представим стандартный сценарий: у нас есть объект ТаблицаЗначений, полученный в результате выполнения запроса. В одной из колонок хранятся числа, например, 145 254. Нам необходимо убрать неразрывный пробел, чтобы получить строку "145254". Разработчик использует привычный цикл обхода:
Для каждого СтрокаИзТЗ из ТаблицаДанных Цикл
СтрокаИзТЗ.МоеЧисло = Формат(СтрокаИзТЗ.МоеЧисло, "ЧГ=0");
КонецЦикла;
При пошаговой отладке выясняется странная деталь: выражение Формат(СтрокаИзТЗ.МоеЧисло, "ЧГ=0") вычисляет верную строку "145254", но как только управление переходит к следующей строке кода, значение в СтрокаИзТЗ.МоеЧисло превращается в "1". Проанализируем причины этого явления.
Основная причина такого поведения кроется в том, как 1С работает с типами данных в колонках таблицы значений. В отличие от простых переменных, колонки таблицы могут иметь жесткую типизацию. Выясним, как именно устанавливаются эти правила:
Колонки.Добавить("Имя") без параметров, она получает тип Произвольный. В такую колонку можно записывать данные любого типа и любой длины.Выгрузить() создает таблицу, структура которой в точности соответствует метаданным запроса. Если в запросе поле имело тип Число(10, 0) или было ограничено конструкцией ВЫРАЗИТЬ("" КАК СТРОКА(1)), то и колонка в таблице значений получит именно такие ограничения.В рассматриваемой ситуации колонка МоеЧисло была типизирована как Строка с длиной 1. Это могло произойти, если в исходном запросе к этому полю применялись преобразования или если запрос объединял данные, где в одной из частей была пустая строка единичной длины. Когда мы пытаемся записать строку "145254" в ячейку, которая "готова" принять только один символ, платформа 1С не выдает ошибку, а просто отсекает лишнее, оставляя первый символ. Именно поэтому мы видим "1" вместо ожидаемого результата.
Чтобы убедиться в наших догадках, рассмотрим способ программной проверки ограничений колонки. Для этого мы можем обратиться к свойству ТипЗначения колонки таблицы:
ОписаниеТипа = ТаблицаДанных.Колонки.МоеЧисло.ТипЗначения;
Для каждого Тип Из ОписаниеТипа.Типы() Цикл
Сообщить("Допустимый тип: " + Тип);
КонецЦикла;
// Проверка квалификаторов строки
Квалификатор = ОписаниеТипа.КвалификаторыСтроки;
Сообщить("Длина строки в колонке: " + Квалификатор.Длина);
Если в окне сообщений вы увидите Длина строки в колонке: 1, причина подтверждена. Теперь разберем по шагам, как это исправить.
Самый правильный метод — исправить источник данных. Если вы понимаете, что число в дальнейшем должно стать строкой, можно подготовить поле прямо в тексте запроса, задав ему достаточную длину. Однако помните, что возможности форматирования (удаление пробелов) внутри SQL-запроса в 1С ограничены. Тем не менее, можно гарантировать длину:
"ВЫБРАТЬ
| ВЫРАЗИТЬ("""" КАК СТРОКА(20)) КАК МоеЧислоСтрокой,
| ... "
Если таблица создается вручную, разберем, как правильно задать описание типа с неограниченной длиной. Для этого используются КвалификаторыСтроки. Значение 0 в параметре длины означает "неограниченно":
КвалификаторСтр = Новый КвалификаторыСтроки(0); // 0 - любая длина
ОписаниеТипаСтр = Новый ОписаниеТипов("Строка", , КвалификаторСтр);
ТаблицаДанных.Колонки.Добавить("МоеЧисло", ОписаниеТипаСтр);
Если таблица уже получена из запроса и вы не можете его изменить, рассмотрим вариант с подменой колонки. Это трудоемкий, но действенный метод:
Формат().
ТаблицаДанных.Колонки.Добавить("ВременнаяКолонка", Новый ОписаниеТипов("Строка"));
Для каждого Стр Из ТаблицаДанных Цикл
Стр.ВременнаяКолонка = Формат(Стр.МоеЧисло, "ЧГ=0");
КонецЦикла;
ТаблицаДанных.Колонки.Удалить("МоеЧисло");
ТаблицаДанных.Колонки.ВременнаяКолонка.Имя = "МоеЧисло";
Часто разработчики пытаются использовать СтрЗаменить(Строка, " ", ""). Проанализируем ситуацию: почему это может не сработать? В 1С при форматировании чисел по умолчанию используется неразрывный пробел (код символа 160), а не обычный (код 32). Обычный поиск пробела в кавычках его не найдет. Поэтому использование функции Формат(Число, "ЧГ=0") — это максимально надежный способ, так как он управляет выводом на уровне ядра системы.
Рассмотрим подробнее, действительно ли вам нужно менять само значение в таблице? Если ваша цель — просто красиво отобразить число без пробелов в списке на форме, то превращать число в строку — плохая практика. Выясним почему:
Вместо изменения данных в ТаблицаЗначений, лучше настроить формат отображения в элементе формы (Табличное поле или Таблица формы). В свойствах колонки на форме найдите поле "Формат" и введите туда ЧГ=0. Данные останутся числами, но пользователь увидит их без пробелов.
Если при записи в таблицу значений данные обрезаются — всегда проверяйте КвалификаторыСтроки в ОписаниеТипов соответствующей колонки. Помните, что таблицы, полученные из запросов, наследуют жесткую типизацию, и для работы с длинными строками вам может потребоваться либо корректировка запроса, либо программное переопределение типов колонок.