В практике сопровождения баз 1С:Предприятие 7.7 (особенно на платформе MS SQL Server) встречается критическая ситуация: при попытке открыть конкретный документ программа аварийно закрывается либо ничего не происходит, а при повторной попытке интерактивного открытия появляется системное предупреждение «Запись заблокирована». При этом точка останова в процедуре ПриОткрытии() модуля формы не срабатывает, встроенный отладчик вообще не перехватывает управление, а типовое «Тестирование и исправление ИБ» не выявляет проблем.
Разберем детально, почему возникает подобное поведение платформы, как локализовать сбойный реквизит и какими способами можно восстановить нормальную работу с документами.
Проанализируем механику работы платформы 1С 7.7 при открытии формы объекта:
_1SJOURN и соответствующей таблице шапки DH*.ПриОткрытии()), ядро платформы выполняет связывание реквизитов документа с элементами управления диалога (MFC/OLE-контролами).DH* хранятся некорректные бинарные данные, нарушена длина строк, присутствуют непредусмотренные нулевые символы или содержатся ссылки с недействительными идентификаторами типов (например, после восстановления файла метаданных 1cv7.md или правки ID объектов сторонними утилитами), механизм связывания вызывает системное исключение Access Violation.При этом программное чтение реквизитов через ПолучитьАтрибут() или построение запросов может отрабатывать без ошибок, так как они считывают сырые данные без попытки привязать их к диалоговой форме.
Если проблема проявилась после аварийного восстановления файла конфигурации или изменения идентификаторов объектов, выполним пошаговую проверку соответствия базы данных и метаданных.
Разберем по шагам порядок диагностики:
IDDOCDEF документа в таблице общего журнала _1SJOURN со значением в словаре базы данных 1cv7.dds.
-- Проверка идентификаторов документов в журнале
SELECT IDDOC, IDDOCDEF, DATE_TIME_IDDOC, DOCNO
FROM _1SJOURN
WHERE IDDOC = ' 7GML1 ';
1cv7.md, создадим один тестовый документ проблемного вида и сверим значения колонок IDJOURNAL и IDDOCDEF с рабочей базой.1cv7.dds найдем описание таблицы шапки проблемного документа (например, DH1234) и сравним типы и имена колонок SP* с фактической структурой таблицы на сервере SQL. Особенное внимание обратим на поля составного (неопределенного) типа, для которых формируются дополнительные служебные колонки (SP*_TYPE, SP*_RTYPE).Рассмотрим практические методы восстановления открытия документов в зависимости от характера повреждения данных.
Если форма падает из-за некорректного значения в одном из реквизитов шапки, локализуем сбойное поле на копии базы данных. Для этого последовательно очищаем подозрительные колонки в таблице шапки DH<ID> для проблемного IDDOC:
-- Пример поочередного сброса реквизитов шапки для поиска виновника
-- Очистка строковых реквизитов:
UPDATE DH1234
SET SP1235 = ''
WHERE IDDOC = ' 7GML1 ';
-- Очистка ссылочных реквизитов (значение пустой ссылки):
UPDATE DH1234
SET SP1236 = ' 0 '
WHERE IDDOC = ' 7GML1 ';
-- Очистка числовых реквизитов:
UPDATE DH1234
SET SP1237 = 0
WHERE IDDOC = ' 7GML1 ';
После каждого шага пробуем открыть документ в режиме «1С:Предприятие». Как только форма успешно откроется — проблемный реквизит найден, и его значение можно перевыбрать интерактивно или перезаполнить корректными данными.
Если чтение реквизитов через встроенный язык работает штатно, а ручное исправление SQL-запросами затруднено, восстановим документ программно:
DH* для конкретного IDDOC:
DELETE FROM DH1234 WHERE IDDOC = ' 7GML1 ';
Записать() (при необходимости временно отключив проведение в модуле документа). Платформа сформирует в таблице DH* абсолютно чистую и валидную структуру записи.Посмотрим на пример обработки для переноса данных проблемного документа в новый экземпляр:
// Пример программного чтения и перезаписи документа
ДокСтарый = СоздатьОбъект("Документ.СписаниеТМЦ");
Если ДокСтарый.НайтиДокумент(ВыбДок) = 1 Тогда
ДокНовый = СоздатьОбъект("Документ.СписаниеТМЦ");
ДокНовый.Новый();
ДокНовый.ДатаДок = ДокСтарый.ДатаДок;
ДокНовый.Склад = ДокСтарый.Склад;
// Переносим табличную часть
ДокСтарый.ВыбратьСтроки();
Пока ДокСтарый.ПолучитьСтроку() = 1 Цикл
ДокНовый.НоваяСтрока();
ДокНовый.Номенклатура = ДокСтарый.Номенклатура;
ДокНовый.Количество = ДокСтарый.Количество;
КонецЦикла;
ДокНовый.Записать();
Сообщить("Создан документ-дубль: " + ДокНовый.ТекущийДокумент());
КонецЕсли;
Если проблема носит массовый характер для определенного вида документов после ручной правки метаданных:
ВременныйРеквизит с типом Число).DH* на уровне базы данных.Такая процедура заставляет платформу пересоздать SQL-структуру таблицы и корректно инициализировать все системные смещения данных в соответствии с текущим файлом 1cv7.md.