Программистам
Компания «АЗСофт» имеет многолетний опыт использования недурных инструментов типа Sybase Powerbuilder, ERwin, Crystal Reports, а также опыт работы с Oracle Database.На этой странице мы выражаем добрые чувства к коллегам и публикуем на наш взгляд интересные и забавные штучки, то, что называют tricks & tips, полезные ссылки, etc.
Сейчас опубликовано:
1. Пример кода на Powerbuilder для вызова Crystal Reports engine(API)
2. Пример кода на Powerbuilder для переконфигурирования источника ODBC
3. Для Powerbuilder - несерьезные "примочки"
4. Пример построения дерева на Power Builder
5. Забавная ситуация (мелочи жизни)
6. Пример использования UNION во VIEW для Oracle
7. Оцените Oracle Enterprise Manager
8. Конфигурирование Microsoft ISA 2004
9. Oracle HTML DB (WEB - приложение)
10. Oracle HTML DB APEX - техника COLLECTIONS
В примерах опущены объявления переменных и внешних функций, если нужны комментарии, пишите info@azsoft.ru
Пример кода на Powerbuilder для вызова Crystal Reports engine(API)
//*****************************************************
// Начало - проверки и указание файла отчета
//*****************************************************
engineopen = PEOpenEngine ()
if engineopen <> 0 then
// messagebox ("Прекрасно!", "Запустили Engine!")
else
messagebox ("Погано...", "Стартер отказал!")
end if
reportfilename = 'Оплата клиентов.rpt'
if engineopen <> 0 then
job = PEOpenPrintJob(reportfilename)
if job = 0 then
messagebox ("Паршиво", "Нет отчета")
else
//
messagebox ("Хорошо", "Отчет засосало")
end if
else
messagebox ("Все же погано", "Стартер отказал")
end if
//******************************************************
// Ниже заполнение структурки для Logon, так изгаляться приходится
// из-за bug в Паше
//******************************************************
long cpos,strlng
li.size = 514
strlng = len(DataSourceName)
for cpos = 1 to strlng
li.servername[cpos] = mid(DataSourceName,cpos,1)
next
strlng = len(databasename)
for cpos = 1 to strlng
li.databasename[cpos] = mid(databasename,cpos,1)
next
strlng = len(userid)
for cpos = 1 to strlng
li.userid[cpos] = mid(userid,cpos,1)
next
strlng = len(userpwd)
for cpos = 1 to strlng
li.password[cpos] = mid(userpwd,cpos,1)
next
rcode = PESetNthTableLogonInfo( job, 0, li, TRUE);
if rcode = 0 then
messagebox ("", "Ошибка при выполнении PESetNthTableLogonInfo для DSN [" +
li.servername + "] !" );
end if
//**************************************************
// Ниже подмена формул в отчете - Selection Formula и простых
//**************************************************
rsformula='({OP_ACCOUNT.ACCOUNT_NUM} = 62.00 or {OP_ACCOUNT.ACCOUNT_NUM} = 63.00
or '+&
' {OP_ACCOUNT.ACCOUNT_NUM} = 64.00) and '+&
'({OP_ACCOUNT_1.OPERATION_TYPE} like "*плата*" ) and '+&
'{OP_ACCOUNT_1.OP_DATE} >= Date('+string(year(date(datest)))+","+ &
string(month(date(datest)))+','+string(day(date(datest)))+') and '+&
'{OP_ACCOUNT_1.OP_DATE} <= Date('+string(year(date(dateend)))+","+ &
string(month(date(dateend)))+','+string(day(date(dateend)))+')'
rcode=PESetSelectionFormula(job,rsformula)
if rcode = 0 then
messagebox("Беда", "Selection Formula NOT Set")
else
// messagebox("Беда", rsformula)
end if
//............................................................................................
rcode=PESetFormula (job, "Дата начала", '"'+string(datest)+'"')
if rcode = 0 then
messagebox("Беда", "Данные не подменились")
else
end if
rcode=PESetFormula (job, "Дата конца", '"'+string(dateend)+'"')
if rcode = 0 then
messagebox("Беда", "Данные не подменились")
else
end if
//............................................................................................
// Ну и пора выводить на экран
//
if job <> 0 then
rcode = PEOutputToWindow(job, "Отчет", 0, 0, 790, 590, 0, 0)
if rcode = 1 then
outputset = 1
else
messagebox ("Беда", "OutputToWindow Not Set")
end if
else
messagebox ("Беда", "Not Print Job Opened")
end if
lc.StructSize=514
lc.hasGroupTree=1
lc.canDrillDown=1
lc.hasNavigationControls=1
lc.hasCancelButton=1
lc.hasPrintButton=1
lc.hasExportButton=1
lc.hasZoomControl=1
lc.hasCloseButton=1
lc.hasProgressControls=1
lc.hasSearchButton=1
lc.hasPrintSetupButton=1
lc.hasRefreshButton=1
PESetWindowOptions (job, lc)
if rcode = 1 then
else
messagebox ("Беда", "OutputToWindowOptions Not Set")
end if
//long hWnd
//PrinterSetup (hWnd)
//..............................................................................................
// А здесь вытаскиваем детальную информацию, если была ошибка
//
if engineopen <> 0 then
if outputset = 1
then
if job <> 0 then
rcode = PEStartPrintJob (job, True)
if rcode = 1 then
else
errcode = PEGetErrorCode(job)
messagebox("Ошибка запуска отчета", "Error Starting Print Job")
messagebox("Код ошибки Crystal Reports", errcode)
rcode = PEGetErrorText( job, texthandle, textLength )
rcode = PEGetHandleString( textHandle, errorText, textLength )
messagebox("Детализация ошибки", errortext)
end if
else
messagebox("Message", "No Job Open to Start")
end if
else
messagebox("Message", "First Select a Print Destination")
end if
else
messagebox ("Information!", "Please open the engine before calling this
function.")
end if
PEClosePrintJob(job)
Пример кода на Powerbuilder для переконфигурирования источника ODBC
//******************************************************
// Здесь маленькая фишка - засунуть NULL в строку DBPARM
// (Привет Игорю!)
//******************************************************
char NullChar='@',IndeedNullChar
whwnd=0
string String1,String2
odbc_driver=ProfileString("app.INI","DBCash","ODBCDrv","")
odbc_dsn = 'DSN='+ProfileString("app.INI","DBCash","DSN","")
odbc_db = 'DB=' + ProfileString("app.INI","DBCash","Database","")
ODBC_CONFIG_DSN=2
dbparm=fill('_',200)
SetNull(IndeedNullChar)
String1='DSN='+DataSourceName
String2=ProfileString("app.INI","DBCash","ODBCDBParam","")+'='+DataBaseName
DBParm=String1+NullChar+String2+NullChar+NullChar
DBParmLen=Len(DBParm)
FOR Position=1 TO DBParmLen
IF DBParm[Position]=NullChar THEN
DBParm[Position]=IndeedNullChar
END IF
NEXT
if not SQLConfigDataSource(whwnd, ODBC_CONFIG_DSN, odbc_driver, DBParm) then
messagebox("ODBC", "Неудача")
else
end if
Для Powerbuilder - несерьезные "примочки"
//*****************************************
// Проиграть музыку
//*****************************************
uint lui_NumDevs
lui_NumDevs = WaveOutGetNumDevs()
IF lui_NumDevs > 0 THEN
sndPlaySoundA( "sound.wav", 1 )
END IF
Пример построения дерева на PowerBuilder.
Пример 1. Обычное (не рекурсивное) дерево
Исходные данные: Таблица «COMMODITY» - номенклатуры товара с произвольным, но заранее заданным количеством типов N. Поля: «TYPE1», «TYPE2», …, «TYPEN».
Задача: Построить дерево групп товаров с иерархией, соответствующей типам.
Используемые объекты: Элемент TreeViewItem.
Решение:
Функция создания дерева:
SetPointer(HourGlass!)
Long ll_Root
TreeViewItem ltvi_Root
// К количеству уровней добавляем единицу для корневого уровня
il_maxlevel = il_maxlevel + 1
// Добавляем корневой элемент
ltvi_Root.Label = "Дерево товаров" // Видимая метка
ltvi_Root.PictureIndex = 1 // Индекс картинки (делается при создании объекта)
ltvi_Root.SelectedPictureIndex = 1 // Индекс картинки при выборе элемента (тот же)
ltvi_Root.Children = True // Наличие подэлементов
ll_Root = tv_1.InsertItemLast(0, ltvi_Root) // Добавление элемента
// Добавляем корневой элемент
tv_1.ExpandItem(ll_Root) // Раскрываем содержимое первого уровня
tv_1.SelectItem(ll_Root) // Выбираем корневой элемент
Скрипт на событие ItemPopulate (первое раскрытие элемента) дерева:
string ls_select_cursor, ls_current_data, ls_err
long ll_errcode, ll_current
Integer li_Rows, li_Level, li_Cnt
TreeViewItem ltvi_Current, ltvi_base, ltvi_New
SetPointer(HourGlass!)
// Определяем уровень
GetItem(handle, ltvi_Current)
GetItem(handle, ltvi_base)
ll_current = handle
li_Level = ltvi_Current.Level
// Строим строку запроса для курсора
ls_select_cursor = 'SELECT DISTINCT TYPE' + string(li_level) +&
' FROM "COMMODITY"'
if li_level > 1 then // Надо составить условие для всех родителей
ls_select_cursor = ls_select_cursor + ' WHERE '
// Идем по уровням вверх до последнего
FOR li_cnt = li_level - 1 TO 1 STEP -1
ls_select_cursor = ls_select_cursor + '"COMMODITY"."TYPE' +&
string(li_cnt) + '" = ' + "'" + string(ltvi_current.data) + "'"
if li_cnt <> 1 then ls_select_cursor = ls_select_cursor + ' AND '
ll_current = FindItem(ParentTreeItem!, ll_current) // Находим родителя
GetItem(ll_current, ltvi_current)
NEXT
end if
ls_select_cursor = ls_select_cursor + ' ORDER BY TYPE' + string(li_level)
// Объявляем курсор и идем по нему (проверка на ошибки для краткости будет опущена)
DECLARE lcur_select DYNAMIC CURSOR FOR SQLSA;
PREPARE SQLSA FROM :ls_select_cursor USING SQL_UO;
OPEN DYNAMIC lcur_select;
FETCH lcur_select into :ls_current_data;
DO WHILE sql_uo.sqlcode <> 100
ltvi_New.Label = ls_current_data // Видимое на экране обозначение
ltvi_New.Data = ls_current_data // Данные – те же
if isnull(ltvi_new.data) then
else
ltvi_New.PictureIndex = 2 // Номера картинок
ltvi_New.SelectedPictureIndex = 3
// Если уровень предельный, то детей быть не может
If li_Level < il_maxlevel - 1 Then
ltvi_New.Children = True
Else
ltvi_New.Children = False
End If
// Добавляем найденный элемент в конец
If tv_1.InsertItemLast(handle, ltvi_New) < 1 Then
MessageBox("Error", "Error inserting item", Exclamation!)
End If
end if
LOOP
CLOSE lcur_select;
Результат:
Забавная ситуация (мелочи жизни)
Буду рад, если кто-нибудь предложит более правильное решение данной проблемы.
При усовершенствовании программного модуля «Счетчик купюр», столкнулся со следующими трудностями.
При нажатии клавиши «Enter» в одном из полей дополнительной колонки, количество купюр должно приплюсоваться к базовой, а само значение этой колонки обнулиться.
Проблема 1. Отслеживание нажатия клавиши “Enter”
Решается просто:
Событие key() для окна:
if key = KeyEnter! then
….
end if
Проблема 2. В каком из полей находится сейчас фокус (или был в последний раз в одном из интересующих нас полей). Такой функции ни для окна, ни для объекта edit mask я не нашел. Пришлось выкручиваться следующим образом:
1. Для события getfocus() каждой из edit_mask_control нужного столбца записываем:
ii_focus_plus = 13 ( где 13 – номер соответствующего объекта)
2. В упомянутом уже событии key() для окна:
if key = KeyEnter! then
CHOOSE CASE ii_focus_plus
CASE 13
em_1.text = string( long(em_13.text) + long(em_1.text) )
em_13.text = '0'
CASE 14
em_2.text = string( long(em_14.text) + long(em_2.text) )
em_14.text = '0'
…
CASE 24
em_12.text = string( long(em_24.text) + long(em_12.text) )
em_24.text = '0'
CASE ELSE
// Ничего не делаем
END CHOOSE
end if
Такие дела…
(продолжение следует)
Господа, позволим себе обратить Ваше внимание на неплохую книжку, продаваемую в Озоне по Crystal Reports
Проект IDEFinfo.Ru - всё о системном проектировании.
IDEF0, IDEF1x, IDEF3, IDEF5, ARIS, UML, RUP, ABC
- книги, стандарты, инструменты. Опыт и секреты моделирования.
Каталог ОнРу.ру: операционные системы, мир программ, языки программирования, разработчики программ, базы данных, и многое другое.
Корпорация Датакрат предлагает. Автоматизация и системы безопасности. Идентификация. Pos-терминал, касс, кассовые аппараты, сканер штрих-код, терминал сбора данных, противокражная система, контроль доступа, видеонаблюдение, принтер этикеток штрих-кода, электронные весы, пластиковые карты, турникет, инвентаризация, видеорегистратор, учет рабочего времени, считыватели, rfid, Zebra, Symbol. wi-fi сети. Программное обеспечение для Автоматизация торговли собственных разработок и не только.
©Copyright AZSoft 2004-2010.