Как выполнить бухгалтерский запрос в 1С 7.7 через COM/OLE?

Программист 1С v7.7 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При интеграции устаревших систем на платформе 1С:Предприятие 7.7 с современными конфигурациями 1С 8.х или внешними аналитическими инструментами (например, Excel, сторонними базами данных) разработчики часто сталкиваются с необходимостью получения оперативных данных бухгалтерского учета. Наиболее простым и доступным способом решения этой задачи является использование механизма OLE Automation.

В этой статье мы подробно рассмотрим, как правильно настроить OLE-соединение с базой 1С 7.7, инициализировать объект бухгалтерских итогов, выполнить запрос и избежать распространенных ошибок, связанных с производительностью и совместимостью типов данных.

Шаг 1. Выбор правильного ProgID для подключения

Перед тем как начать писать код подключения, необходимо определиться с идентификатором OLE-сервера (ProgID). В зависимости от используемой версии платформы и лицензионного ключа защиты, 1С 7.7 предоставляет несколько различных идентификаторов:

  1. V1CEnterprise.Application — универсальный (трехкомпонентный) ProgID, который автоматически определяет и запускает нужную версию платформы. Рекомендуется использовать именно его для большинства задач.
  2. V77.Application — предназначен для запуска сетевой или комплексной версии платформы.
  3. V77S.Application — запускает версию платформы, предназначенную для работы с базой данных MS SQL Server.
  4. V77L.Application — запускает локальную (однопользовательскую) версию 1С.
  5. V77M.Application — используется для запуска многопользовательской версии.

Если вы укажете ProgID, не соответствующий установленной лицензии (например, попытаетесь использовать V77.Application на сервере, где развернута исключительно SQL-версия), операционная система вернет ошибку отсутствия ключа защиты или не сможет создать объект.

Шаг 2. Инициализация OLE-соединения и создание объекта бухгалтерских итогов

Рассмотрим базовый шаблон кода для подключения к базе данных 1С 7.7 и инициализации механизма бухгалтерских итогов. Мы используем метод Initialize, который принимает три параметра: запущенный контекст (обычно передается RMTrade), командную строку подключения и флаг показа заставки.


// Определяем параметры подключения
ПутьКБазе = "C:\DB\TradeAndAccounting\";
Пользователь = "Администратор";
Пароль = "12345";

