Преобразование числа в строку в запросе 1С 8.x

В запросах 1С предприятие 8.x есть ограничение: нельзя преобразовывать число в строку.

Ограничение предсказуемо, т.к. для преобразования числа в строку возникает много  вариантов представления числа: выводить лидирующие нули, до какого знака выводить после запятой, и т.д. Система счисления тоже может быть разная: десятичная, двоичная, шестнадцатеричная или n-ичная.

Данное ограничение можно преодолеть с помощью математической операции округления. Далее представлен текст запроса, который вернет строку «Число приведенное к строке 97443.456».

 

ВЫБРАТЬ
97443.456 КАК Поле
ПОМЕСТИТЬ ТЗ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
"Число приведенное к строке " +
ПОДСТРОКА("0123456789", 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 10000 - 0.5 КАК ЧИСЛО(14, 0))) - (ВЫРАЗИТЬ(ТЗ.Поле / 100000 - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
ПОДСТРОКА("0123456789", 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 1000 - 0.5 КАК ЧИСЛО(14, 0))) - (ВЫРАЗИТЬ(ТЗ.Поле / 10000 - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
ПОДСТРОКА("0123456789", 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 100 - 0.5 КАК ЧИСЛО(14, 0))) - (ВЫРАЗИТЬ(ТЗ.Поле / 1000 - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
ПОДСТРОКА("0123456789", 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 10 - 0.5 КАК ЧИСЛО(14, 0))) - (ВЫРАЗИТЬ(ТЗ.Поле / 100 - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
ПОДСТРОКА("0123456789", 1 + ТЗ.Поле - (ВЫРАЗИТЬ(ТЗ.Поле / 10  - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1)+
"."+
ПОДСТРОКА("0123456789", 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 0.1 - 0.5 КАК ЧИСЛО(14, 0))) - (ВЫРАЗИТЬ(ТЗ.Поле / 1 - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
ПОДСТРОКА("0123456789", 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 0.01 - 0.5 КАК ЧИСЛО(14, 0))) - (ВЫРАЗИТЬ(ТЗ.Поле / 0.1 - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
ПОДСТРОКА("0123456789", 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 0.001 - 0.5 КАК ЧИСЛО(14, 0))) - (ВЫРАЗИТЬ(ТЗ.Поле / 0.01 - 0.5 КАК ЧИСЛО(14, 0))) * 10, 1)
КАК СтрокаПоле
ИЗ
ТЗ КАК ТЗ

 

Рассмотрим как это работает. Каждая цифра вычисляется и выводится отдельно. Для цифры в разряде i вычисление проводится следующим образом

Операция Цел(x) реализуется в запросе 1С 8.x с помощью округления Выразить. Несложно проверить:

Цел(x)=Выразить(x — 0.5 КАК ЧИСЛО(14,0))

Мы получили весь набор цифр числа в виде чисел от 0 до 9. Сделать из них строки можно с помощью Строковой функции ПОДСТРОКА(«0123456789»,1+Цифра).

Аналогично можно реализовать вывод чисел в другой системе счисления.

Подобный функционал можно просмотреть здесь: http://kb.mista.ru/article.php?id=666

19 Comments

  1. u_n_k_n_o_w_n

    Плагиат!!!

    Просьба указать первоисточник!!!

    Reply
  2. starik-2005

    (1) u_n_k_n_o_w_n, тут: http://www.forum.mista.ru/topic.php?id=434287 )))

    Reply
  3. lastcontra

    (1) u_n_k_n_o_w_n, укажи первоисточник, раз ты уже видел такую статью.

    Reply
  4. lastcontra

    (2) starik-2005, в твоей ссылке на статью написано, что это невозможно, кроме одного сообщения, что нужно вывести по разрядам (но как это сделать не расписано, и инициатор в итоге смирился, что это не возможно). Я говорю, что это возможно, вот конкретный пример в статье.

    Reply
  5. starik-2005

    (4) Вы бы в смысл того, что я написал, вдумальсь бы немного. То, что Вы скопипастили один в один запрос из статьи «минимализмы», автор которой скопипастил ее из приведенных им источников — это не плохо. Но моя ссылка на древний источник, в котором это расписано, а там есть посылка в книгу знаний мисты, где данный запрос приведен в том практически виде, который приводите Вы. Странно, что автор первого коммента не уличил в плагиате Ильдаровича !или как его там?)

    Reply
  6. Sgeor

    Может каждому пользователю такую статейку написать? =)

    http://infostart.ru/public/331805/

    Reply
  7. lastcontra

    (5) starik-2005, чтобы вдуматься в смысл того, что ты написал, надо хотя бы что-то написать.

    Из того что ты написал «тут и ссылка» я должен найти очень тайную книгу Мисты и статью «минимализмы»???

    Ссылку на статью кто-нибудь может прислать?

    Так можно про любую статью писать — «все что придумано — плагиат тайной книги которой мы поклоняемся каждый раз в монитор».

    Пока не увижу статью нет смысла трепаться. Да и мне не нужно никому доказывать, что до меня это никто не придумал, не нравится не читай.

    Reply
  8. u_n_k_n_o_w_n

    http://kb.mista.ru/article.php?id=666 — первоисточник.

    Reply
  9. lastcontra

    Добавил ссылку подобную на статью. Признаю, что она более ранняя, чем моя. Но моя статья не является ее копией, ничего особенного нет в этих статьях (включая мою), чтобы их нельзя было написать самому, имея какое-то тайное знание.

    Reply
  10. ildarovich

    (5) starik-2005,

    То, что Вы скопипастили один в один запрос из статьи «минимализмы», автор которой скопипастил ее из приведенных им источников

    вы, думаю, не потрудились разобраться в тонкостях приведенных выражений, а они могут быть интересны и поучительны. Поэтому и возводите напраслину. Прежде чем что либо «изобрести» я обычно просматриваю уже имеющиеся решения и чужие решения стараюсь не повторять. И в «минимализмах» , «минимализмах2» (с) и в статье Выразить число как строку и дату как строку в запросе опубликованы мои собственные оригинальные решения, всегда имеющие признаки какой-либо новизны.

    Преобразование строки в число приведенным здесь способом — более-менее очевидное решение. В своей статье я бы его повторять не стал, но мотивы автора статьи мне понятны, претензию на оригинальность автор объяснил.

    Вообще такое решение я уже видел ранее несколько раз. В ссылке на мисте оно записано наиболее «коряво». Данное решение мне не нравилось тем, что аргумент приходится записывать дважды. В моем решении остаток от деления вычисляется через функции работы с датами (в этом суть изобретения), что дает более короткую запись с одним упоминанием аргумента при нахождении каждого разряда.

    Reply
  11. starik-2005

    (10) ildarovich, вот честно даже не тягет с умным человеком спорить ни разу. Но про плагиат не я написал, заметьте. Уже второй раз пытаюсь защитить позицию автора на данном сайте, но из-за, видимо, проблем с логикой у 1с-ников, мне же и достается)))

    Reply
  12. Fragster

    Регулярно вижу статьи на тему преобразования строки в число и обратно в запросе. И каждый раз возникает вопрос: «А зачем?»

    Reply
  13. lastcontra

    (12) Fragster, значит ты их регулярно читаешь и пишешь отзывы, а зачем? 1. Ничего нового не узнал, 2. чего ты хочешь чтобы тебе ответили? ЗАЧЕМ????

    Reply
  14. Fragster

    (13) реальная применимость этих запросов какая? Ну, кроме «смотрите, как я могу?»

    Reply
  15. speshuric

    (14) Fragster,

    В идеальном мире, где единороги какают радугой, и есть бесконечные ресурсы и бесконечное время на разработку такие запросы, наверное, не нужны. Почти всегда они говорят о каких-то неприятных вещах типа технического долга или кривой архитектуры. Но у нас, в реальном мире, они часто пригождаются. Примеры:

    • Иногда (в отчетах) очень нежелательно протягивать в источнике данных новое поле и нужно сформировать строку типа «Название+Размер». А если этот отчет на построителе отчетов, а не на СКД, то и вообще альтернатив нет, если не переписывать его полностью.
    • При вытягивании достаточно больших объёмов из базы (выгрузки или очень большие отчеты) то же самое представление на сервере будет считаться быстрее и меньше данных придётся тянуть с сервера. А если весь код выгрузки/отчета вообще оперирует только результатами запроса, то опять же — альтернатив кроме как «переписать всё» нет. Я сталкивался с отчетами и выгрузками по 100 млн строк.
    • Внешняя система даёт вам неразбираемый фильтр по такому представлению («Название+Размер»). приходится собирать из своих полей в запросе и сравнивать с таким фильтром. Не тянуть же без фильтра всё на клиента.
    • Нужно отсортировать выборку по представлению числа в алфавитном порядке (1, 10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9)

    В обратную сторону тоже примеры есть. Да, еще раз подчеркну, когда возникает эта задача — это явный признак, что что-то не так в системе. Но обычно решение нужно скорее, чем полная переработка решения и структур данных, особенно, если это задачи отчетов или интеграции (которые часто ставятся и решаются после реализации основного функционала).

    Другой вопрос, что задача тянет на слегка продвинутую задачу на собеседовании (если без текста, то хотя бы путь решения, и это минут на 5-7). Причем для ведущего программиста можно еще и с дополнительными ограничениями (например, «нам не известна разрядность») или ожидать 3-4 решения. А для лида или архитектора еще и вопрос «что надо сделать, чтобы не писать такие запросы».

    Reply
  16. inf012

    А что в итоге универсального решения нет?

    Мне все в запросе надо обработать, у меня строка получается формата:

    00003.000

    А мне надо просто 3 чтобы вернулось.

    Как убрать лидирующие нули? и дробную часть?

    Если я заранее не знаю исходное число (также получается только в запросе)

    Reply
  17. ildarovich

    (16) Универсальные решения есть:

    Выразить число как строку и дату как строку в запросе ,

    Выразить строку как число и строку как дату в запросе.

    Но вам, видимо, нужно не строку в число преобразовать, а строку в строку без ведущих нулей и всего, что справа от точки (и без самой точки).

    Хотя это и можно сделать «универсально» с помощью искусственных таблиц, при вашей длине строки лучше использовать громоздкое выражение ВЫБОР КОГДА ПОДСТРОКА(Х, 1, 1) = «0» ТОГДА ПОДСТРОКА(Х, 2, 8) КОГДА ПОДСТРОКА(Х, 1, 2) = «00» ТОГДА ТОГДА ПОДСТРОКА(Х, 3, 7) … . Аналогично потом можно определить положение точки и обрезать строку справа.

    Reply
  18. k9260130000

    Лидирующие нули выбором убираем. За исключением их весьма годное решение. Как — то так получилось. Надо было писать сроки производства строкой через тире собирая из 2х чисел.

    ВЫБОР
    КОГДА НЕ ЗаказПокупателя.СрокИзготовленияПродукции1 = 0
    ТОГДА ВЫБОР
    КОГДА НЕ ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции1 / 10 — 0.5 КАК ЧИСЛО(3, 0))) — (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции1 / 100 — 0.5 КАК ЧИСЛО(3, 0))) * 10, 1) = «0»
    ТОГДА ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции1 / 10 — 0.5 КАК ЧИСЛО(3, 0))) — (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции1 / 100 — 0.5 КАК ЧИСЛО(3, 0))) * 10, 1)
    ИНАЧЕ «»
    КОНЕЦ + ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции1 / 1 — 0.5 КАК ЧИСЛО(3, 0))) — (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции1 / 10 — 0.5 КАК ЧИСЛО(3, 0))) * 10, 1) + «-»
    ИНАЧЕ «»
    КОНЕЦ + ВЫБОР
    КОГДА НЕ ЗаказПокупателя.СрокИзготовленияПродукции2 = 0
    ТОГДА ВЫБОР
    КОГДА НЕ ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции2 / 10 — 0.5 КАК ЧИСЛО(3, 0))) — (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции2 / 100 — 0.5 КАК ЧИСЛО(3, 0))) * 10, 1) = «0»
    ТОГДА ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции2 / 10 — 0.5 КАК ЧИСЛО(3, 0))) — (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции2 / 100 — 0.5 КАК ЧИСЛО(3, 0))) * 10, 1)
    ИНАЧЕ «»
    КОНЕЦ + ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции2 / 1 — 0.5 КАК ЧИСЛО(3, 0))) — (ВЫРАЗИТЬ(ЗаказПокупателя.СрокИзготовленияПродукции2 / 10 — 0.5 КАК ЧИСЛО(3, 0))) * 10, 1)
    ИНАЧЕ «»
    КОНЕЦ КАК СрокПроизводства

    Показать

    Reply
  19. dgonson

    Дописал код примера, что бы убирались нули, для полноты картины)

    ВЫБРАТЬ
    45.5 КАК Поле
    ПОМЕСТИТЬ ТЗ
    ;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 10000 — 0.5 КАК ЧИСЛО(14, 0))) — (ВЫРАЗИТЬ(ТЗ.Поле / 100000 — 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
    ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 1000 — 0.5 КАК ЧИСЛО(14, 0))) — (ВЫРАЗИТЬ(ТЗ.Поле / 10000 — 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
    ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 100 — 0.5 КАК ЧИСЛО(14, 0))) — (ВЫРАЗИТЬ(ТЗ.Поле / 1000 — 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
    ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 10 — 0.5 КАК ЧИСЛО(14, 0))) — (ВЫРАЗИТЬ(ТЗ.Поле / 100 — 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
    ПОДСТРОКА(«0123456789», 1 + ТЗ.Поле — (ВЫРАЗИТЬ(ТЗ.Поле / 10  — 0.5 КАК ЧИСЛО(14, 0))) * 10, 1)+
    «.»+
    ПОДСТРОКА(«0123456789», 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 0.1 — 0.5 КАК ЧИСЛО(14, 0))) — (ВЫРАЗИТЬ(ТЗ.Поле / 1 — 0.5 КАК ЧИСЛО(14, 0))) * 10, 1) +
    ПОДСТРОКА(«0123456789″, 1 + (ВЫРАЗИТЬ(ТЗ.Поле / 0.01 — 0.5 КАК ЧИСЛО(14, 0))) — (ВЫРАЗИТЬ(ТЗ.Поле / 0.1 — 0.5 КАК ЧИСЛО(14, 0))) * 10, 1)
    КАК СтрокаПоказатель
    Поместить втПредварительныеДанные
    ИЗ
    ТЗ КАК ТЗ;
    
    //////////////////////////////////////////////
    ВЫБРАТЬ
    СтрокаПоказатель,
    ВЫБОР КОГДА ПОДСТРОКА(СтрокаПоказатель,1,4)=»0000″ ТОГДА ПОДСТРОКА(СтрокаПоказатель,5,1)
    КОГДА ПОДСТРОКА(СтрокаПоказатель,1,3)=»000″  ТОГДА ПОДСТРОКА(СтрокаПоказатель,4,2)
    КОГДА ПОДСТРОКА(СтрокаПоказатель,1,2)=»00″   ТОГДА ПОДСТРОКА(СтрокаПоказатель,3,3)
    КОГДА ПОДСТРОКА(СтрокаПоказатель,1,1)=»0″   ТОГДА ПОДСТРОКА(СтрокаПоказатель,2,4)
    ИНАЧЕ ПОДСТРОКА(СтрокаПоказатель,1,5)
    КОНЕЦ
    +
    ВЫБОР КОГДА ПОДСТРОКА(СтрокаПоказатель,7,2)=»00» ТОГДА «»
    ИНАЧЕ
    ВЫБОР КОГДА ПОДСТРОКА(СтрокаПоказатель,8,1)=»0″ ТОГДА ПОДСТРОКА(СтрокаПоказатель,6,2)
    ИНАЧЕ ПОДСТРОКА(СтрокаПоказатель,6,3)
    КОНЕЦ
    КОНЕЦ
    
    ИЗ втПредварительныеДанные

    Показать

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *