ПолучитьОбъект(), HTTP-сервис, OData и COM: доступ к данным 1С на стороне сервера
Содержание
Объект на сервере 1С получают методом ПолучитьОбъект() у ссылки: НоменклатураОбъект = Ссылка.ПолучитьОбъект();. Код должен выполняться в серверном контексте — в общем модуле с флагом «Сервер» или в процедуре формы с директивой &НаСервере / &НаСервереБезКонтекста. Ссылку сначала находят: НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту() или запросом.
Если объект нужен внешней системе, к серверу 1С обращаются снаружи: через HTTP-сервис (свой REST API), стандартный интерфейс OData или COM-соединение. Все способы ниже относятся к платформе 8.3 и работают одинаково в любой конфигурации — БП, ЗУП, УТ, ERP.
| Способ | Когда подходит | Что нужно |
|---|---|---|
ПолучитьОбъект() в серверном коде | Доработки внутри базы, обработки, расширения | Права на объект |
| Вызов сервера из формы | Нужны данные объекта на клиенте | Серверная процедура, возврат структуры |
| HTTP-сервис | Сайт, мобильное приложение, интеграция по своему формату | Публикация на веб-сервере, код обработчика |
| OData | Быстро отдать справочники и документы без программирования | Публикация + состав интерфейса |
| COM-соединение | Обмен двух баз на Windows, скрипты | Зарегистрированный comcntr.dll, лицензия |
Получение объекта по ссылке встроенным языком
В 1С различают ссылку и объект. Ссылка — лёгкий указатель на запись в базе. Объект — полная копия записи со всеми реквизитами и табличными частями, которую можно изменить и записать.
Шаг 1. Найти ссылку
Типовые менеджеры дают несколько способов поиска:
- 🔎
Справочники.Номенклатура.НайтиПоКоду("00-00000015")— по коду; - 🔎
Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка", Истина)— по наименованию, второй параметр включает точное совпадение; - 🔎
Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7701234567")— по значению реквизита; - 🔎
Документы.РеализацияТоваровУслуг.НайтиПоНомеру("0000-000123", ТекущаяДата())— по номеру в пределах периода нумерации; - 🔎
Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор("..."))— по GUID из внешней системы.
Если ничего не найдено, методы НайтиПо… возвращают пустую ссылку, а не Неопределено. Проверяйте результат через Ссылка.Пустая() или ЗначениеЗаполнено(Ссылка).
ПолучитьСсылку() по GUID не проверяет, существует ли запись. Вы получите «правильную на вид» ссылку даже на удалённый объект. Существование проверяйте отдельно — запросом или через ПолучитьОбъект().
Шаг 2. Получить объект и изменить его
// Общий модуль РаботаСНоменклатуройСервер, флаг «Сервер»
Процедура УстановитьКомментарий(Ссылка, ТекстКомментария) Экспорт
НоменклатураОбъект = Ссылка.ПолучитьОбъект();
Если НоменклатураОбъект = Неопределено Тогда
ВызватьИсключение "Объект не найден в базе: " + Строка(Ссылка.УникальныйИдентификатор());
КонецЕсли;
НоменклатураОбъект.Заблокировать(); // объектная блокировка на время правки
НоменклатураОбъект.Комментарий = ТекстКомментария;
НоменклатураОбъект.Записать();
КонецПроцедуры
Три момента, которые часто упускают:
ПолучитьОбъект()возвращаетНеопределено, если записи в базе нет (битая ссылка). Без проверки код упадёт с ошибкой «Значение не является значением объектного типа ».Заблокировать()ставит объектную блокировку. Если документ в это время открыт у другого пользователя, вызов завершится исключением — его стоит перехватить и показать понятный текст.- Для документов запись с проведением —
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение).
💡 Если объект нужен только для чтения, ПолучитьОбъект() избыточен. Платформа читает всю запись вместе с табличными частями. Для пары полей быстрее запрос — подробнее в разделе про оптимизацию.
Как получить объект на сервере из формы и тонкого клиента
В тонком клиенте и веб-клиенте метода ПолучитьОбъект() нет. Попытка вызвать его в клиентской процедуре даёт ошибку Метод объекта не обнаружен (ПолучитьОбъект). Объекты базы между клиентом и сервером не передаются — передаются ссылки и простые значения: строки, числа, структуры, массивы.
Правильная схема: клиент передаёт ссылку на сервер, сервер получает объект и возвращает структуру с нужными полями.
&НаКлиенте
Процедура ПоказатьАртикул(Команда)
Данные = ДанныеНоменклатуры(Объект.Номенклатура);
Если Данные <> Неопределено Тогда
Сообщить("Артикул: " + Данные.Артикул);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ДанныеНоменклатуры(Ссылка)
Если Не ЗначениеЗаполнено(Ссылка) Тогда
Возврат Неопределено;
КонецЕсли;
НоменклатураОбъект = Ссылка.ПолучитьОбъект();
Если НоменклатураОбъект = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Результат = Новый Структура("Наименование, Артикул");
ЗаполнитьЗначенияСвойств(Результат, НоменклатураОбъект);
Возврат Результат;
КонецФункции
&НаСервереБезКонтекста предпочтительнее &НаСервере: форма не гоняется на сервер целиком, вызов легче.
Объект самой формы
Если нужно поработать с объектом, который открыт в форме (вызвать его экспортный метод, заполнить табличную часть по правилам модуля объекта), используйте пару методов формы:
&НаСервере
Процедура ЗаполнитьНаСервере()
ДокументОбъект = РеквизитФормыВЗначение("Объект");
ДокументОбъект.ЗаполнитьТоварыПоОстаткам(); // экспортный метод модуля объекта
ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры
Здесь ЗаполнитьТоварыПоОстаткам() — пример вашего собственного экспортного метода. Изменения попадут в форму, но в базу запишутся только когда пользователь нажмёт «Записать».
HTTP-сервис: отдаём объект 1С наружу по REST
HTTP-сервис — это свой REST API внутри конфигурации. Внешняя система шлёт GET-запрос, обработчик на сервере 1С находит объект и отвечает JSON.
Создание сервиса
- В Конфигураторе (или в расширении) откройте ветку
Общие → HTTP-сервисы, добавьте сервис, задайте корневой URL, напримерapi. - Добавьте шаблон URL
/item/{code}и в нём методGET. - Создайте обработчик метода и напишите код.
Функция ItemGET(Запрос)
Код = Запрос.ПараметрыURL["code"];
Ссылка = Справочники.Номенклатура.НайтиПоКоду(Код);
Если Ссылка.Пустая() Тогда
Возврат Новый HTTPСервисОтвет(404);
КонецЕсли;
Данные = Новый Структура;
Данные.Вставить("code", Код);
Данные.Вставить("name", Ссылка.Наименование);
Данные.Вставить("guid", Строка(Ссылка.УникальныйИдентификатор()));
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Данные);
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(Запись.Закрыть());
Возврат Ответ;
КонецФункции
Обработчик HTTP-сервиса всегда выполняется на сервере, поэтому директивы компиляции здесь не нужны.
Публикация и проверка
Базу публикуют на веб-сервере (IIS или Apache) из Конфигуратора: Администрирование → Публикация на веб-сервере, флажок публикации HTTP-сервисов должен стоять. После этого сервис доступен по адресу вида:
curl -u "api_user:пароль" "https://server/base/hs/api/item/00-00000015"
Часть /hs/ обязательна — по ней веб-расширение 1С понимает, что запрос идёт к HTTP-сервису.
OData: стандартный REST без единой строки обработчиков
OData — готовый интерфейс платформы. Он отдаёт справочники, документы и регистры в формате JSON или XML без написания обработчиков. Подходит для BI, отчётов в Excel и простых интеграций.
Включение
- Укажите, какие объекты открыть. Это делают кодом один раз, с правами администратора:
Состав = Новый Массив;
Состав.Добавить(Метаданные.Справочники.Номенклатура);
Состав.Добавить(Метаданные.Документы.РеализацияТоваровУслуг);
УстановитьСоставСтандартногоИнтерфейсаOData(Состав);
- При публикации на веб-сервере отметьте флажок «Публиковать стандартный интерфейс OData».
- Заведите отдельного пользователя 1С с правами только на чтение этих объектов.
💡 В типовых конфигурациях на БСП бывает обработка «Настройка автоматического REST-сервиса», которая делает первый шаг через интерфейс. Если её нет — хватит кода выше, выполненного, например, в консоли кода.
Запрос объекта
# Один элемент по GUID
curl -u "odata_user:пароль" \
"https://server/base/odata/standard.odata/Catalog_Номенклатура(guid'3f2a1c4e-0000-0000-0000-000000000000')?\$format=json"
# Отбор и выбор нужных полей
curl -u "odata_user:пароль" \
"https://server/base/odata/standard.odata/Catalog_Номенклатура?\$filter=Code%20eq%20'00-00000015'&\$select=Ref_Key,Description&\$format=json"
Имена сущностей строятся по схеме Catalog_, Document_, InformationRegister_ + имя объекта метаданных. Поле ссылки — Ref_Key, наименование — Description, код — Code.
OData отдаёт объект целиком, с табличными частями. Без $select и $top выгрузка большого справочника заметно нагрузит сервер.
Командная строка, консоль кода и отладчик
Консоль кластера (rac, оснастка администрирования серверов) объектами базы не управляет: она видит сеансы, соединения и информационные базы, но не данные. Чтобы получить объект «по-администраторски», используют другие приёмы.
Запуск обработки из командной строки
Пишете внешнюю обработку , которая в серверном модуле находит объект и выполняет действие, и запускаете её без участия пользователя:
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" ENTERPRISE /S "srv1c\buh" /N "Робот" /P "пароль" /Execute "C:\scripts\obrabotka.epf" /C "00-00000015"
Параметр /C передаёт строку в программу, внутри она доступна через ПараметрЗапуска. Номер платформы в пути подставьте свой.
Консоль кода и консоль запросов
Обработки «Консоль кода» и «Консоль запросов» распространяются как внешние обработки. В консоли кода можно выполнить на сервере тот же Ссылка.ПолучитьОбъект() и посмотреть результат. Запускайте её только под пользователем с полными правами и только в копии, если код что-то записывает.
Отладчик и навигационная ссылка
- 🧭 В Конфигураторе остановитесь на точке останова и откройте «Вычислить выражение» (
Shift+F9): введитеСсылка.ПолучитьОбъект()и разверните реквизиты. - 🧭 Чтобы найти конкретную запись, в открытой форме объекта получите навигационную ссылку (
Shift+F11). Она имеет видe1cib/data/Справочник.Номенклатура?ref=…, где послеref=— GUID объекта в шестнадцатеричном виде.
COM-соединение и внешние компоненты
COM-соединение даёт программе на Windows (другой базе 1С, скрипту на VBScript или Python) прямой доступ к объектной модели базы. На стороне подключения работает полноценный серверный контекст: доступны менеджеры, запросы и ПолучитьОбъект().
Коннектор = Новый COMОбъект("V83.COMConnector");
Соединение = Коннектор.Connect("Srvr=""srv1c"";Ref=""buh"";Usr=""Робот"";Pwd=""пароль"";");
Ссылка = Соединение.Справочники.Номенклатура.НайтиПоКоду("00-00000015");
Если Не Ссылка.Пустая() Тогда
УдаленныйОбъект = Ссылка.ПолучитьОбъект();
Сообщить(УдаленныйОбъект.Наименование);
КонецЕсли;
Что нужно для работы:
- 🔧 зарегистрировать
comcntr.dllот имени администратора:regsvr32 "C:\Program Files\1cv8\<версия>\bin\comcntr.dll"; - 🔧 разрядность платформы и вызывающей программы должна совпадать (64-битный скрипт не увидит 32-битный коннектор);
- 🔧 внешнее соединение занимает клиентскую лицензию, как обычный сеанс.
Объекты из COM-соединения нельзя напрямую подставить в реквизиты своей базы. Ссылка «чужой» базы — это COM-объект, а не ссылка вашей конфигурации. Переносите данные через простые значения: код, GUID, строки.
Внешние компоненты (Native API) сами по себе к данным базы доступа не дают. Это библиотеки на C++, которые расширяют язык: работа с оборудованием, криптография, нестандартные протоколы. Объект 1С всё равно получают кодом на встроенном языке, а компоненте передают уже простые значения.
Быстро и без падений: оптимизация и обработка ошибок
Не читайте объект целиком ради одного поля
Обращение через точку Ссылка.Наименование и вызов ПолучитьОбъект() читают из базы всю запись. В цикле на 5 000 строк это 5 000 отдельных обращений. Один запрос по массиву ссылок делает ту же работу за одно обращение:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&Ссылки)";
Запрос.УстановитьПараметр("Ссылки", МассивСсылок);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Выборка.Ссылка, Выборка.Артикул
КонецЦикла;
В конфигурациях на БСП то же самое делают функции ОбщегоНазначения.ЗначениеРеквизитаОбъекта() и ОбщегоНазначения.ЗначенияРеквизитовОбъектов() — они внутри строят такой запрос.
| Задача | Чем делать |
|---|---|
| Прочитать 1–3 поля | Запрос или ЗначенияРеквизитовОбъекта() |
| Прочитать поля у многих объектов | Один запрос с В (&Ссылки) |
| Изменить и записать | ПолучитьОбъект() + Записать() |
| Вызвать метод модуля объекта | ПолучитьОбъект() |
Перехват ошибок
Запись объекта может упасть из-за блокировки, проверки заполнения или прав. Оборачивайте её в Попытка … Исключение и пишите причину в журнал регистрации:
Попытка
НоменклатураОбъект.Заблокировать();
НоменклатураОбъект.Записать();
Исключение
ТекстОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписьЖурналаРегистрации("Интеграция.ЗаписьНоменклатуры",
УровеньЖурналаРегистрации.Ошибка, , Ссылка, ТекстОшибки);
ВызватьИсключение;
КонецПопытки;
Права и безопасность: как не слить данные
Получая объект для внешней системы, вы фактически открываете часть базы наружу. Несколько правил, которые снимают большинство рисков:
- 🔐 Отдельный пользователь под интеграцию. Только нужные роли, только чтение, если запись не требуется. Не публикуйте сервис под учётной записью администратора.
- 🔐 HTTPS обязателен. Basic-аутентификация передаёт логин и пароль в каждом запросе; по HTTP их видно в сети открытым текстом.
- 🔐 Минимальный состав OData. Открывайте только те объекты, которые нужны потребителю. Справочник «Физические лица» или кадровые документы в составе OData — прямая утечка персональных данных.
- 🔐 Осторожно с привилегированным режимом.
УстановитьПривилегированныйРежим(Истина)отключает проверку прав и ограничений на уровне записей. Включайте его на минимальный участок кода, а не на весь обработчик. - 🔐 Безопасный режим для чужого кода. Если обработчик выполняет код, пришедший извне (например, текст запроса из параметра), используйте
УстановитьБезопасныйРежим(Истина)— а лучше вообще не принимайте код снаружи. - 🔐 Пароли не в тексте модуля. Строку подключения COM и учётные данные храните в защищённом хранилище или в константе с ограниченным доступом, а не литералом в коде.
Проверяйте права в коде явно, если сервис отдаёт данные по произвольному идентификатору. Иначе любой, кто знает адрес и пароль интеграционного пользователя, перебором GUID или кодов вытащит весь справочник.
Если Не ПравоДоступа("Чтение", Метаданные.Справочники.Номенклатура) Тогда
Возврат Новый HTTPСервисОтвет(403);
КонецЕсли;
Частые вопросы
Чем ссылка отличается от объекта в 1С?
Можно ли передать объект с сервера на клиент?
Нужно ли получать объект, чтобы пометить его на удаление?
УстановитьПометкуУдаления(Истина), поэтому сначала вызовите ПолучитьОбъект() на сервере.