Как перенести движения документов из поврежденной базы 1С 7.7 один в один

Программист 1С v7.7 Управленческий учет Промышленность, строительство и АПК
← На главную

При работе с базами данных 1С:Предприятие 7.7, особенно в условиях интенсивного производства и многопользовательского доступа, нередко возникают ситуации, когда база становится «глючной». Основные симптомы: несовпадение данных в отчетах, отсутствие движений у проведенных документов или расхождение между данными в табличных частях и записями в регистрах. Это происходит из-за аварийных завершений работы (вылетов), правок модулей проведения «задним числом» или физического повреждения таблиц базы данных.

В данной статье мы разберем комплексный подход к переносу данных из такой базы в чистую, с гарантией сохранения всех движений, чтобы отчеты в исходной и целевой базах полностью совпадали. Рассмотрим несколько стратегий: от программной модификации модулей до прямого воздействия на SQL-индексы.

Причина проблемы: неконсистентность данных

Прежде чем приступать к переносу, проанализируем ситуацию. В 1С 7.7 запись документа и запись его движений — это связанные, но технически разные процессы. Если в момент проведения документа происходит сбой, запись в журнале _1SJOURN может получить флаг CLOSED = 1 (проведен), но соответствующие записи в таблицах движений регистров (таблицы с префиксом RA) могут не создаться или создаться частично. Кроме того, со временем алгоритмы проведения меняются, и простое перепроведение документа в новой базе даст совершенно иной результат.

Решение 1: Использование универсального документа-регистратора

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

Создадим в конфигурации-приемнике документ УниверсальныйДвигательРегистров. У этого документа не будет никакой сложной бизнес-логики. Его задача — просто записывать данные в регистры, которые мы ему передадим.

  1. В структуру документа добавим неограниченную табличную часть (или несколько, по количеству регистров).
  2. Реквизиты табличной части должны соответствовать всем измерениям, ресурсам и реквизитам ваших регистров.
  3. В модуле проведения документа УниверсальныйДвигательРегистров пропишем простой цикл:

Процедура ОбработкаПроведения()
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        // Пример для регистра "ОстаткиТоваров"
        Регистр.ОстаткиТоваров.Номенклатура = Номенклатура;
        Регистр.ОстаткиТоваров.Склад = Склад;
        Регистр.ОстаткиТоваров.Количество = Количество;
        Регистр.ОстаткиТоваров.Приход(); 
    КонецЦикла;
КонецПроцедуры

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

Решение 2: Модификация модулей проведения через таблицу значений (ТЗ)

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

Шаг 1. Экспорт движений. Напишем обработку в исходной базе, которая обходит документы за период, считывает их движения через объект Регистр и сохраняет их во внешний файл (например, в формате .txt или .dbf) в виде сериализованной таблицы значений.

Шаг 2. Подготовка Глобального модуля. В новой базе добавим в Глобальный модуль экспортную функцию, которая будет искать сохраненные движения для конкретного документа:


Функция ПопробоватьВосстановитьДвижения(Конт) Экспорт
    // Конт - контекст документа
    ИмяФайла = "C:\Dump\" + Конт.ТекущийДокумент().Идентификатор() + ".dat";
    Если ФС.СуществуетФайл(ИмяФайла) = 1 Тогда
        // Загружаем ТЗ из файла и выполняем движения
        // ... логика заполнения регистров из ТЗ ...
        Возврат 1; // Движения восстановлены
    КонецЕсли;
    Возврат 0; // Файла нет, нужно штатное проведение
КонецФункции

Шаг 3. Внедрение в модули проведения. В начало каждого модуля проведения документов, которые мы переносим, добавим одну строку:


Процедура ОбработкаПроведения()
    Если ПопробоватьВосстановитьДвижения(Контекст) = 1 Тогда
        Возврат; // Выходим, так как движения уже сделаны из дампа
    КонецЕсли;
    
    // Далее идет штатный код проведения
    // ...
КонецПроцедуры

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

Решение 3: Устранение «глюков» на уровне SQL-сервера

Если база находится на MS SQL Server и повреждения носят структурный характер (ошибки индексов, на которые ругается ТиИ), стандартное тестирование и исправление может не помочь или даже уничтожить данные. Проанализируем ситуацию с индексами. Часто 1С 7.7 некорректно обновляет индексы, что приводит к «неразрешенным ссылкам».

Вместо ТиИ попробуем выполнить полную реорганизацию индексов средствами SQL. Выясним причину ошибок, выполнив следующий скрипт в SQL Query Analyzer:


DECLARE @MyTable varchar(32)
DECLARE @MyIndex varchar(32)
DECLARE MyCursor CURSOR FOR
SELECT o.name, i.name
FROM sysobjects o INNER JOIN sysindexes i ON o.id = i.id
WHERE (o.xtype = 'U') AND (INDEXPROPERTY(i.id, i.name, 'isStatistics') = 0) AND (i.dpages > 0)
ORDER BY o.name, i.indid
OPEN MyCursor
FETCH NEXT FROM MyCursor INTO @MyTable, @MyIndex
WHILE @@FETCH_STATUS=0
BEGIN
    PRINT 'Реорганизация индекса '+@MyIndex+' из таблицы '+@MyTable
    DBCC DBREINDEX (@MyTable,@MyIndex)
    FETCH NEXT FROM MyCursor INTO @MyTable, @MyIndex
END
CLOSE MyCursor
DEALLOCATE MyCursor

Важно: Перед выполнением этого скрипта необходимо выгнать всех пользователей и сделать бэкап. Этот метод часто «оживляет» базу, после чего стандартный перенос через Конвертацию Данных или УРБД проходит без ошибок.

Особенности переноса реквизитов типа «СписокЗначений»

Автор темы столкнулся с проблемой реквизита ПартияПуск, данные в котором искажались при переносе через КД. В 1С 7.7 сложные структуры в строковых реквизитах часто хранятся с использованием системных разделителей. При переносе такие строки могут обрезаться или некорректно кодироваться.

Чтобы избежать этого, при выгрузке используем функцию ЗначениеВСтрокуВнутр(), а при загрузке — ЗначениеИзСтрокиВнутр(). Это гарантирует, что внутренний формат 1С (включая ссылки на объекты) будет передан без искажений. Если же ссылка в исходной базе «битая» (указывает на несуществующий объект), в новой базе после ЗначениеИзСтрокиВнутр() вы получите пустую ссылку, что гораздо безопаснее для системы, чем «битый» GUID.

Метод «Обрезания» (свертки) вместо полного переноса

Если база повреждена слишком сильно, рассмотрим вариант свертки. Посмотрим на этот процесс не как на удаление данных, а как на создание новой базы на основе итогов.

  1. Создаем копию «глючной» базы.
  2. Фиксируем остатки на начало нужного периода (например, 2021 год).
  3. Используем обработку свертки, которая формирует документы ВводОстатков.
  4. Удаляем все документы прошлых периодов.
  5. В новой базе проводим ТиИ. Поскольку данных стало меньше, шансы на успешное исправление ошибок выше.

Этот путь часто оказывается быстрее, чем попытки «вылечить» десятилетнюю историю транзакций с накопленными ошибками.

Резюме: Перенос движений из «глючной» базы 1С 7.7 требует индивидуального подхода. Самым надежным методом является программный экспорт движений в ТЗ и их последующий импорт в новой базе через модифицированный ОбработкаПроведения() или универсальный документ-регистратор. Это единственный способ обеспечить 100% совпадение управленческой отчетности после переезда.

← На главную