При разработке механизмов обмена данными часто возникают ситуации, когда стандартные средства сериализации (XML или JSON) использовать нельзя по условиям задачи. В таких случаях программисту приходится вручную обрабатывать метаданные объектов, работать со ссылочными типами и табличными частями. Разберем подробно, как решить основные проблемы, возникающие при создании универсальной обработки выгрузки/загрузки данных в текстовый файл .txt.
Одной из первых трудностей, с которыми сталкиваются разработчики, является ошибка «Поле объекта не обнаружено» при попытке записи значения в реквизит созданного объекта. Проанализируем типичный код записи: НовыйДок[НазвРекв] = ЗначРекв. Ошибка часто кроется в том, что ЗначРекв, прочитанное из файла, является строкой, в то время как реквизит в конфигурации имеет ссылочный тип (например, СправочникСсылка.Валюты).
Разберем ситуацию: если мы пытаемся записать в поле ВалютаДокумента строку "руб.", 1С не сможет автоматически преобразовать ее в ссылку. Выясним причину: система требует объект строго определенного типа. Чтобы это исправить, нам необходимо перед присвоением найти ссылку в базе данных по строковому представлению или коду.
Если условиями задачи запрещено использовать УникальныйИдентификатор, нам необходимо реализовать поиск по «естественным ключам». Рассмотрим, как это сделать для разных типов данных:
Перечисления[ИмяПеречисления][ИмяЗначения].Посмотрим на пример кода для выгрузки типа реквизита и его значения, чтобы потом иметь возможность восстановить ссылку:
// Получаем полное имя типа для записи в файл
ТипРеквизита = Реквизит.Тип.Типы()[0];
ИмяТипаМетаданных = Метаданные.НайтиПоТипу(ТипРеквизита).ПолноеИмя();
// Выгружаем: ИмяРеквизита | ПолноеИмяТипа | Значение (Код или Наименование)
ТекстФайла.ЗаписатьСтроку(Реквизит.Имя + "::" + ИмяТипаМетаданных + "::" + Значение);
При обратной загрузке проанализируем ситуацию: нам нужно распарсить строку и найти ссылку. Например, если тип — Справочник.ФизическиеЛица, мы будем использовать метод НайтиПоНаименованию или НайтиПоКоду.
Работа с табличными частями требует итерации не только по строкам, но и по колонкам. Часто начинающие разработчики пытаются использовать метод Выгрузить(), но не знают, как получить имена колонок программно. Рассмотрим правильный способ обхода табличной части документа:
Для каждого ТабличнаяЧасть Из ДокументОбъект.Метаданные().ТабличныеЧасти Цикл
ТекстФайла.ЗаписатьСтроку("НачалоТЧ::" + ТабличнаяЧасть.Имя);
ТаблицаДанных = ДокументОбъект[ТабличнаяЧасть.Имя].Выгрузить();
Для каждого СтрокаТЧ Из ТаблицаДанных Цикл
СтрокаДляЗаписи = "";
Для каждого Колонка Из ТаблицаДанных.Колонки Цикл
ЗначениеКолонки = СтрокаТЧ[Колонка.Имя];
// Здесь должна быть логика преобразования ссылки в строку
СтрокаДляЗаписи = СтрокаДляЗаписи + ЗначениеКолонки + "|";
КонецЦикла;
ТекстФайла.ЗаписатьСтроку(СтрокаДляЗаписи);
КонецЦикла;
ТекстФайла.ЗаписатьСтроку("КонецТЧ");
КонецЦикла;
Важный момент: при записи колонок обязательно сохраняйте их порядок или записывайте имена колонок в заголовке секции таблицы в файле, чтобы при загрузке данные не «съехали».
В современных конфигурациях, таких как «Управление торговлей 11.4», структура данных значительно сложнее. Рассмотрим пример создания Контрагента. Выясним причину, почему недостаточно просто создать элемент справочника Контрагенты. В УТ 11 разделены управленческие сущности (Партнеры) и юридические (Контрагенты).
Разберем по шагам алгоритм создания связки:
Справочники.Партнеры. Именно здесь указываются общие данные: бизнес-регион, группа доступа и т.д.Справочники.Контрагенты, где в реквизите Партнер указываем ссылку на созданного ранее партнера.Заполнение адресов — одна из самых трудоемких задач. В 1С используется XML-структура для хранения полей адреса. Рассмотрим пример программного заполнения контактной информации для Партнера:
// Добавляем строку в табличную часть КонтактнаяИнформация
НоваяСтрокаКИ = ОбъектПартнер.КонтактнаяИнформация.Добавить();
НоваяСтрокаКИ.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес;
НоваяСтрокаКИ.Вид = Справочники.ВидыКонтактнойИнформации.АдресПартнера; // Или адрес доставки
НоваяСтрокаКИ.Представление = "г. Москва, ул. Ленина, д. 1";
// Для корректного отображения в УТ 11 рекомендуется заполнять ЗначенияПолей в формате XML
// В идеале следует использовать функции БСП:
// НоваяСтрокаКИ.ЗначенияПолей = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВXML(СтруктураПолейАдреса);
При загрузке банковских счетов из внешних источников (например, Excel), часто доступен только БИК банка. Разберем, как правильно создать банковский счет контрагента:
Проанализируем ситуацию: в справочнике БанковскиеСчетаКонтрагентов есть реквизит Банк, который ссылается на справочник КлассификаторБанков. Чтобы поле не осталось пустым, выполним поиск банка по БИК:
БИК = "044525225";
СсылкаНаБанк = Справочники.КлассификаторБанков.НайтиПоКоду(БИК);
Если СсылкаНаБанк.Пустая() Тогда
// Если банка нет в классификаторе, его нужно создать или загрузить
Сообщить("Банк с БИК " + БИК + " не найден в классификаторе!");
КонецЕсли;
НовыйСчет = Справочники.БанковскиеСчетаКонтрагентов.СоздатьЭлемент();
НовыйСчет.Владелец = КонтрагентСсылка;
НовыйСчет.НомерСчета = "40702810XXXXXXXXXXXX";
НовыйСчет.Банк = СсылкаНаБанк;
НовыйСчет.Записать();
При переносе документов «любого типа» важно учитывать связанные сущности. Например, счет-фактура не является реквизитом документа «Реализация товаров и услуг», а ссылается на него. Чтобы найти счет-фактуру при выгрузке, воспользуемся запросом:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СФ.Ссылка КАК Ссылка
|ИЗ
| Документ.СчетФактураВыданный КАК СФ
|ГДЕ
| СФ.ДокументОснование = &Основание";
Запрос.УстановитьПараметр("Основание", СсылкаНаДокумент);
Результат = Запрос.Выполнить();
// Если результат не пустой, выгружаем найденную счет-фактуру
Таким образом, мы проанализировали основные этапы создания кастомного обмена данными. Главный секрет успеха в таких задачах — внимательная работа с типами данных 1С и понимание структуры метаданных конкретной конфигурации.