Содержание.
- Зачем нужна эта статья?
- Общие правила и Рекомендации.
- Примитивные типы.
- Коллекции.
- Ссылочные типы.
- Заключение.
Зачем нужна эта статья?
Несколько лет назад я работал над проектом логистического ПО. И у нас был расчетный сервер, который на вход получал из торговой 1С сотни точек пути с графиками их работы, тысячи заказов на доставки с параметрами совместимости товаров для возможности совместной доставки, описание парка из десятков машин с различными параметрами и разными тарифами; а на выход выдавал наиболее оптимальное решение по критериям времени/денег/выполнимости в виде сложной древовидной структуры сформированных маршрутов. Объем потока информации был огромен и важным стал вопрос формата для выполнения обмена.
В первых релизах я пробовал обмен сначала с помощью XML, а потом и на JSON. Но слишком много времени уходило на конвертацию. Попробовал вместо типовых функций написать собственный "велосипед" с потоковым парсингом, но и тут получил лишь незначительный выигрыш.
Тогда я вспомнил про внутреннее представление. По моему ТЗ наш сишник сделал задачу парсинга "формата 1С" на расчетном сервере и в результате у нас получилось практически мгновенное превращение расчетного задания в текст для сервера, а затем не менее быстрое превращение результатов расчета в объект, готовый для демонстрации логисту на карте.
К сожаления, я тогда не сохранил свои наработки, так как посчитал, что у нас весьма экзотический случай и ценность для других данной темы не высока. И был крайне удивлен, когда на днях на Toster.ru (сайт вопросов-ответов) один php-программист попросил помощи с парсингом формата 1С. Внезапно оказалось, что:
- До сих пор появляются задачи обмена именно в "формате 1С",
- До сих пор отсутствует документация, которая может помочь специалистам, не знающим внутреннюю кухню платформы 1С.
Общие правила и Рекомендации.
Строка внутреннего представления данных, получаемая с помощью ЗначениеВСтрокуВнутр() или ЗначениеВФайл() - это текст, обычно в формате UTF-8. Отличительная особенность от других текстовых форматов - синтаксис фигурных кавычек. Описание данных, которые представлены внутренним форматом 1С, начинается с открывающейся фигурной скобки "{" и заканчивается закрывающейся фигурной скобкой "}". Содержимое между фигурными скобками - это инструкции парсеру данных (далее - параметры). Если параметров больше одного, то они разделяются символом запятой. Первый параметр - это всегда один символ признака типа в двойных кавычках. Остальные параметры - это или уточнение типа, или указание на количество элементов, или указание на конкретные элементы из множества, или описание значения свойств, или другие инструкции парсеру по сборке.
По моему опыту, для полноценного обмена вполне достаточно описать такие типы как Число, Строка, Дата, Булево, Массив, Соответствие и Неопределено. Эти простые типы, которые интуитивно понятны современным системным и веб-программистам, в которых те увидят аналогии с базовыми типами в своих языках. Тип Структура - это частный случай Соответствия и с точки зрения внутренней структуры они полностью идентичны, а потому я его не рекомендую. СписокЗначений, ТаблицыЗначений и особенно ДереваЗначений - будут мало интересны из-за своей направленности на интерактивную работу с пользователем, а потому имеющие сложную внутреннюю структуру, которую запросто можно повторить многомерным Массивом или Массивом Соответствий. Ссылочные типы я бы тоже не рекомендовал использовать из-за избыточности представляемой информации - те же код/номер или УИД из ссылки будут намного компактнее.
Важные замечание из моего опыта парсинга:
- Регистр символов для обозначения типов (первый параметр) имеет важное значение!
- Игнорируются все пробельные символы (пробелы, табуляции, переносы строк) в произвольных местах между фигурными скобками и параметрами - т.е. руки развязаны и для эстетов, и для любителей покомпактнее.
- Выражения в неправильном формате, но с правильной структурой (ошибочный тип или идентификатор) распознаются как Неопределено!
- Нарушение структуры или неправильные типы параметров на предопределенных позициях приводят к выводу ошибки: "Ошибка преобразования: Ошибка формата потока"
- Лишние параметры игнорируются и не считаются нарушением структуры. Для примера {"N", 5, "S", "Test"} - это все равно будет число 5.
Примитивные типы.
Тип | Шаблон | Описание типа и формат значения | Примеры |
---|---|---|---|
Null | {"L"} | Без значения. Символизирует пустые значения, полученные из запроса как результат соединения или обращения к вложенным полям пустых ссылок через точку. | {"L"} |
Неопределено | {"U"} | Без значения. Символизирует неинициализированные переменную или свойство объекта составного типа. | {"U"} |
Число | {"N",<?>} | Тип для описания вещественных чисел. Во второй позиции представления находится число в десятеричной системе счисления. При наличии дробной части разделителем выступает символ точки. | {"N", 3.14} {"N", 777} |
Строка | {"S","<?>"} | Строковое значение заключается в двойные кавычки. Символы экранирования не используются за исключением двойного вывода самой двойной кавычки, если она должна быть в строке. | {"S", "тест"} = тест {"S", " ""} "} = "} |
Булево | {"B",<?>} | Для False/Ложь значение равно 0, а для True/Истина будет равно 1 | {"B", 0} {"B", 1} |
Дата | {"D",<?>} | Значение даты указывается с точностью до секунды в формате YYYYMMDDhhmmss. В 1С пустая дата - это 1 января 1 года н.е. | {"D",00010101000000} = пустая дата {"D",20190830203450} = 20:34:50 30 августа 2019 года |
Примечание 1. Еще раз обращаю внимание на замечания из предыдущего пункта. Так при парсинге из выражения {"N" , 7 } - мы получаем цифру 7, но если напишем {"n",7} - то в результате будет значение Неопределено!
Примечание 2. С точки зрения логики внутреннего формата к примитивным типам так же относятся Типы (идентификаторы классов данных). Описание Типа состоит из двух параметров - "T" и внутреннего идентификатора. Примеры: тип Строка = {"T",9b6abf8b-0173-48e5-b0a0-83b21fcf63c5}, тип Число = {"T",b0be78f2-0ee6-4d31-a3bb-77dd32ba5bec}, тип Массив = {"T",51e7a0d2-530b-11d4-b98a-008048da3034}.
Коллекции.
Чтобы описать коллекцию значений, необходимо в качестве первого параметра указать символ типа "#", а вторым параметром записать идентификатор типа. Для коллекций (также как и для Ссылок, Объектов, Списков, Выборок и так далее), в качестве идентификатора используется 32-разрядное 16-ричное число. Регистр для символов A-F (цифры с 10 по 15) не имеет значение - хоть большие и маленькие вперемешку. Но важно наличие разделение дефисами на 5 групп символов по правилу 8-4-4-4-12 и отсутствие пробельных символов внутри идентификатора - нарушение этих правил приводит к ошибке потока.
Для коллекций значений предопределены (со времен 7.7, а может даже раньше) следующие идентификаторы:
Тип | Идентификатор |
---|---|
Массив | 51e7a0d2-530b-11d4-b98a-008048da3034 |
Структура | 4238019d-7e49-4fc9-91db-b6b951d5cf8e |
Соответствие | 3d48feae-a9c6-4c5a-a099-9eb6477630c6 |
СписокЗначений | 4772b3b4-f4a3-49c0-a1a5-8cb5961511a3 |
ТаблицаЗначений | acf6192e-81ca-46ef-93a6-5a6968b78663 |
ДеревоЗначений | e603c0f2-92fb-4d47-8f38-a44a381cf235 |
ФиксированныйМассив | 4500381b-db30-4a10-9db4-990038032acf |
ФиксированнаяСтруктура | 3ee983d7-ace7-40f9-bb7e-2e916fcddd56 |
ФиксированноеСоответствие | 220455ea-6c85-4513-996f-bbe79ed07774 |
Примечание. Если заменить символ "#" на "T", то получим вместо объекта значения объект его типа.
Массив.
Это популярный во всех языках программирования тип, который предназначен для хранения некоторого множества данных с доступом по индексу. Так как язык 1С не является строго типизированным языком, то и массив не требует описания типа своих элементов и даже допускается размещение в едином массиве значений различных типов.
Структурно внутреннее описание массива состоит из 3 параметров - "#", 51e7a0d2-530b-11d4-b98a-008048da3034 и содержимого массива в фигурных скобках. Содержимое в свою очередь состоит из количества элементов массива, а потом перечисления этих элементов через запятую, в формате, который соответствует их типу.
Для пустого массива содержимое будет {0}. Если в массиве только одно число 12, то его содержимое равно {1,{"N",12}}. Эти же примеры полностью:
- {"#",51e7a0d2-530b-11d4-b98a-008048da3034,{0}}
- {"#",51e7a0d2-530b-11d4-b98a-008048da3034,{1,{"N",12}}}
Примечание. Практика показала, что точное указание количества на платформах 8.х не важно. Главное написать в первой позиции описания какое-то целое число равное или больше нулю, а далее платформа будет создавать Массив по фактически перечисленным элементам; и при вызов у нового объекта метода Количество() вернет верное фактическое значение. Указание в позиции количества любого значения кроме положительного целочисленного значения или нуля будет приводить к ошибке чтения потока, а если указать отрицательное число - даже к краху платформы с записью дампа.
Структура и Соответствие
Структура и Соответствие - это типы, которые позволяют получать некие значения по указанным ключам. Особенностью этих коллекций является то, что это фактически множество пар Ключа и Значения, которые можно обойти с помощью итератора в цикле. Внутреннее представление отражает эту особенность - описание состоит из троих параметров - "#", идентификатора (4238019d-7e49-4fc9-91db-b6b951d5cf8e или 3d48feae-a9c6-4c5a-a099-9eb6477630c6) и содержимого в фигурных скобках. Содержимое в свою очередь состоит из количества пар Ключ-Значение, а потом перечисления этих пар через запятую. Описывается пара Ключ-Значение с помощью фигурных скобок, где указаны через запятую значение Ключа и значение Значения. Пример описания пары Ключ-Значение вида ID=12 имеет вид: {{"S","ID"},{"N","12"}}
Примеры. Пустое соответствие: {"#",3d48feae-a9c6-4c5a-a099-9eb6477630c6,{0}}. Структура с двумя ключами: {"#",4238019d-7e49-4fc9-91db-b6b951d5cf8e,{2,{{"S","id_local"},{"N",10}},{{"S","id_global"},{"N",215}}}}
Примечание 1. Точно так же, как и в массиве, не важно какое именно целочисленное количество вы укажите (или ноль) - при парсинге платформа игнорирует ваше число и для созданного объекта указывает реальное фактическое. Указание любых других значений в позиции количества приведет к ошибке потока. Только в отличии от массивов - тут можно указывать отрицательное количество и это нормально отработает и не приведет к краху платформы.
Примечание 2. И еще важный момент - это соблюдение уникальности ключей. Если в описании сделать несколько пар Ключ-Значение, то в результирующую структуру попадет только один из них. В моих экспериментах - это была всегда первая найденная в текстовом описании пара, но не рекомендую надеяться, что так будет во всех версиях платформы.
Фиксированные массив, структура и соответствие
Как уже понятно из названия - это типы, которые не поддерживают изменение после своего создания. Они предназначены для использования в качестве параметров сеанса и в некоторых сценариях работы с формами - т.е. вероятнность встретится с ними в "выгрузке из 1С" очень мала.
С точки зрения описания внутреннего формата фиксированные коллекции полностью идентичны своим обычным аналогам. Буквально стоит заменить в описании массива, структуры или соответствия идентификатор на нужный эквивалент и получаем уже фиксированную версию объектов.
Примечание 1. Все мои замечания относительно количества элементов остаются в силе. Все идентично вплоть до того, что отрицательное количество нормально принимается фиксированными структурой и соответствием, а попытка использовать его для создания фиксированного массива вызывает крах платформы.
Примечание 2. Кстати, на будущее получаем лайфхак. Средствами платформы можно преобразовывать только пары Структура с Фиксированной Структурой и Соответствие с Фиксированным Соответствием. Для остальных комбинаций нужно делать циклы и перекидывать пары Ключей-Значений в новый объект. С помощью внутреннего представления и замены идентификатора можно преобразовать намного быстрее, да еще и вернуть результат в ту же переменную :)
Список значений
Это особый вид коллекции значений, который предназначен для формирования вариантов выбора для элементов форм или может самостоятельно выводится на форму или даже в отдельное окно. Интересно, что один заранее сформированный список значений может использоваться для формирования доступных значений в другом списке значений, который интерактивно редактирует пользователь. Так же с помощью специального объекта ОписаниеТипов можно ограничить диапазон допустимых значений (только справочник Склады, или только справочники Покупатели и Физлица, или только строки и числа с точностью до 2 знака). Еще значения иногда могут иметь вид непонятный для пользователей (к примеру, вложенные массивы или коды операций), то в списке поддерживается отдельное хранение понятного строкового представления. Так же для каждого значения можно назначить вывод пиктограммы (из библиотеки предопределенных или из конфигурации). Для необходимости отметить в списке некоторые из значений предусмотрено дополнительное поле, которое при показе связывается с флажком. Все вышеперечисленные возможности ожидаемо отразились на структуре хранимого значения.
Как и другие коллекции, данная состоит из троих параметров - "#", идентификатора (4772b3b4-f4a3-49c0-a1a5-8cb5961511a3) и содержимого в фигурных скобках. Содержимое списка значений состоит из таких элементов: число 6 (или другое целое число большего значения), идентификатор 1e512aab-1b41-4ef6-9375-f0137be9dd91 (можно любой другой), число 0 (или 1), число 0 (или любое другое целое число), описание перечня элементов списка в фигурных кавычках (см. ниже), описание доступных типов или можно так {""}, признак наличия ограничивающего списка - 0 если нет и 1 если да. Если есть ограничивающий значения список, то добавляется еще один параметр - описание вложенного списка (то описание, которое начинается с 6).
Описание перечня элементов списка состоит из количества этих элементов (на самом деле подходит любое целое число) и через запятую описание строк списка в фигурных скобках. Строка списка состоит из двух параметров: идентификатор 1e512aab-1b41-4ef6-9375-f0137be9dd91 (если указать другой, то при парсинге этот элемент будет проигнорирован; при этом тот идентификатор, который был ранее после числа 6, может отличаться) и описание элемента списка в фигурных скобках.
Элемент списка состоит из таких параметров: текстовое описание элемента, отметка выбора (0 - нет, 1 - да), полное описание значения (если там был список, то описание начинается с "#"), описание пиктограммы (для пустого значения: {4,0,{0},"",-1,-1,0,0,""} ). Далее еще могут быть параметры, но их отсутствие ни на что не влияет.
Пример. Если нужно сделать список значений из пары элементов 100 и 200, один из которых с пометкой, то в результате получаем такое описание:
{"#",4772b3b4-f4a3-49c0-a1a5-8cb5961511a3, {6,1e512aab-1b41-4ef6-9375-f0137be9dd91,0,0, {2, { 1e512aab-1b41-4ef6-9375-f0137be9dd91, {"Сотня", 0, {"N",100}, {4,0,{0},"",-1,-1,0,0,""} } }, { 1e512aab-1b41-4ef6-9375-f0137be9dd91, {"Двести", 1, {"N",200}, {4,0,{0},"",-1,-1,0,0,""} } } }, {""},0} }
Примечание. Может показаться, что 1e512aab-1b41-4ef6-9375-f0137be9dd91 из описания строки - это идентификатор строки списка, но на самом деле идентификатором строки является c27d99e0-2f53-11d5-a3be-0050bae0a776. Что же означает первый идентификатор (который после числа 6), я так и не смог выяснить.
Таблица значений
Особенность этого вида коллекций заключается в наличии колонок. По-умолчанию, в колонку можно писать значения любого типа, но при необходимости можно ограничить допустимые типы. Еще каждой колонке можно назначить заголовок и ширину для красивого вывода на форму или для открытия в отдельном окне. В каждой строке таблицы можно заполнять ячейки соответствующих колонок, а явно неинициализированные ячейки примут значения по-умолчанию для типов своих колонок (если типы не заданы, то будет Неопределено). А еще таблицам значений можно создавать произвольные индексы по колонкам для дальнейшего быстрого поиска/сортировки. Эти особенности отразились на структуре хранимого значения.
Как и другие коллекции, данная состоит из троих параметров - "#", идентификатора (acf6192e-81ca-46ef-93a6-5a6968b78663) и содержимого в фигурных скобках. В содержимом таблицы первым параметром должно быть целое число 9 (на самом деле от 7 и выше), на втором месте блок с описанием колонок, на третьем месте блок с описанием строк, на четвертом месте блок с описание индексов.
В блоке описания колонок первым параметром идет количество колонок (тут важно, чтобы было реальное количество колонок!), а далее через запятую блоки описания конкретных колонок. В блоке описания конкретной колонки пять параметров - порядковый индекс (отсчет от нуля; порядок не обязательно прямой, но далее в описании строк нужно не ошибиться с позицией для размещения значения), внутренний идентификатор колонки по правилу наименования переменных (для обращения из программного кода), описание типа колонки (можно просто {""}), строка с заголовком для вывода на формы, ширина колонки для вывода на формы.
В блоке описания строк сначала идет магическое целое число, которое при значениях меньше 2 не создает строки у результирующего объекта ТаблицаЗначений (а при значениях выше не заметил никаких различий в поведении). Далее вторым параметром идет указание сколько колонок из описанных в блоке колонок требуется взять для создания результирующего объекта (т.е. можно описать больше, но взять не все - и они не будут доступны через свойство-коллекцию Колонки у результирующего объекта); после чего указываются через запятую парами индекс колонки для описания позиции значения из расположенного ниже описания строки и соответствующий ей индекс колонки из описания колонок. Таким образом для одной колонки получим {2,1,0,0, ; для двух колонок {2,2,0,0,1,1 ; для троих можно так: {2,3,2,2,0,0,1,1
Примечание. Если напутать порядок индексов для колонок и позиций в данных, то результат будет не совсем ожидаемый (я смог добиться результата, когда у таблицы из троих колонок в коллекции колонок было три идентичных описания, по которым получали одно и тоже значение, но если обратится через индексы, то можем прочитать "скрытые" колонки). Возможно эту фичу можно использовать для быстрого создания таблиц, где разным колонкам нужно дать одинаковое значение, но такую таблицу лучше не редактировать так как тут есть опасность в том, что, изменив значение в одной из колонок, получим изменение в других (разные колонки будут ссылаться на одну и туже ячейку в памяти).
Продолжаем описание блока строк. После перечисления всех нужных нам колонок, открывается новый блок - с содержимым строк. В этом блоке первым параметром снова идет магическое целое число, значение которого ни на что не влияет и может быть даже отрицательным (обычно 1). Вторым параметром блока содержимого строк идет число количества строк - важно указать правильное количество, так как при указании меньшего значения, вы столько и получите (потеряв остальные), а при указании большего числа получите только ошибку формата потока на попытке парсинга такого описания. После числа количества идут через запятую блоки самих строк, после которых указываются еще два числа - максимальный индекс использованной колонки и максимальный индекс строки (индексы начинаются с нуля и потому будут меньше количества на единицу) - хотя практика показала, что для корректного парсинга важно просто поставить там хоть какие-то два числа, хоть нули.
Блок строки таблицы снова открывает какое-то магическое целое число, которое просто должно быть (а дальше хоть в каждой строке свое и даже отрицательное подходит). Вторым параметром указывается индекс строки (практика показала, что этот параметр при загрузке игнорируется - можно хоть одинаковый указать во всех строках). Третьим параметром указывается количество описываемых значений в данной строке - важно, так как количество значений в строке может быть меньше или больше чем колонок (если меньше, то в результирующей таблице в ячейках получим значения по-умолчанию для типа колонок, а если больше чем сделано связок с колонками - лишние значения будут просто проигнорированы). После указания количества значений строки идет перечисление этих значений через запятую, а замыкает строку ноль - число без которого происходит ошибка парсинга (если вместо нуля другое число - тоже ошибка).
Третий блок описания таблицы значений - это блок индексов. По моему мнению, тут не нужно заморачиваться. Программист 1С сам должен решать, что делать с полученной из внешнего источника таблицей значений - если там понадобятся индексы, то пусть он их сам создаст. Если же веб-программисту для загрузки на сайт отдали описание с блоком индексов - при написании своего парсинга проигнорируйте тот блок. Блок без индексов выглядит так - {0,0}.
Пример. Теперь можно создать валидное представление таблицы значений. Для простоты возьмем выгрузку прайса, где есть только артикул и цена. Выйдет что-то такое:
{"#",acf6192e-81ca-46ef-93a6-5a6968b78663, {9, {2, {0,"Артикул",{""},"",0}, {1,"Цена",{""},"",0} }, {2,2,0,0,1,1, {1,3, {2,0,2, {"S","Часы"}, {"N",750.99}, 0}, {2,1,2, {"S","Кеды"}, {"N",150.99}, 0}, {2,2,2, {"S","Шапка"}, {"N",200}, 0} }, 1,2}, {0,0} }}
Дерево значений
Дерево Значений - это коллекция значений, которая очень похожа на Таблицу Значений. Принципиальное различие - это возможность подчинять строки друг к другу. Т.е. у каждой строки помимо свойств для хранения своих значений еще есть доступ к множеству описаний подчиненных строк. Второе отличие от таблицы - отсутствие индексов. В результате внутреннее представление получилось очень похожее на описание Таблицы Значений, но с небольшими различиями.
Как и другие коллекции, данная состоит из троих параметров - "#", идентификатора (e603c0f2-92fb-4d47-8f38-a44a381cf235) и содержимого в фигурных скобках. В содержимом первым параметром должно быть целое число 1 (на самом деле любое, даже отрицательное), на втором месте блок с описанием колонок, на третьем месте блок с описанием строк.
В блоке описания колонок первым параметром идет количество колонок (тут важно, чтобы было реальное количество колонок!), а далее через запятую блоки описания конкретных колонок. В блоке описания конкретной колонки пять параметров - порядковый индекс (отсчет от нуля; порядок не обязательно прямой, но далее в описании строк нужно не ошибиться с позицией для размещения значения), внутренний идентификатор колонки по правилу наименования переменных (для обращения из программного кода), описание типа колонки (можно просто {""}), строка с заголовком для вывода на формы, ширина колонки для вывода на формы.
В блоке описания строк сначала идет магическое целое число, которое при значениях меньше 2 не создает строки у результирующего объекта ДеревоЗначений (тут все как у ТаблицыЗначений). Далее вторым параметром идет указание сколько колонок из описанных в блоке колонок требуется взять для создания результирующего объекта, после чего указываются через запятую парами индекс колонки для описания позиции значения из расположенного ниже описания строки и соответствующий ей индекс колонки из описания колонок (снова все идентично ТаблицеЗначений - подробности смотрите ранее в соответствующем разделе).
После перечисления всех нужных нам колонок открывается новый блок - с содержимым строк. В этом блоке первым параметром снова идет магическое целое число, значение которого ни на что не влияет и может быть даже отрицательным (обычно 1). Вторым параметром блока содержимого строк идет число количества строк - важно указать правильное количество, так как при указании меньшего значения, вы столько и получите, потеряв остальные, а при указании большего числа получите только ошибку формата потока на попытке парсинга такого описания. После числа количества строк через запятую идут блоки самих строк, после которых указываются еще два числа - максимальный индекс использованной колонки и максимальный индекс строки (индексы начинаются с нуля и потому будут меньше количества на единицу) - хотя практика показала, что для корректного парсинга важно просто поставить там хоть какие-то два числа, хоть нули (снова все идентично ТаблицеЗначений).
Блок строки таблицы снова открывает какое-то целое число (значение не важно, как и в ТаблицеЗначений - обычно 2). Вторым параметром указывается индекс строки (практика показала, что этот параметр при загрузке игнорируется - можно хоть одинаковый указать во всех строках). Третьим параметром указывается количество описываемых значений в данной строке - важно, так как количество значений в строке может быть меньше или больше чем колонок (если далее указать не то количество значений как мы тут объявили, то получим ошибку парсинга). После указания количества значений строки идет перечисление этих значений через запятую. Потом идет признак наличия подстрок: 0 - нет подстрок и на том описание блока строки закрывается, 1 - подстроки есть и далее следует еще один параметр с блоком описания этих подстрок.
Пример. На практике все довольно просто. Пусть мы хотим описать состав склада по категориям: у нас есть какие-то запчасти в количестве 1000 штук и бытовая техника из 100 изделий, где 10 видов утюгов, 20 стиральных машин, 30 холодильников и 50 смартфонов, из которых 10 моделей айфонов и 40 - андроидов. Описание дерева значений получается таким:
{"#",e603c0f2-92fb-4d47-8f38-a44a381cf235, {1, {2, {0,"Категория",{""},"",0}, {1,"Количество",{""},"",0} }, {2,2,0,0,1,1, {1,2, {2,0,2, {"S","Запчасти"}, {"N",1000}, 0 }, {2,1,2, {"S","Бытовая техника"}, {"N",100}, 1, {1,4, {2,2,2, {"S","Утюги"}, {"N",10}, 0}, {2,3,2, {"S","Стиральные машины"}, {"N",20}, 0}, {2,4,2, {"S","Холодильники"}, {"N",30}, 0}, {2,5,2, {"S","Смартфоны"}, {"N",50}, 1, {1,2, {2,6,2, {"S","iPhone"}, {"N",10}, 0}, {2,7,2, {"S","Android"}, {"N",40}, 0} } } } } },1,7 } } }
Ссылочные типы.
Если в выгрузке "формата 1С" вам попадается сущность вида: {"#", <идентификатор_1>, <число>: <идентификатор_2>}, то знайте - вам передали значение ссылочного вида, назначение которого ссылаться на конкретное значение в базе данных. Если вы запрашиваете данные по задолженностям, то вам запросто могут выдать таблицу, где вместо кодов клиентов и номеров документов будут именно такие значения.
В представлении ссылочного типа первым идентификатором указывается идентификатор вида данных, который хранится в конфигурации 1С, а второй идентификатор - то указатель внутри таблицы данных, которая связана с указанным видом данных. Еще в представлении есть число - это суффикс физической таблицы, которая создается в СУБД для хранения содержимого данного вида данных.
Сформировать подобное значение можно и без функции ЗначениеВСтрокуВнутр(). Для того нужно выгрузить конфигурацию и выбрать для интересующего вида данных идентификатор для ссылочного типа (там могут быть и другие идентификаторы - объектов, менеджеров, выборок и т.д.). Далее с помощью ПолучитьСтруктуруХраненияБазыДанных() узнаем суффикс. А последний идентификатор получаем из ссылки с помощью метода УникальныйИдентификатор() с последующим преобразование в перевернуты формат (тут подробно про форматы идентификаторов в 1С).
Давайте попробуем получить ссылочное представление для Доллара из справочника Валюты. Начнем с выгрузки конфигурации (стандартная выгрузка в файлы или с помощью v8unpack.exe) и получения идентификатора ссылочного типа справочника Валюты - это 3a87ef2a-9de1-4d34-9e5f-3c8cdf53b3ab
Далее узнаем, что в СУБД суффикс справочника валют будет 53
И узнаем идентификатор из ссылки: 68c80f28-24ce-11e6-8f41-e91b9a8c6dd6 -> 8f41e91b9a8c6dd611e624ce68c80f28
В результате получаем конструкцию вида: {"#", 3a87ef2a-9de1-4d34-9e5f-3c8cdf53b3ab, 53: 8f41e91b9a8c6dd611e624ce68c80f28}, верность которой проверяем с помощью ЗначениеИзСтрокиВнутр()
Заключение.
Я описал далеко не все, что можно представить во внутреннем формате. За рамками статьи остались Запросы, Выборки, Списки, Формы, Графические Схемы, Схемы Компоновки, Элементы Отборов и многое другое. Но я надеюсь, что смог именно для целей обмена дать все необходимые базовые знания по внутреннему формату 1С.
Чтобы любой мог попробовать повторить примеры из статьи, самостоятельно поэкспериментировать (особенно в плане создания таблиц с невидимыми колонками) или проверить валидность результатов выгрузки из внешней системы, я добавляю свою обработку, с которой делал скриншоты для этой статьи. Обработка поддерживает работу в обычном и управляемом интерфейсе. Для демонстрации там уже есть вставка всех популярных типов значений. Результаты парсинга показываются в понятном виде. А если хочется программно создать какой-то произвольный объект и увидеть его представление, то в обработке есть вкладка "Исполняемый код", где нужно установить требуемое значение переменной Значение.
Обработка была проверена в режимах управляемого и обычного интерфейсов на платформе 8.3.15.1565. Но должна работать и на прочих 8.3.*