При переходе на платформу 1С с языков низкого уровня, таких как C++, многие привычные концепции меняются. Одной из частых задач является создание универсальных инструментов для экспорта данных. Рассмотрим ситуацию, когда нам необходимо разработать алгоритм, который позволит пользователю выбрать абсолютно любой документ в системе и сохранить его содержимое в текстовый файл, не прибегая к стандартным механизмам сериализации (JSON или XML). Это требует глубокого понимания того, как устроены метаданные в 1С и как работает объектная модель платформы.
Первым шагом в нашей задаче является предоставление пользователю интерфейса для выбора конкретного документа. В 1С документы имеют разные типы, и для создания универсального кода нам нужно использовать коллекции метаданных. Разберем, как это реализовать на управляемых формах, учитывая разделение контекста на клиент и сервер.
Для вызова диалога выбора используется метод ВвестиЗначение или его асинхронный аналог ПоказатьВводЗначения. Основная сложность здесь заключается в формировании третьего параметра — типа данных, которые мы хотим выбирать. Проанализируем, как получить описание всех типов документов в системе:
&НаСервере
Функция ПолучитьОписаниеТиповВсехДокументов()
// Метод ТипВсеСсылки() возвращает ОписаниеТипов,
// включающее ссылки на все документы конфигурации
Возврат Документы.ТипВсеСсылки();
КонецФункции
&НаКлиенте
Процедура ВыбратьДокумент(Команда)
Перем ВыбраннаяСсылка;
ОписаниеТиповДок = ПолучитьОписаниеТиповВсехДокументов();
// Вызываем диалог выбора
Если ВвестиЗначение(ВыбраннаяСсылка, "Выберите документ для выгрузки", ОписаниеТиповДок) Тогда
// Далее следует логика обработки ссылки
ВыгрузитьДокументВТекст(ВыбраннаяСсылка);
КонецЕсли;
КонецПроцедуры
Важно помнить, что объект Документы доступен только на сервере. Поэтому мы сначала обращаемся к серверной функции, чтобы получить ОписаниеТипов, и только потом передаем его в клиентский метод выбора.
После того как ссылка на документ получена, нам нужно «разобрать» его на составляющие. В 1С каждый объект имеет метод Метаданные(), который возвращает описание его структуры (аналог RTTI в C++). Выясним, из чего состоит типичный документ и как программно обойти все его поля.
Любой документ в 1С включает в себя несколько коллекций:
Рассмотрим универсальный алгоритм обхода этих коллекций. Обратите внимание, что для получения данных табличных частей на стороне сервера необходимо преобразовать ссылку в объект методом ПолучитьОбъект().
&НаСервере
Процедура ВыгрузитьДокументВТекст(ДокСсылка)
// Получаем объект документа для доступа к табличным частям
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ОбъектМетаданных = ДокСсылка.Метаданные();
// Создаем поток для записи текста
Запись = Новый ЗаписьТекста("C:\Export\document.txt", КодировкаТекста.UTF8);
Запись.ЗаписатьСтроку("--- Заголовок документа ---");
// 1. Обход стандартных реквизитов
Для Каждого РеквизитМетаданные Из ОбъектМетаданных.СтандартныеРеквизиты Цикл
ИмяПоля = РеквизитМетаданные.Имя;
ЗначениеПоля = ДокОбъект[ИмяПоля];
Запись.ЗаписатьСтроку(ИмяПоля + ": " + Строка(ЗначениеПоля));
КонецЦикла;
// 2. Обход обычных реквизитов
Для Каждого РеквизитМетаданные Из ОбъектМетаданных.Реквизиты Цикл
ИмяПоля = РеквизитМетаданные.Имя;
ЗначениеПоля = ДокОбъект[ИмяПоля];
Запись.ЗаписатьСтроку(ИмяПоля + ": " + Строка(ЗначениеПоля));
КонецЦикла;
// 3. Обход табличных частей
Для Каждого ТЧМетаданные Из ОбъектМетаданных.ТабличныеЧасти Цикл
Запись.ЗаписатьСтроку("== Табличная часть: " + ТЧМетаданные.Имя + " ==");
ТЧДанные = ДокОбъект[ТЧМетаданные.Имя];
Для Каждого СтрокаТЧ Из ТЧДанные Цикл
СтрокаДляЗаписи = "";
Для Каждого РеквизитТЧ Из ТЧМетаданные.Реквизиты Цикл
СтрокаДляЗаписи = СтрокаДляЗаписи + РеквизитТЧ.Имя + "=" + Строка(СтрокаТЧ[РеквизитТЧ.Имя]) + "; ";
КонецЦикла;
Запись.ЗаписатьСтроку(СтрокаДляЗаписи);
КонецЦикла;
КонецЦикла;
Запись.Закрыть();
КонецПроцедуры
Проанализируем важные нюансы, которые могут возникнуть при записи данных в TXT. В 1С метод Строка() выполняет стандартное представление объекта, но для качественного текстового файла этого может быть недостаточно.
Форматирование чисел и дат: Если вы планируете в дальнейшем считывать этот файл программно, используйте функцию Формат(). Например, чтобы число 1000 не превратилось в "1 000" (с неразрывным пробелом), используйте параметр "ЧГ=0".
Использование ЗаписиТекста: В примере выше мы использовали объект ЗаписьТекста. Это критически важно для производительности. В отличие от конкатенации строк через оператор +, ЗаписьТекста работает напрямую с потоком файла, что исключает избыточное выделение оперативной памяти при работе с большими документами.
Доступ через квадратные скобки: В 1С реализован удобный механизм доступа к свойствам объекта по имени в строковом виде: Объект["ИмяСвойства"]. Это позволяет нам писать универсальные циклы, получая имена полей из метаданных и подставляя их для извлечения значений.
Таким образом, мы построили универсальную систему, которая не зависит от конкретного вида документа (будь то "Реализация товаров" или "Прием на работу"). Мы используем метаданные для определения структуры, программные методы 1С для выбора ссылки и объектные коллекции для обхода данных. Этот подход полностью соответствует принципам гибкой разработки и позволяет легко масштабировать решение на любые объекты конфигурации.