1С. Частичное восстановление данных из копии ИБ

Периодически возникает необходимость выполнить частичное восстановление данных. Восстановить ИБ из резервной копии нельзя, как и допустить потери других изменений.

Например в рабочей ИБ в справочнике Номенклатура, пользователи в части элементов откорректировали значение реквизита Артикул, но изменения эти не корректны.

В рабочей ИБ элементы справочника Номенклатура выглядят так:

Восстановить ИБ из резервной копии нельзя, как и выполнить загрузку элементов справочника Номенклатура из копии ИБ обработкой ВыгрузкаЗагрузкаДанныхXML т.к. изменения обнаружены не сразу, а потери других изменений допускать нельзя.

В копии ИБ элементы справочника Номенклатура выглядят так:

В данной ситуации могут помочь два метода глобального контекста ЗначениеВФайл() и ЗначениеИзфайла(). Первый из них выполняет сохранение любых сериализуемых значений в файл, а второй восстанавливает из файла.

Прелесть в том, что ссылка является сериализуемой и никаких дополнительных манипуляции для сохранения и восстановления не потребуется.

По сути необходимо написать обработку, которая в копии ИБ сформирует коллекцию ссылок справочника Номенклатура со значениями реквизита Артикула и сохранит получившееся в файл. После эта же обработка в ИБ, восстановит заполненные данные из файла и выполнит запись правильных значений реквизита Артикул в справочнике Номенклатура.

 

Создадим новую обработку и назовем ее ЧастичноеВосстановлениеДанныхИзКопииИБ.

Сбор данных

В обработке создаем табличную часть Товары, в нее добавим реквизиты:

  1. Номенклатура. тип СправочникСсылка.Номенклатура;
  2. Артикул. тип Строка(15). Исходя из типа одноименного реквизита справочника Номенклатура.

Создаем форму обработки, на форму добавляем табличную часть Товары и ее реквизиты. Дополнительно в таблицу формы вытащим подчиненный реквизит Артикул из реквизита Номенклатура и установим ему синоним Номенклатура.Артикул. Это необходимо для вывода значения реквизита Артикул из элемента справочника Номенклатура в текущей ИБ.

В форме добавляем команду ЗаполнитьДанные, создаем ее обработчик, в котором заполняем табличную часть Товары исключив элементы с признаком ЭтоГруппа. Не забудь перенести команду на форму)

&НаКлиенте
Процедура ЗаполнитьДанные(Команда)
    
    ЗаполнитьДанныеНаСервере();
    
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьДанныеНаСервере()

    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    Номенклатура.Ссылка КАК Номенклатура,
    |    Номенклатура.Артикул КАК Артикул
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    НЕ Номенклатура.ЭтоГруппа";
                
    Объект.Товары.Загрузить(Запрос.Выполнить().Выгрузить());
    
КонецПроцедуры

При выполнении команды табличная часть будет заполнена

Сохранение данных в файл

Теперь необходимо полученные данные сохранить в файл. Для этого создаем серверную функцию СохранитьДанныеВФайлНаСервере(), которая будет помещать файл с нашими данными во временное хранилище и возвращать его адрес.

Описываем сохранение данных в файл методом ЗначениеВФайл(), затем помещаем файл во временное хранилище и адрес временного хранилища будет результатом работы функции.

&НаСервере
Функция СохранитьДанныеВФайлНаСервере()

    ИмяФайла = ПолучитьИмяВременногоФайла();
    
    ЗначениеВФайл(ИмяФайла, Объект.Товары.Выгрузить());
    
    Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайла));
    
    Возврат Адрес;
    
КонецФункции

На форме добавляем команду СохранитьДанныеВФайл, создаем ее клиентский обработчик.

Получаем адрес временного хранилища с данными файла нашей выгрузки из функции СохранитьДанныеВФайлНаСервере(). Затем получим файл из временного хранилища при помощи метода НачатьПолучениеФайлаССервера().

&НаКлиенте
Процедура СохранитьДанныеВФайл(Команда)
    
    Адрес = СохранитьДанныеВФайлНаСервере();
        
    ПараметрыДиалога = Новый ПараметрыДиалогаПолученияФайлов;
    ПараметрыДиалога.Заголовок        = "Сохранение выгружаемых данных";
    ПараметрыДиалога.ВыборКаталога    = Ложь;
    
    НачатьПолучениеФайлаССервера(Адрес, "Выгруженные данные.tmp", ПараметрыДиалога);  
    

