Доброго дня, господа!
Сложилась такая ситуация, что нужно в базу 8, перегрузить справочник номенклатура, из базы на 7.7, причем делать это в регламентном задании на стороне 8 (клиент-серверная), после первоначальной загрузки в последующих "синхронизациях" нужно проверять на изменение наименования / полного наименования. Честно говоря раньше с такими задачами не сталкивался.
накидал вот такой код
V77 = Новый COMОбъект("V77.Application");
Запрос = V77.CreateObject("Запрос");
ТекстЗапроса=
"//{{ЗАПРОС(Сформировать)
|Обрабатывать НеПомеченныеНаУдаление;
|Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
|Код = Справочник.Номенклатура.Код;
|Наименование = Справочник.Номенклатура.Наименование;
|Родитель = Справочник.Номенклатура.Родитель.Наименование;
|РодительКод = Справочник.Номенклатура.Родитель.Код;
|Группировка Номенклатура;
|";//}}ЗАПРОС
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
ОбщегоНазначения.СообщитьОбОшибке("Ошибка выпонения запроса номенклатуры в базе-источнике");
Возврат;
КонецЕсли;
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Код",,,15);
Таблица.Колонки.Добавить("Наименование",,,50);
Таблица.Колонки.Добавить("Родитель",,,50);
Таблица.Колонки.Добавить("РодительКод",,,15);
Таблица.Колонки.Добавить("ЭтоГруппа",,,1);
Пока Запрос.Группировка() Цикл
Строка = Таблица.Добавить();
Строка.ЭтоГруппа = Запрос.Номенклатура.ЭтоГруппа();
Строка.Код = Запрос.Код;
Строка.Наименование = Запрос.Наименование;
Строка.Родитель = Запрос.Родитель;
Строка.РодительКод = Запрос.РодительКод;
КонецЦикла;
V77 = "";
Но это только заполнение таблицы для последующей ее обработки, 36 тысяч элементов, заполняется почти 4 минуты, можно ли как то ускорить, хотя как, я особо не понимаю, но все же. Плюс может есть-какой то другой путь решения задачи ?
Группировка номенклатура без групп без упорядочивания
.
Тз = создатьобьект("таблицазначений")
Запрос.выгрузить(таблицазначений,....)
Н хрена непонятно про изменение наименования. Где может происходить - только на стороне 77? Если номенклатура в 77 изменяется !!! Только интерактивно!!! Заведи в спр. Номенклатура флаг с сортировка=1, при изменении взводи его, в запросе фильтруй по условию флаг=взведен, после отработки регзадания в конце его сбрасывай в 77 флаг. Первый регламент отработает медленно, остальные будут быстро.
При сбросе флага делай в транзакции по например 10 элементов, чтобы если какой дятел держит номенклатуру открытой - чтобы не сломалось. Сброс флага делай в попытке. Если очередная порция не прошла в транзакции - да и хрен с ней, при следующем регламенте пройдёт.
.
Или контроль изменений номенклатуры регистрируй штатно с использованием УРБД. Регламент будет подчищать таблицу изменений. Можно без урбд, служебный справочник изменений куда писать ссылку на номенклатуру которая изменилась и запрос только по этому списку.
.
Ну или проще всего прямым запросом
Если база файловая - с использованием 1sqlite прямой запрос. Ну и скульную базу тоже можно прямым запросом.
Ускорение на 1-2 порядка будет.
А если еще между регламентами закешировать verstamp элементов справочника и в прямом запросе фильтровать к отбору по несовпадающим верстамп (он у элемента меняется при каждой модификации) то вообще время мизер будет
В 77 поставить по умолчанию режим открытия "для просмотра" ибо нехер открыть, посмотреть и жать ОК.
Это я так, в порядке дежурного бреда накидал, топая пешком домой.
Гуры и сенсейбабаи поправят.
Изменения наименования/полного наименования я бы вообще контролировать забил. Чек только на изменение элемента как факт.
Если номенклатура (наименования) может меняться на двух сторонах - ССЗБ.
Схемы примерно те же самые с добавкой контроля изменений на снеговике
ВЫбросить нафиг ком соединение, делать через файл, самое простое dbf. На стороне 7.7 выгружаешь роботом по расписанию каждую ночь к примеру, а на стороне 8-ки загружаешь из файла. Работает такое фиг знает сколько лет и хлеба не просит. Чтобы уменьшить объем, у нас в номенклатуре 7.7 есть спецполе дата последнего редактирования, и в выгрузку выгружаем только измененные за последние несколько дней
ЗЛОП - спасибо за ответы.
Базы обе SQL правда лежат на разных серверах, прямые запросы в клюшках умею, а как из снеговика добраться до базы SQL 7.7 не умею...буду благодарен за пример.
А почему Группировка номенклатура без групп без упорядочивания - как тогда структуру справочника повторить если групп не будет ?
vladmenleo - чета dbf - совсем как то по олдскульному, но тоже как вариант.
Ну не хочешь по олдскульному, юзай xml к примеру. Хозяин барин ;D
Цитата: SnakePlisskin от 30 августа 2025, 08:39ЗЛОП - спасибо за ответы.
чета dbf - совсем как то по олдскульному, но тоже как вариант.
Дбф читается очень быстро
Например (ADODB):
(ТекстЗапроса - нормальный SQL-запрос)
Функция СоединениеСКЛ(ИмяСервера, ИмяПользователя, ПарольПользователя, ИмяБазы = "") Экспорт
Если НЕ ЗначениеЗаполнено(ИмяСервера) Тогда
Возврат Неопределено;
ИначеЕсли НЕ ЗначениеЗаполнено(ИмяПользователя) Тогда
Возврат Неопределено;
КонецЕсли;
ConnectionString = "Driver={SQL Server Native Client 11.0};Server="+ИмяСервера+";uid="+ИмяПользователя;
Если НЕ ПустаяСтрока(ПарольПользователя) Тогда
ConnectionString = ConnectionString + ";pwd="+ПарольПользователя;
КонецЕсли;
Если ИмяБазы <> "" Тогда
ConnectionString = ConnectionString + ";Database="+ИмяБазы;
КонецЕсли;
СоединениеСКЛ = Новый COMОбъект("ADODB.Connection");
СоединениеСКЛ.ConnectionTimeout = 5;
СоединениеСКЛ.CommandTimeout = 0;
СоединениеСКЛ.CursorLocation = 3;
СоединениеСКЛ.Provider = "MSDASQL";
СоединениеСКЛ.ConnectionString = ConnectionString;
Попытка
СоединениеСКЛ.Open();
Исключение
Сообщить(ОписаниеОшибки());
СоединениеСКЛ = Неопределено;
КонецПопытки;
Возврат СоединениеСКЛ;
КонецФункции
Функция ВыполнитьИнструкцию(Соединение, ТекстЗапроса) Экспорт
ТЗ = Новый ТаблицаЗначений;
Если Соединение = Неопределено Тогда
Сообщить("Соединение не установлено", СтатусСообщения.Внимание);
Возврат Неопределено;
КонецЕсли;
cmd = Новый COMОбъект("ADODB.Command");
cmd.CommandTimeout = 0;
cmd.ActiveConnection = Соединение;
cmd.CommandText = ТекстЗапроса;
rs = cmd.Execute();
Fields = Rs.Fields;
nFields = Fields.Count;
Колонки = ТЗ.Колонки;
мКолонки = новый массив(nFields);
Для нПоле = 0 По nFields-1 Цикл
ИмяКолонки = Fields.Item(нПоле).Name;
мКолонки[нПоле] = ИмяКолонки;
Колонки.Добавить(ИмяКолонки);
КонецЦикла;
Если Не Rs.eof Тогда
rs.MoveFirst();
КонецЕсли;
Пока Не Rs.eof Цикл
стрТЗ = ТЗ.Добавить();
Для каждого ИмяКол из мКолонки Цикл
Значение = Fields.Item(ИмяКол).Value;
Если Значение <> Null Тогда
стрТЗ[ИмяКол] = Значение;
КонецЕсли;
КонецЦикла;
rs.MoveNext();
КонецЦикла;
Возврат ТЗ;
КонецФункции
Функция ВыполнитьСкалярный(Соединение, ТекстЗапроса) Экспорт
стРез = Неопределено;
cmd = Новый COMОбъект("ADODB.Command");
cmd.CommandTimeout = 0;
cmd.ActiveConnection = Соединение;
cmd.CommandText = ТекстЗапроса;
rs = cmd.Execute();
Fields = Rs.Fields;
//Ничего не получилось в результате
Если Rs.EOF И Rs.BOF Тогда
Возврат НЕопределено;
КонецЕсли;
rs.MoveFirst();
Пока Не Rs.EOF Цикл
стРез = Новый Структура;
Для каждого Поле из Fields Цикл
ИмяКол = Поле.Name;
Значение = Поле.Value;
стРез.Вставить(ИмяКол, Значение);
КонецЦикла;
Прервать;
КонецЦикла;
Возврат стРез;
КонецФункции
Стоит упомянуть, что это реализованный функционал в типовой бухгалтерии 7.70.671 (начиная с 7.70.564 - 12 лет в обед) - обработка ПомощникПереходаНа1С8 умеет делать синхронизацию справочников и документов. Вот это вот все: "Справочник.ПараметрыСинхронногоУчета", "Справочник.МенеджерВыгрузок", "Справочник.МодифицированныеОбъекты", глУчестьЭлементПриИзменении, глУчестьДокументПриИзменении, ACC_ACC8.ert etc. При желании можно и с этими поразбираться и стащить себе схему работы. Я бы, если честно, не стал.
+Вопрос: в исходном коде Строка.Родитель и Строка.РодительКод разве заполнены после выполнения запроса?
Цитата: Харлампий Дымба от 01 сентября 2025, 11:15Стоит упомянуть, что это реализованный функционал в типовой бухгалтерии 7.70.671 (начиная с 7.70.564 - 12 лет в обед) - обработка ПомощникПереходаНа1С8 умеет делать синхронизацию справочников и документов. Вот это вот все: "Справочник.ПараметрыСинхронногоУчета", "Справочник.МенеджерВыгрузок", "Справочник.МодифицированныеОбъекты", глУчестьЭлементПриИзменении, глУчестьДокументПриИзменении, ACC_ACC8.ert etc. При желании можно и с этими поразбираться и стащить себе схему работы. Я бы, если честно, не стал.
+Вопрос: в исходном коде Строка.Родитель и Строка.РодительКод разве заполнены после выполнения запроса?
А вот кстати, да я сейчас посмотрел...родитель и родитель код - для элементов заполнены вообще не правильно, а для самих групп - просто пусто все.
Пошел немного по другому пути, сделал обработку того что мне нужно на стороне 7.7, в 8 сделал вызов функции из 7.7, функция возвращает нужную мне тз , вот только уперся в то что, 8-ка определяет ее просто как COM объект, как побороть ?
Таблица = Новый ТаблицаЗначений;
Таблица = V77.глПолучитьРезультатЗапросаДля83();
Попробовал так :
СтрокаРезультат = V77.ValueToStringInternal(V77.глПолучитьРезультатЗапросаДля83());
Таблица = ЗначениеИзСтрокиВнутр(СтрокаРезультат);
Ошибка формата потока.
Ну так структура внутренняя у ТЗ в клюшках и снеговике - разная, чего ж ты хотел...
.
Пусть тебе клюшечная функция возвращает не ТЗ, а, например, XML или джсон и разбирай их в снеговике штатными средствами.
.
Опять же ничто не мешает в снеговике работать с объектами клюшек
Пишешь в снеговике типа
V77.тз.Выбратьстроки() - и это выполняется в контексте клюшек
Цитата: Злоп от 02 сентября 2025, 16:20Ну так структура внутренняя у ТЗ в клюшках и снеговике - разная, чего ж ты хотел...
.
Пусть тебе клюшечная функция возвращает не ТЗ, а, например, XML или джсон и разбирай их в снеговике штатными средствами.
.
Опять же ничто не мешает в снеговике работать с объектами клюшек
Пишешь в снеговике типа
V77.тз.Выбратьстроки() - и это выполняется в контексте клюшек
Не совсем понял, а как работать вот с этим "V77.тз.Выбратьстроки()" - если на стороне снеговика клюшечная функция возвращает ТЗ а снеговик ее воспринимает как COM объект ?
Все эти мытарства, получились из за того что ссылочные реквизиты в номенклатуре, видятся в снеговике как COMобъекты, банально не понятно как определить ВидНоменклатуры - Товар или Услуги, реквизит которой имеет ссылочный тип...как до него добраться в снеговике ?
Ну а как ты в 8ке передашь тз на форму, без массива массивов?
Вроде везде, тз, тз, и тз... Но они все разные тз, просто называются одинаково.
Смирись. Либо сереиализация, через что угодно, либо через файл.
Цитата: Djelf от 02 сентября 2025, 16:52Ну а как ты в 8ке передашь тз на форму, без массива массивов?
Вроде везде, тз, тз, и тз... Но они все разные тз, просто называются одинаково.
Смирись. Либо сереиализация, через что угодно, либо через файл.
А мне не нужна тз на форме - я хотел таблицу значений сформировать в глобальнике - в 7.7, заодно убрав все не примитивные типы, а в снеговике просто получить эту таблицу значений и сделать уже с ней все что нужно
Не совсем понял, а как работать вот с этим "V77.тз.Выбратьстроки()" - если на стороне снеговика клюшечная функция возвращает ТЗ?
-
1. Могу тупить/путать
2. Вариант ТИПА v77.тз. Выбратьстроки()
Выполняется не в контексте снеговика, а в контексте клюшек.
Тз при этом д. Б. Доступна в контексте клюшек, т.е. быть глобальной переменной экспортной. Для этой цели в типовых достаточно глобальных переменных таких, типа глРасшифровка, глУсловие и прочих
Цитата: Злоп от 02 сентября 2025, 18:52Не совсем понял, а как работать вот с этим "V77.тз.Выбратьстроки()" - если на стороне снеговика клюшечная функция возвращает ТЗ?
-
1. Могу тупить/путать
2. Вариант ТИПА v77.тз. Выбратьстроки()
Выполняется не в контексте снеговика, а в контексте клюшек.
Тз при этом д. Б. Доступна в контексте клюшек, т.е. быть глобальной переменной экспортной. Для этой цели в типовых достаточно глобальных переменных таких, типа глРасшифровка, глУсловие и прочих
Короче вот так работает.
тзИзКлюшек = V77.глПолучитьРезультатЗапросаДля83();
тзИзКлюшек.ВыбратьСтроки();
Пока тзИзКлюшек.ПолучитьСтроку() = 1 Цикл
Строка = Таблица.Добавить();
КонецЦикла;
V77 - это COM соединение.
глПолучитьРезультатЗапросаДля83() - функция в глобальнике в клюшках которая формирует таблицу.
типа так.
если углубится, то сможешь воперировать агрегатными объектами 77 прямо из снеговика.
у меня была мега сверочная обработка по Оле (тот же ком?) между двумя базами 77. выборки, сверки ииже бубмли хуяси сесренький козлик. Правда это работало только потому что я не контролировал работу обработки а бил ломом по лицу бухам (условно). Ну не могут они мыслить синтетически/аналитически (по крайне мере рядовые бухи коих тьма), пока не пнешь с пенделя - так и будут сопли жевать или тупить глядя в экран - судя по всему наличие компа окончательно разорвало понимание связей и взаимодействий. Пора возвращаться к бумажным журналам-ордерам и ведомостям. Полная деградация. НУ или я просто злоп. У них 4 - это 2+2. а то что это вообще-то 1+3, 1+1+1+1, 2+1+1 - это где-то в другой вселенной.. некромонгеров...
Встречал весьма адекватных бухов, с которыми работать - как журнал "Лиза" - одно удовольствие (мужской вариант журнала - "Лизун"), но в большинстве - просто нажиматели кнопок, карго-культ... я один такой?
Написал на стороне клюшек, функцию через прямой запрос со всеми данными, которые нужны, попутно переведя все что нужно в примитивные типы, на стороне 8-ке только построчно получаю таблицу и уже загружаю в тз снеговика, далее дисконект от базы 7.7, осталось разобраться с зоопарком единиц измерения...
Я использую два варианта для совместной работы 1С77 и 1С83. Если нет какой-то суперсложной логики со стороны 77, то 83 прямым запросом лезет в SQL-базу 77. Если на 77 нужно обработать данные по сложным алгоритмам, то используется web-сервер. Есть компонента AddIn.HTTPSrv7 на Инфостарте, которая позволяет 77 выступать web-сервером. Очень прилично и быстро работает. Я обмениваюсь данными в JSON, но не критично. Веб-сервер часто месяцами работает. Нагрузка средняя - в районе 1600 запросов в сутки. Главный плюс использования веб-запросов - ураганная скорость, т.к. можно использовать всякие кэши. Типичный запрос выполняется 10-40 мс + накладные расходы на формирование и передачу запроса, которые очень небольшие. Поэтому синхронизация может выполняться почти непрерывно. У меня такая логика реализована - при создании/изменения в 83, например, пациента, в очередь отправляются данные, что этот элемент надо выгрузить в 77. Раз в 30 секунд происходит выгрузка всех накопившихся данных. Если выгрузить не удалось (веб-сервер подвис, ошибка приключилась), то данные будут накапливаться. Со стороны 77 можно было реализовать так же, но исторически сложилось так, что 83 все изменившиеся данные забирает периодически напрямую из SQL 77. Там в элементах есть реквизит со временем последнего изменения. 83 помнит последнее загруженное изменение и выбирает элементы, которые имеют реквизит с бОльшим временем. Для установки такого реквизита можно использовать триггеры, тогда не приходится вручную следить за его обновлением.
Цитата: Ветер в поле от 04 сентября 2025, 11:54Я использую два варианта для совместной работы 1С77 и 1С83. Если нет какой-то суперсложной логики со стороны 77, то 83 прямым запросом лезет в SQL-базу 77. Если на 77 нужно обработать данные по сложным алгоритмам, то используется web-сервер. Есть компонента AddIn.HTTPSrv7 на Инфостарте, которая позволяет 77 выступать web-сервером. Очень прилично и быстро работает. Я обмениваюсь данными в JSON, но не критично. Веб-сервер часто месяцами работает. Нагрузка средняя - в районе 1600 запросов в сутки. Главный плюс использования веб-запросов - ураганная скорость, т.к. можно использовать всякие кэши. Типичный запрос выполняется 10-40 мс + накладные расходы на формирование и передачу запроса, которые очень небольшие. Поэтому синхронизация может выполняться почти непрерывно. У меня такая логика реализована - при создании/изменения в 83, например, пациента, в очередь отправляются данные, что этот элемент надо выгрузить в 77. Раз в 30 секунд происходит выгрузка всех накопившихся данных. Если выгрузить не удалось (веб-сервер подвис, ошибка приключилась), то данные будут накапливаться. Со стороны 77 можно было реализовать так же, но исторически сложилось так, что 83 все изменившиеся данные забирает периодически напрямую из SQL 77. Там в элементах есть реквизит со временем последнего изменения. 83 помнит последнее загруженное изменение и выбирает элементы, которые имеют реквизит с бОльшим временем. Для установки такого реквизита можно использовать триггеры, тогда не приходится вручную следить за его обновлением.
А есть пример работы с данными SQL базы 7.7 напрямую из 8 ? Ибо уже сутки бьюсь с COM объектом в клиент серверном варианте...пока толку 0.
Цитата: SnakePlisskin от 04 сентября 2025, 14:36А есть пример работы с данными SQL базы 7.7 напрямую из 8 ? Ибо уже сутки бьюсь с COM объектом в клиент серверном варианте...пока толку 0.
К сожалению, я не имею доступа к кодам 83. Я отвечаю только за 77.
Знаю, что таблицы 77 в конфигурации 83 подключены через Внешние источники. Тогда в запросах можно использовать русские наименования таблиц и их реквизитов, а не всякие SC1017.SP1020
Хотя вот нашел пример вызова хранимой процедуры, возвращающая набор строк. Но писал это "специалист" ПервогоБита, которые те еще студенты, но некоторое представление о коде дает.
Попытка
ADOСоединение = Новый COMОбъект("ADODB.Connection");
ADOСоединение.ConnectionString = "Driver={SQL Server};Server=192.168.1.163;Database=EC;Uid=v8;Pwd=123456;";
ADOСоединение.Open();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Command = Новый COMObject("ADODB.Command");
Command.ActiveConnection = ADOСоединение;
ТекстЗапроса = "v8_getAnalysisListByPatient";
Command.CommandText = ТекстЗапроса;
Command.CommandType = 4;
Command.Parameters(1).value = Структура.ИД;
Результат = Command.Execute();
Массив = Новый массив;
Если НЕ Результат.EOF() Тогда
МассивСтруктур = Новый Массив;
Пока Результат.EOF() = 0 Цикл
КолКолонок = Результат.Fields.Count();
Строка = Новый Структура;
Для Инд = 0 По КолКолонок-1 Цикл
Строка.Вставить(Строка(Результат.Fields(Инд).Name),Строка(Результат.Fields(Инд).Value));
КонецЦикла;
Массив.Добавить(Строка);
Результат.MoveNext();
КонецЦикла;
КонецЕсли;