du logiciel Avantage
Il y a de cela quelques années, j'ai dévelopé des programmes d'accès aux fichiers du logiciel comptable Avantage en utilisant l'environnement de programmation CA-Clipper 5.2. Ces programmes sont encore utilisés aujourd'hui par Chéné-Sasseville Ltée de Trois-Pistoles. Comme CA-Clipper produit des fichiers exécutables DOS, ces programmes sont plutôt démodés et mériteraient probablement une mise à jour vers Windows.
Les solutions comptables Avantage s'intègrent efficacement dans la stratégie de contrôle des processus de gestion en répondant aux besoins multiples et diversifiés des entreprises de différents secteurs d'activité et aux besoins spécifiques des professionnels comptables. Ces solutions prennent la forme d'un logiciel de comptabilité qui prend plusieurs formes dépendant des besoins du client, soit:
Module | Description |
---|---|
progression | Comptabilité générale, simple entreprise; |
implication | Comptabilité générale et gestion des coûts par projet, gestion de feuilles de temps et salaires; |
intégration | Comptabilité générale, gestion d’inventaire, gestion des coûts par projet, travaux en cours, facturation progressive, gestion des feuilles de temps et salaires CCQ; |
expansion | Comptabilité générale et gestion d’inventaire. |
Une des caractéristiques du logiciel Avantage réside dans le fait que Avantage est un logiciel programmé en FoxPro et que ses données sont logées dans des fichiers dBase avec l'extension .dbf, un format de fichier public. Cette caractéristique permet donc à des programmes extérieurs à Avantage d'avoir accès aux données comptables.
La firme Chéné-Sasseville Ltée de Trois-Pistoles utilise le logiciel Avantage pour sa comptabilité. En avril 1999, ils m'ont demandé de concevoir un logiciel qui permettrait de préparer un rapport couvrant, pour chaque vendeur: les ventes du mois courant, les ventes cumulatives depuis le début de l'année jusqu'à la fin du mois courant ainsi que les ventes pour les mêmes périodes de l'année précédente. Le résultat de cet effort a été le programme RVentes.exe conçu en Clipper 5.2. Par la même occasion, le programmes Vendeurs.exe a été développé: il produit une liste des clients de chaque vendeur.
Programmes existants en Clipper 5.2
Le travail de conception des programmes RVentes.exe et Vendeurs.exe a débuté en avril 1999 à la demande de la firme Chéné-Sasseville Ltée de Trois-Pistoles. Il s'agissait d'une programmation à faire en utilisant le langage CA-Clipper 5.2 de Computer Associates.
CA-Clipper est un environnement de programmation produit par la firme Computer Associates. À l'origine, ce langage de programmation était simplement un compilateur dBase mais il a évolué drastiquement et est devenu un langage de programmation avec des caractéristiques uniques qui supportent autant les bases de données dBase que d'autres types de bases de données. CA-Clipper produit des programmes exécutables sous DOS.
Programme RVentes
Le programme RVentes.exe a été concu pour livrer un rapport des ventes pour chaque vendeur, une partie de la comptabilité que le logiciel Avantage ne couvre pas bien. Ce rapport devrait être envoyé aux vendeurs à chaque mois et leur dire combien et à quels clients ils avaient vendu pendant le mois courant de même que depuis le début de l'année courante. Il fut convenu par la suite que les périodes correspondantes de l'année précédente devraient aussi être affichées.
Une grande partie du programme consiste en la définition d'un interface usager des routines d'affichage et d'impression que nous n'allons pas décrire ici. La Figure 1 ci-dessous présente le diagramme de flux du programme:
La partie importante du programme RVentes.exe se retrouve dans le code Clipper suivant:
USE CLIENT.dbf NEW ALIAS Clients
Index on CNUM to ICNum // Crée un index selon CNUM dans CLIENT.DBF USE RCVBIL.DBF NEW ALIAS Ventes
Index on RCLI to ICLI // Crée un index selon RCLI dans RCVBIL.DBF Set Relation to RCLI into Clients DbSetFilter ({||(cVendeur = Clients->CVEND) .AND. ((cCurrYr1 <= RDATE .AND. cCurrYr2>= RDATE); .OR. (cPrevYr1 <= RDATE .AND. cPrevYr2>= RDATE))}) Sort to TRANSIT.DBF on RCLI, RDATE // Crée le fichier TRANSIT.DBF COUNT to nRec If nRec == 0
@ 14,35 SAY "interrompue!"
@ 15,24 SAY "Aucune transaction pour le vendeur - Code = " + cVendeur
lStop:= .T.
RETURN EndIF // TRANSIT.DBF ne contient que les records pour les périodes spécifiées USE TRANSIT.dbf NEW ALIAS Travail // Utilise le fichier TRANSIT.DBF GO TOP // Lecture de TRANSIT.DBF et extraction des ventes pour le vendeur pendant les périodes concernées DO WHILE .NOT. EOF() // pour chaque record du fichier TRANSIT.DBF nRecNo:= AScan(aTable, {|element| element[2] == RCLI}) // recherche RCLI dans aTable if RDATE >= cCurrYr1 // un record pour cette année
aTable[nRecNo, 4] := aTable[nRecNo, 4] + IIF(RCREDIT, -RMONT1, RMONT1)
if RDATE >= cCurrMo1 // ...et ce mois-ci
aTable[nRecNo, 3] := aTable[nRecNo, 3] + IIF(RCREDIT, -RMONT1, RMONT1)
endif else if RDATE <:= cPrevYr2 // un record de l'an dernier aTable[nRecNo, 6] := aTable[nRecNo, 6] + IIF(RCREDIT, -RMONT1, RMONT1) if RDATE >= cPrevMo1 // même mois l'an dernier aTable[nRecNo, 5] := aTable[nRecNo, 5] + IIF(RCREDIT, -RMONT1, RMONT1)
endif endif end SKIP // prochain record END // Délestage des cas où toutes les cumulatifs de aTable sont tous nuls FOR i:= 1 to len(aTable)
IF Abs(aTable[i,3]) + Abs(aTable[i,4]) + Abs(aTable[i,5]) + Abs(aTable[i, 6]) > 0
aArray:= aTable[i]
AAdd(aTab, aArray) // ajoute une ligne à aTab qui va remplacer aTable ENDIF NEXT aTable:= {} // destruction de aTable car aTab a pris la relève CLOSE DATABASES // Fermeture des bases de données
Chargement des fichiers
Comme on peut le voir, le programme RVentes.exe se sert de deux fichiers de la base de données comptable du logiciel Avantage: CLIENT.DBF (fichier client) et RCVBIL.DBF (fichier des recevables). Afin d'éviter tout problème avec le logiciel Avantage, le programme ne manipule pas ces fichiers dans leur contexte. Dès le départ du programme, les fichiers sont copiés dans un répertoire où ils peuvent être manipulés sans causer le moindre trouble.
Un des problèmes posé par ce chargement des fichiers réside dans le fait que le répertoire où le logiciel Avantage emmagasine ses fichiers a varié avec les mises à jour du logiciel. Il est donc indispensable d'indiquer au programme RVentes.exe l'emplacement des fichiers dans l'ordinateur. Ici, on a simplement assigné à la variable d'environnement "Avantage" le parcours menant aux fichiers du logiciel Avantage. Sous Windows 2000, on initialise donc cette variable dans le fichier AUTOEXEC.NT qui se trouve dans le répertoire C:\WINNT\SYSTEM32\.
Détermination des périodes d'intérêt
Pour les fins du programme RVentes.exe, les date qui nous intéressent sont les suivantes:
- Mois courant - cCurrMo1 <= RDATE <= cCurrMo2 où cCurrMo1 dénote le début du mois courant et cCurrMo2 dénote la fin du mois courant;
- Année courante - cCurrYr1 <= RDATE <= cCurrYr2 où cCurrYr1 dénote le début de l'année courante et où cCurrYr2 = cCurrMo2;
- Mois correspondant de l'année précédente - cPrevMo1 <= RDATE <= cPrevMo2;
- Année prédécente - cPrevYr1 <= RDATE <= cPrevYr2.
Création de la table temporaire Transit.dbf
On commence par utiliser la table CLIENT.DBF et on y ajoute un index appelé ICnum sur le champ CNUM de la table. On utilise ensuite la table RCVBIL.DBF et on y ajoute un index appelé ICli sur le champ RCLI de cette dernière table. Nous sommes alors prêt à joindre les deux tables par les champs clients CNUM et RCLI.
À ce moment, on a déja recueilli les dates qui nous intéressent soit celles du mois courant, de l'année courante, du mois de l'année précédente et celle de l'année précédente. On filtre alors la relation pour ne garder que les records du vendeur choisi ainsi que ceux dont les dates (champ RDATE) sont situées entre le début de l'année courante et la date de fin de mois ainsi que les dates correspondantes de l'année précédente. On trie ensuite cette liste par rapport au client et aux dates et on crée ainsi le fichier temporaite Transit.dbf.
Cette opération est ainsi équivalente à l'énoncé SQL suivant:
SELECT * FROM RCVBIL.DBF, RCVBIL.DBF WHERE CNUM = RCLI AND (cPrevYr1 <= RDATE) AND (RDATE <= cPrevYr2) OR (cCurrYr1 <= RDATE) AND (RDATE <= cCurrYr2) ORDER BY RCLI, RDATE
Construction de la table des cummulatifs
Il nous faut maintenant regrouper les informations de chaque clients à l'intérieur des périodes visées par le programme: le mois courant, le cummulatif de l'année courante, le mois correspondant de l'année précédente ainsi que le cummulatif de l'année précédente.
Pour ce faire, on passe à travers de tous les records de la table TRANSIT.DBF. Comme cette table est triée par client et par date, on peut donc attribuer un record de la table des cummulaifs à chaque client lorsqu'on rencontre son identification pour la première fois, chaque record comprenant un champ pour le nom du client et quatre champs pour additionner le montant de la vente (ou du crédit) aux périodes d'intérêt. La suite est triviale: on ajoute des montants aux champs cummulatifs selon que la date du record correspond à l'une ou plusieurs des périodes considérées comme illustré ci-dessous à la Figure 2.
Le contenu de cette table est alors revu pour en enlever toutes les rangées qui comportent des champs cummulatifs qui sont tous nuls. La table résultante est le résultat du programme qu'on visualise à l'écran ou qu'on imprime afin de le faire parvenir au vendeurs.
Programme Vendeurs
Le programme Vendeurs.exe a été conçu pour générer un rapport donnant ou bien la liste complète des vendeurs avec ou sans leurs clients, ou la liste des clients d'un vendeur donné. Outre la conception de l'interface usager et des routines d'affichage et d'impresion, la partie significative du programme est la suivante:
USE CLIENT.DBF NEW ALIAS Clients
Index on (CVEND + CNOM + CVIL + CNUM) to ICVEND
IF .NOT. lAll // lAll implique tous les vendeurs DBSetFilter({|| cVendeur = Clients->CVEND}) // sélectionne le vendeur ENDIF GO TOP // on commence au premier record de CLIENT.DBF DO WHILE .NOT. EOF() // répète jusqu'à la fin du fichier nRecNo:= AScan(aTable, {|element| element[1] == CVEND}) // recherche CVEND dans aTable IF nRecNo == 0 // on n'a pas trouvé le vendeur aArray:= {CVEND, 1} // on ajoute une entrée au tableau aTable AAdd(aTable, aArray) // tableau comportant une entrée par vendeur ELSE aTable[nRecNo, 2]:= aTable[nRecNo, 2] + 1 // ajoute un client à la somme ENDIF SKIP // prochain record ENDDO
On commence par y utiliser le fichier CLIENT.DBF qu'on trie par rapport aux champs CVEND, CNOM, CVIL et CNUM.
Dépendant du choix fait par l'utilisateur de considérer tous les vendeurs et leurs clients (lAll est vrai), un vendeur donné avec ses clients (lAll est faux) ou une liste sommaire de tous les vendeurs (lAll est vrai et lList est vrai), on va avoir des rapports différents. Ici, si lAll est faux, on va filtrer le fichier CLIENT.DBF et ne retenir que les records où CVEND correspond au vendeur choisi. À ce moment-ci, ou bien CLIENT.DBF contient tous les vendeurs et leurs clients ou bien il n'en contient qu'un seul avec ses clients (la table est filtrée).
On va alors former un tableau comportant une entrée par vendeur et qui, pour chaque vendeur, fera le décompte des clients. Ce tableau sera utilisé lors de l'affichage ou de l'impression du rapport.
Conclusion
Ces programmes sont en opérations chez Chéné-Sasseville Ltée depuis 1999. Il a fallu intervenir à quelques occasions, principalement lors que la firme a mis à jour ses systèmes informatiques ou le logiciel Avantage.
CA-Clipper est un langage de programmation qui produit des programmes opérant sous le système d'exploitation DOS. C'est donc un logiciel démodé même si les programmes peuvent toujours être exécutés sous Windows.
Est-ce que ce serait une bonne idée de moderniser ces programmes pour en faire des programmes Windows? L'environnement de programmation de Delphi se prête bien à un tel projet et ça pourrait se faire pour un montant assez modique.
Annexes
Références
Cette page a pu s'inspirer des références suivantes. Lorsque c'est le cas, j'en remercie les auteurs de ces textes.
- Le livre "CA-Clipper 5.2: Step-By-Step" par Dan Gutierrez est un tutoriel d'introduction à la création de bases de données avec l'environnement de développement CA-Clipper. Il couvre les concepts de base des langages de base de données, leurs opérations standards ainsi que les fonctions spéciales du langage.
- L'article intitulé "CA-CLIPPER PROGRAMMING" du site "The Holme pages" présente des techniques pour atteindre une bonne qualité de programmation en CA-Clipper.
Code des programmes RVentes et Vendeurs
Je n'ai pas inclus de fichier à télécharger donnant le code des programmes et la base de données sous-jacente requise pour leur exécution car la base de données qui a été utilisée est une base de données révélant une partie de la comptabilité d'une entreprise existante.. Cependant, je donne dans les sections qui suivent le code complet des programmes RVentes.prg et Vendeurs.prg qui représentent le sujet de cet article.
Code de RVentes.prg
*********************************************************************
* Fichier : RVENTES.PRG
* Droits : Copyright 1999, GTRO Informatique
* Auteur : Georges Trottier, 10/04/99 @ 15:27
* Version : 2.0 - 25 juin 1999; 2.2 - 14 avril 2003
* Notes : Travail fait pour Chéné & Sasseville
* : Rapport donnant les ventes des clients de chaque vendeur
*Modifié : 15 avril 2003 - cPath pris dans variable d'environnement
********************************************************************* #include "Inkey.ch" #include "Box.ch" PROCEDURE Main() STATIC GetList:= {} SET STATUS OFF SET TALK OFF SET BELL OFF SET ESCAPE ON SET MARGIN TO 7 SET DATE FORMAT "yyyy/mm/dd" SET MESSAGE TO MaxRow() CENTRE
// Liste des variables globales du programme PUBLIC cCurrYr1, cCurrYr2, cPrevYr1, cPevYr2, cPrevMo1, cPrevMo2, cCurrMo1, cCurrMo2
PUBLIC aTable:= {} // tableau client PUBLIC aTab:= {} // tableau client PUBLIC aArray:= {} PUBLIC cVendeur:= ' ' // code du vendeur PUBLIC nMois, nAn // mois et ann‚e considérée PUBLIC nChar := 69 // largeur des pages imprimées PUBLIC nPage := 1, nLine := 0 // compteurs de pages et de lignes PUBLIC nLTotal := 55 // nombre total de lignes par pages imprimées PUBLIC lPFlag := .F. // Affichage: (1) .T. -> imprimante; (2) .F. -> écran PUBLIC lStop // contrôle l'arrêt des procédures PUBLIC nChoice // Choix de menu language PUBLIC cPath // 15 avril 2003 PUBLIC lInit:= .T. PUBLIC cScreenTop, cScreenBot
PRIVATE cColorString:= SetColor() CLEAR cPath:= GetEnv("Avantage") // 15 avril 2003 WHILE .T. Interface() @ 5,20 SAY cPath
if .not. File(cPath + '*.*') @ 6,20 SAY "Source not found" endif @ MaxRow()-1,20 PROMPT "Traiter" MESSAGE "Effectuer le traitement des donn‚es" @ MaxRow()-1,50 PROMPT "Quitter" MESSAGE "Quitter l'application" Menu to nTraite
RestScreen(MaxRow()-1, 0, MaxRow(), MaxCol(), cScreenBot) DO CASE CASE nTraite == 1 Traite() CASE nTraite == 2 CLS QUIT RETURN EndCase ENDDO // WHILE .T. CLEAR RETURN ********************************************************************************
* Procédure: Interface - 06/16/99 9:53:AM
* Par : Georges Trottier, Copyright 1999 GTRO Informatique
* Notes : Affiche l'interface de l'application
******************************************************************************** PROCEDURE Interface
LOCAL cWallPaper:= '', nRow
LOCAL cTitre:= "Ventes aux clients attitr‚s des vendeurs, Version 2.3" LOCAL cFirme:= "Ch‚n‚ & Sasseville Lt‚e" CLEAR // Interface usager SetColor (cColorString) For nRow:= 0 TO 25 @ nRow,0 SAY PADC(cWallPaper, 80, CHR(176)) Next cScreenTop:= SaveScreen(0, 0, 0, MaxCol()) cScreenBot:= SaveScreen(MaxRow()-1, 0, MaxRow(), MaxCol()) SetColor('W/B, N/W,,,N/W') @ 1, 1 CLEAR TO MaxRow()-2, MaxCol()-1 @ 1,1 TO MaxRow()-2,MaxCol()-1 DOUBLE COLOR 'W/B' @ MaxRow()-3, 2 SAY PADC("Copyright GTRO Informatique 2003", MaxCol()-3) @ 2,2 SAY PADC(cFirme, MaxCol()-3) @ 3,2 SAY PADC(cTitre, MaxCol()-3) @ 4,2 TO 4, MaxCol()-2 RETURN /* Interface */ ********************************************************************* * Procedure : Traite * Auteur : Copyright 1999, GTRO Informatique * Par : Georges Trottier, 13/04/99 @ 13:15 * Notes : Saisie du mois ********************************************************************* PROCEDURE Traite
aTab:= {} // variable PUBLIC If lInit
ChargeFichiers(9, 20, 15, 60, "Chargement des fichiers") lInit:= .F. EndIF cToDay:= DTOS(Date()) nMois:= VAL(SUBSTR(cToDay, 5,2)) nAn:= VAL(SUBSTR(cToDay, 1,4)) If nMois = 1 nMois:= 12 nAn-- EndIF nMois-- // Saisies @ 7,20 SAY 'Saisir le mois/ann‚e: / ' @ 7,47 GET nMois PICTURE '99' @ 7,50 GET nAn PICTURE '9999' @ 8,20 SAY 'Saisir le code du vendeur: ' @ 8,47 GET cVendeur PICTURE 'XXXX' READ RestScreen(0, 0, 0, MaxCol(), cScreenTop) cVendeur:= UPPER(cVendeur) nChoice:= 1 @ 9,20 SAY "Langue du rapport" @ 9,40 PROMPT "Rapport en francais" @ 10,40 PROMPT "Report in English" MENU to nChoice
// Initialisation des dates pour les périodes considérées cCurrMo1:= DTOC(CTOD(STR(nAn,4) + '/' + STR(nMois,2) + '/01')) cCurrMo2:= DTOC(dEndMois:= CTOD(STR(nAn,4) + '/' + STR(nMois,2) + '/' + STR(DaysThisMonth(nMois, NAn), 2))) cCurrYr1:= DTOC(CTOD(STR(nAn,4) + '/01/01')) cCurrYr2:= cCurrMo2
cPrevMo1:= DTOC(CTOD(STR(nAn-1,4) + '/' + STR(nMois,2) + '/01')) cPrevMo2:= DTOC(CTOD(STR(nAn-1,4) + '/' + STR(nMois,2) + '/' + STR(DaysThisMonth(nMois, nAn-1),2))) cPrevYr1:= DTOC(CTOD(STR(nAn-1,4) + '/01/01')) cPrevYr2:= cPrevMo2
If dEndMois >= Date() @ 9,10 SAY "ATTENTION! - Le mois choisi n'est pas termin‚!" @ 10,10 SAY "D'autres transactions pourraient s'ajouter d'ici la fin du mois!" EndIF nChoiceAff:= 2 @ MaxRow()-1,20 PROMPT "Imprimante" MESSAGE "Impression sur papier" @ MaxRow()-1,37 PROMPT "Ecran" MESSAGE "Affichage … l'‚cran" @ MaxRow()-1, 57 PROMPT "Fin" MESSAGE "Affiche le menu de d‚part" MENU to nChoiceAff
RestScreen(MaxRow()-1, 0, MaxRow(), MaxCol(), cScreenBot) CLOSE DATABASES IF nChoiceAff = 1 .OR. nChoiceAff = 2 lPFlag = (nChoiceAff = 1) Traitement() ENDIF IF nChoiceAff = 3 ENDIF
RETURN /* Comman1 */ *********************************************************************
* Procedure : Traitement
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 13/04/99 @ 13:30
* Notes : Programme contrôlant les autres sous-programmes
********************************************************************* PROCEDURE Traitement() LOCAL nNext
lStop:= .F. @ MaxRow()-4,2 SAY PADC("", MaxCol()-3) @ 12,24 SAY 'Un instant... En traitement...' @ 13,24 SAY 'Initialisation...' Initialise() If lStop // le vendeur n'est pas inscrit dans le fichier 01CLIENT.DBF @ MaxRow()-1, 32 PROMPT "Prochain cas" MESSAGE "Ce vendeur n'existe pas, passer au prochain cas" Menu to nNext
If nNext == 1 RETURN EndIF RETURN EndIF @ 13,42 SAY 'termin‚e!' @ 14,24 SAY 'Analyse...' Analyse() If lStop // aucune transaction pour ce vendeur dans RCVBIL.DBF RETURN EndIF @ 14,35 SAY "termin‚e!" @ 15,24 SAY "Nombre de clients: " + STR(len(aTab), 5) If lPFlag
@ 16,24 SAY "Nombre de pages: " + STR(RoundUp((len(aTab)+5)/50),5) Else @ 16,24 SAY "Nombre d'‚crans: " + STR(RoundUp((len(aTab)+2)/20),5) EndIf @ MaxRow(), 1 SAY PADC("N'importe quelle touche pour continuer/<ESC> pour arrˆter", MaxCol()) nCle = Inkey(0) if nCle = K_ESC
RETURN endif Cls Impression() CLOSE DATABASES RETURN /* Traite */ *********************************************************************
* Procedure : Initialise
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 14/04/99 @ 11:06
* Notes : Extraction des noms de clients du vendeur
********************************************************************* PROCEDURE Initialise() LOCAL nRec
USE CLIENT.DBF NEW ALIAS Clients
Index on CNOM to ICNom
DBSetFilter({|| cVendeur = Clients->CVEND}) Count to nRec
If nRec == 0 @ 13,42 SAY 'interrompue!' @ 14,24 SAY "Vendeur inexistant - Code = " + cVendeur
lStop:= .T. RETURN EndIF GO TOP DO WHILE .NOT. EOF() aArray:= {CVEND, CNUM, 0, 0, 0, 0, CNOM} AAdd(aTable, aArray) // tableau comportant une entrée par client SKIP ENDDO CLOSE DATABASES DELETE FILE ICNom.ntx
RETURN /* Initialise */ *********************************************************************
* Procedure : Analyse
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 14/04/99 @ 11:06
* Notes :
********************************************************************* PROCEDURE Analyse() LOCAL i, nRecNo, nRec
USE CLIENT.dbf NEW ALIAS Clients
Index on CNUM to ICNum // Crée un index selon CNUM dans CLIENT.DBF USE RCVBIL.DBF NEW ALIAS Ventes
Index on RCLI to ICLI // Crée un index selon RCLI dans 01RCVBIL.DBF Set Relation to RCLI into Clients
DbSetFilter ({||(cVendeur = Clients->CVEND) .AND. ((cCurrYr1<= RDATE .AND. cCurrYr2>= RDATE); .OR. (cPrevYr1<= RDATE .AND. cPrevYr2>= RDATE))}) Sort to TRANSIT.DBF on RCLI, RDATE // Crée le fichier TRANSIT.DBF COUNT to nRec
If nRec == 0 @ 14,35 SAY "interrompue!" @ 15,24 SAY "Aucune transaction pour le vendeur - Code = " + cVendeur
lStop:= .T. RETURN EndIF // TRANSIT.DBF ne contient que les records pour les périodes spécifiées USE TRANSIT.dbf NEW ALIAS Travail // Utilise le fichier TRANSIT.DBF GO TOP // Lecture de TRANSIT.DBF et extraction des ventes pour le vendeur pendant les p‚riodes concern‚es DO WHILE .NOT. EOF() // pour chaque record du fichier TRANSIT.DBF nRecNo:= AScan(aTable, {|element| element[2] == RCLI}) // recherche RCLI dans aTable if RDATE >= cCurrYr1 // un record pour cette année aTable[nRecNo, 4] := aTable[nRecNo, 4] + IIF(RCREDIT, -RMONT1, RMONT1) if RDATE >= cCurrMo1 // ...et ce mois-ci aTable[nRecNo, 3] := aTable[nRecNo, 3] + IIF(RCREDIT, -RMONT1, RMONT1) endif else if RDATE <= cPrevYr2 // un record de l'an dernier aTable[nRecNo, 6] := aTable[nRecNo, 6] + IIF(RCREDIT, -RMONT1, RMONT1) if RDATE >= cPrevMo1 // même mois l'an dernier aTable[nRecNo, 5] := aTable[nRecNo, 5] + IIF(RCREDIT, -RMONT1, RMONT1) endif endif end SKIP END // Délestage des cas où toutes les inscriptions de aTable sont nulles FOR i:= 1 to len(aTable) if Abs(aTable[i,3]) + Abs(aTable[i,4]) + Abs(aTable[i,5]) + Abs(aTable[i, 6]) > 0 aArray:= aTable[i] AAdd(aTab, aArray) // ajoute une ligne à aTab endif NEXT aTable:= {} // destruction de aTable CLOSE DATABASES // Fermeture des bases de données // Suppression des fichiers générés par le programme DELETE FILE TRANSIT.DBF
DELETE FILE ICLI.NTX
DELETE FILE ICNUM.NTX
RETURN /* Analyse */ ********************************************************************************
* Procédure: ChargeFichiers - 06/18/99 5:44:PM
* Par : Georges Trottier, Copyright 1999 GTRO Informatique
* Notes : Affiche un panneau indiquant le chargement des fichiers
******************************************************************************** PROCEDURE ChargeFichiers(nTop, nLeft, nBottom, nRight, cText) LOCAL cScreen:= SaveScreen(nTop, nLeft, nBottom, nRight) @ nTop,nLeft TO nBottom, nRight DOUBLE COLOR "B+/W" @ (nTop + nBottom)/2, nLeft+2 SAY PADC(cText, nRight - nLeft - 2) COPY FILE (cPath + "CLIENT.DBF") TO CLIENT.DBF
COPY FILE (cPath + "RCVBIL.DBF") TO RCVBIL.DBF
RestScreen(nTop, nLeft, nBottom, nRight, cScreen) RETURN /* ChargeFichiers */ *********************************************************************
* Procedure : Impression
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 25/09/97 @ 15:07
* Notes : Version 2.1 - 2 mars 2000
********************************************************************* PROCEDURE Impression () LOCAL Txt
nPage:= 1 nLine:= 0 lStop = .F. // Impression ou visualisation? If lPFlag
nLTotal:= 55 @ 18,26 SAY 'Un instant... Impression...' SET PRINTER ON SET CONSOLE OFF nLine:= Head(nLine) else nLTotal:= MaxRow()-1 // le programme n'écrit pas sur la dernière ligne de l'écran endIF // Test: y a-t-il des records … imprimer IF LEN(aTab) == 0 If lPFlag
SET PRINTER OFF
SET CONSOLE ON
RETURN EndIF RETURN ENDIF nLine:= Entete(nLine) aTotal:= {0, 0, 0, 0} For i:= 1 to Len(aTab) Txt:= PADR(aTab[i,7], 26) + PADR(STR(aTab[i,3],10,2),11) + PADR(STR(aTab[i,4],10,2),11) Txt:= Txt + PADR(STR(aTab[i,5],10,2),11) + PADR(STR(aTab[i,6],10,2),11) If lStop
RETURN // si l'affichage a été interrompu; interromp aussi l'impression EndIF nLine := Detail(nLine, Txt) // Affiche ou imprime une ligne de texte For j:= 1 to 4 // Totalise les ventes pour chaque période aTotal[j]:= aTotal[j] + aTab[i, 2+j] Next Next If nChoice == 1 Txt:= PADR("Total des ventes", 26) + PADR(STR(aTotal[1], 10,2),11) + PADR(STR(aTotal[2], 10,2),11) Else Txt:= PADR("Total of sales", 26) + PADR(STR(aTotal[1], 10,2),11) + PADR(STR(aTotal[2], 10,2),11) EndIF Txt:= Txt + PADR(STR(aTotal[3], 10,2),11) + PADR(STR(aTotal[4], 10,2),11) nLine:= Detail(nLine, "") // Affiche ou imprime une ligne blanche nLine:= IIF(lpFlag, nLine, nlTotal) nLine:= Detail(nLine, Txt) // Affiche ou imprime les totaux If lPFlag // imprime des lignes vides jusqu'à la fin de la page DO while nLine <= nLTotal
? nLine++ EndDO EndPage() EJECT SET PRINTER OFF SET CONSOLE ON EndIF
RETURN /* Impression */ *********************************************************************
* Fonction : CheckLine
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 12:13
* Notes : Compte les lignes; exécute un saut de page lorsqu'il y a lieu
********************************************************************* FUNCTION CheckLine(n) LOCAL nCle
If n >= nLTotal
if lPFlag
nPage++ EndPage() EJECT else Message("N'importe quelle touche pour continuer/<ESC> pour arrˆter") nCle = Inkey(0) if nCle = K_ESC
lStop = .T. RETURN endif Cls endif n:= 0 n = Entete (n) EndIF
RETURN (n) /* CheckLine */ *********************************************************************
* Fonction : DaysThisMonth
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 14/04/97 @ 17:38
* Notes : retourne le nombre de jours dans le mois
********************************************************************* FUNCTION DaysThisMonth(nMo, nYr) LOCAL aDays:= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} Value:= aDays[nMo] If nMo == 2 .AND. IsLeap(nYr) Value:= Value + 1 ENDIF
RETURN (Value) /* DaysThisMonth */ *********************************************************************
* Fonction : IsLeap
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 14/04/97 @ 17:38
* Notes : retourne .T. si l'année est bisextile
********************************************************************* FUNCTION IsLeap(n) LOCAL Value:= .F. If n % 4 == 0 Value:= .T. If n % 100 == 0 .AND. (n/100) % 4 != 0 Value:= .F. EndIf EndIf
RETURN (Value) /* IsLeap */ *********************************************************************
* Fonction : Head
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 11:38
* Notes : Imprime l'entête du rapport
********************************************************************* FUNCTION Head(n) If nChoice == 1 // francais Line(PADC("Rapport des ventes pour le vendeur - Code = " + cVendeur, nChar)) ? Line("pour la p‚riode du " + cCurrMo1 + " au " + cCurrMo2) ? Else // anglais Line(PADC("Sales Report for Sales Person - Code = " + cVendeur, nChar)) ? Line("Period extending from " + cCurrMo1 + " to " + cCurrMo2) ? EndIF n=5 RETURN (n) /* Head */ *********************************************************************
* Function : Entete
* Copyright 1997, GTRO Informatique
* Par Georges Trottier, 26/09/97 @ 12:03
* Notes: Affiche/imprime l'entête de chaque écran/page
********************************************************************* FUNCTION Entete(n) If lPFlag
if nPage != 1 Line(PADC ("- " + LTRIM(STR(nPage) + " -"), nChar)) Line("") n+=2 endif EndIF If nChoice == 1 // francais Line(PADR("Vendeur - Code = " + cVendeur, 26) + PADC("Ann‚e courante", 22) + PADC("Ann‚e derniŠre", 22)) Line(PADR("Client", 26) + PADC("P‚riode", 11) + PADC("Cumulatif", 11) + PADC("P‚riode", 11) + PADC("Cumulatif", 11)) Line(PADR("", nChar, "-")) Else // anglais Line(PADR("Sales person - Code = " + cVendeur, 26) + PADC("Current year", 22) + PADC("Previous year", 22)) Line(PADR("Client", 26) + PADC("Period", 11) + PADC("... to date", 11) + PADC("Period", 11) + PADC("... to date", 11)) Line(PADR("", nChar, "-")) EndIF n+=3 RETURN (n) /* Entete */ *********************************************************************
* Fonction : Detail
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 11:47
* Notes : Affiche/imprime une ligne et vérifie les bas d'écran/page
********************************************************************* FUNCTION Detail(n, Text) n++ Line(Text) n = CheckLine (n) RETURN (n) /* Detail */ *********************************************************************
* Procedure : EndPage
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 14:27
* Notes : Imprime le bas de page
********************************************************************* PROCEDURE EndPage
Line ("") Line(PADR ("", nChar, "-")) If nChoice == 1 // francais Line (PADR("Ch‚n‚ & Sasseville Lt‚e", 30) + PADL(DTOC(DATE()), nChar - 30)) Else // anglais Line (PADR("Ch‚n‚ & Sasseville Ltd", 30) + PADL(DTOC(DATE()), nChar - 30)) EndIF
RETURN /* EndPage */ *********************************************************************
* Fonction : RoundUp
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 07/10/97 @ 12:23
* Notes : Arrondi
********************************************************************* FUNCTION RoundUp(n) LOCAL nInt:= Round(n, 0) n:= If(n > nInt, nInt + 1, nInt) RETURN (n) /* RoundUp */ *********************************************************************
* Procedure : Message
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 07/10/97 @ 12:34
* Notes : Affiche message en bas de l'écran
********************************************************************* PROCEDURE Message(cText) @ MaxRow(), 1 SAY PAdC(cText, MaxCol()) RETURN /* Message */ *********************************************************************
* Procedur : Line
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 15/04/99 @ 13:41
* Notes : Affiche/imprime une ligne
********************************************************************* PROCEDURE Line (c) ? c
RETURN /* Line */ *** Fin de RVENTES.PRG *********************************************
Code de Vendeur.prg
*********************************************************************
* Fichier : Vendeurs.PRG
* Droits : Copyright 1999, GTRO Informatique
* Auteur : Georges Trottier, 18/04/99 @ 09:10
* Version : 1.00
* Notes : Travail fait pour cHÉNÉ & sASSEVILLE
* : Rapport donnant les coordonnées des clients de chaque vendeur
* : Programmation terminée le 16/04/99
* Modifié : 15 avril 2003 - cPath pris dans variable d'environnement
********************************************************************* #include "Inkey.ch" #include "Box.ch" // Liste des variables globales du programme STATIC cVendeur:= ' ' // code du vendeur STATIC aTable:= {} // tableau vendeurs STATIC nChar := 69 // largeur des pages imprimées STATIC nPage := 1, nLine := 0 // compteurs de pages et de lignes STATIC nLTotal := 55 // nombre total de lignes par pages imprimées STATIC lPFlag := .F. // Affichage: (1) .T. -> imprimante; (2) .F. -> écran STATIC lStop // contrôle l'arrêt des procédures STATIC lAll // produits la liste pour tous les vendeurs STATIC lList
STATIC lInit:= .T. STATIC nChoiceLang // Choix de menu language STATIC nChoiceAff // Choix du menu pour l'affichage STATIC cPath // 15 avril 2003 STATIC remVendeur
STATIC nNum
STATIC cScreenTop, cScreenBot
STATIC cTitre:= "Liste des clients attitr‚s des vendeurs" STATIC cFirme:= "Ch‚n‚ & Sasseville Lt‚e" PROCEDURE Main() STATIC GetList:= {} SET STATUS OFF SET TALK OFF SET BELL OFF SET ESCAPE ON SET MARGIN TO 7 SET DATE FORMAT "yyyy/mm/dd" Set Message to MaxRow() CENTRE
cPath:= GetEnv("Avantage") // 15 avril 2003 PRIVATE cColorString:= SetColor() CLEAR WHILE .T. Interface() @ MaxRow()-1,20 PROMPT "Traiter" MESSAGE "Effectuer le traitement des donn‚es" @ MaxRow()-1,53 PROMPT "Quitter" MESSAGE "Quitter l'application" Menu to nTraite
RestScreen(MaxRow()-1, 0, MaxRow(), MaxCol(), cScreenBot) DO CASE CASE nTraite == 1 Traite() CASE nTraite == 2 CLS QUIT RETURN EndCase ENDDO
RETURN ********************************************************************************
* Procédure: Interface - 06/16/99 9:53:AM
* Par : Georges Trottier, Copyright 1999 GTRO Informatique
* Notes : Affiche l'interface de l'application
******************************************************************************** PROCEDURE Interface
LOCAL cWallPaper:= '', nRow
CLEAR
// Interface usager SetColor (cColorString) For nRow:= 0 TO 25 @ nRow,0 SAY PADC(cWallPaper, 80, CHR(176)) Next cScreenTop:= SaveScreen(0, 0, 0, MaxCol()) cScreenBot:= SaveScreen(MaxRow()-1, 0, MaxRow(), MaxCol()) SetColor('W/B, N/W,,,N/W') @ 1, 1 CLEAR TO MaxRow()-2, MaxCol()-1 @ 1,1 TO MaxRow()-2,MaxCol()-1 DOUBLE COLOR 'W/B' @ MaxRow()-3, 2 SAY PADC("Copyright GTRO Informatique 2003", MaxCol()-3) @ 2,2 SAY PADC(cFirme, MaxCol()-3) @ 3,2 SAY PADC(cTitre, MaxCol()-3) @ 4,2 TO 4, MaxCol()-2 RETURN /* Interface */ *********************************************************************
* Procedure : Traite
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 18/04/99 @ 09:15
* Notes : Saisie du mois
********************************************************************* PROCEDURE Traite
aTable:= {} FINI = .T. // Chargement du fichier 01CLIENT.DBF If lInit
ChargeFichiers(9, 20, 15, 60, "Chargement du fichier client") lInit:= .F. EndIF WHILE FINI
nMois:= 1 nAn:= 1999 // Saisies @ 5,20 SAY 'Saisir le code du vendeur: ' @ 5,47 GET cVendeur PICTURE 'XXXX' @ 8,10 say 'Saisir TOUS pour la liste des clients de tous les vendeurs' @ 9,10 SAY "Saisir ?? pour la liste sommaire des vendeurs" READ RestScreen(0, 0, 0, MaxCol(), cScreenTop) cVendeur:= UPPER(cVendeur) nChoiceLang:= 1 @ 6,20 SAY "Langue du rapport" @ 6,40 PROMPT "Rapport en francais" @ 7,40 PROMPT "Report in English" MENU to nChoiceLang
lAll:= .F. lList:= .F. If cVendeur == 'TOUS' lALL:= .T. EndIF If cVendeur == '?? ' lList:= .T. lAll:= .T. EndIF @ MaxRow()-1,20 PROMPT "Imprimante" MESSAGE "Impression sur papier" @ MaxRow()-1,37 PROMPT "Ecran" MESSAGE "Affichage … l'‚cran" @ MaxRow()-1, 57 PROMPT "Fin" MESSAGE "Affiche le menu de d‚part" MENU to nChoiceAff
RestScreen(MaxRow()-1, 0, MaxRow(), MaxCol(), cScreenBot) CLOSE DATABASES IF nChoiceAff = 1 .OR. nChoiceAff = 2 lPFlag = (nChoiceAff = 1) Traitement() FINI = .F. ENDIF IF nChoiceAff = 3 FINI = .F. ENDIF ENDDO /* WHILE FINI */ RETURN *********************************************************************
* Procedure : Traitement
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 18/04/99 @ 09:30
* Notes : Programme contrôlant les autres sous-programmes
********************************************************************* PROCEDURE Traitement() lStop:= .F. @ MaxRow()-4,2 SAY PADC("", MaxCol()-3) @ 12,24 SAY 'Un instant... En traitement...' @ 13,24 SAY 'Analyse...' Initialise() If lStop // le vendeur n'est pas inscrit dans le fichier 01CLIENT.DBF RETURN EndIF @ 13,42 SAY 'termin‚e!' @ 15,24 SAY "Nombre de vendeurs: " + STR(Len(aTable)) @ 16,24 SAY "Nombre de clients : " + STR(nNum) If lPFlag
If lList
@ 17,24 SAY "Nombre de pages : " + STR(RoundUp(Len(aTable)/51)) Else @ 17,24 SAY "Nombre de pages : " + STR(RoundUp((nNum+ Len(aTable))/12)) EndIF Else If lList
@ 17,24 SAY "Nombre d'‚crans : " + STR(RoundUp(Len(aTable)/22)) Else @ 17,24 SAY "Nombre d'‚crans : " + STR(RoundUp((nNum + Len(aTable))/5)) EndIF EndIf @ MaxRow(), 1 SAY PADC("N'importe quelle touche pour continuer/<ESC> pour arrˆter", MaxCol()) nCle = Inkey(0) if nCle = K_ESC
RETURN endif Cls Impression() CLOSE DATABASES DELETE FILE ICVEND.NTX
RETURN /* Traite */ *********************************************************************
* Procedure : Initialise
* Auteur : Copyright 1999, GTRO Informatique
* Par : Georges Trottier, 18/04/99 @ 09:35
* Notes : Extraction des noms de clients du vendeur
********************************************************************* PROCEDURE Initialise() USE CLIENT.DBF NEW ALIAS Clients
Index on (CVEND + CVIL + CNOM) to ICvEND
If .NOT. lAll
DBSetFilter({|| cVendeur = Clients->CVEND}) EndIF GO TOP DO WHILE .NOT. EOF() nRecNo:= AScan(aTable, {|element| element[1] == CVEND}) // recherche CVEND dans aTable If nRecNo == 0 aArray:= {CVEND, 1} AAdd(aTable, aArray) // tableau comportant une entrée par vendeur Else aTable[nRecNo, 2]:= aTable[nRecNo, 2] + 1 EndIf SKIP ENDDO COUNT to nNum
If nNum == 0 @ 13,42 SAY 'interrompue!' @ 14,24 SAY "Vendeur inexistant - Code = " + cVendeur
lStop:= .T. RETURN EndIF
RETURN /* Initialise */ *********************************************************************
* Procedure : Impression
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 25/09/97 @ 15:07
* Notes :
********************************************************************* PROCEDURE Impression () LOCAL Txt
nPage:= 1 nLine:= 0 lStop = .F. // Impression ou visualisation? If lPFlag
nLTotal:= 55 @ 18,26 SAY 'Un instant... Impression...' SET PRINTER ON SET CONSOLE OFF nLine:= Header(nLine) else nLTotal:= MaxRow()-1 // le programme n'écrit pas sur la dernière ligne de l'écran endIF // Test: y a-t-il des records à imprimer LOCATE IF EOF() .OR. .NOT. FOUND() If lPFlag
SET PRINTER OFF
SET CONSOLE ON
RETURN EndIF RETURN ENDIF nLine:= Entete(nLine) remVendeur:= '????' DO WHILE .NOT. EOF() .AND. .NOT. lStop
nLine:= Detail(nLine) SKIP EndDO If lPFlag // imprime des lignes vides jusqu'à la fin de la page DO while nLine <= nLTotal
? nLine++ EndDO EndPage() EJECT SET PRINTER OFF SET CONSOLE ON EndIF
RETURN /* Impression */ ********************************************************************************
* Procédure: ChargeFichiers - 06/18/99 5:44:PM
* Par : Georges Trottier, Copyright 1999 GTRO Informatique
* Notes : Affiche un panneau indiquant le chargement des fichiers
******************************************************************************** PROCEDURE ChargeFichiers(nTop, nLeft, nBottom, nRight, cText) LOCAL cScreen:= SaveScreen(nTop, nLeft, nBottom, nRight) @ nTop,nLeft CLEAR TO nBottom, nRight
@ nTop,nLeft TO nBottom, nRight DOUBLE COLOR "B+/W" @ (nTop + nBottom)/2, nLeft+2 SAY PADC(cText, nRight - nLeft - 2) COPY FILE (cPath + "CLIENT.DBF") TO CLIENT.DBF
RestScreen(nTop, nLeft, nBottom, nRight, cScreen) RETURN /* ChargeFichiers */ *********************************************************************
* Fonction : CheckLine
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 12:13
* Notes : Compte les lignes; exécute saut de page lorsqu'il y a lieu
********************************************************************* FUNCTION CheckLine(n, nn) LOCAL nCle
If n >= nLTotal - nn
if lPFlag
nPage++ EndPage() EJECT else Message("N'importe quelle touche pour continuer/<ESC> pour arrˆter") nCle = Inkey(0) if nCle = K_ESC
lStop = .T. RETURN endif endif Clear n:= 0 n:= Entete(n) endif
RETURN (n) /* CheckLine */ *********************************************************************
* Fonction : Header
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 11:38
* Notes : Imprime l'entête du rapport
********************************************************************* FUNCTION Header(n) If lList
Line(PADC("Liste sommaire des vendeurs", nChar)) Else If nChoiceLang == 1 Line(PADC("Liste des clients", nChar)) Else Line(PADC("List of clients", nChar)) EndIF EndIF ? n=3 RETURN (n) /* Header */ *********************************************************************
* Function : Entete
* Copyright 1997, GTRO Informatique
* Par Georges Trottier, 26/09/97 @ 12:03
* Notes: Affiche/imprime l'entête de chaque écran/page
********************************************************************* FUNCTION Entete(n) If lPFlag
if nPage != 1 Line(PADC ("- " + LTRIM(STR(nPage) + " -"), nChar)) Line("") n+=2 endif EndIF Line(PADR("", nChar, "-")) n+=1 RETURN (n) /* Entete */ *********************************************************************
* Fonction : Detail
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 11:47
* Notes : Affiche/imprime une ligne et vérifie les bas d'écran/page
********************************************************************* FUNCTION Detail(n) LOCAL Txt, nRecNo
If CVEND != remVendeur
If lList
n:= CheckLine(n, 0) nRecNo:= AScan(aTable, {|element| element[1] == CVEND}) Line("Vendeur - Code = " + CVEND + ' (' + ALLTRIM(STR(aTable[nRecNo, 2])) + ' clients)') n++ Else n = CheckLine (n, 3) If lStop
RETURN EndIF Line("") nRecNo:= AScan(aTable, {|element| element[1] == CVEND}) If nChoiceLang == 1 Line("Vendeur - Code = " + CVEND + " (" + ALLTRIM(STR(aTable[nRecNo, 2])) + " clients)") Else Line("Sales Person - Code = " + CVEND + " (" + ALLTRIM(STR(aTable[nRecNo, 2])) + " clients)") EndIF Line(PADR("", MaxCol(), "-")) n:= n + 3 EndIf remVendeur:= CVEND
EndIF If .NOT. lList
n = CheckLine (n, 4) If lStop
RETURN EndIF Txt:= "" Line(CNOM + PADL(RTRIM(CRESP), 27)) If CEXTB != ' ' Txt:= ' X-' + CEXTB
EndIF Txt:= PADL(CTELB + Txt, 25) Txt:= PADR(RTRIM(CADR), 47) + Txt
Line(Txt) Line(PADR(RTRIM(CVIL) + ', ' + CCOD, 47)) Line("") n:= n + 4 EndIf
RETURN (n) /* Detail */ *********************************************************************
* Procedure : EndPage
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 26/09/97 @ 14:27
* Notes : Imprime le bas de page
********************************************************************* PROCEDURE EndPage
Line ("") Line(PADR ("", nChar, "-")) If nChoiceLang == 1 Line (PADR("Ch‚n‚ & Sasseville Lt‚e", 30) + PADL(DTOC(DATE()), nChar - 30)) Else Line (PADR("Ch‚n‚ & Sasseville Ltd", 30) + PADL(DTOC(DATE()), nChar - 30)) EndIF
RETURN /* EndPage */ *********************************************************************
* Fonction : RoundUp
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 07/10/97 @ 12:23
* Notes : Arrondi
********************************************************************* FUNCTION RoundUp(n) LOCAL nInt:= Round(n, 0) n:= If(n > nInt, nInt + 1, nInt) RETURN (n) /* RoundUp */ *********************************************************************
* Procedure : Message
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 07/10/97 @ 12:34
* Notes : Affiche message en bas de l'écran
********************************************************************* PROCEDURE Message(cText) @ MaxRow(), 1 SAY PAdC(cText, MaxCol()) RETURN /* Message */ *********************************************************************
* Procedur : Line
* Auteur : Copyright 1997, GTRO Informatique
* Par : Georges Trottier, 15/04/99 @ 13:41
* Notes : Affiche/imprime une ligne
********************************************************************* PROCEDURE Line (c) ? c
RETURN /* Line */ *** Fin de VENDEURS.PRG *********************************************