При выполнении команды появится диалог с предложением сохранить или открыть полученный файл.

Выбираем сохранение и в появившемся системном диалоге сохранения файла указываем путь сохранения.

Разработка функционала для ИБ-донора завершена, переходим к функционалу для рабочей ИБ.

Загрузка данных из файла

Создадим команду ЗагрузитьДанныеИзФайла, в обработчике опишем диалог выбора файла и описание оповещения, которые передадим в метод НачатьПомещениеФайла().

&НаКлиенте
Процедура ЗагрузитьДанныеИзФайла(Команда)
                
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    
    Диалог.Фильтр                        = "(*.tmp)|*.tmp";
    Диалог.ПроверятьСуществованиеФайла    = Истина;
    Диалог.МножественныйВыбор            = Ложь;
        
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтаФорма);
    
    НачатьПомещениеФайла(Оповещение, , Диалог, Истина, УникальныйИдентификатор); 
        
КонецПроцедуры

После выбора файла вызовется процедура указанная в описании оповещения, в которой необходимо обработать результат. Просто проверим выбран ли файл, и если все в порядке, то вызовем процедуру загрузки данных в ТЧ с передачей в нее адреса временного хранилища выбранного файла.

&НаКлиенте    
Процедура ПослеВыбораФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт 
    
    Если Не Результат Тогда 
        Возврат;
    КонецЕсли;    
        
    ВосстановитьДанныеИзФайлаНаСервере(Адрес);
        
КонецПроцедуры

Теперь опишем процедуру получения файла из временного хранилища, получение данных из файла методом ЗначениеИзФайла() и загрузку их в ТЧ.

&НаСервере
Процедура ВосстановитьДанныеИзФайлаНаСервере(Адрес)
    
    ИмяФайла = ПолучитьИмяВременногоФайла();

    ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
    ДвоичныеДанные.Записать(ИмяФайла);
    
    Объект.Товары.Загрузить(ЗначениеИзФайла(ИмяФайла));
        
КонецПроцедуры

При выполнении команды табличная часть будет заполнена

Запись данных

Остается написать процедуру для записи восстановленных в ТЧ. Обойдем ТЧ получая объект номенклатуры, и при необходимости будем восстанавливать артикул и записывать объект.

С большой вероятностью, есть элементы артикул в которых не изменился, такие элементы перезаписывать не будем.

Так же возможна ситуация, когда в ИБ удалили номенклатуру, которая есть в файле. Учтем и ее проверив на заполненность наименование объекта, наименование обязательно к заполнению.

Если интересна информация по теме «Объект не найден», то разбирал вариант поиска в статье 1C. Поиск «Объект не найден» в регистре и удаление.

&НаСервере
Процедура ЗаписатьДанныеНаСервере()

    Для Каждого СтрокаТовары Из Объект.Товары Цикл 
        
        НоменклатураОбъект            = СтрокаТовары.Номенклатура.ПолучитьОбъект();
        
        Если НоменклатураОбъект = Неопределено Тогда 
            Продолжить; // Пропустим удаленные объекты
        КонецЕсли;    
        
        Если НоменклатураОбъект.Артикул = СтрокаТовары.Артикул Тогда 
            Продолжить; // Пропускаем не измененные артикулы
        КонецЕсли;    
                
        НоменклатураОбъект.Артикул    = СтрокаТовары.Артикул;
        
        НоменклатураОбъект.ОбменДанными.Загрузка = Истина;
        
        Попытка
            НоменклатураОбъект.Записать();
        Исключение
            
            ТекстСообщения = СтрШаблон("Не удалось записать элемент %1. Описание ошибки %2", НоменклатураОбъект.Наименование, ОписаниеОшибки());
            
            Сообщение        = Новый СообщениеПользователю;
            Сообщение.Текст    = ТекстСообщения;
            Сообщение.Сообщить();
            
        КонецПопытки;
        
    КонецЦикла;    
    
КонецПроцедуры

После выполнения команды  получаем восстановленные артикулы в справочнике Номенклатура. Задача решена.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *