Механизм реализации "активных" отчетов



Posted by Васеленко Сергей, Фирма КАРДИНАЛ on August 27, 1999 at 01:24:43:

Предлагаю рассмотреть возможный механизм реализации "активных" отчетов, для построения более эффективного и интересного диалога с пользователями.

Такими отчетами в данный момент являются только системные формы.

Задача:

из формы на экране X ·x1·x2·...·xN·

по нажатию программируемой клавиши (функциональные, Enter, ...)

получить форму на экране Y ·y1·y2·...·yM·

При этом форма Y и ее параметры могут зависеть от положения селектора.
В данный момент селектор позиционируется только на строке.
Следовательно, пока можно сказать, что для принятия решения о форме Y следует знать:

текущую строку селектора
верхнюю строку селектора
нижнюю строку селектора

СО СТОРОНЫ КЛИЕНТА реализация выглядит следующим образом:

В текущем окне запроса R X ·x1·x2·...·xN·
нажата программируемая клавиша.
Следует выполнить запрос серверу на выполнение скрипта обработки, и сервер в ответ пришлет ОТВЕТ на запрос R Y ·y1·y2·...·yM·

Сама форма Y и ее параметры зависят от параметров, переданных скрипту и результата выполнения скрипта.

Далее форма Y обрабатывается как обычно.
Если это готовый отчет, то он выводится.
Если это уточнение, то задаются вопросы и т.д.

Единственное тонкое место - посылается запрос R <скрипт>, а результат возвращается R Y ...
Т.е. клиенту надо знать, какой запрос в дальнейшем обновлять.
Ведь если просто вернуть результат, то обновляться будет R <скрипт>, что не очень хорошо при каскадном погружении из отчета в отчет.

СО СТОРОНЫ СЕРВЕРА реализация выглядит следующим образом:

Поступил запрос R <скрипт>.
Выполни обработку и верни результат R Y ·y1·y2·...·yM·

С этой точки зрения скрипт это есть обычная отчетная форма, но требуется механизм замены ответа R <скрипт> на R Y ·y1·y2·...·yM·

Т.е. требуется некоторый аналог директивы N: но с выводом не в новое окно, а в то же окно, причем с извещением клиента о том, что автообновлять следует запрос
R Y ·y1·y2·...·yM·

Принципиальных проблем, по-моему, нет.

Требуется:
- доработка клиента на реагирование на программируемые клавиши
- доработка клиента на замену запроса R <скрипт> на R Y ·y1·y2·...·yM·
- доработка сервера на замену запроса R <скрипт> на R Y ·y1·y2·...·yM·

Но это позволит полностью "оживить" поведение любых форм.

Рассмотрим протокол передачи параметров скрипту. Назовем скрипт SCRIPT.RPT.

Следует передать:
- Запрос "откуда" X ·x1·x2·...·xN·
- Нажатую программируемую клавишу
- Строки селектора: текущую, верхнюю, нижнюю.

Количество параметров запроса Х может быть различным, поэтому следует передать:
- Количество параметров запроса Х.

Предлагаю следующий протокол (порядок):
- Клавиша
- Текущая строка
- Верхняя строка
- Нижняя строка
- Количество параметров запроса
- Форма Х
- Параметры запроса Х

Т.к. символ 250 (·) является разделителем параметров запроса по протоколу
обмена клиента и сервера, то строки селектора следует обрезать, если встретился
символ 250. Это будет гарантировать точность передачи параметров.

Обработчик входных параметров формы SCRIPT.RPT, процедура GETPAR:


*****************************************************************************
:GETPAR Получение входных параметров
*****************************************************************************
[p 1,[strip [is ' Клавиша: ' ,' ', 10]]]
[p 2,[strip [is ' Тек.строка: ' ,' ', 50]]]
[p 3,[strip [is ' Верх.строка: ' ,' ', 50]]]
[p 4,[strip [is ' Нижн.строка: ' ,' ', 50]]]
[p 5, [ir ' Кол-во пар-ров: ' , 0, 0]]
[p 6,[strip [is ' Форма Х: ' ,' ', 8]]]
*
for I=1 to [p 5]
[x I,[strip [is ' Пар-р X'+[intsn I]+': ',' ',50]]]
endfor
return
*****************************************************************************

