Компонента "Быстрый регистр" для 1С 7.7 (на прямых запросах SQL 1c++)

Ускорение операций с регистрами 1с 7.7 через объектную модель, за счет доступа через прямые запросы SQL (1c++). Существует возможность добавления произвольных подзапросов соединений c другими таблицами и отборов WHERE,   гибкой настройки вывода полей в результат

Установка:

Компонента реализована в виде класса 1С++. Подключение компоненты стандартно (прописывается строка c описанием класса) в файл defcls.prm в папке базы:

class БыстрыйРегистр = БыстрыйРегистр.ert
{}

 

Использование:


Создание экземпляра объекта БыстрыйРегистр:

БыстрыйРег = СоздатьОбъект(«БыстрыйРегистр»);

Перед каждым использованием желательно вызвать метод СброситьНастройки();

Чтобы отобрать по значению измерения (реквизита в случае движений) нужно перед получением данных вызвать метод ИспользоватьОтбор

ИспользоватьОтбор(ИмяРеквизитаОтбора , ЗначениеОтбора, ПризнакРазворачивания );

ИмяРеквизитаОтбора — Имя измерения или реквизита в виде строки

ЗначениеОтбора — Одно значение или список значений

ПризнакРазворачивания — Должно (1) или нет (0) попадать поле таблицы в группировку (в результирующие данные). Актуально для списков значений

Если отбор не осуществляется, но поле необходимо добавить в результат, нужно вызвать ВыводитьИзмерение

ВыводитьИзмерение(ИмяИзмерения, ТипИзмерения )

ТипИзмерения в виде «Справочник.МестаХранения», «Число» ….

Само получение данных осуществуляется вызовом следующих методов:

Функция ПолучитьОстатки(ИмяРегистра, ПолеКоличество = «Количество», ПолеСумма = «Сумма», МоментВремени = 0,
УсловиеСоединения = «», Параметры = «», СтандартныйРегистр = 0, СтрокаСортировки = «», ТЗ = «», СтрокаWHERE = «») Экспорт

Функция ПолучитьДвижения(ИмяРегистра, Регистратор = 0,
МоментВремениОт = 0, МоментВремениДо = 0,
ПолеКоличество = «Количество», ПолеСумма = «Сумма», СтандартныйРегистр = 0, ТЗ = «», СтрокаWHERE = «» ) Экспорт

ИмяРегистра — Имя регистра в кавычках (например, «ТоварыНаСкладах»)

ПолеКоличество, ПолеСумма — названия 1-го и 2-го ресурса (могут быть любыми, кол-во и сумма взяты для примера как самые распространенные )

МоментВремени (МоментВремениОт, МоментВремениДо) — дата или документ на который рассчитываются итоги или между которыми берутся движения

Регистратор — если нужно получить движения по данному регистратору (документу)

УсловиеСоединения — строка , в которой можно добавить соеднение с другими таблицами (см. пример ниже)

