Как получить доступ к реквизитам объекта конфигурации "Обработка" через COM в 1С 8.3?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

При работе с COM-соединением в 1С 8.3 часто возникают вопросы о доступе к реквизитам объектов конфигурации. В особенности, это касается объекта "Обработка", который имеет свою специфику. Мы выясним, как правильно работать с реквизитами обработок через COM, чтобы избежать типичных ошибок и эффективно решать поставленные задачи.

Предположим, что у нас уже установлено COM-соединение с базой 1С (например, через COM объект на Python) и объект smol1c_COM_Exemplar является экземпляром COM-объекта 1С (например, COMОбъект("V83.Application") или COMОбъект("V83.COMConnector")).

Понимание природы объекта "Обработка" в 1С

Прежде чем мы перейдем к техническим деталям, нам критически важно понять фундаментальное отличие объекта "Обработка" от других объектов конфигурации, таких как "Документ", "Справочник" или "РегистрСведений".

  1. "Обработка" не хранит данные в базе данных. В отличие от документов, которые записываются в таблицы базы данных, или справочников, элементы которых также имеют свое постоянное хранение, обработки предназначены для выполнения действий. Это инструменты, которые могут выполнять различные операции: обработка данных, формирование отчетов, импорт/экспорт и т.д.
  2. Реквизиты "Обработки" – это параметры выполнения. Реквизиты, которые мы добавляем в обработки, являются по сути свойствами или параметрами, которые будут использоваться в момент выполнения кода обработки. Они существуют только в оперативной памяти во время работы с конкретным экземпляром обработки. После завершения работы экземпляра обработки эти значения не сохраняются в информационной базе.

Из этого следует, что мы не можем "прочитать" значение реквизита "Обработки" из базы данных, потому что оно там просто не хранится. Мы можем создать экземпляр обработки, установить или прочитать значения ее реквизитов, но эти значения будут актуальны только для данного конкретного запущенного экземпляра.

Доступ к метаданным реквизитов "Обработки"

Если наша цель состоит не в получении текущего значения реквизита в работающей обработке, а в том, чтобы узнать структуру объекта "Обработка", то есть получить список ее реквизитов, их типы и другие метаданные, мы можем использовать объект Метаданные. Этот подход позволяет нам получить информацию о том, какие реквизиты вообще существуют в конфигурации для данной обработки, но не их значения.

  1. Получение ссылки на объект метаданных "Обработка".

    Сначала мы получаем доступ к коллекции обработок через объект Метаданные, а затем находим нужную обработку по имени. Например, для обработки "МояОбработка":

    
    var K1: Variant;
    K1 := smol1c_COM_Exemplar.Метаданные.Обработки.Найти('МояОбработка');
    // K1 теперь содержит объект Метаданные.Обработка
    

    Или напрямую, если имя известно:

    
    var K1: Variant;
    K1 := smol1c_COM_Exemplar.Метаданные.Обработки.МояОбработка;
    // K1 теперь содержит объект Метаданные.Обработка
    
  2. Доступ к коллекции реквизитов метаданных.

    После получения объекта метаданных обработки, мы можем получить доступ к коллекции ее реквизитов:

    
    var K1, K2: Variant;
    K1 := smol1c_COM_Exemplar.Метаданные.Обработки.Найти('МояОбработка');
    K2 := K1.Реквизиты.Найти('Мой_реквизит_число'); 
    // K2 теперь содержит объект Метаданные.РеквизитОбработки
    

    Объект Метаданные.РеквизитОбработки даст нам информацию о самом реквизите (его имя, тип, составной ли тип и т.д.), но не его значение. Например, мы можем узнать имя реквизита:

    
    ShowMessage(smol1c_COM_Exemplar.String(K2.Имя)); // Выведет "Мой_реквизит_число"
    

Важно: Этот подход полезен для анализа структуры конфигурации, выгрузки метаданных в JSON или динамического формирования запросов, но не для получения значений, которые пользователь мог ввести в форму обработки или которые были установлены в ходе ее выполнения.

Создание экземпляра объекта "Обработка" и работа с его реквизитами

