[SQL, Функциональное программирование] Как в ЦФТ реализовать то, что мы всегда делали в Бисквите (с примерами)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет, Хабр!Редакторы советуют начинать статью именно с такого приветствия, ну так я спорить не буду:) Меня зовут Баранов Михаил, работаю программистом более 20 лет. В далеком, примерно 2003-м, году умные люди мне сказали: «Бросай этот язык программирования Progress 4Gl, он устарел, срочно переходи на какой-нибудь другой». Я не согласился. «На этом языке написано несколько банковских систем, и я буду востребован», - подумал я. Тогда я устроился работать с банковской системой Банкир/Про, написанной на языке Progress. Работал с ней около 5 лет. Но потом банки стали от нее отказываться. Тогда я стал работать с системой Бисквит тоже написанной на языке Progress. Прошло еще 10 лет и от Бисквита стали банки отказываться. И вот в 2019 году я оказался в крайне неприятной ситуации: я отлично знаю только то, что уже мало кому нужно. Осенью 2019 года я получил отличное предложение от РСХБ-ИНТЕХ, где я сейчас и работаю. Я устроился туда выполнять задачи по разработке в системе Бисквит и одновременно изучать систему ЦФТ на языке программирования Pl Plus. Уже на испытательном сроке мне назначили 14 учебных курсов на учебном портале ЦФТ и стали давать элементарные задачки по разработке в системе ЦФТ. А примерно с лета 2020 года я полностью перешел на разработку в системе ЦФТ (и этому очень рад). Эта статья о том, как сделать в ЦФТ то, что мы привыкли делать в Бисквите. Начинал я ее писать только для себя, чтобы упорядочить свои знания. Однако потом оказалась, что эта тема важна для всех разработчиков, которые переходят на ЦФТ и не только с Бисквита. Именно поэтому я решил разместить ее на Хабре. Покажу на примерахПримеры из Бисквита будут курсивом, примеры из ЦФТ - жирные или виде блоков кода:Сообщение в поток:MESSAGE “Hello world”.
debug_pipe('Hello world', 0);
Сообщение в окно:MESSAGE “Hello world” VIEW-AS ALERT-BOX.
debug('Hello world', 0);
Операторы:+ (для цифр) ++ (для строк) || (конкатенация)= (для сравнения) == (для присваивания) :=<> !=В остальном так же.Если: if ….. then do: программный код end.else do: программный кодend.
If …. then
программный код
elsif …. then
программный код
else
программный код
end if;
Разбор строк через разделитель:ENTRY
Inp_str string; --строка для разбора с разделителем ‘;’
item_command rtl.string_table; --специальный массив
item_command := STR_2.split(p_expression == Inp_str, p_delimiter == ';');
debug_pipe(item_command(1) , 0); -- Это как MESSAGE ENTRY(1…
debug_pipe(item_command(2) , 0); -- Это как MESSAGE ENTRY(2…
Выбор данных из базы1) Простой поиск уникальной записи в таблице (в ТБП)FINDПример: Поиск счета по номеру
s_ac_str string_100; --входная строка с номером счета
r_ac_fin ref [AC_FIN]; --ссылка на счет
r_AC_FIN := ::[AC_FIN]([MAIN_V_ID] = s_ac_str); --получение ссылки
debug_pipe(‘Имя счета: ‘ || r_AC_FIN.[NAME], 0); --вывод в сообщение имени счета
При таком поиске нужно быть уверенным, что запись существует и что запись действительно уникальная. Если уверенности нет, то его применять нельзя.Также в ЦФТ есть важная особенность. В нем, в отличие от Бисквита, часто записи вообще не нужно искать, чтобы получить из них информацию. В этом помогает механизм, который называется «разыменованность».Пример: У нас есть ссылка на счет (нашли в предыдущем примере), а нам нужно вывести имя владельца счета. Это имя лежит в другой таблице клиентов CLIENT, но нам не нужно там осуществлять поиск самой записи, достаточно написать так:
debug_pipe(r_AC_FIN. [CLIENT_V].[NAME], 0);
В реквизите CLIENT_V на счете хранится ссылка на клиента - владельца счета.2) Поиск первой записи с обработкой ситуации, когда запись не найдена.FIND FIRST …… NO-ERROR.….IF NOT AVAILABLE…..
s_ac_str string_100; --входная строка с номером счета
r_ac_fin ref [AC_FIN]; --ссылка счет
begin
locate r_ac_fin in ::[AC_FIN]
where r_ac_fin.[MAIN_V_ID] = s_ac_str
order by r_ac_fin.[MAIN_V_ID] asc;
debug_pipe(‘Имя счета: ‘ || r_AC_FIN.[NAME], 0);exception when NO_DATA_FOUND then
debug_pipe('Запись не найдена', 0);end;
3) Поиск последней записи.FIND LASTАналогично, но вместо asc нужно писать des4) Перебор всех записей по некоторому условию одной таблицы.FOR EACHСпособ 1:
s_ac_str string_100; --входная строка с номером счета
for acc in ::[AC_FIN] all where acc.[MAIN_V_ID] = s_ac_str loop
debug_pipe(‘Имя счета: ‘ || acc.[NAME], 0);
end loop;
Способ 2:
s_ac_str string_100; --входная строка с номером счета
for (
select acc(
acc.[NAME] : C_NAME
)
in ::[AC_FIN] all
where acc.[MAIN_V_ID] = s_ac_str
) loop
debug_pipe(‘Имя счета: ‘ || acc.[C_NAME], 0);
end loop;
Слышал (но не проверял), что оба способа абсолютно одинаковы по быстродействию, поскольку код этих примеров Pl Plus во время компиляции преобразуется в одинаковый код Pl SQL.
5) Перебор всех записей по некоторому условию для нескольких таблиц.FOR EACH…. ,EACH… Вывести имя счета и имя владельца.
for (
select acc(
acc.[NAME] : C_NAME,
cl.[NAME] : C_NAME2
)
in ::[AC_FIN], (::[CLIENT] all : cl) all
where acc.[MAIN_V_ID] = s_ac_str
and acc.[CLIENT_V] = cl
) loop
debug_pipe('Имена_: ' || acc.[C_NAME] || ' ' || acc.[C_NAME2], 0);end loop;
Для выполнения этой задачи необязательно было работать с 2-мя таблицами, можно сделать запрос к одной [AC_FIN] и использовать разыменованность.
Точно такой же результат выдаст такой код:
for (
select acc(
acc.[NAME] : C_NAME,
acc.[CLIENT_V].[NAME] : C_NAME2
)
in ::[AC_FIN] all
where acc.[MAIN_V_ID] = s_ac_str
) loop
debug_pipe('Имена2_ : ' || acc.[C_NAME] || ' ' || acc.[C_NAME2], 0);end loop;
Запуск одной операции из другой:RUN oper.p (par1, par2). Способ 1. В этом случае запускается только «тело» операции.
::[tbp_oper].[oper](
P_PAR1 == par1,
P_PAR2 == par1
);
Способ 2. В этом случае запускается вся операция вместе с формой.На вызывающей операции должна стоять галочка «Выводить команды в буфер сессии».
stdio.put_line_buf('<% PLPCALL [TBP_OPER].[OPER](%PARAM%.P_PAR1 => %VAR%.PAR1, %PARAM%.P_PAR2 => %VAR%.PAR2) %>');
Переменные PAR1 и PAR2 должны быть заданы в свойствах вызывающей операции в разделе «Переменные».Способ 3. Вызов из клиент-скрипта тоже всей операции.
Runtime.PlayEx("<% PLPCALL [TBP_OPER].[OPER](%PARAM%.P_PAR1 => %VAR%.PAR1, %PARAM%.P_PAR2 => %VAR%.PAR2) %>")
Инклюды:{globals.i}
pragma include(::[RUNTIME].[MACRO_LIB]);
Препроцессоры:&GLOBAL-DEFINE DELIM ";" /* разделитель для csv формата */
pragma macro(DELIM, ';'); -- разделитель для csv формата
Использовать в коде: &DELIMNO-UNDO, NO-LOCK:Можно считать, что все переменные описываются как NO-UNDO. bank.[DEPART] --NO-LOCKEXCLUSIVE-LOCK:Способ 1. bank=>[DEPART] –-блокировка одного реквизита записиСпособ 2.bank%lock –-блокировка всей записиГде bank – ссылка на банки.Первый способ обращения к записи типа bank.[DEPART], в отличие от NO-LOCK Бисквита, дает возможность изменить запись, поэтому bank=>[DEPART] применяется редко.Транзакции:DO TRANSACTION:………END.Для управления транзакциями существует ряд операторов:commit;Фиксирует сделанные изменения в базе данных и делает их видимыми для других пользователей.savepoint < имя >;Устанавливает точку отката с именем < имя >.rollback [ to < имя > ]Отменяет сделанные изменения, начиная от последнего commit или начиная с места, где была установлена точка отката с именем < имя >.Следует иметь ввиду, что операторы commit и rollback снимают все установленные пользователем физические блокировки и дают возможность другим пользователям изменять блокированные ранее данные.Обмен данными между базой и файлами в разных форматах:1) Выгрузка в XLS.Для вывода в XLS используется шаблон. Его необходимо подгрузить в справочник «Справочник шаблонов документов».
pragma macro(xl, '::[OOXML].[API_XL]'); --препроцессор
pragma macro(lib_ooxml,'::[SHABLON_DOC].[LIB_OOXML]'); --препроцессор
&lib_ooxml.xl_init(p_shablon_code == 'RSB_REP_KSPL'); -- вызов шаблона
&xl.Open_Sheet(1); -- установим нужный лист
&xl.put(3, 6, ‘информация для вывода в ячейку 3 6 листа 1’)); -- вывод в строку 3, колонку 6
&lib_ooxml.xl_finish; --вывод xls на экран
2) Выгрузка в word.Для вывода в word используется шаблон. Его необходимо подгрузить в справочник «Справочник шаблонов документов».
pragma macro(wd, '::[OOXML].[API_DOC_SAX]'); --препроцессор
p_shablon_ref ref [SHABLON_DOC]; --переменная для ссылки на шаблон
v_tf_field constant.MEMO_TABLE_S; --массив для переменных шаблона
p_shablon_ref := ::[SHABLON_DOC]%locate(x where x.CODE = 'SHABLON_CODE'); --поиск шаблона по коду
v_report_data := ::[SHABLON_DOC].[LIB_OOXML].wd_init(
p_shablon_ref == p_shablon_ref ,p_filial == stdlib.userid().[FILIAL] ,p_stop_on_error == false); --подгрузка шаблона
v_tf_field := &wd.GetDocVars; --подгрузка переменных из шаблона в массив
v_tf_field('ДАТА'):= vDate_Str; --заполнение переменной ДАТА неким значением
v_tf_field('ФИО'):= P_CLIENT; --заполнение переменной ФИО неким значением
&wd.PutDocVars(v_tf_field); --возврат значений с массива на документ
&wd.finish(v_report_data); --вывод документа на экран
3) Загрузка из файла csv (файл лежит на сервере, клиентом не выбирается, имя файла прописывается в операции)
--Необходимые переменные
ifile integer;
ofile [FILE$LOAD];sbuffer varchar2(1000);
--Определим путь и имя файла
ofile.[SRC_PATH] := stdio.Get_Env('FIO_ROOT_DIR');
ofile.[SRC_NAME] := 'for_test.csv';
ofile.[SRC_TYPE] := true;
--Вычитали данные
ifile := stdio.open(ofile.[SRC_PATH], ofile.[SRC_NAME], 'r');
while stdio.get_line(ifile, sbuffer, True, stdio.WINTEXT, Null) loop
if sbuffer is not null then
sbuffer:= replace(replace(sbuffer, chr(10), ''), chr(13), '');
--В переменной sbuffer строки из файла for_test.csv.
--Далее их можно обрабатывать, например разбирать
--используя аналог функции ENTRY (пункт 5 из данный статьи)
end if;
end loop;
stdio.f_close(ifile);
4) Загрузка из XLS (файл лежит на клиенте или сервере и выбирается пользователем).У операции необходимо создать параметр P_FILE типа FILE$LOAD и переменные V_FILEPATH типа STRING_4000, V_FILENAME типа STRING_4000. P_FILE необходимо разместить на экранной форме.В секции «Локальные описания» необходимо написать код:
pragma macro (xl, '::[OOXML].[API_XL]'); --препроцессор для работы с xls
pragma macro (get, '&xl.getSheetRowColVal(
p_row == [1] --Строка адреса ячейки
,p_col == [2] --Колонка адреса ячейки
,p_sheet == 1 --Номер листа
,p_tp == v_s_tp --Тип ячейки см. xl_tp_...
,p_st == v_n_st --Индекс стиля ячейки
)', substitute); --препроцессор для получения данных из ячейки xlsv_s_tp string(128); --переменная для &get
v_n_st number; --переменная для &get
v_blob_file blob := empty_blob(); --переменная для загрузки данных
В секции «Проверка» для p_message = 'VALIDATE' и p_info = 'OK' необходимо написать код:
if nvl(P_FILE.[SRC_TYPE], false) then
P_FILE.[SRC_TYPE] := null;
P_FILE.[DST_TYPE] := null; end if;
P_FILE.[DST_NAME] := P_FILE.[SRC_NAME];
V_FILEPATH := P_FILE.[SRC_PATH];
V_FILENAME := P_FILE.[SRC_NAME];
В секции «тело» разбор файла XLS:
::[SHABLON_DOC].[LIB_OOXML].read_from_file( p_blob == v_blob_file --Содержимое файла (BLOB)
,p_dir == V_FILEPATH --Путь к файлу на сервере
,p_fname == V_FILENAME --Имя файла на сервере
,p_delete == false --Удаление файла на сервере после чтения
); -- чтение файла в переменную v_blob_fileif v_blob_file is null
then
pragma error('Файл не выбран!');
end if; if not &xl.open_file(v_blob_file)
then
pragma error('Ошибка чтения файла!');
end if; &xl.open_sheet(1); -- открытие страницы 1 файла
Debug_pipe(&get(6, 3), 0); --данные из ячейки (строка 6,столбец 3,страница 1)
А где в ЦФТ настроечные параметры и классификаторы? В справочнике Настройки. (FP_TUNE) и то, и другое. А где с ЦФТ шедулер и бисмарк?
- SYSTEM_JOBS (Выполнение заданий по расписанию): в навигаторе настраивается в Система/Выполнение заданий по расписанию
- TEXT_JOBS (Выполнение текстовых заданий): в навигаторе настраивается в Система/Выполнение текстовых заданий.
- Справочник BGP(Фоновые процессы)
Временные таблицы: DEFINE temp-tableКак известно, функциональность временных таблиц Бисквита ничуть не хуже постоянных таблиц. Полноценного аналога в ЦФТ я не нашел. Есть 3 аналога хуже.Вариант 1. Тип TEMP_TABLE_S (Временная таблица). Она так называется, а на самом деле это постоянная таблица. Она описана в базе.Можно использовать, хотя это делают редко.Вариант 2. Создать свою таблицу в базе данных и использовать ее как временную. Необходимо на закладке "Таблица" указывать параметр "Время жизни" = "Пропадет по окончании сессии". Тогда она гарантированно будет чиститься и не будет загрязнять БД.Вариант 3. Массивы, описанные в операциях (применяются часто).Массивы действительно временные, но функциональность их сильно ограничена по сравнению с temp-table Бисквита. В массивах всего 1 индекс, он может быть целочисленный или строковый. Нельзя осуществлять поиск по полю массива. Можно осуществить поиск по индексу или полный перебор. Пример описания массива:
type strucType is record ( FileName string,
helloString string,
procName string );
type rezType is table of strucType index by integer;
rez rezType;
Как массив применять, описывать не буду – примеров огромное множество.Показать табличные данные пользователю Объекты browse, navigate. Способ 1. Представления.Тема обширная, раскрывать не буду. Можно делать SQL-представления и писать для них запросы. Можно создавать простые представления, для них есть удобный конструктор. Простые представления можно конвертировать в SQL-представления при загрузке в Admin 2.0 (Eclipse).Способ 2. GRID на форме операции.Создать параметр операции как массив, например:
В качестве источника можно применить существующий в базе массив с данными или задействовать временную таблицу (пример 2, пункта 22 данной статьи).Открыть в редакторе формы список параметров и оттуда перетащить на форму созданный параметр, а также необходимые реквизиты массива для вывода в GRID.
Задать пользователю вопрос после запуска операции по кнопке «OK»:Эта задача меня поразила тем, как легко она реализуется в Бисквите и как сложно в ЦФТ.Спасибо за пример и консультацию Олегу Опалихину.В Бисквите:if is_question then DO: MESSAGE "Вы хотите продолжить?" VIEW-AS ALERT-BOX QUESTION BUTTONS YES-NO UPDATE is_need_bl_process AS LOGICAL. if not is_need_bl_process then RETURN.end. В ЦФТ: 1. Создать переменную операции V_IS_QUESTION типа Логика2. Разместить переменную V_IS_QUESTION на форме операции. Поставить свойства переменной V_IS_QUESTION на форме Visible=False и ValidateName=V_IS_QUESTION. Поставить свойство кнопки OK на форме CheckValidate=True3. Поставить в дополнительных свойствах операции «при смене элемента управления»= «Сервер,Клиент».4. Написать в разделе операции «Клиент-скрипт» код на языке VBScript, который поднимет форму для вопроса пользователю:
Public Function Main(LastControl)
Main = True
If LastControl Is Ok Then
Main = Null
if Form1.ScriptServerValidate(Nothing, "QUESTION") then
if V_IS_QUESTION then
call Runtime.ShowMonitor
if MsgBox("Вы хотите продолжить?", vbYesNo + vbQuestion + vbDefaultButton2, "Вопрос") = vbYes then
if Form1.ScriptServerValidate(Nothing, "PROCESS_BL_YES") then
Main = True
end if
else
if Form1.ScriptServerValidate(Nothing, "PROCESS_BL_NO") then
Main = True
end if
end if
else
Main = True
end if
end if
End If
End Function
5. В разделе «Локальные описания» задать переменную:
v_b_need_bl_process boolean;
6. В разделе «Проверка» написать код:
begin
if p_message = 'VALIDATE' then if p_info = 'QUESTION' then
--Здесь некий код который определяет нужно ли задавать вопрос пользователю
V_IS_QUESTION := TRUE; --например нужно elsif p_info = 'PROCESS_BL_YES' then
v_b_need_bl_process := true;
elsif p_info = 'PROCESS_BL_NO' then
v_b_need_bl_process := false;
end if; end if;end;
7. В разделе «Тело» написать код:
begin
if not v_b_need_bl_process then
return;
end if; --Здесь код, который выполняется если пользователь ответил «Да»
-- и не выполняется если пользователь ответил «Нет». debug_pipe('Сработало!', 0); --например так
end;
Вопрос будет выглядеть так:
То, что нельзя сделать в Бисквите, но есть в ЦФТ:1. В Бисквите практически нельзя создавать свои таблицы, поля для таблиц и индексы. Теоретическая такая возможность есть, но не практическая. В ЦФТ никаких проблем с этим нет. Создавайте столько, сколько нужно для ваших задач.2. В Бисквите отсутствует полноценный отладчик. В ЦФТ в новой среде разработки Admin 2.0 появилась возможность запускать полноценный отладчик с точками останова и соответственно с просмотром значения всех переменных и во время остановки выполнения операции.3. Разыменованность. Об этом писал выше.ЗаключениеЯ не претендую на полноту данных, а также на абсолютную правильность, я отображаю свое понимание на данный момент, которое возможно вскоре изменится. Буду благодарен опытным разработчикам ЦФТ за комментарии, замечания и исправления. Хочу выразить благодарность людям, благодаря которым данная статья появилась:Харченко Сергею, опытному разработчику Бисквита, с которым мы часто обсуждаем темы данной статьи. Именно во время этих бесед у меня появилась идея ее написания.Саламову Камилю за непосредственный импульс в написании статьи, за ценные замечания к тексту статьи, за моральную поддержку и за постоянные напоминания, что нужно переходить на Admin 2.0 :)Наумкину Анатолию за организацию обучения на учебном портале ЦФТ.Миниярову Ринату, Давыдову Денису и Опалихину Олегу за ответы на вопросы в начале моего обучения ЦФТ и за примеры исходного кода.Руфееву Максиму за внимательность. За то, что заметил мою ошибку в слове elsif :)Шершову Андрею на помощь в публикации на Хабре.
===========
Источник:
habr.com
===========
Похожие новости:
- [Системное администрирование, PHP, MySQL, Программирование, Cisco] Автоматический и автоматизированный способы блокировки ресурсов по поисковой выдаче
- [Высокая производительность, PostgreSQL, SQL, Администрирование баз данных] Борем deadlock при пакетном UPDATE
- [Развитие стартапа, Облачные сервисы, Serverless] Firebase чуть не погубила мой стартап (перевод)
- [Разработка мобильных приложений, Разработка под Android, SQLite] Использование Android App Search для full-text поиска данных в android-приложениях
- [Oracle, PostgreSQL, SQL] Почему мы перешли с Oracle на PostgeSQL, и как это сделать
- [PostgreSQL, Администрирование баз данных, Big Data, DevOps] Mail.ru Cloud Solutions открывает доступ к Arenadata DB Cloud версии Enterprise
- Стабильный выпуск СУБД MariaDB 10.6
- [Flutter] Получаем реальное покрытие тестами для приложений на Flutter (перевод)
- [SQL, Microsoft SQL Server, Visual Basic for Applications, Data Engineering] И снова про MS Excel
- [Виртуализация, Восстановление данных, Резервное копирование] Мгновенное восстановление баз данных с Veeam
Теги для поиска: #_sql, #_funktsionalnoe_programmirovanie (Функциональное программирование), #_rosselhozbank (россельхозбанк), #_rosselhoz (россельхоз), #_tsft (цфт), #_blog_kompanii_rosselhozbank (
Блог компании Россельхозбанк
), #_sql, #_funktsionalnoe_programmirovanie (
Функциональное программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:45
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет, Хабр!Редакторы советуют начинать статью именно с такого приветствия, ну так я спорить не буду:) Меня зовут Баранов Михаил, работаю программистом более 20 лет. В далеком, примерно 2003-м, году умные люди мне сказали: «Бросай этот язык программирования Progress 4Gl, он устарел, срочно переходи на какой-нибудь другой». Я не согласился. «На этом языке написано несколько банковских систем, и я буду востребован», - подумал я. Тогда я устроился работать с банковской системой Банкир/Про, написанной на языке Progress. Работал с ней около 5 лет. Но потом банки стали от нее отказываться. Тогда я стал работать с системой Бисквит тоже написанной на языке Progress. Прошло еще 10 лет и от Бисквита стали банки отказываться. И вот в 2019 году я оказался в крайне неприятной ситуации: я отлично знаю только то, что уже мало кому нужно. Осенью 2019 года я получил отличное предложение от РСХБ-ИНТЕХ, где я сейчас и работаю. Я устроился туда выполнять задачи по разработке в системе Бисквит и одновременно изучать систему ЦФТ на языке программирования Pl Plus. Уже на испытательном сроке мне назначили 14 учебных курсов на учебном портале ЦФТ и стали давать элементарные задачки по разработке в системе ЦФТ. А примерно с лета 2020 года я полностью перешел на разработку в системе ЦФТ (и этому очень рад). Эта статья о том, как сделать в ЦФТ то, что мы привыкли делать в Бисквите. Начинал я ее писать только для себя, чтобы упорядочить свои знания. Однако потом оказалась, что эта тема важна для всех разработчиков, которые переходят на ЦФТ и не только с Бисквита. Именно поэтому я решил разместить ее на Хабре. Покажу на примерахПримеры из Бисквита будут курсивом, примеры из ЦФТ - жирные или виде блоков кода:Сообщение в поток:MESSAGE “Hello world”. debug_pipe('Hello world', 0);
debug('Hello world', 0);
If …. then
программный код elsif …. then программный код else программный код end if; Inp_str string; --строка для разбора с разделителем ‘;’
item_command rtl.string_table; --специальный массив item_command := STR_2.split(p_expression == Inp_str, p_delimiter == ';'); debug_pipe(item_command(1) , 0); -- Это как MESSAGE ENTRY(1… debug_pipe(item_command(2) , 0); -- Это как MESSAGE ENTRY(2… s_ac_str string_100; --входная строка с номером счета
r_ac_fin ref [AC_FIN]; --ссылка на счет r_AC_FIN := ::[AC_FIN]([MAIN_V_ID] = s_ac_str); --получение ссылки debug_pipe(‘Имя счета: ‘ || r_AC_FIN.[NAME], 0); --вывод в сообщение имени счета debug_pipe(r_AC_FIN. [CLIENT_V].[NAME], 0);
s_ac_str string_100; --входная строка с номером счета
r_ac_fin ref [AC_FIN]; --ссылка счет begin locate r_ac_fin in ::[AC_FIN] where r_ac_fin.[MAIN_V_ID] = s_ac_str order by r_ac_fin.[MAIN_V_ID] asc; debug_pipe(‘Имя счета: ‘ || r_AC_FIN.[NAME], 0);exception when NO_DATA_FOUND then debug_pipe('Запись не найдена', 0);end; s_ac_str string_100; --входная строка с номером счета
for acc in ::[AC_FIN] all where acc.[MAIN_V_ID] = s_ac_str loop debug_pipe(‘Имя счета: ‘ || acc.[NAME], 0); end loop; s_ac_str string_100; --входная строка с номером счета
for ( select acc( acc.[NAME] : C_NAME ) in ::[AC_FIN] all where acc.[MAIN_V_ID] = s_ac_str ) loop debug_pipe(‘Имя счета: ‘ || acc.[C_NAME], 0); end loop; Слышал (но не проверял), что оба способа абсолютно одинаковы по быстродействию, поскольку код этих примеров Pl Plus во время компиляции преобразуется в одинаковый код Pl SQL.
for (
select acc( acc.[NAME] : C_NAME, cl.[NAME] : C_NAME2 ) in ::[AC_FIN], (::[CLIENT] all : cl) all where acc.[MAIN_V_ID] = s_ac_str and acc.[CLIENT_V] = cl ) loop debug_pipe('Имена_: ' || acc.[C_NAME] || ' ' || acc.[C_NAME2], 0);end loop; Для выполнения этой задачи необязательно было работать с 2-мя таблицами, можно сделать запрос к одной [AC_FIN] и использовать разыменованность.
for (
select acc( acc.[NAME] : C_NAME, acc.[CLIENT_V].[NAME] : C_NAME2 ) in ::[AC_FIN] all where acc.[MAIN_V_ID] = s_ac_str ) loop debug_pipe('Имена2_ : ' || acc.[C_NAME] || ' ' || acc.[C_NAME2], 0);end loop; ::[tbp_oper].[oper](
P_PAR1 == par1, P_PAR2 == par1 ); stdio.put_line_buf('<% PLPCALL [TBP_OPER].[OPER](%PARAM%.P_PAR1 => %VAR%.PAR1, %PARAM%.P_PAR2 => %VAR%.PAR2) %>');
Runtime.PlayEx("<% PLPCALL [TBP_OPER].[OPER](%PARAM%.P_PAR1 => %VAR%.PAR1, %PARAM%.P_PAR2 => %VAR%.PAR2) %>")
pragma include(::[RUNTIME].[MACRO_LIB]);
pragma macro(DELIM, ';'); -- разделитель для csv формата
pragma macro(xl, '::[OOXML].[API_XL]'); --препроцессор
pragma macro(lib_ooxml,'::[SHABLON_DOC].[LIB_OOXML]'); --препроцессор &lib_ooxml.xl_init(p_shablon_code == 'RSB_REP_KSPL'); -- вызов шаблона &xl.Open_Sheet(1); -- установим нужный лист &xl.put(3, 6, ‘информация для вывода в ячейку 3 6 листа 1’)); -- вывод в строку 3, колонку 6 &lib_ooxml.xl_finish; --вывод xls на экран pragma macro(wd, '::[OOXML].[API_DOC_SAX]'); --препроцессор
p_shablon_ref ref [SHABLON_DOC]; --переменная для ссылки на шаблон v_tf_field constant.MEMO_TABLE_S; --массив для переменных шаблона p_shablon_ref := ::[SHABLON_DOC]%locate(x where x.CODE = 'SHABLON_CODE'); --поиск шаблона по коду v_report_data := ::[SHABLON_DOC].[LIB_OOXML].wd_init( p_shablon_ref == p_shablon_ref ,p_filial == stdlib.userid().[FILIAL] ,p_stop_on_error == false); --подгрузка шаблона v_tf_field := &wd.GetDocVars; --подгрузка переменных из шаблона в массив v_tf_field('ДАТА'):= vDate_Str; --заполнение переменной ДАТА неким значением v_tf_field('ФИО'):= P_CLIENT; --заполнение переменной ФИО неким значением &wd.PutDocVars(v_tf_field); --возврат значений с массива на документ &wd.finish(v_report_data); --вывод документа на экран --Необходимые переменные
ifile integer; ofile [FILE$LOAD];sbuffer varchar2(1000); --Определим путь и имя файла ofile.[SRC_PATH] := stdio.Get_Env('FIO_ROOT_DIR'); ofile.[SRC_NAME] := 'for_test.csv'; ofile.[SRC_TYPE] := true; --Вычитали данные ifile := stdio.open(ofile.[SRC_PATH], ofile.[SRC_NAME], 'r'); while stdio.get_line(ifile, sbuffer, True, stdio.WINTEXT, Null) loop if sbuffer is not null then sbuffer:= replace(replace(sbuffer, chr(10), ''), chr(13), ''); --В переменной sbuffer строки из файла for_test.csv. --Далее их можно обрабатывать, например разбирать --используя аналог функции ENTRY (пункт 5 из данный статьи) end if; end loop; stdio.f_close(ifile); pragma macro (xl, '::[OOXML].[API_XL]'); --препроцессор для работы с xls
pragma macro (get, '&xl.getSheetRowColVal( p_row == [1] --Строка адреса ячейки ,p_col == [2] --Колонка адреса ячейки ,p_sheet == 1 --Номер листа ,p_tp == v_s_tp --Тип ячейки см. xl_tp_... ,p_st == v_n_st --Индекс стиля ячейки )', substitute); --препроцессор для получения данных из ячейки xlsv_s_tp string(128); --переменная для &get v_n_st number; --переменная для &get v_blob_file blob := empty_blob(); --переменная для загрузки данных if nvl(P_FILE.[SRC_TYPE], false) then
P_FILE.[SRC_TYPE] := null; P_FILE.[DST_TYPE] := null; end if; P_FILE.[DST_NAME] := P_FILE.[SRC_NAME]; V_FILEPATH := P_FILE.[SRC_PATH]; V_FILENAME := P_FILE.[SRC_NAME]; ::[SHABLON_DOC].[LIB_OOXML].read_from_file( p_blob == v_blob_file --Содержимое файла (BLOB)
,p_dir == V_FILEPATH --Путь к файлу на сервере ,p_fname == V_FILENAME --Имя файла на сервере ,p_delete == false --Удаление файла на сервере после чтения ); -- чтение файла в переменную v_blob_fileif v_blob_file is null then pragma error('Файл не выбран!'); end if; if not &xl.open_file(v_blob_file) then pragma error('Ошибка чтения файла!'); end if; &xl.open_sheet(1); -- открытие страницы 1 файла Debug_pipe(&get(6, 3), 0); --данные из ячейки (строка 6,столбец 3,страница 1)
type strucType is record ( FileName string,
helloString string, procName string ); type rezType is table of strucType index by integer; rez rezType; В качестве источника можно применить существующий в базе массив с данными или задействовать временную таблицу (пример 2, пункта 22 данной статьи).Открыть в редакторе формы список параметров и оттуда перетащить на форму созданный параметр, а также необходимые реквизиты массива для вывода в GRID. Задать пользователю вопрос после запуска операции по кнопке «OK»:Эта задача меня поразила тем, как легко она реализуется в Бисквите и как сложно в ЦФТ.Спасибо за пример и консультацию Олегу Опалихину.В Бисквите:if is_question then DO: MESSAGE "Вы хотите продолжить?" VIEW-AS ALERT-BOX QUESTION BUTTONS YES-NO UPDATE is_need_bl_process AS LOGICAL. if not is_need_bl_process then RETURN.end. В ЦФТ: 1. Создать переменную операции V_IS_QUESTION типа Логика2. Разместить переменную V_IS_QUESTION на форме операции. Поставить свойства переменной V_IS_QUESTION на форме Visible=False и ValidateName=V_IS_QUESTION. Поставить свойство кнопки OK на форме CheckValidate=True3. Поставить в дополнительных свойствах операции «при смене элемента управления»= «Сервер,Клиент».4. Написать в разделе операции «Клиент-скрипт» код на языке VBScript, который поднимет форму для вопроса пользователю: Public Function Main(LastControl)
Main = True If LastControl Is Ok Then Main = Null if Form1.ScriptServerValidate(Nothing, "QUESTION") then if V_IS_QUESTION then call Runtime.ShowMonitor if MsgBox("Вы хотите продолжить?", vbYesNo + vbQuestion + vbDefaultButton2, "Вопрос") = vbYes then if Form1.ScriptServerValidate(Nothing, "PROCESS_BL_YES") then Main = True end if else if Form1.ScriptServerValidate(Nothing, "PROCESS_BL_NO") then Main = True end if end if else Main = True end if end if End If End Function v_b_need_bl_process boolean;
begin
if p_message = 'VALIDATE' then if p_info = 'QUESTION' then --Здесь некий код который определяет нужно ли задавать вопрос пользователю V_IS_QUESTION := TRUE; --например нужно elsif p_info = 'PROCESS_BL_YES' then v_b_need_bl_process := true; elsif p_info = 'PROCESS_BL_NO' then v_b_need_bl_process := false; end if; end if;end; begin
if not v_b_need_bl_process then return; end if; --Здесь код, который выполняется если пользователь ответил «Да» -- и не выполняется если пользователь ответил «Нет». debug_pipe('Сработало!', 0); --например так end; То, что нельзя сделать в Бисквите, но есть в ЦФТ:1. В Бисквите практически нельзя создавать свои таблицы, поля для таблиц и индексы. Теоретическая такая возможность есть, но не практическая. В ЦФТ никаких проблем с этим нет. Создавайте столько, сколько нужно для ваших задач.2. В Бисквите отсутствует полноценный отладчик. В ЦФТ в новой среде разработки Admin 2.0 появилась возможность запускать полноценный отладчик с точками останова и соответственно с просмотром значения всех переменных и во время остановки выполнения операции.3. Разыменованность. Об этом писал выше.ЗаключениеЯ не претендую на полноту данных, а также на абсолютную правильность, я отображаю свое понимание на данный момент, которое возможно вскоре изменится. Буду благодарен опытным разработчикам ЦФТ за комментарии, замечания и исправления. Хочу выразить благодарность людям, благодаря которым данная статья появилась:Харченко Сергею, опытному разработчику Бисквита, с которым мы часто обсуждаем темы данной статьи. Именно во время этих бесед у меня появилась идея ее написания.Саламову Камилю за непосредственный импульс в написании статьи, за ценные замечания к тексту статьи, за моральную поддержку и за постоянные напоминания, что нужно переходить на Admin 2.0 :)Наумкину Анатолию за организацию обучения на учебном портале ЦФТ.Миниярову Ринату, Давыдову Денису и Опалихину Олегу за ответы на вопросы в начале моего обучения ЦФТ и за примеры исходного кода.Руфееву Максиму за внимательность. За то, что заметил мою ошибку в слове elsif :)Шершову Андрею на помощь в публикации на Хабре. =========== Источник: habr.com =========== Похожие новости:
Блог компании Россельхозбанк ), #_sql, #_funktsionalnoe_programmirovanie ( Функциональное программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:45
Часовой пояс: UTC + 5