В процессе разработки на платформе 1С:Предприятие 8 мы часто сталкиваемся с необходимостью получить строковое представление типа той или иной переменной. Это может быть нужно для логирования, отладки, динамического анализа данных или отображения информации пользователю. Особый интерес представляет задача получения строкового представления типа в формате, максимально приближенном к тому, который мы видим в окне отладчика 1С в колонке "Тип", например, "ДокументСсылка.МойДокумент" или "СправочникОбъект.МойСправочник". Мы подробно рассмотрим различные подходы к решению этой задачи, проанализируем их особенности, преимущества и недостатки, а также найдем наиболее точные и универсальные методы.
ТипЗнч() и Тип()Прежде чем углубляться в получение строкового представления, давайте вспомним основные функции, которые платформа 1С предоставляет нам для работы с типами значений.
Функция ТипЗнч(Значение) позволяет нам получить объект типа Тип для любого переданного ей значения. Например, если у нас есть переменная, содержащая ссылку на документ, вызов ТипЗнч(МойДокументСсылка) вернет нам объект типа Тип, который представляет собой тип этого документа (например, "ДокументСсылка.ЗаказПокупателя"). Этот объект типа Тип является фундаментальным для дальнейших операций.
Функция Тип(ИмяТипа), напротив, позволяет получить значение типа Тип по его строковому имени. Например, Тип("ДокументСсылка.ЗаказПокупателя") вернет тот же объект типа Тип, что и в предыдущем примере. Эта функция полезна, когда мы хотим работать с типом, зная только его строковое имя.
Эти две функции являются базовыми и служат отправной точкой для всех дальнейших манипуляций с типами в 1С:Предприятии.
Строка(ТипЗнч(Значение))Самый простой и интуитивно понятный способ получения строкового представления типа – это прямое преобразование полученного объекта типа Тип к строке с помощью функции Строка().
// Предположим, у нас есть ссылка на элемент справочника "Валюты"
МоеЗначение = Справочники.Валюты.НайтиПоКоду("643");
// Получаем объект типа "Тип"
ТипЗначения = ТипЗнч(МоеЗначение);
// Преобразуем объект типа к строке
СтроковоеПредставление = Строка(ТипЗначения);
Сообщить(СтроковоеПредставление); // Например, "СправочникСсылка"
Однако, как показывает практика, этот метод не всегда дает желаемый результат, особенно если мы стремимся к формату, аналогичному отладчику (например, "СправочникСсылка.Валюты"). Проанализируем его особенности и ограничения:
Строка() для объекта Тип часто зависит от текущего языка интерфейса 1С. Например, для одного и того же типа в русской локализации мы можем получить "СправочникСсылка", а в английской – "CatalogRef". Это делает его менее надежным для программного анализа, где требуется консистентный формат, независимый от локализации.
Строка(Типа) может отличаться от того, что мы видим в окне отладчика. Чаще всего он возвращает только общее наименование типа (например, "СправочникСсылка", "Число", "Строка"), без указания конкретных метаданных объекта (например, "Валюты"). То есть, мы не получим "СправочникСсылка.Валюты", а только "СправочникСсылка".
Строка() для объектов Тип могло изменяться в разных версиях платформы (например, при переходе с 8.1 на 8.2 и далее), что может создавать проблемы при разработке универсальных решений, работающих в разных конфигурациях и версиях платформы.
Таким образом, хотя этот метод прост в использовании, его ограничения делают его малопригодным для получения точного, детализированного и стабильного строкового представления типа, как того требует исходная задача.
XMLТипЗнч() для получения имени типаСледующим шагом рассмотрим метод, который активно обсуждался на форуме – использование функции XMLТипЗнч(). Эта функция предназначена для получения объекта XMLТип, который описывает тип значения с точки зрения XML-сериализации. У объекта XMLТип есть полезное свойство ИмяТипа, которое может быть использовано для нашей цели.
Мы можем применить этот подход следующим образом:
// Пример значения: ссылка на элемент справочника
МоеЗначение = Справочники.Организации.ОсновнаяОрганизация;
// Получаем объект XMLТип для значения
XMLТипЗначения = XMLТипЗнч(МоеЗначение);
Перем ТипСтрокой;
Если XMLТипЗначения = Неопределено Тогда
// Для несериализуемых или специфических типов XMLТипЗнч может вернуть Неопределено.
// Например, для типа "ИнформацияОбОшибке" эта функция вернет Неопределено.
ТипСтрокой = Строка(МоеЗначение); // Как запасной вариант
// Здесь можно добавить собственную логику обработки известных проблемных типов.
Иначе
// Получаем имя типа из объекта XMLТип
ТипСтрокой = XMLТипЗначения.ИмяТипа;
КонецЕсли;
Сообщить(ТипСтрокой); // Например, "CatalogRef.Организации"
Важно отметить, что в обсуждении на форуме изначально было упомянуто XMLТип(). Однако для конкретных значений (например, ссылка на элемент справочника или документ, число, строка) следует использовать именно XMLТипЗнч(). Функция XMLТип() используется, если само "значение" уже является объектом типа Тип. Например, XMLТип(ТипЗнч(МоеЗначение)).ИмяТипа будет работать аналогично XMLТипЗнч(МоеЗначение).ИмяТипа, поскольку ТипЗнч(МоеЗначение) вернет нам объект Тип, который затем будет передан в XMLТип().
Проанализируем особенности этого подхода:
ИмяТипа объекта XMLТип всегда возвращает англоязычное представление типа. Например, для типа "СправочникСсылка.Организации" мы получим "CatalogRef.Организации", а для "ДокументСсылка.РеализацияТоваровУслуг" – "DocumentRef.РеализацияТоваровУслуг". Хотя это не соответствует русскоязычному формату отладчика, это может быть приемлемо для программного использования, требующего стабильного, не зависящего от локализации имени типа.
ИнформацияОбОшибке. Для значения такого типа XMLТипЗнч() вернет Неопределено, что требует дополнительной обработки, как показано в примере выше. В этом случае нам придется либо прибегнуть к простому Строка(Значение) (что для ИнформацияОбОшибке может вернуть сообщение об ошибке, а не ее тип), либо реализовать собственную, более сложную логику для этих специфических типов.
Таким образом, XMLТипЗнч().ИмяТипа является полезным инструментом, особенно когда требуется стабильное англоязычное имя типа, но он требует учета особенностей обработки несериализуемых типов.
Метаданные.НайтиПоТипу()Если нам нужно получить полное имя объекта метаданных, например, "Справочник.ИмяОбъекта" или "Документ.ИмяОбъекта", а не "СправочникСсылка.ИмяОбъекта", мы можем воспользоваться глобальным объектом Метаданные.
Рассмотрим следующий пример:
// Значение: ссылка на элемент справочника
МоеЗначение = Справочники.Организации.ОсновнаяОрганизация;
// Получаем объект типа "Тип"
ТипЗначения = ТипЗнч(МоеЗначение);
// Ищем объект метаданных по полученному типу
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗначения);
Перем ТипСтрокой;
Если МетаданныеОбъекта <> Неопределено Тогда
// Получаем полное имя метаданных объекта
ТипСтрокой = МетаданныеОбъекта.ПолноеИмя();
// Результат: "Справочник.Организации" (без "Ссылка")
Иначе
ТипСтрокой = "Неизвестный тип метаданных";
КонецЕсли;
Сообщить(ТипСтрокой);
Также, если у нас уже есть ссылка на объект (например, переменная Справ, содержащая СправочникСсылка.МойСправочник), мы можем получить имя самого справочника из метаданных напрямую, используя метод Метаданные() этого объекта:
// Предположим, Справ - это СправочникСсылка.Валюты
Справ = Справочники.Валюты.НайтиПоКоду("643");
// Получаем объект метаданных для этой ссылки
МетаданныеСсылки = Справ.Метаданные();
// Получаем имя объекта метаданных
ИмяСправочника = МетаданныеСсылки.Имя;
// Результат: "Валюты"
Сообщить(ИмяСправочника);
// Получаем полное имя метаданных
ПолноеИмяСправочника = МетаданныеСсылки.ПолноеИмя();
// Результат: "Справочник.Валюты"
Сообщить(ПолноеИмяСправочника);
Этот подход позволяет нам получить имя метаданных ("Справочник.Организации"), но не в точном формате "СправочникСсылка.Организации" или "СправочникОбъект.Организации", который мы видим в отладчике. Для формирования именно такого формата нам потребуется дополнительный анализ и конкатенация строк. Например, нам нужно будет определить, является ли тип ссылочным (проверив, содержит ли его коллекция Справочники.ТипВсеСсылки() или другие аналогичные коллекции типов), и затем вручную добавить "Ссылка" или "Объект" к имени метаданных. Для комплексного анализа структуры объектов конфигурации и их свойств можно воспользоваться инструментом для построения дерева метаданных.
ОбщегоНазначения.СтроковоеПредставлениеТипа из БСПЕсли ваша конфигурация использует Библиотеку стандартных подсистем (БСП), то наиболее полным, точным и удобным решением, максимально соответствующим формату отладчика, является функция ОбщегоНазначения.СтроковоеПредставлениеТипа. Эта функция специально разработана для возврата строкового представления типа в формате, который наиболее информативен для пользователя и удобен для программного анализа.
Проанализируем, как работает эта функция и какие преимущества она предоставляет:
СправочникСсылка.Валюты или ДокументСсылка.РеализацияТоваровУслуг), она вернет строку в формате "СправочникСсылка.ИмяОбъекта" или "ДокументСсылка.ИмяОбъекта". Это полностью соответствует исходному запросу автора темы и формату, который мы видим в отладчике.
СправочникОбъект.Валюты), функция вернет "СправочникОбъект.ИмяОбъекта".
Число, Строка, Дата, Булево, функция вернет их русскоязычное наименование ("Число", "Строка", "Дата", "Булево").
XMLТипЗнч(), функция из БСП часто корректно обрабатывает типы, которые не сериализуются в XML, например, ИнформацияОбОшибке, возвращая их имя ("ИнформацияОбОшибке").
Посмотрим на примеры использования этой функции:
// Предположим, что функция доступна через ОбщегоНазначения
// В реальном коде вам может понадобиться обернуть ее в серверную функцию,
// если вы вызываете ее из клиентского контекста.
// 1. Ссылочный тип
МояСсылка = Справочники.Валюты.НайтиПоКоду("643");
Сообщить("Тип (ссылка): " + ОбщегоНазначения.СтроковоеПредставлениеТипа(МояСсылка));
// Ожидаемый вывод: "СправочникСсылка.Валюты"
// 2. Объект метаданных
МойОбъект = Справочники.Валюты.СоздатьЭлемент();
МойОбъект.Наименование = "Тестовая валюта"; // Чтобы объект был заполнен
Сообщить("Тип (объект): " + ОбщегоНазначения.СтроковоеПредставлениеТипа(МойОбъект));
// Ожидаемый вывод: "СправочникОбъект.Валюты"
// 3. Простой тип: Число
МоеЧисло = 123.45;
Сообщить("Тип (число): " + ОбщегоНазначения.СтроковоеПредставлениеТипа(МоеЧисло));
// Ожидаемый вывод: "Число"
// 4. Простой тип: Дата
МояДата = ТекущаяДата();
Сообщить("Тип (дата): " + ОбщегоНазначения.СтроковоеПредставлениеТипа(МояДата));
// Ожидаемый вывод: "Дата"
// 5. Простой тип: Строка
МояСтрока = "Пример текста";
Сообщить("Тип (строка): " + ОбщегоНазначения.СтроковоеПредставлениеТипа(МояСтрока));
// Ожидаемый вывод: "Строка"
// 6. Тип Неопределено
МоеНеопределено = Неопределено;
Сообщить("Тип (Неопределено): " + ОбщегоНазначения.СтроковоеПредставлениеТипа(МоеНеопределено));
// Ожидаемый вывод: "Неопределено"
// 7. Тип ИнформацияОбОшибке (проблемный для XMLТипЗнч)
Попытка
Результат = 1 / 0; // Генерируем ошибку
Исключение
ИнформацияОшибки = ИнформацияОбОшибке();
Сообщить("Тип (ИнформацияОбОшибке): " + ОбщегоНазначения.СтроковоеПредставлениеТипа(ИнформацияОшибки));
// Ожидаемый вывод: "ИнформацияОбОшибке"
КонецПопытки;
Преимущества использования функции ОбщегоНазначения.СтроковоеПредставлениеТипа:
ИнформацияОбОшибке).
Недостатки:
В целом, если БСП доступна, ОбщегоНазначения.СтроковоеПредставлениеТипа является наиболее рекомендуемым и эффективным решением для получения строкового представления типа по значению, соответствующего запрошенному формату.
Как мы убедились, ни один из методов не является абсолютно универсальным для всех типов без исключений. Рассмотрим, как мы можем комбинировать подходы для достижения наилучшего результата, особенно при отсутствии БСП или при работе со специфическими типами.
Для типа ИнформацияОбОшибке и других несериализуемых типов:
XMLТипЗнч() для ИнформацияОбОшибке вернет Неопределено. Это делает данный метод непригодным для прямого получения имени типа в таких случаях.ОбщегоНазначения.СтроковоеПредставлениеТипа из БСП обычно корректно обрабатывает такие типы, возвращая их имя (например, "ИнформацияОбОшибке").Строка(Значение). Однако помним, что этот метод часто возвращает не имя типа, а строковое представление самого значения, что не всегда то, что нам нужно для анализа типа. Например, для ИнформацияОбОшибке Строка(Значение) может вернуть сообщение об ошибке (например, "Ошибка при выполнении операции..."), что является содержимым объекта, а не его именем типа.Представим комплексную функцию, которая пытается использовать различные методы в порядке их предпочтительности:
// Функция для получения строкового представления типа значения
// Пытается использовать ОбщегоНазначения.СтроковоеПредставлениеТипа (БСП),
// затем XMLТипЗнч().ИмяТипа, и как крайний вариант - базовое строковое представление.
Функция ПолучитьСтрокуТипаЗначения(ЗначениеДляАнализа)
Перем ТипСтрокой;
// 1. Попытка использовать ОбщегоНазначения.СтроковоеПредставлениеТипа из БСП
// Этот метод наиболее предпочтителен, так как дает русскоязычное представление,
// максимально схожее с отладчиком и хорошо обрабатывает множество типов.
#Если Сервер ИЛИ ТолстыйКлиентОбычноеПриложение ИЛИ ВнешнееСоединение Тогда
// Проверяем наличие модуля ОбщегоНазначения, если его нет, попытка вызова вызовет ошибку
Если ОбщегоНазначения <> Неопределено И ТипЗнч(ОбщегоНазначения.СтроковоеПредставлениеТипа) = Тип("Функция") Тогда
Попытка
ТипСтрокой = ОбщегоНазначения.СтроковоеПредставлениеТипа(ЗначениеДляАнализа);
Возврат ТипСтрокой; // Если БСП успешно обработала, возвращаем результат
Исключение
// Если возникла ошибка при вызове БСП-функции (например, неподдерживаемый тип или версия)
// Продолжаем к следующим методам
КонецПопытки;
КонецЕсли;
#КонецЕсли
// 2. Альтернатива с XMLТипЗнч().ИмяТипа для сериализуемых типов
// Дает англоязычное имя, но стабильно для многих типов.
Попытка
XMLТипЗначения = XMLТипЗнч(ЗначениеДляАнализа);
Если XMLТипЗначения <> Неопределено Тогда
ТипСтрокой = XMLТипЗначения.ИмяТипа;
Возврат ТипСтрокой; // Если XMLТипЗнч успешно обработал, возвращаем результат
КонецЕсли;
Исключение
// Игнорируем ошибки XMLТипЗнч и продолжаем
КонецПопытки;
// 3. Обработка несериализуемых и других специфических типов вручную
// Используем ТипЗнч() для получения объекта Тип и обрабатываем его.
ТипЗначения = ТипЗнч(ЗначениеДляАнализа);
Если ТипЗначения = Тип("ИнформацияОбОшибке") Тогда
ТипСтрокой = "ИнформацияОбОшибке"; // Явное указание для известного проблемного типа
ИначеЕсли ТипЗначения = Тип("Неопределено") Тогда
ТипСтрокой = "Неопределено";
ИначеЕсли ТипЗначения = Тип("Null") Тогда
// Некоторые внешние системы могут передавать Null
ТипСтрокой = "Null";
ИначеЕсли ТипЗначения.Метаданные() <> Неопределено Тогда
// Для типов, связанных с метаданными (СправочникСсылка, ДокументОбъект и т.д.)
// Формируем русскоязычное представление, как в отладчике.
ИмяТипаМетаданных = ТипЗначения.Имя; // Например, "СправочникСсылка"
МетаданныеОбъекта = ТипЗначения.Метаданные(); // Получаем объект метаданных
Если МетаданныеОбъекта <> Неопределено Тогда
ИмяОбъектаМетаданных = МетаданныеОбъекта.Имя; // Например, "Валюты"
// Соединяем для получения "СправочникСсылка.Валюты"
ТипСтрокой = ИмяТипаМетаданных + "." + ИмяОбъектаМетаданных;
Иначе
// Если не удалось найти метаданные (например, для типа "СписокЗначений")
ТипСтрокой = ИмяТипаМетаданных;
КонецЕсли;
Иначе
// Если ничего из вышеперечисленного не помогло, используем базовое строковое представление объекта Тип
// Это даст общее имя типа, например "Число", "Строка", "Массив"
ТипСтрокой = Строка(ТипЗначения);
// Если очень нужно хоть что-то для любых значений, можно использовать Строка(ЗначениеДляАнализа),
// но это не всегда будет именем типа (например, для объектов это будет ПредставлениеОбъекта).
КонецЕсли;
Возврат ТипСтрокой;
КонецФункции
// --- Тестирование комплексной функции ---
Сообщить("--- Тестирование функции ПолучитьСтрокуТипаЗначения ---");
// 1. Ссылочный тип
СсылкаДокумента = Документы.РеализацияТоваровУслуг.СоздатьСсылку();
Сообщить("Тип Документа (Ссылка): " + ПолучитьСтрокуТипаЗначения(СсылкаДокумента));
// 2. Объект метаданных
ОбъектСправочника = Справочники.Валюты.СоздатьЭлемент();
ОбъектСправочника.Наименование = "Тестовая валюта 1";
Сообщить("Тип Справочника (Объект): " + ПолучитьСтрокуТипаЗначения(ОбъектСправочника));
// 3. Простой тип: Число
ЧисловоеЗначение = 123.45;
Сообщить("Тип Числа: " + ПолучитьСтрокуТипаЗначения(ЧисловоеЗначение));
// 4. Простой тип: Дата
ДатаЗначение = ТекущаяДата();
Сообщить("Тип Даты: " + ПолучитьСтрокуТипаЗначения(ДатаЗначение));
// 5. Простой тип: Строка
СтроковоеЗначение = "Пример строки";
Сообщить("Тип Строки: " + ПолучитьСтрокуТипаЗначения(СтроковоеЗначение));
// 6. Тип Неопределено
НеопределеноЗначение = Неопределено;
Сообщить("Тип Неопределено: " + ПолучитьСтрокуТипаЗначения(НеопределеноЗначение));
// 7. Тип ИнформацияОбОшибке
Попытка
ДелениеНаНоль = 1 / 0;
Исключение
ИнфоОбОшибке = ИнформацияОбОшибке();
Сообщить("Тип ИнформацияОбОшибке: " + ПолучитьСтрокуТипаЗначения(ИнфоОбОшибке));
КонецПопытки;
// 8. Пустая ссылка
ПустаяСсылка = Справочники.Организации.ПустаяСсылка();
Сообщить("Тип Пустой ссылки: " + ПолучитьСтрокуТипаЗначения(ПустаяСсылка));
// 9. Массив
МассивЗначений = Новый Массив();
МассивЗначений.Добавить("Текст");
Сообщить("Тип Массива: " + ПолучитьСтрокуТипаЗначения(МассивЗначений));
// 10. Структура
СтруктураЗначений = Новый Структура("Ключ", "Значение");
Сообщить("Тип Структуры: " + ПолучитьСтрокуТипаЗначения(СтруктураЗначений));
// 11. ПеречислениеСсылка
ПеречислениеСсылка = Перечисления.ВидыКонтактнойИнформации.Телефон;
Сообщить("Тип Перечисления (Ссылка): " + ПолучитьСтрокуТипаЗначения(ПеречислениеСсылка));
// 12. ПеречислениеОбъект
ПеречислениеОбъект = Перечисления.ВидыКонтактнойИнформации.Телефон; // Объект перечисления не создается, ссылка и есть объект
Сообщить("Тип Перечисления (Объект): " + ПолучитьСтрокуТипаЗначения(ПеречислениеОбъект));
Этот комплексный подход позволяет нам сначала попытаться использовать наиболее точное и удобное решение (функция БСП, если она доступна), а затем последовательно переходить к другим методам. В случае отсутствия БСП, мы можем вручную сформировать строковое представление для типов метаданных, обрабатывать известные проблемные типы (как ИнформацияОбОшибке) и предоставлять базовое строковое представление в качестве последней инстанции. Для тестирования и отладки подобных алгоритмов непосредственно в режиме 1С:Предприятие подойдёт консоль кода для управляемых форм с поддержкой методов.
Мы подробно рассмотрели различные способы получения строкового представления типа по значению в 1С:Предприятии 8. От простых функций Строка(ТипЗнч()), которые имеют ограничения по точности и языковой зависимости, до использования XMLТипЗнч().ИмяТипа, предоставляющего стабильные англоязычные имена, но с нюансами для несериализуемых типов. Мы также проанализировали получение имен метаданных с помощью Метаданные.НайтиПоТипу() и, наконец, остановились на наиболее полном и удобном решении – функции БСП ОбщегоНазначения.СтроковоеПредставлениеТипа, которая максимально точно воспроизводит формат отладчика.
Выбор конкретного метода будет зависеть от нескольких факторов:
ОбщегоНазначения.СтроковоеПредставлениеТипа является оптимальным выбором.XMLТипЗнч()) возвращают Неопределено (например, ИнформацияОбОшибке)?Для создания универсального решения, которое будет надежно работать в различных условиях, рекомендуем использовать комплексный подход, комбинируя несколько методов и обрабатывая специфические случаи. Всегда анализируйте конкретные типы данных, с которыми вы работаете, чтобы выбрать оптимальное решение, соответствующее вашим требованиям.