Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: COM Соединение с другой базой
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 > Программисту > Программирование в 1С Предприятие 8.3
Profi_1C77
Есть база BAS UT , и есть база BAS бух CORP
В базе УТ нужно построить отчет по остаткам товаров ( бех проблем ) + создать соединение к бух базе ( она кстати SQL ) - получить тоже остатки по 281 , выгрузить их в ТЗ и потом соединить в отчете остатков UT;
Номенклатура / Склады - синхронизированы ( Код - Артикул - ШтрихКод)

1. Не не писал такое ни разу , накидайте пож пример соединения и как через объект COM пишется запрос на 281.
2. В отчете как инициализировать ТЗ с бух базы и передать его как ИсточникДанных ?
UmbertoVasyl`ovich
Profi_1C77 @ Сегодня, 9:48 необходимо зарегистрироваться для просмотра ссылки ,
щось типу цього
Функция ПодключениеВыполнено(ткошибка) Экспорт
    ПодклУстановлено = Истина;
    СомСоединение = Новый COMОбъект("V83.ComConnector");    
        
    СтрокаСоединения = ПутьКБазе+"Usr = """+СокрЛП(Логин)+"""; Pwd = """+СокрЛП(Пароль)+"""";
    Если НЕ Серверная Тогда                
        СтрокаСоединения = "File = """+СокрЛП(ПутьКБазе)+"""; Usr = """+СокрЛП(Логин)+"""; Pwd = """+СокрЛП(Пароль)+"""";
    КонецЕсли;  
                
    Попытка
        Подключение = СомСоединение.Connect(СтрокаСоединения);
    Исключение
        ткошибка = ОписаниеОшибки();
        Если ПустаяСтрока(ткошибка) Тогда
            ткошибка = НСтр("ru='ошибка подключения';uk='помилка підключення'");
        КонецЕсли;    
        Подключение = Неопределено;
        СомСоединение = Неопределено;
        ПодклУстановлено = Ложь;
    КонецПопытки;
    
    Возврат ПодклУстановлено;
    
КонецФункции


Profi_1C77 @ Сегодня, 9:48 необходимо зарегистрироваться для просмотра ссылки ,
запрос так само як звичайний
Запрос = Подключение.NewObject("Запрос");
Slon747
После успешного соединения со сторонней базой:
ЗапросВнешнейБазы = ВнешняяБаза.NewObject("Запрос");
ЗапросВнешнейБазы.Текст = ""; //тут текст запроса, как бы он выглядел в бухгалтерии
ЗапросВнешнейБазы.УстановитьПараметр(.....);
Выборка = ЗапросВнешнейБазы.Выполнить().Выбрать();


P.S. уже ответили
Profi_1C77
Slon747 @ Сегодня, 11:32 необходимо зарегистрироваться для просмотра ссылки ,
После этого Запрос в ТЗ , и в модуле объекта отчета ПриКомпоновкеРезультата ?
Slon747
Цитата(Profi_1C77 @ 27.05.25, 11:36) необходимо зарегистрироваться для просмотра ссылки
После этого Запрос в ТЗ , и в модуле объекта отчета ПриКомпоновкеРезультата ?

Тут не скажу. Не загружал данные в СКД.
TohaMonster
Выборка - это будет COM-объект. Если Вы сделаете ТЗ = ЗапросВнешнейБазы.Выполнить().Выгрузить(), то ТЗ - ето тоже COM-объект, если я ничего не путаю. И, если это не примитивные типы, колонки будут тоже COM-объектом.
Поэтому, если Вам нужна, например, Номенклатура в Вашей Базе, нужно потом еще полученную ТЗ обработать и сопоставить её элементы элементам в Вашей Базе
andytg
Profi_1C77 @ Сегодня, 11:36 необходимо зарегистрироваться для просмотра ссылки ,
вам, как я понимаю, надо сравнить данные управленческого учета (УТ) с бухгалтерским (КОРП), так?

ну вот и делайте как выше написали, сперва в бухии КОРП через com-объект получаете данные из УТ и кладете их в одну таблицу значений (назовем Тз1), затем закрываем подключение и удаляем com-объект за ненадобностью, затем то же самое в УТ и результат кладете в другую таблицу (Тз2), затем сравниваете эти таблицы, перед сравнением постройте в каждой из таблиц поисковый индекс (чтоб удобнее и быстрее было искать) такого примерно вида (колонку "Ключ" добавьте)

Ключ = [код].[артикул].[штрихкод]

таблицы перед добавлением индекса сворачиваем по кодам/артикулам/штрихкодам

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

и потом сравнение двух таблиц по этому индексу -- есть / нет

ну и результат -- в отчет


TohaMonster @ Сегодня, 12:13 необходимо зарегистрироваться для просмотра ссылки ,
колонки в ТЗ нужно делать примитивными типами (строка/число), т.е. код/артикул/наименование/количество/стоимость -- для сравнения остатков в двух базах будет достаточно
xlmel
В Бухгалтерии КОРП можно создать webservice, опубликовать его на web-сервере, и опубликовать метод, который будет возвращать таблицу значений. Я везде, где мог, уходил от COM в пользу webservice.
Во-первых существенно быстрее устанавливается соединение.
Во-вторых запросы пишутся в родной базе, а если через COM, то приходится делать запрос в консоли запросов в одной базе, потом его переносить во вторую. Это дополнительная работа.
В-третьих, при возврате через COM приходится использовать пару функций ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр, или перегонять в JSON. С JSON проблема в том, что для обработки таблицы в запросе, она должна быть типизирована. То есть надо на стороне приемника создать таблицу, заполнить ее из JSON. Касательно 2 функций - вендор не рекомендует их использовать, о причине не знаю. А проверить получится ли работать с СериализаторXDTO через COM у меня как-то руки не дошли. В webservice, если добавите пакет XDTO необходимо зарегистрироваться для просмотра ссылки, то станет доступен тип ValueTable и сможете на стороне приемника использовать СериализаторXDTO.ПрочитатьXDTO(), а на стороне источника СериализаторXDTO.ЗаписатьXDTO();
В расширение можно добавить webservice, режим совместимости 8.3.12 вроде как позволяет это сделать.
andytg
Цитата(xlmel @ 28.05.25, 10:13) необходимо зарегистрироваться для просмотра ссылки
В расширение можно добавить webservice, режим совместимости 8.3.12 вроде как позволяет это сделать

оно-то так, но как показывает отечественная практика, практически везде для бухий и подач документов в налоговые (особенно в массовом режиме) уже больше 12 лет используется что-то из серии Медок/Фредо, а оно существует только под винду (ибо написано на net framework), поэтому на буховских машинах 100% будет именно винда, так что эквилибристика с линуксами, апачами, веб-сервисами и тому подобным imho в наших условиях излишня, разве что если специально не попросят smile.gif

а при взаимодействии через com надо только не забывать, что передать можно только простые типы, и в другой базе нужны будут дополнительные поиски и сопоставления (клиенты, номенклатура и т.д.), но и тут все решается поисками по ЕДРПОУ, артикулам, штрих-кодам и т.д. (которые и задаются именно простыми типами -- строка/чиало), так что в итоге не проблема



Цитата(xlmel @ 28.05.25, 10:13) необходимо зарегистрироваться для просмотра ссылки
Касательно 2 функций - вендор не рекомендует их использовать, о причине не знаю.

если это про ЗначениеВСтрокуВнутр(), то в мануалах написано, что оставлено только для совместимости с клюшками (как по мне, отличная функция, крайне удобная и нужная smile.gif)
xlmel
andytg @ Сегодня, 13:12 необходимо зарегистрироваться для просмотра ссылки ,
так я не возражаю, каждый ищет то, что ему удобнее. У меня 4 базы на Винде, которые должны обмениваться данными и все реализовано через веб-сервисы. Можно было сделать через COM, но открытие COM обычно в 5-7 раз медленнее, чем веб-сервис. И сделаны аналогичные отчеты, которые собирают данные из разных баз и удалось добиться разумных времен ожидания
andytg
Цитата(xlmel @ 28.05.25, 15:45) необходимо зарегистрироваться для просмотра ссылки
но открытие COM обычно в 5-7 раз медленнее

тут соглашусь для случая, когда com на разных серверах, удаленных друг от друга
в нашем случае тоже 4 базы (3 бух корп и 1 типа управленческая унф), обмен идет из унф в бух, на com в пределах локалки 100 мбит -- соединение за пару секунд
в роли "серверов" -- i7 3770k и i5 2320, винда, postgresql
а вот если базы находятся в разных местах и соединение через интернет -- тогда соглашусь, да, com сильно тупит, веб-сервис наверное будет быстрее (не пробовал, лень переписывать smile.gif)
xlmel
andytg @ Сегодня, 15:10 необходимо зарегистрироваться для просмотра ссылки ,
пока простые запросы, еще терпимо, когда нужно использовать МенеджерВременныхТаблиц, то я лучше буду через сервисы делать
Profi_1C77
UmbertoVasyl`ovich @ 27.05.25, 11:30 необходимо зарегистрироваться для просмотра ссылки ,
Хелп.
&НаСервере

Функция ПодключениеВыполнено(ткошибка) Экспорт
    ПодклУстановлено = Истина;
    СомСоединение = Новый COMОбъект("V83.ComConnector");    
     // параметры
     ПутьКБазе  = "C:\BAS бух\";
     Логин         = "Ольга";
     Пароль     = "261080";
     Серверная = Ложь;
     Подключение = Неопределено;
    СтрокаСоединения = ПутьКБазе+"Usr = """+СокрЛП(Логин)+"""; Pwd = """+СокрЛП(Пароль)+"""";
    Если НЕ Серверная Тогда                
        СтрокаСоединения = "File = """+СокрЛП(ПутьКБазе)+"""; Usr = """+СокрЛП(Логин)+"""; Pwd = """+СокрЛП(Пароль)+"""";
    КонецЕсли;  
                
    Попытка
        Подключение = СомСоединение.Connect(СтрокаСоединения);
    Исключение
        ткошибка = ОписаниеОшибки();
        Если ПустаяСтрока(ткошибка) Тогда
            ткошибка = НСтр("ru='ошибка подключения';uk='помилка підключення'");
        КонецЕсли;    
        Подключение = Неопределено;
        СомСоединение = Неопределено;
        ПодклУстановлено = Ложь;
    КонецПопытки;
    
    Возврат ПодклУстановлено;
    
КонецФункции

такое вышло , не создает и все, все время в отладке на исключение уходит ;
Что может быть не так?
Vofka
Цитата(Profi_1C77 @ 03.06.25, 12:30) необходимо зарегистрироваться для просмотра ссылки
ОписаниеОшибки()

Так а что здесь возвращается?
Profi_1C77
Vofka @ Сегодня, 12:41 необходимо зарегистрироваться для просмотра ссылки ,
СтрокаСоединения = File = "C:\BAS бух\"; Usr = "Ольга"; Pwd = "261080"
СомСоединение = COMОбъект
Ошибка = {ВнешнийОтчет.ОстаткиТоваровUT_BAS.МодульОбъекта(17)}: Метод об’єкта не виявлено (Connect)

может права / не установлена длл?
andytg
Цитата(Profi_1C77 @ 03.06.25, 12:30) необходимо зарегистрироваться для просмотра ссылки
Что может быть не так?


всё smile.gif

у вас время жизни подключения равно времени жизни вашей функции, которая возвращает булево значение, а само подключение закрывается после отработки функции
Profi_1C77
andytg @ Сегодня, 13:12 необходимо зарегистрироваться для просмотра ссылки ,
Я код потом код перенесу ""правильно" " мне важно что что б Подключение было
andytg
Цитата(Profi_1C77 @ 03.06.25, 13:11) необходимо зарегистрироваться для просмотра ссылки
Метод об’єкта не виявлено (Connect)

в этом случае надо зарегистрировать comcntrl.dll в системе (причем, если их несколько, то надо именно от нужной версии платформы)



Цитата(Profi_1C77 @ 03.06.25, 13:18) необходимо зарегистрироваться для просмотра ссылки
Я код потом код перенесу ""правильно" " мне важно что что б Подключение было

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

необходимо зарегистрироваться для просмотра ссылки

        V7 = _V7.Connect(СтрокаСоединения);

        _СтруктураCOM = Новый Структура;
        _СтруктураCOM.Вставить("COMОбъект", V7);
        _КонтейнерCOM = ПоместитьВоВременноеХранилище(_СтруктураCOM, Новый УникальныйИдентификатор);
Profi_1C77
andytg @ Сегодня, 13:23 необходимо зарегистрироваться для просмотра ссылки ,
эта зараза не регается
Regsvr32 comcntr.dll

Profi_1C77 @ Сегодня, 13:41 необходимо зарегистрироваться для просмотра ссылки ,
regsvr32 /i "C:\Program Files\1cv8\8.3.23.2236\bin\comcntr.dll"
так прошло
andytg
Цитата(Profi_1C77 @ 03.06.25, 13:56) необходимо зарегистрироваться для просмотра ссылки
так прошло

так полный путь надо указывать же!

upd: можете через com+ необходимо зарегистрироваться для просмотра ссылки
у меня так зарегистрирована 8.5 (для тестов) и 8.3 с ней прекрасно работает, т.к. ком-коннекторы разных версий v83.ComConnector и v85.ComConnector
Profi_1C77
И еще вопрос
Попытка 
        V8BAS = СомСоединение.Connect(СтрокаСоединения);
    Исключение
        ткошибка = ОписаниеОшибки();
        
        Подключение = Неопределено;
        СомСоединение = Неопределено;
        ПодклУстановлено = Ложь;
         Возврат Неопределено;
    КонецПопытки;    
    
    
    
    // получаем ТЗ из базы BAS
    ТекстЗапроса = "
        |ВЫБРАТЬ
        |    ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
        |    ХозрасчетныйОстатки.Субконто3 КАК Склад,
        |    ХозрасчетныйОстатки.КоличествоОстатокДт КАК КоличествоОстатокДт
        |ИЗ
        |    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаИтогов, Счет = &Счет, , ) КАК ХозрасчетныйОстатки
        |";

        
    ЗапросВнешнейБазы = V8BAS.NewObject("Запрос");
    ЗапросВнешнейБазы.Текст = ТекстЗапроса;
    
    
    // Присвоение значений переменным параметров.
    ДатаИтогов = Дата(2025, 06, 03, 00, 00, 00);
    
    V8ПланСчетов = V8BAS.NewObject("ПланыСчетов");
    
    Счет = V8ПланСчетов.Хозрасчетный.ТоварыНаСкладе;

    // Установка параметров.
    ЗапросВнешнейБазы.УстановитьПараметр("ДатаИтогов", ДатаИтогов);
    ЗапросВнешнейБазы.УстановитьПараметр("Счет", Счет);


    //ТЗОстаткиБух = ЗапросВнешнейБазы.Выполнить().Выгрузить();


V8ПланСчетов = V8BAS.NewObject("ПланыСчетов");

Счет = V8ПланСчетов.Хозрасчетный.ТоварыНаСкладе;
не отрабатывает
пытался также
| РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаИтогов, Счет.Код = "281", , ) КАК ХозрасчетныйОстатки
|";
тоже не хочет , помогите
andytg
Цитата(Profi_1C77 @ 03.06.25, 16:02) необходимо зарегистрироваться для просмотра ссылки
V8ПланСчетов = V8BAS.NewObject("ПланыСчетов");


не так

ЕМНИП, NewObject -- это для всевозможных таблиц значений, списков значений, запросов и т.д.

пробуйте так:

V8BAS = СомСоединение.Connect(СтрокаСоединения);
// ...
V8BAS.ПланыСчетов.Хозрасчетный.ТоварыНаСкладе  // или .НайтиПоКоду("281")
xlmel
Profi_1C77 @ Сегодня, 15:02 необходимо зарегистрироваться для просмотра ссылки ,
NewObject("ПланыСчетов") - это для всего, что создается через конструктор Новый в языке 1с, например, Новый запрос, Новый Структура и так далее.
Счет = V8BAS.ПланыСчетов.Хозрасчетный.ТоварыНаСкладе;
Обращение таким должно быть
andytg
Цитата(Profi_1C77 @ 03.06.25, 16:02) необходимо зарегистрироваться для просмотра ссылки
Счет = V8ПланСчетов.Хозрасчетный.ТоварыНаСкладе;

потому что вот тут у вас ком-объект в той базе, а не счет
надо
Счет = V8BAS.ПланыСчетов.Хозрасчетный.ТоварыНаСкладе;

это для вашего второго случая
Profi_1C77
Всем спасибо парни!
В итоге получил ТЗ которую 2 этапом засуну в отчет СКД и свяжу остатки
Код вышел примерно такой, новичкам на будущее ( это жестяк) :
&НаСервере
Функция ПолучитьТаблицуДанных(НачальнаяДата,КонечнаяДата) Экспорт
    ТЗОстаткиБух = Неопределено;
    СомСоединение = Новый COMОбъект("V83.ComConnector");    
    // параметры
    ПутьКБазе  = "***";
    Логин         = "**";
    Пароль     = "**";
    Серверная = Ложь;
    ткошибка ="";
    Подключение = Неопределено;
    СтрокаСоединения = ПутьКБазе+"Usr = """+СокрЛП(Логин)+"""; Pwd = """+СокрЛП(Пароль)+"""";
    Если НЕ Серверная Тогда                
        СтрокаСоединения = "File = """+СокрЛП(ПутьКБазе)+"""; Usr = """+СокрЛП(Логин)+"""; Pwd = """+СокрЛП(Пароль)+"""";
    КонецЕсли;  
    
    Попытка
        V8BAS = СомСоединение.Connect(СтрокаСоединения);
    Исключение
        ткошибка = ОписаниеОшибки();
        
        Подключение = Неопределено;
        СомСоединение = Неопределено;
        ПодклУстановлено = Ложь;
        Возврат ТЗОстаткиБух;
    КонецПопытки;    
    
    
    // получаем ТЗ из базы BAS
    ТекстЗапроса = "
    |ВЫБРАТЬ
    |    ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
    |    ХозрасчетныйОстатки.Субконто3 КАК Склад,
    |    ХозрасчетныйОстатки.КоличествоОстатокДт КАК Остаток
    |ИЗ
    |    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаИтогов, Счет.Код = &КодСчета, , ) КАК ХозрасчетныйОстатки
    |";
    
    
    ЗапросВнешнейБазы = V8BAS.NewObject("Запрос");
    ЗапросВнешнейБазы.Текст = ТекстЗапроса;
    
    //// Присвоение значений переменным параметров.
    //ДатаИтогов = Дата(2025, 06, 03, 00, 00, 00);
    ЗапросВнешнейБазы.УстановитьПараметр("ДатаИтогов", КонечнаяДата);
    ЗапросВнешнейБазы.УстановитьПараметр("КодСчета", "281");
    
    Выборка = ЗапросВнешнейБазы.Выполнить().Выбрать();
    
    ТЗОстаткиБух  = Новый ТаблицаЗначений;
    ТЗОстаткиБух.Колонки.Добавить("Наименование",ОбщегоНазначения.ОписаниеТипаСтрока(100));
    ТЗОстаткиБух.Колонки.Добавить("Код",ОбщегоНазначения.ОписаниеТипаСтрока(11));
    ТЗОстаткиБух.Колонки.Добавить("Склад",ОбщегоНазначения.ОписаниеТипаСтрока(50));        
    ТЗОстаткиБух.Колонки.Добавить("Остаток",ОбщегоНазначения.ОписаниеТипаЧисло(15,3));        
    
    Пока Выборка.Следующий() Цикл
        НС = ТЗОстаткиБух.Добавить();
        НС.Наименование =  Выборка.Номенклатура.НаименованиеПолное;
        НС.Код        =  Выборка.Номенклатура.Code;
        НС.Склад   =  Выборка.Склад.Description;
        НС.Остаток =  Выборка.Остаток;
        
    КонецЦикла;    
    
    Возврат ТЗОстаткиБух;
    
    
КонецФункции
andytg
Цитата(Profi_1C77 @ 03.06.25, 16:58) необходимо зарегистрироваться для просмотра ссылки
    
// получаем ТЗ из базы BAS
    ТекстЗапроса = "
    |ВЫБРАТЬ
    |    ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
    |    ХозрасчетныйОстатки.Субконто3 КАК Склад,
    |    ХозрасчетныйОстатки.КоличествоОстатокДт КАК Остаток
    |ИЗ
    |    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаИтогов, Счет.Код = &КодСчета, , ) КАК ХозрасчетныйОстатки
    |";


можно филиграннее попробовать (т.к. перебор в цикле и заполнение таблицы остатков может быть долгим, если у вас их много)

    // получаем ТЗ из базы BAS
    ТекстЗапроса = "
    |ВЫБРАТЬ
    |    ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто1.НаименованиеПолное КАК СТРОКА(100)) КАК Номенклатура,
    |    ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто3.Наименование КАК СТРОКА(50)) КАК Склад,
    |    ХозрасчетныйОстатки.КоличествоОстатокДт КАК Остаток
    |ИЗ
    |    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаИтогов, Счет.Код = &КодСчета, , ) КАК ХозрасчетныйОстатки
    |";
// ну и так далее, т.е. определяем все нужные поля сразу в запросе как вам надо


далее делаем так (без циклов):

ТЗОстаткиБух = ЗначениеИзСтрокиВнутр( V8BAS.ЗначениеВСтрокуВнутр(ЗапросВнешнейБазы.Выполнить().Выгрузить()));


не пробовал, но должно работать wink.gif
Profi_1C77
andytg @ Сегодня, 17:33 необходимо зарегистрироваться для просмотра ссылки ,
Работает, да это оптимальное icon_beer17.gif
andytg
Profi_1C77 @ Сегодня, 17:50 необходимо зарегистрироваться для просмотра ссылки ,
ну и дальше ставьте проверку обазательно

Если ТипЗнч(ТЗОстаткиБух ) = Тип("ТаблицаЗначений") Тогда
        // потому что если в ком-базе запрос почему-то там не выполнился, то вернется пустая строка

....
xlmel
Не обязательно выгружать данные в таблицу значений. Через ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр можно передать и результат выполнения запроса. Выгрузка в таблицу значений довольно ресурсоемкая операция и если планируется обход полученного результата, то лучше делать это через выборку. Вполне возможно, что стоит обработать полученные данные до того, как передать их в качестве объекта в отчет СКД
Profi_1C77
Итог , склеил строковые Номенклатура ( код) - Склад - Наименование в СКД , вообщем пока задержка до 2 мин норм
andytg
Profi_1C77 @ Вчера, 22:48 необходимо зарегистрироваться для просмотра ссылки ,
можете ключ для "склейки" бух. данных с управленческими строить еще в запросе в com-базе и сразу выгружать готовую колонку -- будет еще быстрее, плюс аналогичный ключ в запросе по управленческим данным уже в СКД и в этом же запросе левое соединение с бух.данными -- будет все строиться за один проход в одном запросе, не?

andytg @ Сегодня, 9:41 необходимо зарегистрироваться для просмотра ссылки ,
и групппировки по номенклатуре с суммами в com-запрос добавьте
Profi_1C77
andytg @ Сегодня, 9:50 необходимо зарегистрироваться для просмотра ссылки ,
Там в скд может быть вариант с запросам к бух остаткам и без, потому так пока удобнее;
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.