Перенос данных между информационными базами — процедура ответственная, и завершающим этапом всегда должна быть сверка итогов. Самый распространенный способ контроля — сравнение оборотно-сальдовых ведомостей (ОСВ). Однако, когда данных много, ручная сверка становится невозможной. Рассмотрим, как автоматизировать этот процесс с помощью программирования, разберем типичные ошибки при использовании COM-соединения и выясним, какие инструменты помогут справиться с большими объемами информации.
Разберем ситуацию: у нас есть база-источник и база-приемник. Мы хотим получить данные из обеих баз, объединить их в одну таблицу, где суммы из источника будут с обратным знаком (минусом), сгруппировать по аналитике и вывести только те строки, где итог не равен нулю. Это отличная стратегия, но на практике программисты часто сталкиваются с тем, что запрос «не работает».
Проанализируем основную ошибку в подходе через COM-соединение. В языке запросов 1С невозможно передать результат внешнего запроса напрямую в предложение ИЗ, как это пытался сделать автор темы: ИЗ &ВнешнийЗапрос. Параметр запроса может быть только значением (числом, строкой, ссылкой) или таблицей значений, но для использования таблицы значений её необходимо предварительно загрузить в Менеджер временных таблиц.
Важный нюанс: при работе через COM-соединение таблица значений, полученная из внешней базы, является COM-объектом. Ее нельзя просто передать в локальный запрос. Сначала ее нужно «переложить» в родную таблицу значений текущей базы.
Рассмотрим алгоритм правильной организации сравнения. Мы выполним запрос в каждой базе отдельно, выгрузим результаты в локальные таблицы и объединим их для анализа.
Для начала подготовим структуру таблицы в текущей базе, которая будет хранить данные обеих систем:
ТЗ_Сравнение = Новый ТаблицаЗначений;
ТЗ_Сравнение.Колонки.Добавить("Счет", Новый ОписаниеТипов("Строка"));
ТЗ_Сравнение.Колонки.Добавить("Организация", Новый ОписаниеТипов("Строка"));
ТЗ_Сравнение.Колонки.Добавить("Субконто1", Новый ОписаниеТипов("Строка"));
ТЗ_Сравнение.Колонки.Добавить("Субконто2", Новый ОписаниеТипов("Строка"));
ТЗ_Сравнение.Колонки.Добавить("СуммаНачальныйОстаток", Новый ОписаниеТипов("Число"));
ТЗ_Сравнение.Колонки.Добавить("СуммаОборотДт", Новый ОписаниеТипов("Число"));
ТЗ_Сравнение.Колонки.Добавить("СуммаОборотКт", Новый ОписаниеТипов("Число"));
ТЗ_Сравнение.Колонки.Добавить("СуммаКонечныйОстаток", Новый ОписаниеТипов("Число"));
Затем мы подключаемся к внешней базе через V83.COMConnector, выполняем там запрос по регистру бухгалтерии и в цикле переносим данные в нашу ТЗ_Сравнение, умножая числовые показатели на -1. После этого аналогичным образом добавляем данные из текущей базы (уже с положительными знаками).
Рассмотрим, почему важно использовать строковые представления: При переносе данных ссылки на объекты (счета, справочники) в разных базах могут отличаться. Чтобы сопоставление прошло успешно, лучше использовать Код для счетов и Наименование (или УникальныйИдентификатор) для объектов субконто. Выражение ПРЕДСТАВЛЕНИЕ() в запросе поможет получить готовые строки для сравнения.
Если перенос данных осуществлялся с сохранением идентификаторов (например, через Конвертацию данных), то самым надежным способом будет сравнение по GUID. Разберем, как вытащить GUID из внешней базы через COM-соединение:
// Во внешней базе в запросе получаем Ссылку
Выборка = ВнешнийЗапрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
УникальныйИдентификаторСтрокой = Соединение.String(Выборка.Ссылка.UUID());
// Далее используем эту строку для поиска объекта в текущей базе
КонецЦикла;
Использование GUID позволяет избежать проблем, когда в разных базах есть объекты с одинаковыми наименованиями, но разным смыслом. Проанализируем ситуацию: если мы сравниваем ОСВ по счету 01 «Основные средства», то сравнение по наименованию может выдать ошибку, если в одной базе объект называется «Компьютер», а в другой — «Компьютер в сборе».
Для небольших баз или экспресс-проверки можно воспользоваться стандартным механизмом 1С. Сохраните оборотно-сальдовую ведомость из базы-источника и базы-приемника в файлы формата .mxl. Далее воспользуйтесь меню Файл — Сравнить файлы.
Однако, как было отмечено в обсуждении, этот метод имеет существенный недостаток — ограничение памяти. При сравнении файлов большого объема (десятки тысяч строк) 32-разрядное клиентское приложение может выдать ошибку «Недостаточно оперативной памяти». Это связано с тем, что механизм сравнения .mxl пытается построить графическую карту различий, что крайне ресурсозатратно.
Если задача сверки стоит часто или объемы данных колоссальны, рекомендуется использовать специализированные инструменты, такие как «Сравнитель таблиц» из состава Инструментов Разработчика (ИР). Посмотрим, в чем преимущество такого подхода:
Методика работы проста: выгружаем результат запроса из базы 1 в файл, затем из базы 2 в другой файл, и открываем их в сравнителе. Это намного эффективнее, чем пытаться написать сложный универсальный запрос «на все случаи жизни».
Если вы все же решили писать свое решение, проанализируем, как сделать его быстрым. Вместо того чтобы объединять таблицы в запросе (что требует много временной памяти сервера), можно использовать алгоритм слияния отсортированных списков в коде 1С:
КлючСвязи, в которую запишите конкатенацию строковых представлений всей аналитики.КлючСвязи.Такой подход позволит вам обрабатывать сотни тысяч строк проводок за считанные секунды, не перегружая сервер 1С сложными операциями ГРУППИРОВАТЬ ПО и ОБЪЕДИНИТЬ над внешними данными.
Подведем итог: для успешного сравнения обороток после переноса данных используйте либо выгрузку в промежуточные таблицы значений с последующим программным сравнением по текстовым ключам, либо специализированные инструменты разработчика, избегая тяжелых визуальных методов сравнения макетов .mxl.