При переносе данных между базами 1С 7.7 (особенно при использовании старых механизмов обмена или кастомных правил) разработчики часто сталкиваются с неприятной ситуацией: документы успешно загружаются в базу-приемник вместе со своими проводками и движениями по регистрам, однако сами документы в журнале отображаются как непроведенные (без характерной галочки или красного значка).
Попытка решить проблему «в лоб» через стандартное перепроведение документов часто приводит к плачевным результатам. Алгоритмы проведения в базе-приемнике могут отличаться от базы-источника, из-за чего оригинальные проводки «плывут», заменяются неверными данными или вовсе задваиваются. Нам же необходимо сохранить проводки в том виде, в котором они были выгружены, но при этом заставить систему считать документ проведенным. Разберемся, как устроена эта механика на уровне базы данных 1С 7.7, и как решить эту задачу безопасно.
Для начала проанализируем, как платформа 1С:Предприятие 7.7 понимает, проведен документ или нет. В отличие от версии 8.x, где у документа есть явное булево свойство Проведен, в «семерке» все устроено на уровне битовых масок в общей таблице журналов.
Каждый документ в системе записывается в несколько таблиц базы данных:
_1SJOURN) — общий журнал документов. Здесь хранится дата, время, номер, тип документа, а также статус его проведения.Связующим звеном между всеми этими таблицами выступает уникальный девятисимвольный идентификатор документа — IDDOC.
За статус проведения документа отвечает числовое поле CLOSED в таблице 1SJOURN. Это поле представляет собой битовую маску, где каждый бит отвечает за свое состояние:
Складывая эти биты, платформа получает итоговое состояние документа. Рассмотрим типичные значения поля CLOSED:
0 — документ записан, но не проведен (движений нет).3 (1 + 2) — документ проведен в оперативном учете (актуально для торговли).5 (1 + 4) — документ проведен в бухгалтерском учете (актуально для бухгалтерии).7 (1 + 2 + 4) — документ проведен одновременно по регистрам оперативного учета и по бухгалтерии (комплексная конфигурация).4 — документ не проведен, но физически в таблице 1SENTRY есть его проводки. Именно эта ситуация и произошла у автора темы на форуме!Следовательно, наша задача — изменить значение поля CLOSED с 4 (или 0, если проводки были залиты отдельно) на 5 (для бухгалтерской базы) либо на 7 (для комплексной).
Если ваша база данных 1С 7.7 работает на Microsoft SQL Server, лучшим и самым быстрым решением будет использование прямого запроса к СУБД с помощью популярной компоненты 1С++. Это позволит мгновенно обновить статус проведения тысяч документов без их физической перезаписи.
Проанализируем пример кода на встроенном языке 1С 7.7:
// Создаем объект для работы с прямыми запросами
ЗапросSQL = СоздатьОбъект("ODBCRecordset");
// Формируем текст запроса для обновления поля CLOSED
// Устанавливаем значение 5 (проведен + есть проводки) для конкретного документа
ТекстЗапроса = "
|UPDATE _1SJOURN
|SET CLOSED = 5
|WHERE IDDOC = :ВыбДокумент
|";
// Подготавливаем параметр (передаем ссылку на документ)
ЗапросSQL.УстановитьТекстовыйПараметр("ВыбДокумент", ВыбранныйДокумент);
// Выполняем обновление в транзакции
ЗапросSQL.Выполнить(ТекстЗапроса);
Предупреждение("Статус проведения документа успешно изменен!");
Если вам нужно обновить сразу группу документов (например, за определенный период по конкретному виду документа), вы можете модернизировать запрос, добавив условия по дате (поле DATE_TIME_IDDOC) или по идентификатору вида документа (поле IDDOCDEF).
Если база данных файловая (хранится в формате DBF/CDX), мы можем использовать стандартный встроенный объект 1С 7.7 XBase для работы с базой на физическом уровне.
Важное предупреждение: При редактировании файлов базы данных напрямую программным путем обязательно делайте резервную копию! Также критически важно открывать DBF-файл совместно с его индексным файлом CDX, иначе индексы «слетят», и база потребует полного переиндексирования.
Рассмотрим пошагово, как реализовать этот алгоритм:
Процедура ИзменитьФлагПроведенияВDBF(ВыбДок)
// Получаем внутренний 9-значный IDDOC документа
ВнутреннийID = ЗначениеВСтрокуВнутр(ВыбДок);
// Извлекаем чистый IDDOC (9 символов начиная с 11-й позиции в системной строке)
IDDOC = Сред(ВнутреннийID, 11, 9);
ПутьКБазе = КаталогИБ();
ФайлDBF = СоздатьОбъект("XBase");
// Открываем таблицу журналов вместе с индексами
ФайлDBF.ОткрытьФайл(ПутьКБазе + "1SJOURN.dbf", ПутьКБазе + "1SJOURN.cdx");
Если ФайлDBF.Открыт() = 0 Тогда
Сообщить("Не удалось открыть файл 1SJOURN.dbf!", "!");
Возврат;
КонецЕсли;
// Устанавливаем индексный порядок по IDDOC для быстрого поиска
ФайлDBF.ТекущийИндекс("IDDOC");
// Ищем запись нашего документа
Если ФайлDBF.Найти(IDDOC, 0) = 1 Тогда
// Получаем текущее значение битовой маски
ТекущееЗначение = ФайлDBF.CLOSED;
// Проверяем, есть ли уже проводки (битовое значение 4)
// Если флаг проведения (1) отсутствует, добавляем его
Если (ТекущееЗначение % 2) = 0 Тогда
НовоеЗначение = ТекущееЗначение + 1; // Устанавливаем бит проведения
// Записываем новое значение в файл
ФайлDBF.CLOSED = НовоеЗначение;
ФайлDBF.Записать();
Сообщить("Документ " + ВыбДок + " успешно помечен как проведенный!");
Иначе
Сообщить("Документ уже имеет признак проведения.");
EndIf;
Иначе
Сообщить("Документ не найден в таблице 1SJOURN!", "!");
КонецЕсли;
// Обязательно закрываем файл для освобождения блокировок
ФайлDBF.ЗакрытьФайл();
КонецПроцедуры
Существует еще один изящный способ, не требующий прямого вмешательства в СУБД. Мы можем временно отключить генерацию движений в самом коде документа.
Для этого в модуле документа в процедуре ОбработкаПроведения() мы можем прописать проверку специального флага (например, значения глобальной переменной или константы «РежимЗагрузкиДанных»):
Процедура ОбработкаПроведения()
// Если включен режим переноса данных, мы не формируем проводки заново
Если ГлРежимПереносаБезПроведения = 1 Тогда
// Просто выходим из процедуры.
// Платформа сама установит флаг проведения документу,
// но новые проводки генерироваться не будут.
Возврат;
КонецЕсли;
// ... Здесь идет ваш стандартный код проведения документа ...
// ВыбратьСтрокиДокумента();
// Пока ПолучитьСтроку() = 1 Цикл
// Регистр.Продажи.Движение...
// КонецЦикла;
КонецПроцедуры
Важная деталь: Этот способ сработает только в том случае, если в свойствах данного документа в Конфигураторе выключена опция «Автоматическое удаление движений» (флаг автоудаления). Если этот флаг включен, то перед заходом в процедуру ОбработкаПроведения() сама платформа 1С автоматически очистит все существующие проводки этого документа. В таком случае этот способ использовать нельзя, и вам придется прибегнуть к Решению 1 или Решению 2.
В компоненте «Бухгалтерский учет» 1С 7.7 существует штатная фича — возможность отключения проводок у конкретной операции. Если вы откроете Журнал операций и нажмете клавишу F8 на клавиатуре (или выберете соответствующий пункт меню), проводки документа станут «выключенными».
Внешне это выглядит так: проводки у документа физически существуют и видны в форме операции, но их значки становятся серыми, и они полностью исключаются из бухгалтерских итогов (оборотно-сальдовая ведомость их не видит). Убедитесь, что проблема не вызвана случайным нажатием этой горячей клавиши при просмотре документов в базе-приемнике.