Параметры — список значений, в который передаются параметры (значение и имя параметра в качестве строкового описания значения в списке — см. пример ниже

СтрокаWHERE — строка, которая может быть поставлена в место для оператора WHERE

СтрокаСортировки  —  строка, которая может быть поставлена в место для оператора ORDER BY 

ТЗ — можно передать готовую ТЗ для уменьшения операций копирования (экономия памяти)

где возвращаемое значение — таблица значений с выходными полями измерений и реквизитов, а также ресурсов (максимальное количество ресурсов в данной реализации  — 2 (например, «Количество» и «Сумма»), но его не трудно расширить)

и упрощенной функции получения скалярного остатка:

Функция  ПолучитьОстаток(ИмяРегистра, ИмяРесурса, МоментВремени = 0, УсловиеСоединения = «», Параметры = «»)

Параметры данной функции аналогичны предыдущим

Кроме того, если используется соединение с другими таблицами (например, со Справочник.Номенклатура), то можно вывести поля из этой таблицы в результат с помощью метода ВыводитьПроизвольноеПоле:

ВыводитьПроизвольноеПоле(ИмяТаблицы, ИмяПоля)

ИмяТаблицы — имя таблицы, с которой идет соединение (ВНИМАНИЕ, если используется символ разыменования 1С++ «$» в запросе, то здесь он тоже должен быть указан!)

ИмяПоля — имя поля из этой таблицы


ПРИМЕР1 (получить скалярный остаток):

 Функция глПолучитьОстаток(Товар = «», Склад = «», Серия = «», Поставка = «», ДатаОстатков = 0,                              ДатаПроверкиПоставок = 0) Экспорт

БыстрыйРег.СброситьНастройки();
БыстрыйРег.ИспользоватьОтбор(«Товар», Товар);
Если Склад <> «» Тогда

БыстрыйРег.ИспользоватьОтбор(«Склад», Склад);

КонецЕсли;

Если Серия <> «» Тогда

БыстрыйРег.ИспользоватьОтбор(«Серия», Серия);

КонецЕсли;

Если Поставка <> «» Тогда

БыстрыйРег.ИспользоватьОтбор(«Поставка», Поставка);

КонецЕсли;

Если ДатаПроверкиПоставок <> 0 Тогда

Условие = «
| JOIN $Справочник.Поставки as Поставки ON ($Р.Поставка = Поставки.Id
| AND $Поставки.ДатаПоставки <= «+глСКЛПараметрДаты(«ДатаПроверкиПоставок») +«)»;
Параметры = СоздатьОбъект(«СписокЗначений»);
Параметры.Установить(«ДатаПроверкиПоставок», ?(ДатаПроверкиПоставок = 0, ТекущаяДата(), ДатаПроверкиПоставок));

Возврат БыстрыйРег.ПолучитьОстаток(«ОстаткиТоваров», «Количество», ДатаОстатков, Условие, Параметры);

Иначе

Возврат БыстрыйРег.ПолучитьОстаток(«ОстаткиТоваров», «Количество», ДатаОстатков);

КонецЕсли;

КонецФункции


ПРИМЕР2 (получить выборку остатков по настраиваемым условиям):

 Примечание: Все переменные списки могут быть как одиночными значениями, так и списками значений

Функция глПолучитьОстаткиПоТоварам(Склад = «», СписокТоваров = «», СписокСерий = «», СписокПоставок = «»,
РазворачиватьТовары = 1, РазворачиватьСерии = 1, РазворачиватьПоставки = 0, ДатаОстатков = 0, ДатаПроверкиПоставок = 0,
УчитыватьГорячийРезерв = 0, РазворачиватьСклады = 0, ПолучатьСертификационныеДанные = 0, ТЗ = «») Экспорт

БыстрыйРег.СброситьНастройки();
Если Склад <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Склад», Склад, РазворачиватьСклады);
ИначеЕсли РазворачиватьСклады = 1 Тогда
БыстрыйРег.ВыводитьИзмерение(«Склад», «Справочник.МестаХранения»);
КонецЕсли;

Если СписокТоваров <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Товар», СписокТоваров, РазворачиватьТовары);
ИначеЕсли РазворачиватьТовары = 1 Тогда
БыстрыйРег.ВыводитьИзмерение(«Товар», «Справочник.Товары»);
КонецЕсли;

Если СписокСерий <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Серия», СписокСерий, РазворачиватьСерии);
ИначеЕсли РазворачиватьСерии = 1 Тогда
БыстрыйРег.ВыводитьИзмерение(«Серия», «Справочник.Серии»);
КонецЕсли;

Если СписокПоставок <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Поставка», СписокПоставок, РазворачиватьПоставки);
ИначеЕсли РазворачиватьПоставки = 1 Тогда
БыстрыйРег.ВыводитьИзмерение(«Поставка», «Справочник.Поставки»);
КонецЕсли;

Условие = «»;

Если ПустоеЗначение(ДатаПроверкиПоставок) = 0 Тогда
Условие = «
| JOIN $Справочник.Поставки as Поставки « + ?(глСКЛ = 1,» WITH (nolock) «, » «) + » ON ($Р.Поставка = Поставки.Id
| AND $Поставки.ДатаПоставки <= «+ глСКЛПараметрДаты(«ДатаПроверкиПоставок») +«)»;
КонецЕсли;

Если ПолучатьСертификационныеДанные = 1 Тогда

Условие = Условие + «
| JOIN $Справочник.Товары as Товары « + ?(глСКЛ = 1,» WITH (nolock) «, » «) + » ON ($Р.Товар = Товары.Id)
| LEFt JOIN $Справочник.СтавкиНДС СтавкиНДС ON СтавкиНДС.Id = $Товары.СтавкаНДС»;

БыстрыйРег.ВыводитьПроизвольноеПоле(«$Товары», «СрСебестоимость»);
БыстрыйРег.ВыводитьПроизвольноеПоле(«$СтавкиНДС», «Ставка»);
Условие = Условие + «
| JOIN $Справочник.Серии as Серии « + ?(глСКЛ = 1,» WITH (nolock) «, » «) + » ON ($Р.Серия = Серии.Id)»;
БыстрыйРег.ВыводитьПроизвольноеПоле(«$Серии», «СрокГодности»);

Условие = Условие + «
| JOIN $Справочник.Сертификаты as Сертификаты « + ?(глСКЛ = 1,» WITH (nolock) «, » «) + » ON ($Поставки.Сертификат = Сертификаты.Id)»;

