Kérdeztétek, hogy minek fejlesztek játékokat, amikor nem is lehet futtatni a cégnél!?
Ki mondta, hogy cégnél futtatom? A neten sok ingyenes AS/400-as találhattok, én például Holger Scherer ingyenes AS/400-asát használom ilyen (és a többi) fejlesztési célra. Egyszerű regisztrációhoz kötött az elérése, ami 5 perc, aminek a végén az AS/400-on lesz 2 könyvtáratok. Én az egyikben tartom a forrásokat, a másikban pedig a programokat, adat állományokat. Igaz hogy egyszerű, jól le is van korlátozva, de a célomnak tökéletesen megfelel.
Holger AS/400-asát itt találjátok: http://www.holgerscherer.de/
Mindent le fog írni, hogy hogyan használjátok, de akkor itt a jelenlegi IP cím: 178.249.3.21 vagy használjátok a PUB1.RZKH.DE host nevet az emulátorotokban.
Good luck!
(van magyar felirat is hozzá... ehhez klikkelj a YouTube feliratra, majd válaszd ki a Feliratokat a videó alatti ikonok közül)
Még junior programozóként kérdezgettem az "öregeket", hogy van-e arra lehetőség, hogy mondjuk programban megtudjuk, hogy az adott táblában mennyi rekord van, vagy hogy egy adott feltételnek mennyi felel meg.
"Nincs" jött a válasz, amibe akkor még belenyugodtam, elfogadtam, elhittem. Kár volt. Mert bizony lehet és erre mutatok most egy rövid programot, példaként.
A program SQL utasítást hajt végre és a megadott paramétereknek megfelelő rekordszámot adja vissza.
FIGYELEM!
A program típusa SQLRPGLE legyen! (A neve bármi lehet...)
CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len++D+HiLoEq
D DS
D vRecCount 1 10S 0
*
* ENTRY PARM LIST
C *ENTRY PLIST
C PARM P#COUNT 8 0
C PARM P#PTNK 8 0
*=====================================================================
* PROGRAM START
*=====================================================================
*
C EXSR GETCOUNTS
C EVAL P#COUNT = vRecCount
C EVAL *INLR = *ON
C RETURN
*
*=====================================================================
* GetCounts
*======================================================================
C GetCounts BEGSR
*
C/exec sql
C+ select COUNT(*) into :vRecCount
C+ from LIBRARY/SFILE
C+ where SFPTNK =: P#PTNK and
C+ SFSYSD >= '2014-01-01' and SFCNTY = 'HU'
C/end-exec
*
C ENDSR
A program paraméterként kap egy partnerkódot (P#PTNK), és azt a rekordszámot adja vissza a P#COUNT paraméterben, ahány rekord megfelel annak a feltételnek, ahol az SFPTNK = a paraméterben megkapott partnerkóddal ÉS a rendszerben rögzített dátuma nagyobb vagy egyenlő "2014-01-01"-nél ÉS az országkódja "HU".
Természetesen az utóbbi 2 adat is lehetne paraméterként beérkező, illetve akár több feltételt is vizsgálhatnánk.
∴ Overlay-ek mozgatása nyomtatáskor
Ahol a történet véget ér..., oda teszünk aláírást
2014.04.26. 21:02
Pár napja írtam az overlay-ekről. Akkor azt ígértem, megmutatom hogyan lehet ezeket adott pontba helyezni nyomtatáskor. Nos, nézzük is, hogy mondjuk egy aláírást hogyan lehet a megfelelő helyre mozgatni. Ehhez természetesen az kell, hogy a pozícióját futás időben tudjuk megadni, ne pedig fix értékkel a printerfájlban. Beállíthatóságához szükségünk lesz két változóra, amit a printerfájlban veszünk fel, ott deklarálunk.
.....AAN01N02N03T.Name++++++RLen++TDpBLinPosFunctions++++++++++++++++++
A R WRALAIRAS
A OVERLAY(ALAIRAS &XD1 &YD1)
A XD1 5S 3P
A YD1 5S 3P
illetve ha egy változót (pl. megnevezés) is mozgatunk, akkor annál az alábbiak szerint kell a beállításokat megejteni:
A R WRDETAIL
A DTERMEKKOD 10 TEXT('TERMÉKKÓD')
A POSITION(&XD2 &YD1)
A DMEGNEVEZ 30 TEXT('MEGNEVEZÉS')
A POSITION(&XD2 &YD2)
A XD2 5S 3P
A YD1 5S 3P
A YD2 5S 3P
A programban pedig értéket adunk a változóknak, majd kiíratjuk a rekordot:
CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len++D+HiLoEq
* Aláírás
C EVAL XD1=19.6
C EVAL YD1=17.0
C WRITE WRALAIRAS
* Detail - tételek
C EVAL XD2=10.2
C EVAL YD1=2.0
C EVAL YD2=5.2
C WRITE WRDETAIL
Természetesen az értékeket számolni kell, itt csak az értékadást mutattam be. Én mindig egy változót szoktam használni annak rögzítésére, hogy éppen hol járok a papíron. Mondjuk kiíratom a fejrészt, ami 9 cm-rel a lap tetejétől ér véget. Akkor a változót (mondjuk AktPoz) feltöltöm a szükséges értékkel:
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++
D AktPoz S 5 3
D SorTavolsag S 5 3
/Free
AktPoz = 9,0;
/End-Free
Én a sortávolságra is fel szoktam venni egy változót, mert akkor még azt is tudom változtatni:
/Free
SorTavolsag = 0,6; // 6 mm lesz a sortávolság
/End-Free
Ha kiírok egy sort, akkor az aktuális pozíciót is növelni kell, mégpedig a sortávolsággal:
/Free
AktPoz = AktPoz + SorTavolsag; // Ekkor AktPoz 9,6 cm lesz (9,0 + 0,6)
/End-Free
Természetesen a lap alját figyelni kell, és ha túl közel vagyunk hozzá, akkor lapdobást kell eszközölnünk. Ehhez a printerfájlban fel kell vennünk egy új rekordot:
A R NEWPAGE
A ENDPAGE
A programban pedig így tudunk lapdobást végrehajtani, ha elértük mondjuk a 27 cm-t:
* lapdobás
C IF AktPoz > 27,0
C WRITE NEWPAGE
C EVAL AktPoz = 9,0
C ENDIF
Még kezdő RPG fejlesztőként gyakran találkoztam azzal a problémával teszteléskor, hogy parancssorból numerikus paraméterrel kellett meghívnom egy programot.
Tapasztaltabb kollégákat kérdeztem a hogyanról, de azt a választ kaptam, hogy csináljam meg karakteresre, aztán a programon belül mozgassam át a numerikusba. Már akkor szöget ütött ez a megoldás a fejembe, de hát nem vitatkoztam. Inkább utánanéztem a lehetőségeknek. Nos, természetesen van rá megoldás.
Tételezzük fel, hogy van egy programunk (PROG1 a LIB1 könyvtárban), aminek egy numerikus 5 hosszú paramétere van. A numerikus paraméterrel való hívásához használjuk az X'0...f'-et. A parancssorból történő program hívás így néz ki, ha a numerikus paraméter értéke 55555.
CALL LIB1/PROG1 PARM(X'055555f')
Amennyiben 10000-nél kisebb értékkel szeretnénk meghívni a PROG1-et, akkor elő kell nulláznunk. Például nézzük a 333-at:
CALL LIB1/PROG1 PARM(X'000333f')
A személyes mappámat néztem át takarítás céljából, amikor a videón szereplő programra akadtam. Már el is feledkeztem róla, pedig amikor írtam, nagyon érdekesnek találtam. A program ugyanis a jól megszokott Windows-os menü fílinget adja vissza az AS-on. A menüre feltettem PC-s programokat is épp úgy, mint ahogy AS-os programok is megtalálhatók rajta. A minél egyszerűbb bemutathatóság kedvéért, a könyvtárlisták beállítását nem a programban végeztem el.
Mellékelem a forráskódokat is, itt a programé, itt pedig a képernyőé.
Pascal-t oktató tanárom szavai jutottak nemrég az eszembe, aki azt mondta anno, hogy igyekezzünk minden eshetőségre felkészíteni programjainkat, próbáljuk "bolondbiztossá" tenni.
Ami miatt eszembe jutott a fenti gondolat, az egy program beviteli mezőjénél jelentkezett. A felhasználó fogalmam sincs hogy honnan másolt egy nevet (sajnos később Ő sem emlékezett rá, így nem tudtam leellenőrizni), amit beillesztett az ominózus beviteli mezőbe, majd lementette az adatot. A másolt névben egy speciális karakter is szerepelt, egy vezérlő karakter.
Ezt a program lementette, ami nem is jelentett volna problémát, de aztán egy másik rendszer másik programhoz került át paraméterként, ahol ez hibát okozott. Ezt nem részletezem, hanem inkább azt a program részletet mutatom meg, amit az esetet követően egyszerre beépítettem az alap program ellenőrzési rendszerébe. Nos lássuk is. A D kártyán az alábbi bejegyzéseket helyeztem el (a ? az a színezés miatt található a komment sorban):
*?ellenőrzésekhez
D R#Akt S 2 0
D R#Hosz S 2 0
D R#POS S 2 0
D R$Char S 1A
*
D R$ALAP C 'abcdefghijklmnopqrstuvwxyzöüóőúéáűí-
D ABCDEFGHIJKLMNOPQRSTUVWXYZÖÜÓŐÚÉÁŰÍ-
D 0123456789()-_.;,'
*?Char -> Hex
D ToHex PR EXTPROC('cvthc')
D szHexVal 65535A OPTIONS(*VARSIZE)
D szCharVal 65535A CONST OPTIONS(*VARSIZE)
D nSrcLen 10I 0 VALUE
*
*?Hex -> Dec
D CVTHex2To1 PR EXTPROC('cvtch')
D shortReceiver * VALUE
D longSource * VALUE
D sourceBytes 10i 0 VALUE
*
D Alpha S 65535A
D Hex S 65535A
D CharVal S 2a inz('0A')
D intResult S 3i 0
D NumResult S 4 0
Itt pedig a programrészlet, ami elvégzi az ellenőrzéseket. A 99-es indikátor a hibaindikátor, ha ez átbillen, akkor az ellenőrzés folytatása felesleges. A konkrét esetben már korábban is átbillenthetett, ezért a /Free utáni IF vizsgálat. WSNEVE a vizsgált mező neve. Első körben megnézzük a Scan függvénnyel, hogy az aktuális karakter szerepel-e az ALAP felsorolásban. Ebben a magyar kis- és nagybetűk mellett számokat és pár gyakran használt egyéb karaktert helyeztem el. Ha ebben nem találjuk meg a vizsgált karaktert, akkor nézzük meg, hogy mennyi a dec kódja. Ha ez 64 alatti, vagy 255, akkor ezt nem fogadjuk el. Ekkor egy MSGF-ból íratunk ki a képernyőre egy üzenetet (ERR0083):
/Free
If *in99=*Off;
R#Akt = 1;
R#Hosz = %Len(%Trim(WSNEVE));
Dow (R#Akt <= R#Hosz) and *in99=*Off;
R$Char = %Subst(WSNEVE:R#Akt);
If R$Char <> ' ';
R#POS = %Scan(R$Char : R$ALAP); //az alapkészletben megtalálható?
//?Elfogadott karakterek: dec(64)-től a dec(255)-ig
// ?Cél: ?vezérlő karaktereket ne lehessen rögzíteni, mert
//? azok hibás működéshez vezethetnek, ha más rendszerekbe
//? is átkerülnek.
//?1.CH
If R#POS = 0; //ha nem található meg, akkor további ellenőrzés
Alpha = R$Char;
Hex = *BLANKS;
ToHex(Hex : Alpha : %LEN(Alpha));
//?2.HD
CharVal = %Subst( Hex : 1 : 2 );
Callp CVThex2To1 (%addr(intResult)
: %addr(CharVal)
: %size(intResult) * 2);
//? 128
If intResult < 0;
NumResult = intResult + 256;
Else;
NumResult = intResult;
Endif;
If ((NumResult < 64 and NumResult >= 0) //?vezérlő karakter?
or NumResult = 255); //?EO-? EndOf
*in99=*On; // *In99 bebillentése
*in53=*On; // mezőhöz tartozó indikátor bebillentése
//?0083: Érvénytelen karakter szerepel a névben!
WSER01='ERR0083';
Endif;
Endif;
Endif;
R#Akt += 1;
EndDo;
Endif;
/End-Free