Перенос данных между информационными базами — одна из самых частых задач разработчика 1С. Обычно для этого используются стандартные форматы XML или JSON, однако в учебных целях или при специфических требованиях заказчика может возникнуть необходимость реализовать этот механизм через обычный текстовый файл (TXT). В данной статье мы подробно разберем, как создать универсальную обработку, которая позволит выгрузить любой документ и загрузить его копию, используя только возможности платформы 1С и работу с метаданными.
Первая сложность, с которой сталкиваются новички — как дать пользователю возможность выбрать абсолютно любой тип документа из существующих в конфигурации. Программное заполнение списка выбора именами документов из метаданных (как предлагалось в некоторых сообщениях форума) — путь трудоемкий и не всегда удобный. Разберем более изящное решение.
Для того чтобы поле на форме принимало ссылку на любой документ, необходимо правильно настроить реквизит обработки. В дереве конфигурации для созданной обработки добавим реквизит ДокументОбъект (или просто Документ). В поле Тип вместо выбора конкретного документа (например, «Реализация товаров и услуг») следует выбрать тип ЛюбаяСсылка или сформировать составной тип данных, отметив галочками все необходимые документы.
После того как реквизит создан, просто перетащим его на форму. Платформа 1С автоматически создаст поле ввода, при нажатии на которое пользователю сначала будет предложено выбрать тип документа, а затем — конкретный экземпляр из списка. Это избавляет нас от написания лишнего кода для формирования списков выбора.
Поскольку нам запрещено использовать ЗначениеВСтрокуВнутр и уникальные идентификаторы (UUID), наша задача — превратить объект документа в структурированный текст. Проанализируем, из чего состоит документ: это заголовок (тип документа), основные реквизиты и табличные части. Для программного обхода структуры документа мы будем использовать объект Метаданные.
Рассмотрим пошагово, как реализовать выгрузку данных:
Метаданные().Для Каждого переберем коллекцию Реквизиты метаданных документа. Для каждого реквизита получим его имя и значение из выбранного документа.ТабличныеЧасти. Внутри каждой ТЧ пройдемся по всем строкам и колонкам.ЗаписьТекста для последовательного сохранения данных.Пример кода для выгрузки основных реквизитов:
// Создаем объект для записи
Текст = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.UTF8);
// Записываем тип документа, чтобы знать, что создавать при загрузке
МетаданныеДока = ВыбранныйДокумент.Метаданные();
Текст.ЗаписатьСтроку("[ТипОбъекта]" + МетаданныеДока.Имя);
// Выгружаем основные реквизиты
Текст.ЗаписатьСтроку("[Реквизиты]");
Для Каждого РеквизитМетаданных Из МетаданныеДока.Реквизиты Цикл
ИмяРеквизита = РеквизитМетаданных.Имя;
Значение = ВыбранныйДокумент[ИмяРеквизита];
// Преобразуем значение в строку (для дат и чисел используем спецформат)
СтрокаЗначения = ФормироватьСтрокуИзЗначения(Значение);
Текст.ЗаписатьСтроку(ИмяРеквизита + "=" + СтрокаЗначения);
КонецЦикла;
Чтобы файл был пригоден для загрузки, необходимо продумать систему маркеров. Мы рекомендуем использовать квадратные скобки для обозначения разделов. Например:
[Header] — общая информация о документе.[Attributes] — список реквизитов шапки.[Table_Товары] — начало данных конкретной табличной части.[EndTable] — маркер окончания табличной части.Важный нюанс: согласно условию, номер документа выгружать не нужно, так как он должен присваиваться автоматически (быть уникальным). Однако дату выгружать необходимо, так как она часто определяет период нумерации.
Самый сложный момент в этой задаче — передача ссылок на справочники (например, Склад, Контрагент, Номенклатура). Так как UUID использовать нельзя, единственным надежным способом является поиск по уникальным полям самого справочника — Коду или Наименованию.
Рассмотрим ситуацию: в документе есть реквизит «Склад». При выгрузке нам нужно записать не просто «Склад», а тип справочника и его наименование. Например: Склад|Справочник.Склады|Основной склад. При загрузке нам придется парсить эту строку и использовать метод НайтиПоНаименованию().
Проанализируем пример функции для обработки ссылок:
Функция ФормироватьСтрокуИзЗначения(Значение)
Если ТипЗнч(Значение) = Тип("Число") Тогда
Возврат "Ч:" + Строка(Значение);
ИначеЕсли ТипЗнч(Значение) = Тип("Дата") Тогда
Возврат "Д:" + Формат(Значение, "ДФ=ггггММддЧЧммсс");
ИначеЕсли ТипЗнч(Значение) = Тип("Булево") Тогда
Возврат "Б:" + ?(Значение, "1", "0");
ИначеЕсли Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
// Для ссылок сохраняем тип и наименование (или код)
Возврат "С:" + Значение.Метаданные().Имя + "|" + Строка(Значение);
Иначе
Возврат "Т:" + Строка(Значение);
КонецЕсли;
КонецФункции
Процесс загрузки — это обратное преобразование текста в объект 1С. Выясним последовательность действий:
ЧтениеТекста. Читаем файл построчно в цикле Пока.Документы[ИмяДокумента].СоздатьДокумент().Добавить() и заполняем её колонки.НовыйОбъект.Записать().Посмотрим, как выглядит поиск ссылки при загрузке:
// Пример парсинга строки ссылки "С:Склады|Основной склад"
Если Лево(ЗначениеИзФайла, 2) = "С:" Тогда
ДанныеСсылки = Сред(ЗначениеИзФайла, 3); // "Склады|Основной склад"
ПозицияРазделителя = Найти(ДанныеСсылки, "|");
ИмяСправочника = Лев(ДанныеСсылки, ПозицияРазделителя - 1);
Наименование = Сред(ДанныеСсылки, ПозицияРазделителя + 1);
// Ищем объект в базе
НайденнаяСсылка = Справочники[ИмяСправочника].НайтиПоНаименованию(Наименование);
Объект[ИмяРеквизита] = НайденнаяСсылка;
КонецЕсли;
Нужно понимать, что поиск по наименованию — это «костыль», который может привести к ошибкам, если в базе есть два элемента с одинаковым именем. Именно поэтому в реальных задачах 1С всегда использует УникальныйИдентификатор. Однако в рамках данного учебного задания такой подход позволяет лучше понять механику работы со ссылочными типами данных и строковыми функциями.
Также важно помнить о стандартных реквизитах. Помимо тех реквизитов, что вы создали сами, у документа есть системные поля: Дата, Проведен, ПометкаУдаления. Их также следует включить в цикл обхода, обращаясь к коллекции МетаданныеДокумента.СтандартныеРеквизиты или просто прописав их обработку вручную.
Использование этого метода разработки позволит вам не только решить текущую задачу, но и глубже изучить дерево метаданных 1С, что является критически важным навыком для любого профессионального разработчика.