Использование механизма OLE очень широко освещалось на этом ресурсе. Есть немало различных примеров его приложений. В частности, своей публикацией я не открою Америки. Но я решил по горячим следам выложить здесь обработку, избавившую от нервенной болезни нескольких уважаемых людей на уважаемом предприятии. Ибо... в своем неуемном стремлении достичь совершенства в учете, некоторые главные бухгалтеры иногда теряют осторожность и с попустительства таких же неосторожных программистов открывают документы за весьма длительный период времени на изменение. Что при этом случается, - не мне вам рассказывать. Все бухгалтерские итоги по плану счетов за годы (десятилетия) летят в тар-та-ра-ры.
Именно с такой ситуацией мне и пришлось недавно столкнуться. И речи не было о том, чтобы пытаться пригладить модули проведения документов за 15лет, чтобы они давали ожидаемые проводки (в различных периодах - отличающиеся). Предлагаемая здесь обработка довольно универсальна. Но решает весьма узкую задачу: из резервной базы данных извлекаются проводки документов и записываются в рабочую базу данных. На этом универсальность заканчивается. В процессе, - перед записью, - вы можете внести изменения в сами проводки. Кому-что требуется. Я только обозначил место в обработке, куда нужно втискивать эти дополнительные алгоритмы, удалив оттуда свой конкретный случай в массе не интересный.
Конфигурация, в которой мне пришлось решать эту задачу, эксплуатируется уже около 15 лет. Ее правили многие программисты, вносили множество изменений. И в ней осталось уже мало общего с типовой конфигурацией. Но я попытался аккуратно выделить все необходимые для обработки процедуры и функции. Часть из них должна быть размещена в глобальном модуле рабочей и резервной баз данных. Некоторые включил в состав внешней обработки. А есть и такие, которые (по моим ожиданиям) уже имеются и весьма давно в глобальном модуле конфигураций для бухгалтерского учета. Если я что-то упустил и у вас возникнут затруднения на сей счет (обработка не сработает), - пишите в комментариях. Я постараюсь выложить дополнительные алгоритмы.
Глобальный модуль показать/скрыть
Функция ПолучитьРеквизитыПроводок () Экспорт
Сп = СоздатьОбъект("СписокЗначений") ;
Для Инд = 1 По Метаданные.РеквизитПроводки() Цикл
сп.ДобавитьЗначение(Метаданные.РеквизитПроводки(Инд).Идентификатор);
КонецЦикла;
Возврат сп;
КонецФункции
Функция ПолучитьПроводки (Док, СДополнением=0) Экспорт
тбПроводки = СоздатьОбъект ("ТаблицаЗначений");
тбПроводки.НоваяКолонка("ДтСчет", "Счет");
тбПроводки.НоваяКолонка("ДтСубконто1");
тбПроводки.НоваяКолонка("ДтСубконто2");
тбПроводки.НоваяКолонка("ДтСубконто3");
тбПроводки.НоваяКолонка("КтСчет", "Счет");
тбПроводки.НоваяКолонка("КтСубконто1");
тбПроводки.НоваяКолонка("КтСубконто2");
тбПроводки.НоваяКолонка("КтСубконто3");
тбПроводки.НоваяКолонка("Сумма");
тбПроводки.НоваяКолонка("Валюта");
тбПроводки.НоваяКолонка("ВалСумма");
тбПроводки.НоваяКолонка("Количество");
Если СДополнением = 1
Тогда
сп = ПолучитьРеквизитыПроводок ();
КвоРеквизитов = сп.РазмерСписка();
Если КвоРеквизитов <> 0
Тогда
Для Инд = 1 По КвоРеквизитов Цикл
тбПроводки.НоваяКолонка(сп.ПолучитьЗначение(Инд));
КонецЦикла;
КонецЕсли;
тбПроводки.НоваяКолонка("Пометка");
КонецЕсли;
Если (Док.Проведен() = 0) И (Док.Вид()<> "Операция")
Тогда
Возврат тбПроводки;
КонецЕсли;
Опер = Док.Операция;
Опер.ВыбратьПроводки ();
Пока Опер.ПолучитьПроводку () = 1 Цикл
тбПроводки.НоваяСтрока();
тбПроводки.ДтСчет = Опер.Дебет.Счет;
тбПроводки.ДтСубконто1 = Опер.Дебет.Субконто(1);
тбПроводки.ДтСубконто2 = Опер.Дебет.Субконто(2);
тбПроводки.ДтСубконто3 = Опер.Дебет.Субконто(3);
тбПроводки.КтСчет = Опер.Кредит.Счет;
тбПроводки.КтСубконто1 = Опер.Кредит.Субконто(1);
тбПроводки.КтСубконто2 = Опер.Кредит.Субконто(2);
тбПроводки.КтСубконто3 = Опер.Кредит.Субконто(3);
тбПроводки.Сумма = Опер.Сумма;
тбПроводки.Валюта = Опер.Валюта;
тбПроводки.ВалСумма = Опер.ВалСумма;
тбПроводки.Количество = Опер.Количество;
Если СДополнением = 1
Тогда
Если КвоРеквизитов <> 0
Тогда
Для Инд = 1 По КвоРеквизитов Цикл
ИмяРеквизита = сп.ПолучитьЗначение(Инд);
тбПроводки.УстановитьЗначение(тбПроводки.КоличествоСтрок(), ИмяРеквизита, Опер.ПолучитьАтрибут(ИмяРеквизита));
КонецЦикла;
КонецЕсли;
тбПроводки.Пометка = 0;
КонецЕсли;
КонецЦикла;
Возврат тбПроводки;
КонецФункции
Функция ПроводкиВФайл (НомерДок, ДатаДок, ВидДок, ИмяФайла) Экспорт
Док = СоздатьОбъект("Документ");
Если Док.НайтиПоНомеру(НомерДок, ДатаДок, ВидДок) = 0
Тогда
Возврат 0;
КонецЕсли;
тб = ПолучитьПроводки(Док, 1);
ЗначениеВФайл(ИмяФайла, тб);
Возврат 1;
КонецФункции
Функция СводныеПроводкиВФайл (НомерДок, ДатаДок, ВидДок, ИмяФайла) Экспорт
Док = СоздатьОбъект("Документ");
Если Док.НайтиПоНомеру(НомерДок, ДатаДок, ВидДок) = 0
Тогда
Возврат 0;
КонецЕсли;
тб = ПолучитьПроводки(Док);
тб.Свернуть("ДтСчет,КтСчет","Количество,Сумма");
ЗначениеВФайл(ИмяФайла, тб);
Возврат 1;
КонецФункции
Функция СводныеПроводки (Док) Экспорт
тб = ПолучитьПроводки(Док);
тб.Свернуть("ДтСчет,КтСчет","Количество,Сумма");
Возврат тб;
КонецФункции
// Возвращает список объектов метаданных указанного типа
Функция глПолучитьСписокОбъектовМетаданных (ТипОбъекта) Экспорт
сп = СоздатьОбъект("СписокЗначений");
Если ТипОбъекта = "Константа"
Тогда
Для Инд = 1 По Метаданные.Константа() Цикл
сп.ДобавитьЗначение(Нрег (Метаданные.Константа(Инд).ПолныйИдентификатор()),
Метаданные.Константа(Инд).Идентификатор);
КонецЦикла;
ИначеЕсли ТипОбъекта = "Справочник"
Тогда
Для Инд = 1 По Метаданные.Справочник() Цикл
сп.ДобавитьЗначение(Нрег (Метаданные.Справочник(Инд).ПолныйИдентификатор()),
Метаданные.Справочник(Инд).Идентификатор);
КонецЦикла;
ИначеЕсли ТипОбъекта = "Документ"
Тогда
Для Инд = 1 По Метаданные.Документ() Цикл
сп.ДобавитьЗначение(Нрег (Метаданные.Документ(Инд).ПолныйИдентификатор()),
Метаданные.Документ(Инд).Идентификатор);
КонецЦикла;
ИначеЕсли ТипОбъекта = "Перечисление"
Тогда
Для Инд = 1 По Метаданные.Перечисление() Цикл
сп.ДобавитьЗначение(Нрег (Метаданные.Перечисление(Инд).ПолныйИдентификатор()),
Метаданные.Перечисление(Инд).Идентификатор);
КонецЦикла;
ИначеЕсли ТипОбъекта = "Отчет"
Тогда
Для Инд = 1 По Метаданные.Отчет() Цикл
сп.ДобавитьЗначение(Нрег (Метаданные.Отчет(Инд).ПолныйИдентификатор()),
Метаданные.Отчет(Инд).Идентификатор);
КонецЦикла;
ИначеЕсли ТипОбъекта = "Обработка"
Тогда
Для Инд = 1 По Метаданные.Обработка() Цикл
сп.ДобавитьЗначение(Нрег (Метаданные.Обработка(Инд).ПолныйИдентификатор()),
Метаданные.Обработка(Инд).Идентификатор);
КонецЦикла;
КонецЕсли;
Возврат сп;
КонецФункции
Функция ПолучитьЦвет(Красный = 0,Зеленый = 0,Синий = 0) Экспорт
// функция для формирования значения цвета из составляющих (RGB)
Возврат Макс(0,Синий)*65536+Макс(0,Зеленый)*256+Макс(0,Красный);
КонецФункции
Функция глНЕ (Оп) Экспорт
Если Оп = 0
Тогда
Возврат 1;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
// Устанавливает пометки элеметов списка
// Если Пометка = -1 - инверсия текущих пометок
Процедура ПометитьСписокЗначений (сп, Пометка=1) Экспорт
Для Инд = 1 По сп.РазмерСписка() Цикл
Если Пометка < 0
Тогда
сп.Пометка(Инд, глНЕ(сп.Пометка(Инд)));
Иначе
сп.Пометка(Инд, Пометка);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Во внешней обработке, проводки документа из резервной базы данных помещаются в таблицу значений ПроводкиДляВосстановления. Перед тем, как записать их в рабочую базу данных, можете подвергнуть их изменениям в процедуре ОбработатьПроводкиДокументаПередВосстановлением. Это если хочется. Для простого восстановления проводок никакие дополнительные действия не требуются.
Сравнить - по нажатию этой кнопки сравниваются проводки документов в рабочей и в резервной базах данных. Можно ограничиться сравнением сводных проводок, когда количество и сумма сворачиваются по счетам Дт и Кт. В таком случае, показывается результат этого сравнения для несовпадающих документов. Но далеко не всегда сравнение сводных проводок извлекает полный перечень документов, требующих восстановления. В процессе, можно сформировать список "кривых" документов.
Перепровести - перепроведение документов согласно полученного списка в рабочей базе данных.
Восстановить - восстановление проводок документов согласно полученного списка из резервной базы данных. Если флажок "Модифицировать проводки..." включен и вы прописали алгоритмы модификаций в процедуре ОбработатьПроводкиДокументаПередВосстановлением, - изменения будут выполнены перед записью.
Три маленьких кнопки над списками: первая устанавливает все флажки, вторая - сбрасывает, третья - инвертирует. Не думаю, что картинки у вас будут такие же, если вообще будут.