Как отредактировать движения документов в 1С 7.7


Редактирование движений документов информационной базы 1С:Предприятие, версии 7.7, так как это возможно в версии 8.Х. В том числе и обработка движений выборки документов программно.

В 1С 8 — вечном источнике моего вдохновения ))), есть возможность через свойство «Движения» обратиться к набору движений документа напрямую из любого модуля. Что дает довольно много возможностей, в том числе, редактирование движений документа «вручную». Это там — вообще, стандартная «вещь». К сожалению, в 1С 7.7, это не так. И в данной статье, мы постараемся с этим что-то сделать.

О классе «ВыполняемыйМодуль» компоненты 1С++ я уже говорил [ссылка], когда описывал добавление дополнительных модулей в конфигурацию 1С 7.7.

Создадим новую конфигурацию информационной базы. Зададим справочник «Клиенты», документ «Продажа» с реквизитами в шапке «Клиент» — тип «Справочник.Клиенты» и «СуммаДокумента» — тип «Число». Документ будет проводится по оборотному регистру накопления «Продажи», в котором следует определить измерение «Клиент» — тип «Справочник.Клиенты» и ресурс «Сумма».

Также, добавим общий журнал «ОбщийЖурнал», на форме списка которого зададим кнопку «Провести» с определением обработчика в модуле формы:

//*******************************************
// запись движений
 
Процедура Провести()
 
    Документы = СоздатьОбъект("Документ");
 
    Документы.НайтиДокумент(ТекущийДокумент);
 
    // передача управления в модуль документа
 
    Документы.Провести(, РучноеФормированиеДвижений());
 
КонецПроцедуры

Процедура «РучноеФормированиеДвижений» служит для эмуляции создания, нового, уже отредактированного вручную набора движений текущего документа журнала. Представим, что в некоторой диалоговой форме, мы отредактировали вручную движения документа и теперь хотим записать изменения.

//*******************************************
// формирование движений отредактированных вручную
 
Функция РучноеФормированиеДвижений()
 
    // движения документа в xml-формате
 
    хмлПарсер = СоздатьОбъект("Msxml2.DOMDocument.6.0");
 
    хмлДвиженияДокумента = хмлПарсер
        .appendChild(хмлПарсер.createElement("ДвиженияДокумента"));
 
    // определение набора движений [по регистру]
 
    хмлНаборДвижений = хмлДвиженияДокумента
        .appendChild(хмлПарсер.createElement("Продажи"));
 
    // запись набора   
  
    хмлЗапись = хмлНаборДвижений.appendChild(хмлПарсер.createElement("п"));
 
    // реквизиты записи
 
    хмлРеквизит = хмлЗапись.appendChild(хмлПарсер.createElement("Направление"));
 
    хмлРеквизит.text = 0;
 
    хмлРеквизит = хмлЗапись.appendChild(хмлПарсер.createElement("Клиент"));
 
    хмлРеквизит.text = ЗначениеВСтрокуВнутр(ТекущийДокумент.Клиент);
 
    хмлРеквизит = хмлЗапись.appendChild(хмлПарсер.createElement("Сумма"));
 
    хмлРеквизит.text = 2000;   
 
    Возврат хмлПарсер;
 
КонецФункции

Сам набор движений, как видите, представлен в xml-формате. Что очень удобно для разного рода манипуляций с этими данными. В модуле документа «Продажа», в обработке проведения, передадим управление глобальной процедуре проведения с передачей, в качестве параметра, контекста этого самого документа.

//*******************************************
// вызов процедуры проведения документа
 
Процедура ОбработкаПроведения(Параметр)
 
    // передача управления в глобальный модуль
 
    глОбработкаПроведения(Контекст, Параметр);
 
КонецПроцедуры

«глОбработкаПроведения» — это и есть та самая универсальная процедура записи движений документа. Она позволяет нам корректировать движения документа в журнале. Определить документ корректировки записей регистров, наподобие того, как это сделано в некоторых конфигурациях на платформе 1С 8. И, как я покажу дальше, не только это. Текст процедуры представлен ниже:

//*******************************************
// глобальная процедура проведения документа
 
Процедура глОбработкаПроведения(Конт, ДвиженияДокумента) Экспорт   
 
    хмлДвиженияДокумента = ДвиженияДокумента
        .getElementsByTagName("ДвиженияДокумента").item(0);
 
    // обход наборов движений       
 
    хмлВыбНаборЗаписей = хмлДвиженияДокумента.childNodes;
   
    Для й = 0 По хмлВыбНаборЗаписей.length - 1 Цикл      
 
        хмлНаборЗаписей = хмлВыбНаборЗаписей.item(й);
 
        ВыпМодуль = СоздатьОбъект("ВыполняемыйМодуль");    
 
        // назначение контекста модуля документа       
 
        ВыпМодуль.НазначитьКонтекст(Конт);      
 
        // объявление регистра накопления
 
        ВыпМодуль.УстановитьМодуль("Рег = Регистр."
            + хмлНаборЗаписей.tagName);    
 
        ВыпМодуль.КомпилироватьМодуль();
 
        ВыпМодуль.ВыполнитьМодуль();   
 
        // передача регистра в контекст глобального модуля
 
        Рег =  ВыпМодуль.Рег;
 
        // обход записей набора
 
        хмлВыбЗаписей = хмлНаборЗаписей.childNodes;
 
        Для ж = 0 По хмлВыбЗаписей.length - 1 Цикл 
 
            хмлЗапись = хмлВыбЗаписей.item(ж);
 
            Направление = 0;  
 
            // обход реквизитов записи
 
            хмлВыбРеквизитов = хмлЗапись.childNodes;
 
            Для к = 0 По хмлВыбРеквизитов.length - 1 Цикл
 
                хмлРеквизит = хмлВыбРеквизитов.item(к);
 
                Ид = хмлРеквизит.tagName;
 
                // формирование движений
 
                Если Ид = "Направление" Тогда 
 
                    Направление = хмлРеквизит.text;
 
                Иначе
 
                    Значение = хмлРеквизит.text;
 
                    // преобразование значения ссылочного типа
 
                    Значение = ?(Лев(Значение, 1) <> "{", Значение,
                        ЗначениеИзСтрокиВнутр(Значение));
 
                    Рег.УстановитьАтрибут(Ид, Значение);
 
                КонецЕсли;
 
            КонецЦикла;
 
            Если Направление = 0 Тогда
 
                Рег.ДвижениеВыполнить();
 
            ИначеЕсли Направление =    1 Тогда
 
                Рег.ДвижениеПриходВыполнить();
 
            Иначе
 
                Рег.ДвижениеРасходВыполнить();
 
            КонецЕсли;
 
        КонецЦикла;   
 
    КонецЦикла;   
 
КонецПроцедуры

Естественно, для использования компоненты 1С++, ее нужно подключить:

//*******************************************
// подключение внешней компоненты 1С++
 
ИмяФайлаКомпоненты = "1cpp.dll";
 
Если ЗагрузитьВнешнююКомпоненту(ИмяФайлаКомпоненты) = 0 Тогда
 
    // исключительное сообщение:
 
    Сообщить("Ошибка при загрузке внешней компоненты: "
        + ИмяФайлаКомпоненты, "!");
 
КонецЕсли;

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