Если нам нужно установить или прочитать значения реквизитов конкретного, работающего экземпляра обработки, нам необходимо этот экземпляр создать. Только после создания объекта обработки в памяти мы сможем взаимодействовать с его реквизитами как со свойствами.

  1. Создание экземпляра встроенной обработки.

    Для обработок, входящих в состав конфигурации (встроенных), мы сначала получаем объект-менеджер обработки, а затем вызываем его метод Создать(). Это наиболее распространенный и корректный способ:

    
    var K1: Variant;
    K1 := smol1c_COM_Exemplar.Обработки.ЗакрытиеМесяца.Создать();
    // K1 теперь является экземпляром ОбработкаОбъект.ЗакрытиеМесяца
    

    Если мы попытаемся получить объект напрямую через smol1c_COM_Exemplar.Обработки.ЗакрытиеМесяца; без .Создать(), то получим не сам объект обработки, а ее менеджер (ОбработкаМенеджер.ЗакрытиеМесяца), который предназначен для работы с метаданными и создания новых объектов.

  2. Создание экземпляра обработки по имени типа объекта.

    В некоторых случаях (например, для внешних обработок, или если полный тип объекта доступен), мы можем попытаться создать экземпляр через метод NewObject(), указав полный тип объекта ОбработкаОбъект.<ИмяОбработки>:

    
    var K1: Variant;
    // Этот вариант может работать для некоторых сценариев,
    // но 'не найден тип' часто возникает для внутренних обработок
    K1 := smol1c_COM_Exemplar.NewObject("ОбработкаОбъект.ОбработкаВнутренняЛюбая");
    

    Если мы получаем ошибку "не найден тип" (как это было в изначальном вопросе), это часто означает, что платформа 1С не может найти или корректно распознать указанный тип объекта в данном контексте COM-соединения. В таких случаях метод smol1c_COM_Exemplar.Обработки.ИмяОбработки.Создать() является предпочтительным и более надежным для встроенных обработок.

  3. Установка значений реквизитов экземпляра.

    После того как мы успешно создали экземпляр обработки, мы можем устанавливать значения ее реквизитов как обычные свойства объекта:

    
    var K1: Variant;
    K1 := smol1c_COM_Exemplar.Обработки.ЗакрытиеМесяца.Создать();
    // Устанавливаем значение реквизита "ПериодРегистрации"
    K1.ПериодРегистрации = smol1c_COM_Exemplar.NewObject("Дата", 2023, 12, 31);
    // Устанавливаем значение реквизита "Организация"
    K1.Организация = smol1c_COM_Exemplar.Справочники.Организации.НайтиПоКоду("001");
    

    Обратите внимание: если реквизит имеет ссылочный тип (например, СправочникСсылка.Организации), нам нужно передавать ему не просто строку с кодом или наименованием, а ссылку на объект 1С, полученную через COM.

  4. Чтение значений реквизитов экземпляра.

    Точно так же, как мы устанавливали значения, мы можем их и считывать. Важно помнить, что мы считываем значения, которые были установлены для данного экземпляра обработки:

    
    var K1, ЗначениеПериода: Variant;
    K1 := smol1c_COM_Exemplar.Обработки.ЗакрытиеМесяца.Создать();
    K1.ПериодРегистрации = smol1c_COM_Exemplar.NewObject("Дата", 2023, 12, 31);
            
    ЗначениеПериода = K1.ПериодРегистрации;
    ShowMessage(smol1c_COM_Exemplar.String(ЗначениеПериода)); 
    // Выведет дату, которую мы установили
    
  5. Вызов методов обработки.

    После заполнения реквизитов, мы можем вызвать методы обработки для выполнения ее функционала. Например, если у обработки есть метод ВыполнитьЗакрытие():

    
    K1.ВыполнитьЗакрытие();
    

    В этом случае, логика обработки будет использовать значения реквизитов, которые мы установили для данного экземпляра.

Таким образом, для работы с реквизитами объекта "Обработка" через COM, мы всегда взаимодействуем с ее экземпляром в памяти, а не с какой-либо хранимой в базе записью.

Доступ к функциям общих модулей через COM

В некоторых случаях, когда мы пытаемся получить "значение", которое раньше присваивалось реквизиту обработки, это значение на самом деле могло вычисляться в каком-либо общем модуле, а затем использоваться обработкой. Если цель состоит в получении результата работы такой функции, то более прямым и эффективным способом будет вызов этой функции общего модуля напрямую через COM.

  1. Требования к общему модулю.

    Чтобы функция общего модуля была доступна через COM-соединение, сам общий модуль должен иметь установленные свойства:

    • "Сервер" (для выполнения на сервере 1С).
    • "Внешнее соединение" (для доступа из внешних приложений, таких как COM-соединение).

    Без этих флагов, попытка обращения к функциям модуля извне приведет к ошибке.

  2. Вызов функции общего модуля.

    Если общий модуль соответствует требованиям, мы можем вызвать его функции, используя следующий синтаксис:

    
    var РезультатФункции: Variant;
    // Предполагаем, что есть общий модуль "МойОбщийМодуль" с функцией "ПолучитьЧисло"
    РезультатФункции := smol1c_COM_Exemplar.МойОбщийМодуль.ПолучитьЧисло(Параметр1, Параметр2);
    ShowMessage(smol1c_COM_Exemplar.String(РезультатФункции));
    

    В исходном вопросе был пример:

    
    // Это более сложный случай, где ОбщегоНазначения, возможно, не сам модуль,
    // а некий объект, предоставляющий доступ к функционалу,
    // как это часто бывает с БСП (Библиотекой Стандартных Подсистем).
    K1:=smol1c_COM_Exemplar.ОбщегоНазначения.ОбщийМодуль('ЗакрытиеМесяца');
    // Затем, если K1 это объект, который имеет метод или свойство "КлючОбъектаПодсказки"
    // ShowMessage(smol1c_COM_Exemplar.String(K1.КлючОбъектаПодсказки));
    

    В стандартном случае без БСП, вызов функции общего модуля выглядит проще: smol1c_COM_Exemplar.ИмяОбщегоМодуля.ИмяФункции(Параметры). Если же используется функционал БСП, как в примере с ОбщегоНазначения.ОбщийМодуль('ЗакрытиеМесяца'), это может быть специфичный механизм получения ссылки на функционал, который работает через специализированные методы БСП.

  3. Особенности в файловой и серверной базах.

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

Получение значений реквизитов объектов, хранящих данные (Документы, Справочники, Регистры)

Если мы все-таки хотим получить значения, которые хранятся в базе данных и лишь каким-то образом связаны с обработкой (например, обработка их создала, изменила или отобразила), то нам следует обращаться не к самой обработке, а к тем объектам, которые эти данные непосредственно хранят.

  1. Использование объекта "Запрос".

    Для чтения данных из базы данных наиболее мощным и универсальным инструментом является объект Запрос. Мы можем формировать запросы к таблицам документов, справочников, регистров и получать нужные нам поля:

    
    var K1, K1DATA: Variant;
    K1 := smol1c_COM_Exemplar.NewObject('Запрос');
    K1.Text := 
        "ВЫБРАТЬ
        |    ДокументПоступлениеТоваровУслуг.Ссылка,
        |    ДокументПоступлениеТоваровУслуг.Дата,
        |    ДокументПоступлениеТоваровУслуг.Организация
        |ИЗ
        |    Документ.ПоступлениеТоваровУслуг КАК ДокументПоступлениеТоваровУслуг
        |ГДЕ
        |    ДокументПоступлениеТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
            
    K1.УстановитьПараметр("НачалоПериода", smol1c_COM_Exemplar.NewObject("Дата", 2023, 1, 1));
    K1.УстановитьПараметр("КонецПериода", smol1c_COM_Exemplar.NewObject("Дата", 2023, 12, 31));
            
    K1DATA := K1.Выполнить().Выбрать();
    while K1DATA.Следующий() do begin
        ShowMessage(smol1c_COM_Exemplar.String(K1DATA.Ссылка) + " | " + smol1c_COM_Exemplar.String(K1DATA.Дата));
    end;
    

    Именно этот подход следует использовать, когда мы хотим получить данные, сохраненные в информационной базе.

  2. Чтение реквизитов по ссылке на объект.

    Если у нас уже есть ссылка на конкретный объект (например, на документ или элемент справочника), мы можем прочитать его реквизиты напрямую:

    
    var СсылкаНаДокумент, ОбъектДокумент, ЗначениеРеквизита: Variant;
    // Получаем ссылку на какой-либо документ (например, по UUID)
    СсылкаНаДокумент := smol1c_COM_Exemplar.Документы.ПоступлениеТоваровУслуг.ПолучитьСсылку(smol1c_COM_Exemplar.NewObject("УникальныйИдентификатор", "{ваш_uuid_документа}"));
            
    // Получаем объект документа (читаем его из базы)
    ОбъектДокумент := СсылкаНаДокумент.ПолучитьОбъект();
            
    // Читаем реквизит
    ЗначениеРеквизита := ОбъектДокумент.Организация;
    ShowMessage(smol1c_COM_Exemplar.String(ЗначениеРеквизита));
    

    Этот способ позволяет получить все реквизиты объекта, которые были сохранены в базе данных.

  3. Использование функций БСП (Библиотеки стандартных подсистем).

    Если в конфигурации используется БСП, можно воспользоваться функцией ОбщегоНазначения.ЗначениеРеквизитаОбъекта(). Эта функция позволяет получить значение реквизита, прочитанного из информационной базы по ссылке на объект, без необходимости получать весь объект целиком. Однако она доступна только на сервере 1С.

    
    var СсылкаНаОбъект, ЗначениеРеквизита: Variant;
    // Получаем ссылку на объект (например, на Организацию)
    СсылкаНаОбъект := smol1c_COM_Exemplar.Справочники.Организации.НайтиПоНаименованию("ООО Рога и Копыта");
            
    // Если функция доступна через COM и имеет нужные флаги
    // ЗначениеРеквизита := smol1c_COM_Exemplar.ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаОбъект, "ИНН");
    // ShowMessage(smol1c_COM_Exemplar.String(ЗначениеРеквизита));
    

    Для использования этой функции через COM также требуется, чтобы общий модуль ОбщегоНазначения имел флаг "Внешнее соединение".

Заключение

Мы видим, что доступ к реквизитам объекта конфигурации "Обработка" через COM требует четкого понимания ее природы. Если наша цель — получить описание структуры обработки, мы используем объект Метаданные. Если мы хотим установить или прочитать параметры выполнения конкретного экземпляра обработки, мы создаем этот экземпляр через .Создать() и работаем с его свойствами в памяти. Если же искомое "значение" является результатом вычислений, вынесенных в общий модуль, мы напрямую вызываем функцию этого модуля (при условии, что он доступен для внешнего соединения). Наконец, если нам нужны данные, которые хранятся в базе данных, мы обращаемся к соответствующим объектам конфигурации (документам, справочникам, регистрам) через запросы или прямым чтением реквизитов объекта.

Выбор правильного подхода зависит от конкретной задачи и от того, где именно находится искомая информация.

← На главную