При переносе данных между базами 1С (особенно при переходе на новые конфигурации, такие как переход с «УПП 1.3» на «ERP 2» или с «Бухгалтерии 2.0» на «Бухгалтерию 3.0») разработчики и бухгалтеры часто сталкиваются с неприятной проблемой: после выполнения конвертации данных не все проводки ложатся корректно. Обнаруживаются расхождения в оборотно-сальдовой ведомости, а ручной поиск ошибок в базах объемом в сотни гигабайт превращается в бесконечную рутину.
В этой статье мы подробно разберем, как автоматизировать этот процесс, минимизировав затраты времени. Рассмотрим несколько эффективных сценариев: от готовых внешних утилит до написания собственного запроса через COM-соединение и использования встроенных инструментов платформы «1С:Предприятие».
Если вам необходимо сравнить стандартные бухгалтерские отчеты напрямую, не изобретая велосипед, отличным решением станет готовый специализированный инструмент. Одним из таких решений является расширение «Проверка проводок после переноса данных» (публикация на Инфостарт № 721345).
Рассмотрим, как работает данный подход:
COM-соединения.Этот способ идеален для бухгалтеров и аналитиков, так как не требует написания кода и работает в привычном интерфейсе стандартной ОСВ.
Если вам требуется более глубокий технический анализ, выходящий за рамки стандартных бухгалтерских отчетов, можно воспользоваться специализированной обработкой «Консоль сравнения данных».
Этот инструмент работает по следующему принципу:
Счет + Субконто1 + Субконто2).Когда мы имеем дело с базами огромного объема (например, более 200 ГБ), прямое COM-подключение в режиме реального времени может вызывать существенные задержки, блокировки таблиц в СУБД или даже аварийное завершение сеанса по таймауту. В такой ситуации применим проверенный «безкодовый» метод платформы.
Разберем этот алгоритм по шагам:
.mxl). Назовем его, например, OSV_Source.mxl.OSV_Receiver.mxl..mxl и нажмите кнопку «ОК».Платформа 1С выполнит посимвольное и построчное сравнение макетов. Все добавленные, удаленные строки, а также ячейки с изменившимися суммами будут подсвечены разными цветами. Метод работает молниеносно даже на слабых компьютерах и при терабайтных объемах данных, так как платформа сравнивает уже готовые текстово-графические представления, а не обращается к СУБД.
Если вам, как программисту, необходимо создать полностью автоматизированный регламент сверки или кастомный отчет, рассмотрим, как реализовать сравнение программно с использованием объекта V83.COMConnector.
Проанализируем технические нюансы, которые критически важно учесть при написании кода:
РегистрБухгалтерии.Хозрасчетный.Обороты или ОстаткиИОбороты). Никогда не делайте запросы к физической таблице движений (таблице значений субконто) на базах большого объема — это приведет к зависанию всей системы.Контрагенты, Договоры, Номенклатура) в базах могут различаться. Сравнивать ссылки напрямую через COM нельзя. Нам придется сопоставлять аналитику по естественным бизнес-ключам. Для контрагентов это связка ИНН + КПП, для договоров — Номер + Дата, для счетов — строковый код счета.Посмотрим на пример программной реализации такого сравнения:
// 1. Устанавливаем подключение к внешней информационной базе
Connector = Новый COMОбъект("V83.COMConnector");
СтрокаПодключения = "Srvr=""MyServer"";Ref=""OldBase"";Usr=""Admin"";Pwd=""123"";";
Попытка
ВнешняяБаза = Connector.Connect(СтрокаПодключения);
Исключение
ВызватьИсключение "Ошибка COM-подключения: " + ОписаниеОшибки();
КонецПопытки;
// 2. Создаем и выполняем запрос во внешней базе
ЗапросВнешний = ВнешняяБаза.NewObject("Запрос");
ЗапросВнешний.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОбороты.Счет.Код КАК СчетКод,
| ХозрасчетныйОбороты.СуммаОборотДт КАК СуммаДт,
| ХозрасчетныйОбороты.СуммаОборотКт КАК СуммаКт
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Обороты(&Начало, &Конец, , , , , , ) КАК ХозрасчетныйОбороты";
ЗапросВнешний.УстановитьПараметр("Начало", НачалоПериода);
ЗапросВнешний.УстановитьПараметр("Конец", КонецПериода);
ВнешняяТЗ = ЗапросВнешний.Выполнить().Выгрузить();
// 3. Переносим данные из COM-таблицы в локальную таблицу значений
// Это необходимо, так как типы данных COM-объектов нельзя напрямую использовать в локальном запросе
ЛокальнаяТЗ = Новый ТаблицаЗначений;
ЛокальнаяТЗ.Колонки.Добавить("СчетКод", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(20)));
ЛокальнаяТЗ.Колонки.Добавить("СуммаДт", Новый ОписаниеТипов("Число", , Новый КвалификаторыЧисла(15, 2)));
ЛокальнаяТЗ.Колонки.Добавить("СуммаКт", Новый ОписаниеТипов("Число", , Новый КвалификаторыЧисла(15, 2)));
Для Каждого СтрокаCOM Из ВнешняяТЗ Цикл
НоваяСтрока = ЛокальнаяТЗ.Добавить();
НоваяСтрока.СчетКод = СтрокаCOM.СчетКод;
НоваяСтрока.СуммаДт = СтрокаCOM.СуммаДт;
НоваяСтрока.СуммаКт = СтрокаCOM.СуммаКт;
КонецЦикла;
// 4. Помещаем локальную таблицу в запрос текущей базы и сравниваем
ЗапросЛокальный = Новый Запрос;
ЗапросЛокальный.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
ЗапросЛокальный.УстановитьПараметр("ТаблицаВнешняя", ЛокальнаяТЗ);
ЗапросЛокальный.УстановитьПараметр("Начало", НачалоПериода);
ЗапросЛокальный.УстановитьПараметр("Конец", КонецПериода);
ЗапросЛокальный.Текст =
"ВЫБРАТЬ
| Тв.СчетКод КАК СчетКод,
| Тв.СуммаДт КАК СуммаДт_Внешняя,
| Тв.СуммаКт КАК СуммаКт_Внешняя
|ПОМЕСТИТЬ Вт_ВнешниеДанные
|ИЗ
| &ТаблицаВнешняя КАК Тв
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ХозрасчетныйОбороты.Счет.Код КАК СчетКод,
| ХозрасчетныйОбороты.СуммаОборотДт КАК СуммаДт_Локальная,
| ХозрасчетныйОбороты.СуммаОборотКт КАК СуммаКт_Локальная
|ПОМЕСТИТЬ Вт_ЛокальныеДанные
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Обороты(&Начало, &Конец, , , , , , ) КАК ХозрасчетныйОбороты
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ЕСТЬNULL(Лок.СчетКод, Внеш.СчетКод) КАК СчетКод,
| ЕСТЬNULL(Лок.СуммаДт_Локальная, 0) КАК ЛокДт,
| ЕСТЬNULL(Внеш.СуммаДт_Внешняя, 0) КАК ВнешДт,
| ЕСТЬNULL(Лок.СуммаКт_Локальная, 0) КАК ЛокКт,
| ЕСТЬNULL(Внеш.СуммаКт_Внешняя, 0) КАК ВнешКт
|ИЗ
| Вт_ЛокальныеДанные КАК Лок
| ПОЛНОЕ СОЕДИНЕНИЕ Вт_ВнешниеДанные КАК Внеш
| ПО Лок.СчетКод = Внеш.СчетКод
|ГДЕ
| ЕСТЬNULL(Лок.СуммаДт_Локальная, 0) <> ЕСТЬNULL(Внеш.СуммаДт_Внешняя, 0)
| ИЛИ ЕСТЬNULL(Лок.СуммаКт_Локальная, 0) <> ЕСТЬNULL(Внеш.СуммаКт_Внешняя, 0)";
РезультатСравнения = ЗапросЛокальный.Выполнить().Выгрузить();
// РезультатСравнения теперь содержит только те счета, по которым есть расхождения сумм
Этот подход можно легко масштабировать: добавить выгрузку субконто (приведя их к строковому представлению, например Наименование или Код), отборы по конкретным организациям или выгрузку результатов напрямую в файл Excel для дальнейшего разбора на стороне пользователей.
Таким образом, мы детально разобрали, как решить задачу сверки данных. Выбор конкретного метода зависит от ваших технических возможностей, объема базы данных и регулярности выполнения этой задачи.