// Формируем командную строку запуска
ПараметрыЗапуска = "/D""" + ПутьКБазе + """ /N" + Пользователь + " /P" + Пароль;

// Создаем COM-объект подключения
Попытка
    V77 = Новый COMОбъект("V1CEnterprise.Application");
Исключение
    Сообщить("Не удалось запустить OLE-сервер 1С 7.7: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

// Инициализируем соединение без показа заставки
ФлагЗапуска = "NO_SPLASH_SHOW";
РезультатПодключения = V77.Initialize(V77.RMTrade, ПараметрыЗапуска, ФлагЗапуска);

Если РезультатПодключения = 0 Тогда
    Сообщить("Ошибка авторизации или неверно указан путь к базе данных!");
    Возврат;
КонецЕсли;

Сообщить("Соединение успешно установлено!");

После того как соединение установлено, мы можем обращаться к метаданным и создавать встроенные объекты 1С 7.7 через метод CreateObject. Создадим объект для работы с бухгалтерскими итогами:


// Создаем OLE-объект БухгалтерскиеИтоги
ОлеБИ = V77.CreateObject("БухгалтерскиеИтоги");

Шаг 3. Нюансы настройки фильтров и вызова методов

Проанализируем классический пример настройки фильтров субконто и выполнения запроса. В родной среде 1С 7.7 разработчики привыкли опускать необязательные параметры методов, разделяя их запятыми. Например:


// Так пишется код внутри базы 1С 7.7:
БИ.ИспользоватьСубконто(ВидыСубконто.Контрагенты, , 1);

Важное предупреждение: При работе через внешнее COM/OLE-соединение (особенно при вызове из 1С 8.х или скриптов VBScript/VBA) пропускать параметры через запятые категорически не рекомендуется! Это часто приводит к возникновению исключений вида «Типы не совпадают» или полной неработоспособности метода.

Чтобы избежать ошибок совместимости типов, используйте один из двух надежных подходов:

Вариант А. Использование строковых идентификаторов видов субконто

Метод ИспользоватьСубконто в 1С 7.7 умеет принимать строковое название вида субконто вместо ссылки на объект метаданных. Это существенно упрощает код и снижает вероятность ошибок:


// Передаем вид субконто строкой, явно указывая все параметры
ОлеБИ.ИспользоватьСубконто("Контрагенты", , 1, 1);

Вариант Б. Передача пустых значений через EvalExpr

Если вам все же необходимо передать пустой параметр, но внешняя среда не позволяет сделать это простым пропуском, можно воспользоваться функцией EvalExpr OLE-сервера для получения пустого значения или выполнения выражения на стороне 7.7:


// Явное получение объекта вида субконто через контекст OLE
ВидСубконтоКонтрагенты = V77.ВидыСубконто.Контрагенты;
// Передаем параметры без пропусков, заменяя их на пустые значения или используя явную логику
ОлеБИ.ИспользоватьСубконто(ВидСубконтоКонтрагенты, , 1);

Теперь выполним сам бухгалтерский запрос по счету 62.1 ("Расчеты с покупателями и заказчиками") за определенный период:


ДатаНачала = '20230101'; // 1 января 2023 года
ДатаКонца  = '20230131'; // 31 января 2023 года
КодСчета   = "62.1";

// Выполняем запрос
РезультатЗапроса = ОлеБИ.ВыполнитьЗапрос(ДатаНачала, ДатаКонца, КодСчета);

Если РезультатЗапроса = 0 Тогда
    Сообщить("Не удалось выполнить запрос к бухгалтерским итогам!");
КонецЕсли;

Шаг 4. Оптимизация производительности: критическая проблема маршалинга

Разберем типичную архитектурную ошибку, которую совершают многие программисты при переносе данных из 1С 7.7 через OLE. Получив выборку бухгалтерских итогов, разработчики начинают стандартный обход в цикле:


// Крайне медленный способ обхода данных!
Пока ОлеБИ.ПолучитьСубконто(1) = 1 Цикл
    КонтрагентНаименование = ОлеБИ.Субконто(1).Наименование;
    СальдоДебет = ОлеБИ.СКД();
    // Обработка полученных данных...
КонецЦикла;

Выясним причину низкой скорости работы такого кода. Каждая итерация цикла, каждое обращение к свойствам Субконто(1) или методам получения остатков (СКД(), СКК()) инициирует межпроцессный вызов (маршалинг данных). Если в вашей выборке содержатся тысячи контрагентов, программа будет выполнять миллионы сетевых/процессных переключений контекста. На практике такой простой отчет может формироваться часами.

Как решить проблему производительности? Рассмотрим два эффективных метода:

  1. Пакетная сериализация через временный файл или строку.

    Вместо построчного чтения данных на стороне клиента, напишите небольшую экспортную процедуру в Глобальном модуле базы 1С 7.7 (или передайте динамический исполняемый код через метод ExecuteBatch). Эта процедура должна локально на максимальной скорости обойти бухгалтерские итоги, собрать все данные в одну структурированную строку (например, в формате XML или JSON) и вернуть её OLE-клиенту за один-единственный вызов. На стороне клиента останется лишь быстро распарсить полученную строку.

  2. Прямые SQL-запросы к таблицам итогов.

    Если база данных 1С 7.7 развернута на MS SQL Server, забудьте про OLE для тяжелых выборок. Используйте прямое ADO-соединение к таблицам остатков и оборотов (например, таблице 1SBKTTL для общих итогов или 1SBKTTLC для итогов по субконто). Совместно с внешней компонентой 1С++ это позволит получать любые бухгалтерские выборки за доли секунды.

Шаг 5. Понимание разницы между COM и OLE в контексте 1С 7.7

Часто на форумах возникают споры о том, работает ли «чистый» COM в версии 7.7. С технической точки зрения важно понимать следующее:

В отличие от платформы 1С 8.х, где предусмотрен легкий и производительный компонент V83.COMConnector (который работает в рамках процесса вызывающего приложения и не создает графического интерфейса), при любом OLE-подключении к 1С 7.7 операционная система всегда инициализирует полноценный, «тяжелый» экземпляр платформы. Даже если вы передадите флаг скрытия заставки NO_SPLASH_SHOW, в диспетчере задач Windows все равно появится полноценный рабочий процесс 1cv7s.exe или 1cv7.exe, требующий значительных системных ресурсов. Всегда не забывайте корректно завершать соединение и освобождать память после выполнения всех необходимых операций.

← На главную