Для Сч = 1 По глСписРегионы.РазмерСписка() Цикл
Стр = 0;
глСписРегионы.ПолучитьЗначение(Сч, Стр);
БыстрыйРег.ВыводитьПроизвольноеПоле(«$Сертификаты», «Статус» + Стр, «Перечисление.СтатусыСерий»);
КонецЦикла;
КонецЕсли;

Если УчитыватьГорячийРезерв = 1 Тогда
Условие = Условие + «
| JOIN $Справочник.ПрайсЛист « + ?(глСКЛ = 1,» WITH (nolock) «, » «) + » as ПрайсЛист ON ($Р.Товар = $ПрайсЛист.Товар)»;
БыстрыйРег.ВыводитьПроизвольноеПоле(«$ПрайсЛист»,«КоличествоГорРезерв»);
КонецЕсли;

Параметры = СоздатьОбъект(«СписокЗначений»);
Параметры.Установить(«ДатаПроверкиПоставок», ?(ДатаПроверкиПоставок = 0, ТекущаяДата(), ДатаПроверкиПоставок));

Если ТЗ = «» Тогда
ТЗ = СоздатьОбъект(«ТаблицаЗначений»);
КонецЕсли;

БыстрыйРег.ПолучитьОстатки(«ОстаткиТоваров», , «», ДатаОстатков, Условие, Параметры,,, ТЗ);
БыстрыйРег.РежимОтладки = 0;

Возврат ТЗ;

КонецФункции



ПРИМЕР3 (получить выборку движений):


 

Функция глПолучитьДвиженияПоРегиструОстатков(ДатаОт = 0, ДатаДо = 0, Склад,
СписокТоваров = «», СписокСерий = «», СписокПоставок = «», Док = 0, РазворачиватьСклады = 0) Экспорт

БыстрыйРег.СброситьНастройки();

Если Склад <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Склад», Склад, 1);
ИначеЕсли РазворачиватьСклады = 1 Тогда
БыстрыйРег.ВыводитьИзмерение(«Склад», «Справочник.МестаХранения»);
КонецЕсли;

Если СписокТоваров <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Товар», СписокТоваров, 1);
КонецЕсли;

Если СписокСерий <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Серия», СписокСерий, 1);
КонецЕсли;

Если СписокПоставок <> «» Тогда
БыстрыйРег.ИспользоватьОтбор(«Поставка», СписокПоставок, 1);
КонецЕсли;

Возврат БыстрыйРег.ПолучитьДвижения(«ОстаткиТоваров», Док ,ДатаОт, ДатаДо, , «» );

КонецФункции




 


 


 

6 Comments

  1. Rothschild

    Смотрю еще кто-то что-то для 7.7 делает,

    да еще нетривиальное — на прямых запроса.

    ***

    смотрю примерчики в статье все для SQL



    а что будет в DBF…в монопольном режиме…при проведении документа?

    Reply
  2. Rothschild

    (0) victor_goodwill,

    PS

    Использование слова «компонента» в названии статьи — не очень удачно.

    Есть устаявшаяся ассоциация этого слова с понятием «внешней компаненты».

    Такое название вносит определенное непонимание.

    Народ читает и думает — «вот очередной костыль к 1С»

    Назови уж статью гордо:

    «Класс «Быстрый регистр»».

    Заодно позлишь ортодоксов от 1С, люто ненавидящих ООП.

    😉

    Reply
  3. victor_goodwill

    Спасибо за отзыв!

    Изначально класс разрабатывался именно под DBF и служил верою и правдою чуть больше года на базе до 2ГБ (сейчас база выросла до 7 Гб на SQL Express)

    Да в монопольном режиме там стоит вызов стандартных регистров (они вообще лучше оптимизированы под монопольный режим)

    Совместимость с DBF уже не поддерживалась давно, но вернуть ее при необходимости думаю не сложно.

    Насчет изменения заголовка статьи я подумаю. Согласен, что это не совсем корректное строго говоря название, но «класс» боюсь будет непонятно многим 1С-прогам, а с точки зрения использования, он немного напоминает внешнюю компоненту, поэтому остановился на таком названии 🙂

    Reply
  4. Rothschild

    (3) victor_goodwill,

    для DBF в монопольном режиме могу посоветовать 1sqlite.dll

    совместно с 1cpp.dll.

    ***

    первая обеспечит прямые запросы к базе

    ну а вторая нужна для поддержки классов.

    Reply
  5. victor_goodwill

    Спасибо, очень интересно… такую компоненту еще не пробовал использовать.

    Правда уже может и не попробую — все таки, думаю, что уже будем переходить на 8 -ку и на 7-ке разработки постепенно будут свернуты 🙂

    Reply
  6. NoRazum

    Обработка немного не допилиная.

    Есть процедуры и функция не дописанные в обработке)

    Нужно дорабатывать напильником.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *