gifts2017

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

Опубликовал Victor Kostenich (victor_goodwill) в раздел Программирование - Универсальные функции

Ускорение операций с регистрами 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);
КонецЕсли;

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

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




 


 


 

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Реализация класса + Файл описания класса (пример)
.zip 14,45Kb
09.01.14
6
.zip 0.99 14,45Kb 6 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Nathan Rothschild (Rothschild) 13.01.14 16:17
Смотрю еще кто-то что-то для 7.7 делает,
да еще нетривиальное - на прямых запроса.
***
смотрю примерчики в статье все для SQL
...
а что будет в DBF...в монопольном режиме...при проведении документа?
2. Nathan Rothschild (Rothschild) 13.01.14 18:18
(0) victor_goodwill,
PS
Использование слова "компонента" в названии статьи - не очень удачно.

Есть устаявшаяся ассоциация этого слова с понятием "внешней компаненты".
Такое название вносит определенное непонимание.
Народ читает и думает - "вот очередной костыль к 1С"

Назови уж статью гордо:
"Класс "Быстрый регистр"".

Заодно позлишь ортодоксов от 1С, люто ненавидящих ООП.
;)
3. Victor Kostenich (victor_goodwill) 14.01.14 13:29
Спасибо за отзыв!

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

Насчет изменения заголовка статьи я подумаю. Согласен, что это не совсем корректное строго говоря название, но "класс" боюсь будет непонятно многим 1С-прогам, а с точки зрения использования, он немного напоминает внешнюю компоненту, поэтому остановился на таком названии :)
4. Nathan Rothschild (Rothschild) 14.01.14 13:37
(3) victor_goodwill,
для DBF в монопольном режиме могу посоветовать 1sqlite.dll
совместно с 1cpp.dll.
***
первая обеспечит прямые запросы к базе
ну а вторая нужна для поддержки классов.
5. Victor Kostenich (victor_goodwill) 14.01.14 14:13
Спасибо, очень интересно... такую компоненту еще не пробовал использовать.
Правда уже может и не попробую - все таки, думаю, что уже будем переходить на 8 -ку и на 7-ке разработки постепенно будут свернуты :)
6. Юрий Патласов (NoRazum) 19.06.15 17:58
Обработка немного не допилиная.
Есть процедуры и функция не дописанные в обработке)

Нужно дорабатывать напильником.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа