, , , , Utiliser ACS pour produire des fichiers Excel depuis l’IBM i

Access Client Solutions (ACS)

Pour rappel, ACS est le successeur de Client Access et permet toujours les exports de données.

ACS est également un produit entièrement Java, et utilisable en mode ligne de commande.

Il est donc possible de le piloter sur l’IBM i. Pour cela il vous faut :

  • Avoir le produit sous licence 5770JV1 (Java) version 8 ou supérieur
  • Access Client Solutions sur l’IFS (désormais installé via PTF (7.4: SI71900 / 7.3: SI71934 / 7.2: SI71935) dans /QIBM/ProdData/Access/ACS/Base

Exemples

Il est alors possible de provoquer le transfert de données de deux façons :

  • le fichier complet
  • une requête SQL permettant la sélection, transformation, jointure …

Syntaxe :

/PLUGIN=cldownload /system=<system>
                          [/userid=<userid>]
                          {/hostfile=<library/filename> | /sql="statement"}
                          {/clientfile=<path><filename>.<extension> | /display}
                          [/<options>]

    /userid     - user id to use when connecting to the target system
    /hostfile   - Source library and file on the IBM i system for the download
                  e.g. /hostfile=QIWS/QCUSTCDT
    /sql        - specify an SQL statement
                  e.g. /sql="select CUSNUM,LSTNAM,INIT,ZIPCOD from QIWS/QCUSTCDT"
    /clientfile - Target file location for the download.
                  The format of this file will be determined by the specified
                  extension (for example, .csv .ods .xlsx .xlsx)
                  If the file extension is not specified or is of a type
                  not supported, the data will be formatted as a .csv file
    /display    - write the output to the terminal
    
    Valid options are:
       /colheadings=<1/0> - Include column headings as the first row. When specified, the column names will be the heading.
       /usecollabels      - Use column labels for the heading.

Puisque ACS est directement sur votre IBM i, on peut utiliser localhost pour la valeur /system. Cela permet également la portabilité de la commande d’une machine à l’autre.

Pour transférer tout un fichier on utilisera le paramètre /hostfile. Ici sous QSH :

cd /QIBM/ProdData/Access/ACS/Base

java -jar acsbundle.jar
/PLUGIN=cldownload /system=localhost
/hostfile=sqlsample/employee
/clientfile=/home/nb/export/employe.xlsx

Cela produit :

Remarquer le nom de l’onglet.

Pour transférer par une requête SQL :

cd /QIBM/ProdData/Access/ACS/Base

java -jar acsbundle.jar
/PLUGIN=cldownload /system=localhost
/sql="select trim(firstnme) concat ' ' concat trim(lastname), hiredate, current date - hiredate as \"Ancienneté\" from sqlsample.employee" /clientfile=/home/nb/export/employesql.xlsx

Attention à l’échappement des caractères spéciaux …

On obtient :

Des options supplémentaires vous permettent d’affiner la sortie :

  • /colheadings=<1/0> – Inclure ou non l’entête
  • /usecollabels – Utiliser les labels au lieu des noms de colonne

Ces fonctions nécessitent une version de ACS > 1.1.8.6 pour fonctionner correctement.

Comment automatiser ?

Il est relativement simple d’intégrer cette commande Java dans un programme CL. Ici en utilisant /clientfile.

Par exemple avec RUNJVA :

Ou par QSH :

Ici on a paramétré plus d’éléments pour avoir une base de programme plus générique.

Avantages ?

Access Client Solutions permet facilement d’automatiser vos conversions depuis l’IBM i, et non depuis un poste client. Cela rend beaucoup plus naturel l’intégration de ces traitements dans vos chaines, la maitrise des transferts par l’IT et non par les utilisateurs, la maitrise des flux, des versions de produits utilisées etc …

, Création d’un référentiel de vos sources

Cette astuce ne remplace pas un outil du marché qui vous offrira beaucoup plus d’opportunités, en terme d’analyses et d’interactions avec d’autres outils de développements de la plateforme IBM i.

Mais il est possible que vous n’ayez pas la chance de posséder un de ces outils, et voici une méthode qui va vous permettre basiquement de trouver ou est utilisée une zone par exemple si vous désirez changer ses attributs.

La méthode utilisée dans notre cas consiste à créer un fichier avec l’intégralité de vos lignes sources, que vous pouvez faire générer chaque nuit par exemple

Pour cela il va falloir d’abord faire liste des membres sources de votre machine

Creation de la table pour votre liste

CREATE TABLE LSTMBRsrc (
LIB CHAR(10) CCSID 297 NOT NULL ,
FILE CHAR(10) CCSID 297 NOT NULL ,
MBR CHAR(10) CCSID 297 NOT NULL ,
TYP CHAR(10) CCSID 297 DEFAULT NULL )

Remplissage de la table, vous pouvez affiner en éliminant des bibliothèques inutilisées.

ici on utilise le fichier de référence du système SYSPARTITIONSTAT en SQL une partition = un membre

insert into lstmbrsrc
SELECT
substr(TABLE_SCHEMA, 1, 10) as lib,
substr(TABLE_NAME, 1, 10) as file,
substr(TABLE_PARTITION, 1, 10) as mbr,
source_type
FROM SYSPARTITIONSTAT WHERE substr(TABLE_SCHEMA, 1, 1) <>  »Q » and +
not source_type isnull and NUMBER_ROWS > 0′)

Création de la table résultat

qui aura les informations du sources (srcdta, srcseq, srcdta et du fichier srclib, srcfil, srcmbr, srctyp) , vous pouvez ajouter d’autre zones sur les dates par exemple .

CREATE TABLE LSTSRC (
SRCLIB CHAR(10) CCSID 1147 NOT NULL DEFAULT  » ,
SRCFIL CHAR(10) CCSID 1147 NOT NULL DEFAULT  » ,
SRCMBR CHAR(10) CCSID 1147 NOT NULL DEFAULT  » ,
SRCTYP CHAR(10) CCSID 1147 NOT NULL DEFAULT  » ,
SRCSEQ NUMERIC(6, 2) NOT NULL DEFAULT 0 ,
SRCDTA CHAR(100) CCSID 1147 NOT NULL DEFAULT  » ,
SRCDAT NUMERIC(6, 0) NOT NULL DEFAULT 0 )

Maintenant, il faut la remplir en lisant le fichiers des membres

Voici en clp un exemple de code, à faire pour chaque membre

Création de l’alias (nécessaire à SQL pour accéder aux données d’un membre)

CHGVAR &REQUETE ( +
‘CREATE ALIAS QTEMP/WLSTMBR FOR’ *BCAT &LIB *TCAT ‘/’ *TCAT &FILE +
*BCAT ‘(‘ *TCAT &MBR *TCAT ‘)’)
RUNSQL SQL(&REQUETE) COMMIT(*NONE)
monmsg sql0000

Remplissage du fichier avec les informations du membre

CHGVAR &REQUETE +
(‘INSERT INTO LSTSRC SELECT  »’ *TCAT &LIB *TCAT  »’ ,  »’ *TCAT +
&FILe *TCAT  »’ ,  »’ *TCAT +
&MBR *TCAT  »’ ,  »’ *TCAT +
&typ *TCAT  »’ , ‘ BCAT + ‘SRCSEQ , SRCDTA , SRCDAT FROM WLSTMBR’) RUNSQL SQL(&REQUETE) COMMIT(NONE)
monmsg sql0000

Suppression de l’alias

CHGVAR &REQUETE ( +
‘DROP ALIAS QTEMP/WLSTMBR’)
RUNSQL SQL(&REQUETE) COMMIT(*NONE)
monmsg sql0000

Ce traitement est un peu long , il est fréquent d’avoir plusieurs millions d’enregistrements dans votre fichier résultat, attention donc aussi à la place disponible sur votre partition !

Maintenant vous pouvez rechercher une chaine de caractère dans votre fichier exemple un NOM de ZONE.

Dans notre exemple recherche *LDA en majuscule ou minuscule avec création d’un fichier source ici LISTE

create table QTEMP/LISTE as (
SELECT * FROM
lstsrc
WHERE SRCDTA like(‘%*LDA%’)
) with data

Conclusion :

Pensez à faire du ménage dans tout les sources qui ne servent plus.
Si vous n’avez pas les sources vous ne pouvez rien faire mais c’est vrai dans tous les cas.
En cas d’analyse d’impacts vous devrez croiser avec une analyse sur les objets , exemple sortie de dsppgmref
Si vous devez faire de gros changements à effectuer, il est opportun de s’équiper d’un produit qui fera tout ca pour vous .
En attendant d’avoir tout dans l’IFS et de pouvoir tout mettre sous GIT … , c’est le monde d’après .

Editer du RPGLE avec Visual Studio Code

Voici une autre solution pour éditer vos codes sources RPGLE

Vous connaissez RDI basé sur Eclipse et ILEditor

Voici une troisième alternative pour les gens réfractaires à SEU !

Ce n’est pas une alternative complète, puisqu’on ne pourra que manipuler des sources de L’IFS sans compilations et autres opérations sur le système.

C’est Visual Studio Code que vous pouvez télécharger gratuitement à cette url https://visualstudio.microsoft.com/fr/ , il est intéressant pour gens qui code sur d’autre langages C#, .NET etc …

Comme Eclipse vous allez pouvoir choisir des extensions (on parle plutôt de plugin sur Eclipse), il en existe 3 principales pour éditer du RPG sur IBMi .

Voici les principaux contributeurs merci à eux

Niels Liisberg
Steve Richter, il a fait également un éditeur pour SQL
Barrett Otte

Nos équipes ont choisi celui de Barrett Otte parce qu’il fait également le CLLE et qu’il fonctionne bien.

Anand Kekhale a fait fait un gros travail (SSH FS) pour que vous puissiez accéder à votre ifs, vous pouvez charger ici

https://www.anandk.dev/2020/11/VSCode-IBMi-AS400.html

Conclusion:

Ce n’est pas la solution miracle mais pour les utilisateurs multi-techno qui font de la maintenance occasionnelle, ca peut permettre d’avoir un seul IDE

Son point fort c’est l’interfacage avec GIT qui permet de créer des repositories à la volée !

Un autre lien utile pour en savoir plus

https://en.wikipedia.org/wiki/Visual_Studio_Code

, , Exécuter une action sur une liste SQL service

Vous avez tous compris qu’une grande partie de l’administration de vos IBMi se fera par SQL service.

Pour faire des contrôles, l’accès aux vues est suffisante.

Par exemple, le contrôle du nombre de pages dans une OUTQ :

SELECT sum(TOTAL_PAGES)
FROM QSYS2.OUTPUT_QUEUE_ENTRIES_BASIC
where OUTPUT_QUEUE_LIBRARY_NAME = ‘SRCEXPL’ and OUTPUT_QUEUE_NAME = ‘VOTREOUTQ’

Mais pour agir c’est plus compliqué, dans certains cas il existe des procédures pour les DTAQ par exemple.

Mais la plus part du temps, vous devrez passer par une commande système dans ce cas en SQL ; vous pouvez utiliser la procédure cataloguée QCMDEXC.

Elle fonctionne comme l’api du même nom.

Exemple :

Pour épurer l’OUTQ QEZJOBLOG

Call qcmdexc(‘CLROUTQ QEZJOBLOG’)

Mais comment faire pour agir sur une liste sans faire un programme ou une procédure qui lirait un curseur ?

L’astuce est d’utiliser un For et dans le select de générer directement la commande à exécuter

Voici un exemple de script qui déplace les spools des OUTQs, commençant par ACT en mettant en référence utilisateur l’OUTQ d’origine.

les zones SPOOLNAME, JOBNAME, FILENUM, OUTQ_QUEUE_NAME proviennent de la vue.

begin
for
SELECT ‘ chgsplfa FILE(‘ concat SPOOLNAME concat ‘) JOB(‘ concat JOB_NAME concat ‘) SPLNBR(‘ concat char(FILENUM) concat ‘) outq(Votreoutq) save(*yes) usrdta( »’ concat OUTPUT_QUEUE_NAME concat  »’)’ as chgspl
FROM QSYS2.OUTPUT_QUEUE_ENTRIES_BASIC
where OUTPUT_QUEUE_LIBRARY_NAME = ‘Votrelib’ and OUTPUT_QUEUE_NAME like(‘ACT%’)
do
call qcmdexc(CHGSPL);
end for;
end

Conclusions :

Cette solution est souvent utilisée par exemple avec la fonction table OBJECT_STATISTICS.

Exemple :

pour faire la liste des fichiers SAVF

SELECT objname, objlib, ifnull(objtext, ‘ ‘) as objtext
FROM TABLE (QSYS2.OBJECT_STATISTICS(‘ALL’,’FILE’) ) AS X
WHERE OBJATTRIBUTE = ‘SAVF’

La seule limite est qu’il est un peu plus compliqué pour gérer les erreurs sur le qcmdexc …

Bien sûr pour la bible rendez vous sur la page de Scott Forstie

, 5 choses à connaitre sur la notion de membre

1) Qu’est ce qu’un membre ?
Un membre est une notion purement IBM i, il sert à cloisonner les données dans un fichier, l’usage le plus connu c’est les fichiers sources où chaque objet est défini dans un membre.
mais on peut également utiliser cette notion pour des fichiers de données , exemple un fichier client avec un membre par régions pour cloisonner les informations.

Pour choisir le membre, on utilisait la commande ovrdbf
OVRDBF FILE(VOTREFIC) MBR(VOTREMEMBRE) quand vous aviez fini, vous faisiez un DLTOVR

Attention un LF peut pointer sur les données de pluseiurs membre du PF, c’est même la valeur par défaut de la commande,
CRTLF … DTAMBRS(*ALL)

2) Pourquoi utiliser la commande DSPPFM
Parce que c’est la seule commande qui montre les données brutes dans l’ordre réel, en effet SQL pourra faire des modifications de présentation, voire indiquer des erreurs de lectures.
Les touches de fonction F10 et F11 permettent de voir les données en hexadécimal.

3) Pourquoi réorganiser les membres des fichiers.
Quand on supprime un enregistrement dans un fichier donc dans un membre, cet enregistrement est juste tagué comme étant inutilisable.
il y a 2 cas:

  • en DDS, les fichiers sont créés avec le paramètre par défaut reusedlt(no) => un nouvel enregistrement est ajouté à la fin.
  • en SQL, les fichiers sont créés avec le paramètre par défaut reusedlt(yes) => un nouvel enregistrement est ajouté sur la place d’un enregistrement supprimé.

En SQL, on a donc besoin de moins de RGZPFM et surtout, si on a sensiblement le même nombre de créations et de suppressions.

4) Executer une requête sql sur un membre d’un fichier physique

Par défaut SQL s’exécute sur le premier membre crée en effet, il considère qu’il n’y a qu’un membre,
en effet un create table ne permet qu’un membre.

Si vous voulez lire un membre particulier sur un fichier physique multi-membres par SQL, vous devez faire un create alias
exemple :
CREATE ALIAS BIBLIO/NOMALIAS FOR BIBLIO/FICHIER (NOMMEMBRE)

vous utilisez désormais votre alias comme un fichier ou une vue

Select * from BIBLIO/NOMALIAS

Vous pouvez supprimer votre alias
DROP ALIAS BIBLIO/NOMALIAS

5) Avoir des informations sur les membres
il y a 2 solutions, de manière historique en lançant la commande dspfd … TYPE(*MBRLIST)
ou avoir des informations par SQL (on parle de partition …)
Vous avez une vue dans qsys2 qui s’appelle SYSPARTITIONSTAT et qui permet de voir ces informations.

Conclusion :
Utiliser les membres n’est pas le sens de l’histoire
En SQL on utilise des fichiers mono-membre
Pour les sources préférer L’IFS qui vous permettra d’utiliser des outils comme GIT
Mais il serait étonnant que vous n’en rencontriez pas, il faut donc comprendre comment ça marche.