Таким образом в массиве p будут постоянные передаваемые параметры,
а в массиве x будут параметры запроса X.

Рассмотрим реализацию скрипта SCRIPT.RPT для системных форм:


*****************************************************************************
call GETPAR Получение входных параметров
*
K =[p 1] Клавиша
X =[p 6] Форма, в которой нажата клавиша, - "Откуда"
*
if X='__SYS001' Обороты счетов
if K='ENTER'
if [cp [p 2],1,1]='L' Если нажато на строке субсчетов
S =[p 3] счет следует выделить из верхней строки
call GETLEXEM Выделение счета в переменную L
Y ='__SYS002' Форма, которая должна быть запущена,
[y 1,L] Ее параметры - счет
call EXECUTE_Y Формирование директивы запуска формы Y
else
S =[p 2] Счет следует выделить из текущей строки
call GETLEXEM
Y ='__SYS003'
[y 1,L]
call EXECUTE_Y
endif
elseif K='F9'
S =[p 2]
call GETLEXEM
Y ='__SYS005'
[y 1,L]
call EXECUTE_Y
else
endif
elseif X='__SYS002' Обороты субсчетов счета
if K='ENTER'
S =[p 2]
call GETLEXEM
Y ='__SYS003'
[y 1,L]
call EXECUTE_Y
elseif K='F9'
S =[p 2]
call GETLEXEM
Y ='__SYS005'
[y 1,L]
call EXECUTE_Y
else
endif
elseif X='__SYS003' Анализ счета
if K='ENTER'
* Здесь необходима директива вывода текущей операции
* по коду. Видимо, еще одна доработка сервера
* и/или клиента.
else
endif
elseif X='__SYS004' Анализ корреспонденции
if K='ENTER'
* Здесь необходима директива вывода текущей операции
* по коду. Видимо, еще одна доработка сервера
* и/или клиента.
else
endif
elseif X='__SYS005' Корреспонденции со счетами
if K='ENTER'
S =[p 2]
call GETLEXEM
Y ='__SYS004'
[y 1,L]
call EXECUTE_Y
elseif K='F6' Форма не зависит от селектора
Y ='__SYS006'
for I=1 to [x 0] Передаются все параметры формы Х
[y I,[x I]]
endfor
call EXECUTE_Y
else
endif
elseif X='__SYS006' Корреспонденции с субсчетами
if K='ENTER'
S =[p 2]
call GETLEXEM
Y ='__SYS004'
[y 1,L]
call EXECUTE_Y
elseif K='F6'
Y ='__SYS005'
for I=1 to [x 0] Передаются все параметры формы Х
[y I,[x I]]
endfor
call EXECUTE_Y
else
endif
else
* Возвращается пустота. Клиент ничего не делает.
endif
stop
*****************************************************************************
:EXECUTE_Y Формирование директивы запуска формы Y
*****************************************************************************
R ='R '+Y+' ' Запрос на выполнение формы Y
for I=1 to [y 0] Формирование строки параметров формы Y
R =R+'·'+[strip [y I]]
endfor
if [y 0]>0 Если были параметры, добавляем последнюю точку
R =R+'·'
endif
EXECUTE:^R^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* В этом месте формируется замена запроса R <скрипт> на R Y ...
return
*****************************************************************************
:GETLEXEM Выделение счета в переменную L
*****************************************************************************
if [ps ' ',S]>0
L =[cp S,1,[ps ' ',S]-1]
else
L =S
endif
return
*****************************************************************************

Работу скрипта я проверял. Работает в модификации UltraH только от 11.08.99 в связи с реализацией функции [ps ' ',...].

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

Буду рад, если эта технология получит применение и будет улучшена.



Пpишедшие ответы: