1c преобразовать в hex
Как перевести средствами встроенного языка 1С 10-ное число в HEX ?
Ну и заодно - в BIN, в OCT и в другие системы исчисления ?
Пришлось достать учебники по математике и написать эту статью.
В результате - получил 2ва алгоритма:
- первый : с рекурсивными вызовами после остатка от деления по основанию Х
- второй : через логарифмы с циклом
Коротко о главном:
1) первый алгоритм - получился быстрее. Вот результаты:
2) второй алгоритм (если честно) был подсмотрен в реализации SQL-функции для _IdToStr
и модифицирован для универсальности (не только для основания 36, а для любого основания).
Эта SQL-функция широко используется в сообществе 1С++
(К сожалению, автора-первооткрывателя : не знаю, поэтому - поклон ему и всем участникам проекта )
Алгоритмы (что во вложении) написаны для 1С.7.7
Алгоритмы универсальные: поэтому легко переделать для 1С8.* с учетом особенностей языков.
Где применяются двоичные данные в 1С?
Чаще всего, двоичные данные в 1С используются в следующих случаях:
Как работать с двоичными данными в 1С?
При работе с двоичными данными в 1С, следует понимать, что это промежуточное “агрегатное состояние” данных. Сами они нигде не хранятся, а размещаются полностью или частично в оперативной памяти. Получить двоичные данные можно множеством способов. Вот лишь некоторые:
Следующее, что чаще всего делают с двоичными данными – это либо записывают в базу, либо сохраняют в файл.
Записать в базу можно в реквизит с типом ХранилищеЗначения:
дд = Новый ДвоичныеДанные(ПутьКФайлу);
СпрКартинка = Справочники.Картинки.Картинка; //Картинка – реквизит с типом ХранилищеЗначения
Об = СпрКартинка.ПолучитьОбъект();
Об.Картинка = Новый ХранилищеЗначения(дд);
Об.Записать();
Либо в реквизит с типом Строка неограниченной длины. О том, как преобразовать двоичные данные в строку – чуть выше.
Ну и кроме того, двоичные данные нужны для того, чтобы сохранить их в файл. Для того чтобы это сделать, предусмотрены целых три метода!
- Записать – стандартный синхронный метод, который записывает двоичные данные в файл. При этом платформа будет ожидать окончания выполнения записи, прежде чем продолжить выполнение кода.
- НачатьЗапись – асинхронная процедура, которая не блокирует выполнение кода. При этом по завершении записи в файл, будет вызвана процедура-обработчик.
- ЗаписатьАсинх – новый вариант асинхронной записи, появившийся в версии 8.3.18.
Специальные предложения
Понадобилась функция для перевода из одного основания в другое.
Сначала написал свою, потом скачал это.
Вариант 2 содержит ошибку.
Когда число = Основание в степени Н, то происходит лишняя итерация.
Ошибка тут:
Знч = цел(Ln(ч10)/Ln(чОснование)) +1
Для i=1 По Знч-1 Цикл
чСтепень = чСтепень*чОснование;
КонецЦикла;
Вот демонстрация:
Вариант 1: время = 0.475, КвоИтераций=10000
1679616 = 19A100
1679616 = 110011010000100000000
1679616 = 6320400
1679616 = 10000
Вариант 2: время = 0.465, КвоИтераций=10000
1679616 = 19A100
1679616 = 110011010000100000000
1679616 = 6320400
1679616 = 000
Вариант 3: время = 0.046, КвоИтераций=10000
1679616 = 19A100
1679616 = 110011010000100000000
1679616 = 6320400
1679616 = 10000
Благо это самый тормозной алгоритм и его вряд ли кто использовал.
Просто будьте внимательнее.
P.S. 3-й вариант мой, но он использует еще и внешние компоненты.
К сожалению, в 1С++ используется сильно ограниченная версия перевода числа из одной системы в другую.
Она только для чисел до 2^31 - 1. Это чуть больше 2 миллиардов.
Два примера функций, которые корректно преобразуют в 1С 8.3 строку из Unicode в UTF-8. Используется вспомогательная функция Dec_to_Hex (перевод десятичного числа в шестнадцатеричное).
Пример №1 Конвертация строки из Unicode в UTF-8 (более оптимизирован от пользователя Ruffer1C) в 1С 8.3:
Если Разрядность = 2 Тогда
Возврат Сред ( ПредставлениеHex , пDec * 2 + 1 , 2 );
КонецЕсли;
пHex = "0123456789ABCDEF" ;
Результат = "" ;
Для СимвЧисло = 1 По Разрядность Цикл
ТекЧисло = пDec % 16 ;
пDec = Цел ( пDec / 16 );
Результат = Сред ( пHex , ТекЧисло + 1 , 1 ) + Результат ;
КонецЦикла;
Функция ПереводТекстаUnicodeToUTF8 ( СтрокаДляКодировки )
// ВНИМАНИЕ! При вставке в 1С из переменной ПредставлениеHex удалить переносы (перенесены для отображения на странице)
СимволыДляИсключения = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~" ;
Результат = "" ;
Для а = 1 По СтрДлина ( СтрокаДляКодировки ) Цикл
ТекСимв = Сред ( СтрокаДляКодировки , а , 1 );
Если ТекСимв = " " Тогда
Результат = Результат + "+" ;
Продолжить;
КонецЕсли;
Если Найти ( СимволыДляИсключения , ТекСимв ) > 0 Тогда
Результат = Результат + ТекСимв ;
Продолжить;
КонецЕсли;
ЮниКод = КодСимвола ( ТекСимв );
Если ЮниКод < 128 Тогда
Результат = Результат + "%" + Dec_to_Hex ( ЮниКод , ПредставлениеHex );
Иначе
ИндексЮникод = 32 ;
Байт = 8 ;
ХексКод = "" ;
Пока ИндексЮникод > 4 Цикл
// установка следующих за первым байтов
ТекБайт = ЮниКод % 64 ;
ХексКод = "%" + Dec_to_Hex ( 128 + ТекБайт , ПредставлениеHex ) + ХексКод ;
ЮниКод = Цел ( ЮниКод / 64 );
// проверка на закрывающий байт
Если ЮниКод < ИндексЮникод Тогда
ХексКод = "%" + Dec_to_Hex (( Байт - 2 ) * ИндексЮникод + ЮниКод , ПредставлениеHex ) + ХексКод ;
Прервать;
КонецЕсли;
// переход к следующему уровню закрытия
ИндексЮникод = ИндексЮникод / 2 ;
Байт = Байт * 2 ;
КонецЦикла;
Результат = Результат + ХексКод ;
КонецЕсли;
КонецЦикла;
Возврат Результат ;
КонецФункции
пHex = "0123456789ABCDEF" ;
Результат = "" ;
Для СимвЧисло = 1 По Разрядность Цикл
ТекЧисло = пDec % 16 ;
пDec = Цел ( пDec / 16 );
Результат = Сред ( пHex , ТекЧисло + 1 , 1 ) + Результат ;
КонецЦикла;
Функция ПереводТекстаUnicodeToUTF8 ( СтрокаДляКодировки )
СимволыДляИсключения = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~" ;
Результат = "" ;
Для а = 1 По СтрДлина ( СтрокаДляКодировки ) Цикл
ТекСимв = Сред ( СтрокаДляКодировки , а , 1 );
Если ТекСимв = " " Тогда
Результат = Результат + "+" ;
Продолжить;
КонецЕсли;
Если Найти ( СимволыДляИсключения , ТекСимв ) > 0 Тогда
Результат = Результат + ТекСимв ;
Продолжить;
КонецЕсли;
ЮниКод = КодСимвола ( ТекСимв );
Если ЮниКод < 128 Тогда
Результат = Результат + "%" + Dec_to_Hex ( ЮниКод );
Иначе
ИндексЮникод = 32 ;
Байт = 8 ;
ХексКод = "" ;
Пока ИндексЮникод > 4 Цикл
// установка следующих за первым байтов
ТекБайт = ЮниКод % 64 ;
ХексКод = "%" + Dec_to_Hex ( 128 + ТекБайт ) + ХексКод ;
ЮниКод = Цел ( ЮниКод / 64 );
// проверка на закрывающий байт
Если ЮниКод < ИндексЮникод Тогда
ХексКод = "%" + Dec_to_Hex (( Байт - 2 ) * ИндексЮникод + ЮниКод ) + ХексКод ;
Прервать;
КонецЕсли;
// переход к следующему уровню закрытия
ИндексЮникод = ИндексЮникод / 2 ;
Байт = Байт * 2 ;
КонецЦикла;
Результат = Результат + ХексКод ;
КонецЕсли;
КонецЦикла;
Для тех, кто не может скачивать, публикую тут самое основное:
Функция ПреобразоватьЦвет ( рИсходныйЦвет , рВидИтоговогоЦвета , тЦветов = «» ) Экспорт
Попытка
Если ТипЗнч ( рИсходныйЦвет )= Тип ( «Цвет» ) Тогда
Если рИсходныйЦвет . Вид = ВидЦвета . ЭлементСтиля Тогда
стрЦвет = ПолучитьЦветИзСтиляПлатформы ( рИсходныйЦвет ); // вернёт hex, т.е. 16-ричный
Если не ПустаяСтрока ( стрЦвет ) Тогда
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Шестнадцатиричный» );
Если строц <>Неопределено Тогда
Возврат строц . Название ;
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Шестнадцатиричный» );
Если строц <>Неопределено Тогда
Возврат Новый Структура ( «Красный,Синий,Зеленый» , строц . Красный , строц . Синий , строц . Зеленый );
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Возврат стрЦвет ; // это он и есть
КонецЕсли;
КонецЕсли;
ИначеЕсли рИсходныйЦвет . Вид = ВидЦвета . WebЦвет Тогда
// вытащим из скобок англоязычное написание цвета
стрЦвет = СокрЛП ( Строка ( рИсходныйЦвет ));
пози1 = Найти ( стрЦвет , «(« );
Если пози1 <> 0 Тогда
стрЦвет = НРег ( СтрЗаменить ( Сред ( стрЦвет , пози1 + 1 ), «)» , «» ));
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Возврат стрЦвет ; // это он и есть
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов (Истина);
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Название» );
Если строц <>Неопределено Тогда
Возврат Новый Структура ( «Красный,Синий,Зеленый» , строц . Красный , строц . Синий , строц . Зеленый );
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов (Истина);
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Название» );
Если строц <>Неопределено Тогда
Возврат строц . Шестнадцатиричный ;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ИначеЕсли рИсходныйЦвет . Вид = ВидЦвета . Абсолютный Тогда
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
отб =Новый Структура ( «Красный,Синий,Зеленый» , рИсходныйЦвет . Красный , рИсходныйЦвет . Синий , рИсходныйЦвет . Зеленый );
мстроц = тЦветов . НайтиСтроки ( отб );
Если мстроц . Количество ()<> 0 Тогда
Возврат мстроц[0] . Название ;
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
// фактически, он и есть
Возврат Новый Структура ( «Красный,Синий,Зеленый» , рИсходныйЦвет . Красный , рИсходныйЦвет . Синий , рИсходныйЦвет . Зеленый );
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
отб =Новый Структура ( «Красный,Синий,Зеленый» , рИсходныйЦвет . Красный , рИсходныйЦвет . Синий , рИсходныйЦвет . Зеленый );
мстроц = тЦветов . НайтиСтроки ( отб );
Если мстроц . Количество ()<> 0 Тогда
Возврат мстроц[0] . Шестнадцатиричный ;
КонецЕсли;
КонецЕсли;
КонецЕсли; // по вариантам видов цвета как типа Цвет
ИначеЕсли ТипЗнч ( рИсходныйЦвет )= Тип ( «Строка» ) Тогда
// ищем во всех колонках таблицы, т.к. заведомо не знаем, какой это цвет
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
строц = тЦветов . Найти ( СокрЛП ( рИсходныйЦвет ));
Если строц <>Неопределено Тогда
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Возврат строц . Название ;
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
Возврат Новый Структура ( «Красный,Синий,Зеленый» , строц . Красный , строц . Синий , строц . Зеленый );
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Возврат строц . Шестнадцатиричный ;
КонецЕсли;
КонецЕсли;
Всё крайне кондово, но может пригодиться. Единственно, учитывайте, что лучше 1 раз прочитать таблицу соответствий и далее по ней искать. Ну и проиндексируйте по нужной колонке, исходя из ситуации.
На днях столкнулся с интересной особенностью 1С.
Нужно было передать в 1С двоичные данные (varbinary), но как говорится все проблемы на стыке систем. 1С восприняла данные как объект, каковыми они не являлись. Памятуя о том что 1С любит строковые данные, я начал пытаться преобразовать их в строку. И вот что у меня получилось на выходе:
-
Использование не документированных функций [sys].[fn_varbintohexstr] и [sys].[fn_varbintohexsubstring] Если стоит простое преобразование, то можно воспользоваться [sys].[fn_varbintohexstr] , она принимает только один параметр: бинарную переменную.
Вот ее полное описание.
Как вы видете функция [sys].[fn_varbintohexstr] является оберткой для [sys].[fn_varbintohexsubstring], и вызывает ее всегда с одними и темиже параметрами.
[sys].[fn_varbintohexsubstring], в свою очередь имеет более продвинутый функционал. Например, позволяет преобразовывать в строку не всю последовательность, а некую «подстроку». К таким выводам я пришел после просмотра заголовочной части:
Остается только проблема обратного преобразования, дело в том что в SQL нет встроенной функции для такого действия. Точнее не было, в MS SQL 2008 есть, но об этом чуть позже.
Со своими коллегами я договорился что им будут отдавать строку вида 0x0123456789, соответственно и мне они будут отдавать уже не в виде строки, а в виде binary, например так:
В CTE выражении я просто готовлю даные, для дальнейшего использования. Самое интересно начинается в SELECT :
- В поле [ColBin_xml] мы плучаем солонку [ColChar] из [cte_d] — команда sql:column(«ColChar»)
- Дальше берем подстроку от этой колонки начиная с 3-го знака (отрезаем «0x») — функция substring(,,)
- Заставляем xml процессор считать полученую строку как hexBinary
- А в момент возврата данных они интерпретируются как varbinary(max)
Аналогичным образом работает и прямое преобразование из binary в varchar (поле [ColChar_xml])
- Берем колонку [ColBin] sql:column(«ColBin»)
- Заставляем процессор считать ее как hexBinary
- И возвращаем как varchar(max)
- И по желанию можно добавить в начало строки «0x»
- 0 — преобразование в соответствии с ASCII кодами (используется по умолчанию)
- 1 — текстовое представление с добавлением «0x» в начале строки, например так «0x0123456789»
- 2 — текстовое представление без добавленя «0x» в начале строки, например так «0123456789»
При конвертировании в обратную сторону ( из hexString в binary) у нас теже 3 стиля, которые задают условие преобразования.
Замечание! Если при обратном преобразовании строка не будет соответствовать маске (стили 1 и 2) то SQL будет генерировать ошибку.
В статье рассматриваются двоичные данные, способы их хранения в 1С, примеры использования, а также примеры программного кода для работы с двоичными данными.
Содержание
Что хранится в двоичных данных?
Если совсем кратко – все что угодно. Картинки, внешние обработки, документы, внешние компоненты, и т.д. Платформа “не знает”, что содержится в двоичном файле, и реализация логики ложится на плечи разработчика – он сам должен решить, как эти данные обрабатывать, и что они из себя представляют в каждом случае.
Специальные предложения
Понадобилась функция для перевода из одного основания в другое.
Сначала написал свою, потом скачал это.
Вариант 2 содержит ошибку.
Когда число = Основание в степени Н, то происходит лишняя итерация.
Ошибка тут:
Знч = цел(Ln(ч10)/Ln(чОснование)) +1
Для i=1 По Знч-1 Цикл
чСтепень = чСтепень*чОснование;
КонецЦикла;
Вот демонстрация:
Вариант 1: время = 0.475, КвоИтераций=10000
1679616 = 19A100
1679616 = 110011010000100000000
1679616 = 6320400
1679616 = 10000
Вариант 2: время = 0.465, КвоИтераций=10000
1679616 = 19A100
1679616 = 110011010000100000000
1679616 = 6320400
1679616 = 000
Вариант 3: время = 0.046, КвоИтераций=10000
1679616 = 19A100
1679616 = 110011010000100000000
1679616 = 6320400
1679616 = 10000
Благо это самый тормозной алгоритм и его вряд ли кто использовал.
Просто будьте внимательнее.
P.S. 3-й вариант мой, но он использует еще и внешние компоненты.
К сожалению, в 1С++ используется сильно ограниченная версия перевода числа из одной системы в другую.
Она только для чисел до 2^31 - 1. Это чуть больше 2 миллиардов.
Два примера функций, которые корректно преобразуют в 1С 8.3 строку из Unicode в UTF-8. Используется вспомогательная функция Dec_to_Hex (перевод десятичного числа в шестнадцатеричное).
Пример №1 Конвертация строки из Unicode в UTF-8 (более оптимизирован от пользователя Ruffer1C) в 1С 8.3:
Если Разрядность = 2 Тогда
Возврат Сред ( ПредставлениеHex , пDec * 2 + 1 , 2 );
КонецЕсли;
пHex = "0123456789ABCDEF" ;
Результат = "" ;
Для СимвЧисло = 1 По Разрядность Цикл
ТекЧисло = пDec % 16 ;
пDec = Цел ( пDec / 16 );
Результат = Сред ( пHex , ТекЧисло + 1 , 1 ) + Результат ;
КонецЦикла;
Функция ПереводТекстаUnicodeToUTF8 ( СтрокаДляКодировки )
// ВНИМАНИЕ! При вставке в 1С из переменной ПредставлениеHex удалить переносы (перенесены для отображения на странице)
СимволыДляИсключения = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~" ;
Результат = "" ;
Для а = 1 По СтрДлина ( СтрокаДляКодировки ) Цикл
ТекСимв = Сред ( СтрокаДляКодировки , а , 1 );
Если ТекСимв = " " Тогда
Результат = Результат + "+" ;
Продолжить;
КонецЕсли;
Если Найти ( СимволыДляИсключения , ТекСимв ) > 0 Тогда
Результат = Результат + ТекСимв ;
Продолжить;
КонецЕсли;
ЮниКод = КодСимвола ( ТекСимв );
Если ЮниКод < 128 Тогда
Результат = Результат + "%" + Dec_to_Hex ( ЮниКод , ПредставлениеHex );
Иначе
ИндексЮникод = 32 ;
Байт = 8 ;
ХексКод = "" ;
Пока ИндексЮникод > 4 Цикл
// установка следующих за первым байтов
ТекБайт = ЮниКод % 64 ;
ХексКод = "%" + Dec_to_Hex ( 128 + ТекБайт , ПредставлениеHex ) + ХексКод ;
ЮниКод = Цел ( ЮниКод / 64 );
// проверка на закрывающий байт
Если ЮниКод < ИндексЮникод Тогда
ХексКод = "%" + Dec_to_Hex (( Байт - 2 ) * ИндексЮникод + ЮниКод , ПредставлениеHex ) + ХексКод ;
Прервать;
КонецЕсли;
// переход к следующему уровню закрытия
ИндексЮникод = ИндексЮникод / 2 ;
Байт = Байт * 2 ;
КонецЦикла;
Результат = Результат + ХексКод ;
КонецЕсли;
КонецЦикла;
Возврат Результат ;
КонецФункции
пHex = "0123456789ABCDEF" ;
Результат = "" ;
Для СимвЧисло = 1 По Разрядность Цикл
ТекЧисло = пDec % 16 ;
пDec = Цел ( пDec / 16 );
Результат = Сред ( пHex , ТекЧисло + 1 , 1 ) + Результат ;
КонецЦикла;
Функция ПереводТекстаUnicodeToUTF8 ( СтрокаДляКодировки )
СимволыДляИсключения = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~" ;
Результат = "" ;
Для а = 1 По СтрДлина ( СтрокаДляКодировки ) Цикл
ТекСимв = Сред ( СтрокаДляКодировки , а , 1 );
Если ТекСимв = " " Тогда
Результат = Результат + "+" ;
Продолжить;
КонецЕсли;
Если Найти ( СимволыДляИсключения , ТекСимв ) > 0 Тогда
Результат = Результат + ТекСимв ;
Продолжить;
КонецЕсли;
ЮниКод = КодСимвола ( ТекСимв );
Если ЮниКод < 128 Тогда
Результат = Результат + "%" + Dec_to_Hex ( ЮниКод );
Иначе
ИндексЮникод = 32 ;
Байт = 8 ;
ХексКод = "" ;
Пока ИндексЮникод > 4 Цикл
// установка следующих за первым байтов
ТекБайт = ЮниКод % 64 ;
ХексКод = "%" + Dec_to_Hex ( 128 + ТекБайт ) + ХексКод ;
ЮниКод = Цел ( ЮниКод / 64 );
// проверка на закрывающий байт
Если ЮниКод < ИндексЮникод Тогда
ХексКод = "%" + Dec_to_Hex (( Байт - 2 ) * ИндексЮникод + ЮниКод ) + ХексКод ;
Прервать;
КонецЕсли;
// переход к следующему уровню закрытия
ИндексЮникод = ИндексЮникод / 2 ;
Байт = Байт * 2 ;
КонецЦикла;
Результат = Результат + ХексКод ;
КонецЕсли;
КонецЦикла;
Для тех, кто не может скачивать, публикую тут самое основное:
Функция ПреобразоватьЦвет ( рИсходныйЦвет , рВидИтоговогоЦвета , тЦветов = «» ) Экспорт
Попытка
Если ТипЗнч ( рИсходныйЦвет )= Тип ( «Цвет» ) Тогда
Если рИсходныйЦвет . Вид = ВидЦвета . ЭлементСтиля Тогда
стрЦвет = ПолучитьЦветИзСтиляПлатформы ( рИсходныйЦвет ); // вернёт hex, т.е. 16-ричный
Если не ПустаяСтрока ( стрЦвет ) Тогда
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Шестнадцатиричный» );
Если строц <>Неопределено Тогда
Возврат строц . Название ;
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Шестнадцатиричный» );
Если строц <>Неопределено Тогда
Возврат Новый Структура ( «Красный,Синий,Зеленый» , строц . Красный , строц . Синий , строц . Зеленый );
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Возврат стрЦвет ; // это он и есть
КонецЕсли;
КонецЕсли;
ИначеЕсли рИсходныйЦвет . Вид = ВидЦвета . WebЦвет Тогда
// вытащим из скобок англоязычное написание цвета
стрЦвет = СокрЛП ( Строка ( рИсходныйЦвет ));
пози1 = Найти ( стрЦвет , «(« );
Если пози1 <> 0 Тогда
стрЦвет = НРег ( СтрЗаменить ( Сред ( стрЦвет , пози1 + 1 ), «)» , «» ));
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Возврат стрЦвет ; // это он и есть
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов (Истина);
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Название» );
Если строц <>Неопределено Тогда
Возврат Новый Структура ( «Красный,Синий,Зеленый» , строц . Красный , строц . Синий , строц . Зеленый );
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов (Истина);
КонецЕсли;
строц = тЦветов . Найти ( стрЦвет , «Название» );
Если строц <>Неопределено Тогда
Возврат строц . Шестнадцатиричный ;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ИначеЕсли рИсходныйЦвет . Вид = ВидЦвета . Абсолютный Тогда
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
отб =Новый Структура ( «Красный,Синий,Зеленый» , рИсходныйЦвет . Красный , рИсходныйЦвет . Синий , рИсходныйЦвет . Зеленый );
мстроц = тЦветов . НайтиСтроки ( отб );
Если мстроц . Количество ()<> 0 Тогда
Возврат мстроц[0] . Название ;
КонецЕсли;
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
// фактически, он и есть
Возврат Новый Структура ( «Красный,Синий,Зеленый» , рИсходныйЦвет . Красный , рИсходныйЦвет . Синий , рИсходныйЦвет . Зеленый );
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
отб =Новый Структура ( «Красный,Синий,Зеленый» , рИсходныйЦвет . Красный , рИсходныйЦвет . Синий , рИсходныйЦвет . Зеленый );
мстроц = тЦветов . НайтиСтроки ( отб );
Если мстроц . Количество ()<> 0 Тогда
Возврат мстроц[0] . Шестнадцатиричный ;
КонецЕсли;
КонецЕсли;
КонецЕсли; // по вариантам видов цвета как типа Цвет
ИначеЕсли ТипЗнч ( рИсходныйЦвет )= Тип ( «Строка» ) Тогда
// ищем во всех колонках таблицы, т.к. заведомо не знаем, какой это цвет
Если ТипЗнч ( тЦветов )<> Тип ( «ТаблицаЗначений» ) Тогда
тЦветов = ПрочитатьТаблицуЦветов ();
КонецЕсли;
строц = тЦветов . Найти ( СокрЛП ( рИсходныйЦвет ));
Если строц <>Неопределено Тогда
Если рВидИтоговогоЦвета = 1 Тогда // нужен web-цвет
Возврат строц . Название ;
ИначеЕсли рВидИтоговогоЦвета = 2 Тогда // нужен RGB
Возврат Новый Структура ( «Красный,Синий,Зеленый» , строц . Красный , строц . Синий , строц . Зеленый );
ИначеЕсли рВидИтоговогоЦвета = 3 Тогда // нужен 16-ричный
Возврат строц . Шестнадцатиричный ;
КонецЕсли;
КонецЕсли;
Всё крайне кондово, но может пригодиться. Единственно, учитывайте, что лучше 1 раз прочитать таблицу соответствий и далее по ней искать. Ну и проиндексируйте по нужной колонке, исходя из ситуации.
На днях столкнулся с интересной особенностью 1С.
Нужно было передать в 1С двоичные данные (varbinary), но как говорится все проблемы на стыке систем. 1С восприняла данные как объект, каковыми они не являлись. Памятуя о том что 1С любит строковые данные, я начал пытаться преобразовать их в строку. И вот что у меня получилось на выходе:
-
Использование не документированных функций [sys].[fn_varbintohexstr] и [sys].[fn_varbintohexsubstring] Если стоит простое преобразование, то можно воспользоваться [sys].[fn_varbintohexstr] , она принимает только один параметр: бинарную переменную.
Вот ее полное описание.
Как вы видете функция [sys].[fn_varbintohexstr] является оберткой для [sys].[fn_varbintohexsubstring], и вызывает ее всегда с одними и темиже параметрами.
[sys].[fn_varbintohexsubstring], в свою очередь имеет более продвинутый функционал. Например, позволяет преобразовывать в строку не всю последовательность, а некую «подстроку». К таким выводам я пришел после просмотра заголовочной части:
Остается только проблема обратного преобразования, дело в том что в SQL нет встроенной функции для такого действия. Точнее не было, в MS SQL 2008 есть, но об этом чуть позже.
Со своими коллегами я договорился что им будут отдавать строку вида 0x0123456789, соответственно и мне они будут отдавать уже не в виде строки, а в виде binary, например так:
В CTE выражении я просто готовлю даные, для дальнейшего использования. Самое интересно начинается в SELECT :
- В поле [ColBin_xml] мы плучаем солонку [ColChar] из [cte_d] — команда sql:column(«ColChar»)
- Дальше берем подстроку от этой колонки начиная с 3-го знака (отрезаем «0x») — функция substring(,,)
- Заставляем xml процессор считать полученую строку как hexBinary
- А в момент возврата данных они интерпретируются как varbinary(max)
Аналогичным образом работает и прямое преобразование из binary в varchar (поле [ColChar_xml])
- Берем колонку [ColBin] sql:column(«ColBin»)
- Заставляем процессор считать ее как hexBinary
- И возвращаем как varchar(max)
- И по желанию можно добавить в начало строки «0x»
- 0 — преобразование в соответствии с ASCII кодами (используется по умолчанию)
- 1 — текстовое представление с добавлением «0x» в начале строки, например так «0x0123456789»
- 2 — текстовое представление без добавленя «0x» в начале строки, например так «0123456789»
При конвертировании в обратную сторону ( из hexString в binary) у нас теже 3 стиля, которые задают условие преобразования.
Замечание! Если при обратном преобразовании строка не будет соответствовать маске (стили 1 и 2) то SQL будет генерировать ошибку.
В статье рассматриваются двоичные данные, способы их хранения в 1С, примеры использования, а также примеры программного кода для работы с двоичными данными.
Содержание
Потоки и побитовые операции с двоичными данными в 1С.
Помимо записи в файл, с двоичными данными можно работать при помощи потоков. Потоки – это отдельный механизм платформы, достойная отдельной статьи. Здесь отмечу лишь, что потоки позволяют обрабатывать очень большие объемы данных за счет последовательной записи и чтения.
Также, потоки позволяют избежать использования временных файлов, выполняя все операции с данными в оперативной памяти.
Двоичные данные можно объединять, разделять, получать часть данных в виде буфера в оперативной памяти, а также выполнять побитовые операции. Побитовые операции имеют довольно узкую специфику применения, и используются не так часто. Например, для генерации QR кодов, ключей шифрования, картинок, или при декодировании формата обмена с торговым оборудованием.
На этом все, надеюсь, статья структурировала ваше представлении о двоичных данных, и была хоть немного полезна.
Где хранить двоичные данные в базе 1С?
Двоичные данные можно хранить несколькими способами.
В макетах с типом “Двоичные данные”, в объектах конфигурации. В этом случае запись двоичных данных в макет производится еще на этапе разработки конфигурации.
В реквизитах с типом ХранилищеЗначения, в объектах базы данных, например, в справочниках, регистрах сведений, документах.
В реквизитах типа строка, в формате base64, в Base 16 (Hex), либо в виде строки в указанной кодировке. Рассмотрим пример. Допустим, у нас есть текстовый файл с содержимым “Тест тест тест”, который мы прочитали в виде двоичных данных в переменную ДД. Платформа предусматривает несколько методов получения строки из двоичных данных, каждому из которых соответствует обратный метод – формирование двоичных данных из строки того или иного формата.
Читайте также: