NomChampTable.NomColonne..OptionTri = ccRespecteNumériqueTableTrie(NomChampTable, "+"+NomChampTable.NomColonne..NomComplet)
- Le masque "099,99" affiche un résultat de la forme "012.34" et pas "12.34".
- Le masque "999,00" affiche un résultat de la forme "999" et pas "999.00".
- Le masque "+999;-999" affiche un résultat de la forme "+999" et pas "999".
- Le masque "999,99%" affiche "12.3%" et retourne un résultat de la forme "0.123".
- Le masque "999,99%%" affiche "12.3%" et retourne un résultat de la forme "12.3".
ST_Point3D est une StructurenX est un entiernY est un entiernZ est un entierFINstUnPoint3D est un ST_Point3D = [0, 0, 50]
L'affichage du champ ou de la fenêtre n'est demandé qu'après le traitement.
NomChampTable..AffichageActif = FauxPOUR i = 1 À 1000TableAjouteLigne(NomChampTable, TraitementPourLaLigne(i))FINNomChampTable..AffichageActif = Vrai
Le séparateur n'est pas concaténé si la chaîne de départ est une chaîne vide.
sUneChaîne est une chaînePOUR i = 1 À 10sUneChaîne += [":"] + NumériqueVersChaîne(i)FIN// La variable sUneChaîne vaut "1:2:3:4:5:6:7:8:9:10"
tab1 est un tableau de chaîne = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi"]sUneChaîne est une chaîne = TableauVersChaîne(tab1, ";")// La variable sUneChaîne vaut "Lundi;Mardi;Mercredi;Jeudi;Vendredi"
Inversement, pour transformer une chaîne en tableau avec un séparateur connu :
sUneChaîne est une chaîne = "5,4,3,2,1"tab1 est un tableau de chaîneChaîneVersTableau(sUneChaîne, tab1, ",")// La variable tab1 vaut ["5", "4", "3", "2", "1"]
// A placer dans le code de l'événement clic sur une colonne de type image d'un champ tableTableSelectPlus(NomChampTable, NomChampTable)Trace( TableSelect(NomChampTable) )
// A placer dans le code de l'affichage d'une ligne du haut de rupture dans un champ tableNomChampTable[TableIndiceRupture(NomHautDeRupture)].NomChamp = NomChampTable.NomColonne
Cette fonction doit être appelée avant le début d'une impression (exemple : avant la fonction iImprime() ou iImprimeEtat(), ...).
iFenêtreAbandon(Faux)
Voici comment intercepter le déplacement de l'ascenseur dans la table 1 pour le transmettre à la table 2 :
Dans le code d'initialisation du champ Table1 :
// On intercepte le déplacement de l'ascenseurEvénement("DeplaceTable1", NomChampTable1..Nom, 276) // WM_HSCROLL=276
Dans une nouvelle procédure locale nommée "DeplaceTable1" :
// On transmet ce déplacement à une seconde tablePROCÉDURE DeplaceTable1(nMessage, WPARAM , LPARAM)SendMessage(Handle(NomChampTable2..Nom), nMessage, WPARAM, LPARAM)
Depuis la version 19 de WINDEV® et grâce à la nouvelle fonction AscenseurPosition() :
AscenseurPosition(NomChampTable2, ascHorz, AscenseurPosition(NomChampTable1, ascHorz))
S'il y a une utilisation de l'IHM (thread principal) dans une des tâches parallèles alors la fonction TâcheParallèleAttendToutes() ne fonctionnera pas. Il faut alors utiliser le code ci-dessous.
tabTP est un tableau de TâcheParallèle// La ligne ci-dessous ne fonctionne pas//TâcheParallèleAttendToutes(tabTP)nIndice est un entier = 1TANTQUE (nIndice = 1 À tabTP..Occurrence)SI tabTP[nIndice]..Terminée ALORSnIndice++SINONTemporisation(25, tempoSourisEtClavier)FINFIN
S'il y a une utilisation de l'IHM (thread principal) dans le thread secondaire alors la fonction ThreadAttend() sera bloquante. Il faut alors utiliser le code ci-dessous.
// La ligne ci-dessous ne fonctionne pas//ThreadAttend(sThreadIdentifiant, 100)nChrono est un entier = DonneIdentifiant()ChronoDébut(nChrono)// Si le thread secondaire n'existe plus ou que la durée d'attente est supérieure à 1 seconde alors sortir de la boucleTANTQUE (ThreadEtat(sThreadIdentifiant) <> threadInexistant) _ET_ (ChronoValeur(nChrono) < 100)Temporisation(5, tempoSourisEtClavier)FINChronoFin(nChrono)
L’exécution d'une fonction d'attente (ThreadPause / Multitâche / SignalAttend / ...) provoque un interblocage (deadlock).
Dans le code de l'événement "Enroulé, déroulé d'un nœud" d'un champ arbre, ajouter le code suivant :
RENVOYER Faux
Trace( dbgInfo(dbgElément, dbgTraitementAppelant) )
HLitDernier(NomTableBDD)SI PAS HEnDehors(NomTableBDD) ALORS// L’identifiant automatique est fixé au dernier enregistrementHModifie(NomTableBDD, hNumEnrEnCours, hFixeIdAuto)FIN
L'opérateur d'échange permet d'échanger le contenu de deux éléments.
// Affecte la valeur 5 à la variable i et la valeur 6 à la variable ji, j est un entier = (5, 6)// Le résultat de la trace vaut "i=5 j=6"Trace("i="+i, "j="+j)i <=> j// Le résultat de la trace vaut "i=6 j=5"Trace("i="+i, "j="+j)
Pour échanger des éléments de type avancé :
PROCÉDURE VariablesEchange(v1, v2)vTemp est un VariantvTemp = v1v1 = v2v2 = vTemp
Le séparateur des miliers peut être un séparateur insécable, ce qui peut fausser l'affichage dans les états ou dans les champs.
// Si le séparateur insécable - Caract(160) [Windows 11] - est le séparateur des milliers alors ...// ... forcer le séparateur des milliers par un Espace - caract(32) [Windows 10] -SI (Milieu(NumériqueVersChaîne(1000, "4S"), 2, 1) = Caract(160)) ALORSChangeSéparateur(sepMILLIER, Caract(32))FIN
sUrl_à_tester est une chaîne = "<URL>"sUrl_urlDomaine est une chaîne = URLExtraitChemin(sUrl_à_tester, urlDomaine)sUrl_urlCheminComplet est une chaînesUrl_urlCheminComplet = URLExtraitChemin(sUrl_à_tester, urlCheminRessource+urlNomRessource+urlExtensionRessource)sMessage est une chaîne = [HEAD /%1 HTTP/1.1Host: %2Connection: Close] // Message à transmettresMessage = ChaîneConstruit(sMessage, sUrl_urlCheminComplet, sUrl_urlDomaine) +RC+RCSI SocketExiste("MaSocketHTTP") ALORSSocketFerme("MaSocketHTTP")FINSI SocketConnecte("MaSocketHTTP", 80, sUrl_urlDomaine, 5000) ALORS// Le marqueur de fin est la chaîne de caractères "<EOF>"SocketChangeTransmissionMode("MaSocketHTTP", SocketMarqueurFin)SI SocketEcrit("MaSocketHTTP", sMessage) ALORSTrace( ExtraitChaîne(SocketLit("MaSocketHTTP"), 2, " ") )FINSocketFerme("MaSocketHTTP")FIN
Depuis la version 20 de WINDEV® et grâce aux nouvelles variables httpRequête et httpRéponse :
cMaRequête est un httpRequêtecMaRequête..URL = "<URL>"cMaRequête..Méthode = httpHeadcMaRéponse est un httpRéponse = HTTPEnvoie(cMaRequête)SI PAS ErreurDétectée() _ET_ (cMaRéponse..CodeEtat = 200) ALORSTrace( cMaRéponse..CodeEtat )FIN
cMaRequête est un httpRequêtecMaRequête..URL = "<URL>" // Lien vers un fichier sur le webcMaRéponse est un httpRéponse = HTTPEnvoie(cMaRequête)SI PAS ErreurDétectée() _ET_ (cMaRéponse..CodeEtat = 200) ALORSsTempFichier est une chaîne = fRepTemp() +[fSep]+ fExtraitChemin(cMaRequête.URL, fFichier+fExtension)SI fSauveTexte(sTempFichier, cMaRéponse..Contenu) ALORSTrace(sTempFichier)FINFIN
sImageOrigine est une chaîne = "C:\logo.jpg" // Lien vers un fichier imagesTempFichier est une chaîne = fRepTemp() +[fSep]+ fExtraitChemin(sImageOrigine, fFichier+fExtension)SI fEstUneImage(sTempFichier) ALORSimg est une Image = dChargeImage(sImageOrigine)dRedimensionne(img, img..Largeur/2, img..Hauteur/2, drHauteQualite)dSauveImageJPEG(img, sTempFichier, 60) // Compression de 40%Trace(sTempFichier)FIN
// Effectuer une requête HTTP de type GET avec autorisation via socketsMessage est une chaîne = [GET %1 HTTP/1.1Host: %2User-Agent: %3Connection: keep-aliveAuthorization: Basic %4] // Message à transmettresMessage = ChaîneConstruit(sMessage, "<URL>", "UneAdresseIP", "", Crypte("UnIdentifiant:UnMotDePasse", "", crypteAnsi, encodeBASE64)) +RC+RCSI SocketExiste("MaSocketHTTP") ALORSSocketFerme("MaSocketHTTP")FINSI SocketConnecte("MaSocketHTTP", UnNuméroDePort, "UneAdresseIP", 5000) ALORS// Aucun marqueur n'est ajouté/enlevé au messageSocketChangeModeTransmission("MaSocketHTTP", SocketSansMarqueurFin)SI SocketEcrit("MaSocketHTTP", sMessage) ALORSTrace( SocketLit("MaSocketHTTP", Vrai) )FINFIN
Nous allons prendre comme exemple un fichier au format PDF :
- Ouvrir la base de registre grâce à la commande "regedit"
- Accéder à "HKEY_CLASSES_ROOT\.pdf"
- Lire le contenu de la chaîne par défaut, dans mon cas "AcroExch.Document.11"
- Accéder à "HKEY_CLASSES_ROOT\AcroExch.Document.11\shell\Print\command"
- Lire le contenu de la chaîne par défaut
Exemples de contenu de la base de registre pour l'impression d'un fichier PDF :
"C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe" /p /h "%1"
"C:\Program Files (x86)\Foxit Software\Foxit Reader\Foxit Reader.exe" /p "%1"
"C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.exe" /p /h "%1"
Sous l'AGL WINDEV®, le code suivant exécute les étapes ci-dessus :
LanceAppliAssociée(sCheminEtNomDuFichier, "print")
Si vous souhaitez intercepter les touches enfoncées du clavier en dehors d'une interface WINDEV®, voici un petit exemple :
Dans le code d'initialisation du projet :
EXTERNE "keyconst.wl" // Constantes standard utilisées pour les touches du clavierEXTERNE "winconst.wl" // Constantes standardgnHandleHook est un entier systèmegnHandleHook = API("User32", "SetWindowsHookExA", WH_KEYBOARD_LL, &KeyboardHook, Instance(), 0)
Dans le code de fermeture du projet :
// Retirer la procédure de traitement de la chaîne de procédures de traitementAPI("user32","UnhookWindowsHookEx", gnHandleHook)
Création d'une procédure globale :
PROCÉDURE KeyboardHook(nCode est un entier système, wparam est un entier système, lparam est un entier système)nCaractTouche est un entier systèmeSI (nCode = 0) ALORSTransfert(&nCaractTouche, lparam, 4)// ... Le traitement à exécuterTrace( nCaractTouche, ToucheEnfoncée(VK_LCONTROL, Vrai), ToucheEnfoncée(VK_LSHIFT, Vrai) )FINRENVOYER API("user32", "CallNextHookEx", gnHandleHook, nCode, wparam, lparam)// Renvoyer Vrai afin de permettre le traitement de l'appui par la fenêtre d'origine
Si vous souhaitez optimiser l'initialisation de plusieurs variables de type tableau avec les mêmes valeurs, voici un petit exemple :
tab1, tab2, tab3, tab4, tab5 est un tableau de chaîne// Code non optimisé :POUR i = 1 À 100 000TableauAjoute(tab1, NumériqueVersChaîne(i))TableauAjoute(tab2, NumériqueVersChaîne(i))TableauAjoute(tab3, NumériqueVersChaîne(i))TableauAjoute(tab4, NumériqueVersChaîne(i))TableauAjoute(tab5, NumériqueVersChaîne(i))FIN// Code optimisé :POUR i = 1 À 100 000TableauAjoute(tab1, NumériqueVersChaîne(i))FINTableauCopie(tab1, tab2)TableauCopie(tab1, tab3)TableauCopie(tab1, tab4)TableauCopie(tab1, tab5)
En bonus, voici le code pour optimiser la déclaration d'une variable de type structure d'un tableau de structure comportant un ou plusieurs tableaux :
ST_Structure est une StructurenEntier est un entierschaîne est une chaînetabchaîne est un tableau de chaîneFINgtabStructure est un tableau de ST_Structure
PROCÉDURE TrtTableau(LOCALE i est un entier)// Code non optimisé :stS est un ST_StructurestS = gtabStructure[i]... // Traitement// Code optimisé :stS est un ST_Structure dynamiquestS <- gtabStructure[i]... // Traitement
sdReq est une Source de DonnéessReq est une chaîne = "SELECT * FROM SOCIETE WHERE IDSOCIETE IN ({pListe_IDSOCIETE})"sListe_IDSOCIETE est une chaînePOUR i = 1 À 7000sListe_IDSOCIETE += [","]+ NumériqueVersChaîne(i)FIN// Si la connexion n'est pas sur une base MSSQL Serveur alors exécuter le code classique :HAnnuleDéclaration(sdReq)sdReq.pListe_IDSOCIETE = sListe_IDSOCIETEHExécuteRequêteSQL(sdReq, hRequêteDéfaut, sReq)POUR TOUT sdReq// TraitementFINHAnnuleDéclaration(sdReq)// Pour contrer la limitation des 2100 paramètres en MSSQL Server en utilisant l'accès natif de WINDEV® :// "The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect.// Too many parameters were provided in this RPC request. The maximum is 2100."// Si la connexion est sur une base MSSQL Serveur alors exécuter le code suivant :sListeIDSOCIETE_MssqlLimiteParam est une chaînePOUR TOUTE CHAÎNE sUnIDSOCIETE, nPos, nCompteur DE sListe_IDSOCIETE SEPAREE PAR ","sListeIDSOCIETE_MssqlLimiteParam += [","]+ sUnIDSOCIETESI (Modulo(nCompteur, 2098) = 0) _OU_ (nCompteur = ChaîneOccurrence(sListe_IDSOCIETE, ",")+1) ALORSHAnnuleDéclaration(sdReq)sdReq.pListe_IDSOCIETE = sListeIDSOCIETE_MssqlLimiteParamHExécuteRequêteSQL(sdReq, hRequêteDéfaut, sReq)POUR TOUT sdReq// TraitementFINHAnnuleDéclaration(sdReq)sListeIDSOCIETE_MssqlLimiteParam = ""FINFIN
Pour sauvegarder l'état d'un champ table :
PROCÉDURE TableSauveParam(champTable est un Champ) : tableau associatif de chaînetaParam est un tableau associatif de chaînetaParam["Trie"] = TableColonnesTriées(champTable)taParam["Filtre"] = TableColonnesFiltrées(champTable)taParam["PosSel"] = TableSauvePositionEtSélection(champTable)taParam["AscPos_Vert"] = AscenseurPosition(champTable, ascVert)taParam["AscPos_Horz"] = AscenseurPosition(champTable, ascHorz)RENVOYER taParam
Pour restaurer l'état d'un champ table :
PROCÉDURE TableRestaureParam(champTable est un Champ, LOCALE taParam est une tableau associatif de chaîne)SI (PAS taParam["Trie"]..Vide) _ET_ (PAS taParam["Trie"] ~= "") ALORSsValeur est une chaîne = ""POUR TOUTE CHAÎNE sColonne DE taParam["Trie"] SEPAREE PAR TABSI (sColonne[[1]] = "-") ALORS //Sens du tri : décroissantsValeur += [TAB]+ "-"+ champTable..NomComplet +"."+ sColonne[[2 À]]SINONsValeur += [TAB]+ champTable..NomComplet +"."+ sColonneFINFINTableTrie(sValeur)FINSI (PAS taParam["Filtre"]..Vide) _ET_ (PAS taParam["Filtre"] ~= "") ALORSPOUR TOUTE CHAÎNE sFiltre DE taParam["Filtre"] SEPAREE PAR RCTableActiveFiltre(champTable..NomComplet +"."+ ExtraitChaîne(sFiltre, 1, ";"), Val(ExtraitChaîne(sFiltre, 2, ";")), ExtraitChaîne(sFiltre, 3, ";"))FINFINSI (PAS taParam["PosSel"]..Vide) _ET_ (PAS taParam["PosSel"] ~= "") ALORSTableRestaurePositionEtSélection(champTable, taParam["PosSel"])FINSI (PAS taParam["AscPos_Vert"]..Vide) _ET_ (Val(taParam["AscPos_Vert"]) = 0 À AscenseurPositionMax(champTable, ascVert)) ALORSAscenseurPosition(champTable, ascVert, Val(taParam["AscPos_Vert"]))FINSI (PAS taParam["AscPos_Horz"]..Vide) _ET_ (Val(taParam["AscPos_Horz"]) = 0 À AscenseurPositionMax(champTable, ascHorz)) ALORSAscenseurPosition(champTable, ascHorz, Val(taParam["AscPos_Horz"]))FIN
Un exemple d'utilisation :
taParam est un tableau associatif de chaînetaParam = TableSauveParam(NomChampTable)TableAffiche(NomChampTable, taInit)TableRestaureParam(NomChampTable, taParam)
Pour obtenir le dernier jour d'un mois, il suffit d'affecter le nombre 31 à la propriété ..Jour.
dTemp est une DatedTemp..Année = 2016dTemp..Mois = 2dTemp..Jour = 31Trace( DateVersChaîne(dTemp) )
Depuis la version 16 de WINDEV® et grâce à la nouvelle fonction DernierJourDuMois() :
dTemp est une DatedTemp = DernierJourDuMois(2016, 2)Trace( DateVersChaîne(dTemp) )
WINDEV® permet facilement d'ajouter un nombre entier d'années, de mois, de jours, d'heures, de minutes et de secondes à une variable de type dateheure. Mais il ne permet pas d'ajouter des nombres décimaux/flottants.
Dans une déclaration globale :
ENUM_PERIODE est une énumérationPERIODE_ANNEEPERIODE_MOISPERIODE_JOURPERIODE_HEUREPERIODE_MINUTEPERIODE_SECONDEFIN
Dans une procédure :
PROCÉDURE DateHeureAjoute(LOCALE dhAjout est une DateHeure, LOCALE ePeriode est un ENUM_PERIODE, LOCALE xNbAjout est un numérique (*)) : DateHeureSI (xNbAjout <> 0) ALORSSELON ePeriodeCAS ENUM_PERIODE.PERIODE_ANNEE :dhAjout..Année += xNbAjout// Avec comme postulat que 1 an = 12 moisdhAjout = DateHeureAjoute(dhAjout, ENUM_PERIODE.PERIODE_MOIS, PartieDécimale(xNbAjout) * 12 * ((xNbAjout < 0) ? -1 SINON 1))CAS ENUM_PERIODE.PERIODE_MOIS :dhAjout..Mois += xNbAjout// Avec comme postulat que 1 mois = 30 joursdhAjout = DateHeureAjoute(dhAjout, ENUM_PERIODE.PERIODE_JOUR, PartieDécimale(xNbAjout) * 30 * ((xNbAjout < 0) ? -1 SINON 1))CAS ENUM_PERIODE.PERIODE_JOUR :dhAjout..Jour += xNbAjout// Avec comme postulat que 1 jour = 24 heuresdhAjout = DateHeureAjoute(dhAjout, ENUM_PERIODE.PERIODE_HEURE, PartieDécimale(xNbAjout) * 24 * ((xNbAjout < 0) ? -1 SINON 1))CAS ENUM_PERIODE.PERIODE_HEURE :dhAjout..Heure += xNbAjout// Avec comme postulat que 1 heure = 60 minutesdhAjout = DateHeureAjoute(dhAjout, ENUM_PERIODE.PERIODE_MINUTE, PartieDécimale(xNbAjout) * 60 * ((xNbAjout < 0) ? -1 SINON 1))CAS ENUM_PERIODE.PERIODE_MINUTE :dhAjout..Minute += xNbAjout// Avec comme postulat que 1 minute = 60 secondesdhAjout = DateHeureAjoute(dhAjout, ENUM_PERIODE.PERIODE_SECONDE, PartieDécimale(xNbAjout) * 60 * ((xNbAjout < 0) ? -1 SINON 1))CAS ENUM_PERIODE.PERIODE_SECONDE :dhAjout..Seconde += xNbAjoutAUTRE CAS :FINFINRENVOYER dhAjout
Un exemple d'utilisation :
// Ajoute 6 mois à la date du 01/01/2021 00h00 :Trace( DateHeureAjoute("20210101000000", ENUM_PERIODE.PERIODE_MOIS, 6) )// Retire 2 jours à la date du 02/03/2020 12h34 :Trace( DateHeureAjoute("20200302123400", ENUM_PERIODE.PERIODE_JOUR, -2) )
// Pour extraire les intiales d'un nom/prénomPROCÉDURE InitialesExtrait(LOCALE sNom est une chaîne) : chaînesInitiale est une chaîne = ""// Recherche les mots séparés par un espace et/ou un tiretPOUR TOUTE CHAÎNE sUnMot DE sNom SEPAREE PAR [" ", "-"]sInitiale += Majuscule(sUnMot[[1]]) +"."FINRENVOYER sInitiale
Un exemple d'utilisation :
Trace( InitialesExtrait("yves dupont") ) // Affiche Y.D.Trace( InitialesExtrait("Jean-Luc DE-VINCI") ) // Affiche J.L.D.V.
Ce code effectue une capture d'écran à l'emplacement d'un champ, c'est-à-dire que s'il y a un élément par dessus le champ alors cet élément sera aussi capturé dans l'image.
PROCÉDURE ChampCapture(cUnChamp est un Champ, LOCALE sCheminEtNomDuFichier est une chaîne) : booléenbufImage est un BufferbufImage = dCopieImageEcran(FenIntPosX()+cUnChamp..X, FenIntPosY()+cUnChamp..Y, cUnChamp..Largeur, cUnChamp..Hauteur)//bufImage = dCopieImageChamp(cUnChamp) // Nouveauté en version 28SI PAS fEstUneImage(bufImage) ALORSRENVOYER FauxFIN// Création du répertoire si inexistantSI PAS fRépertoireExiste(fExtraitChemin(sCheminEtNomDuFichier, fDisque+fRépertoire)) ALORSfRepCrée(fExtraitChemin(sCheminEtNomDuFichier, fDisque+fRépertoire))FINRENVOYER fSauveBuffer(sCheminEtNomDuFichier, bufImage)
Un exemple d'utilisation :
Trace( ChampCapture(IMG_Logo, ComplèteRep(fDisqueEnCours())+"capture.jpg") )
Ce code est à utiliser avec la plus grande prudence.
nX est un entier = 0SI (SysVersionWindows() _DANS_ ("NT 3.5", "NT 4", "NT 5", "XP", "2003S", "2008S", "VISTA")) ALORSnX = API("KERNEL32", "GetCurrentProcess")API("KERNEL32", "SetProcessWorkingSetSize", nX, -1, -1)SI (SysVersionWindows(sysVersionPlateForme) = "NT") ALORSAPI("psapi", "EmptyWorkingSet", nX)FINFIN
// Créer tous les fichiers de la base de données.PROCÉDURE HCréationSiInexistant() : booléenbHCréationSiInexistant est un booléen = VraiSI PAS WL.HCréationSiInexistant("*") ALORSsHListeFichier est chaîne = HListeFichier(hLstNormal)POUR TOUTE CHAÎNE sHFichier DE sHListeFichier SEPAREE PAR RCQUAND EXCEPTION DANSSI PAS WL.HCréationSiInexistant(sHFichier) ALORSbHCréationSiInexistant = FauxFINFAIREExceptionActive()FINFINFINRENVOYER bHCréationSiInexistant
// Résumé : Surcharge la fonction PDFFusionne() au cas où il n'y ait qu'un élément dans le tableau.// Paramètres :// sFichierPdfResultat (chaîne ANSI) : Nom et chemin complet du fichier PDF à créer. Ce fichier contiendra la fusion des différents fichiers PDF.// tabFichiersPdf (tableau (chaîne ANSI)) : Nom du tableau de chaînes contenant les chemins des fichiers PDF à fusionner.// Valeur de retour :// entier : 1: tout s'est bien passé ; -1 : Erreur sur PDFFusionne() ; -2 Erreur sur fCopieFichier() ; 0 : aucun élément dans le tableau//PROCÉDURE PDFFusionne(LOCALE sFichierPdfResultat est une chaîne, LOCALE tabFichiersPdf est un tableau de chaîne) : entierSI fFichierExiste(sFichierPdfResultat) ALORSfSupprime(sFichierPdfResultat, frLectureSeule)FINSI (tabFichiersPdf..Occurrence > 1) ALORSSI PAS WL.PDFFusionne(sFichierPdfResultat, tabFichiersPdf) ALORSErreurPropage()RENVOYER -1FINSINON SI (tabFichiersPdf..Occurrence = 1) ALORSSI PAS fCopieFichier(tabFichiersPdf[1], sFichierPdfResultat) ALORSErreurPropage()RENVOYER -2FINSINONErreurDéclenche(1, "Aucun élément à fusionner.")RENVOYER 0FINRENVOYER fFichierExiste(sFichierPdfResultat)
Ne pas oublier d'initialiser les jours fériés avec la fonction JourFériéAjoute(). (exemple : https://doc.pcsoft.fr/?1000017304)
// Résumé : Calculer le nombre de jours (ouvrés, ouvrants, personnalisés) pour une période.// ! Ne pas oublier d'initialiser les jours fériés avec la fonction JourFériéAjoute()// Paramètres :// dDebut (date) : date de début de la période de calcul// dFin (date) : date de fin de la période de calcul// tabJours (tableau) : numéros de jour de la semaine à ne pas prendre en compte (avec 1:Lundi, 2:Mardi, 3:Mercredi, 4:Jeudi, 5:Vendredi, 6:Samedi, 7:Dimanche)// Valeur de retour :// entier : nombre de jours calculés pour la période//PROCÉDURE NombreDeJoursOuvrés(LOCALE dDebut est une Date, LOCALE dFin est une Date, LOCALE tabJours est un tableau de entier) : entiernNombreDeJoursCalculés est un entier = 0SI DateValide(dDebut) _ET_ DateValide(dFin) ALORSTANTQUE (dDebut <= dFin)SI (TableauCherche(tabJours, tcLinéaire, DateVersJour(dDebut)) = -1) _ET_ PAS JourFérie(dDebut) ALORSnNombreDeJoursCalculés++FINdDebut..Jour++FINFINRENVOYER nNombreDeJoursCalculés
Un exemple d'utilisation :
// Calculer le nombre de jours ouvrés entre le 01/01/2021 et le 31/01/2021 pour une semaine travaillée du lundi au vendredi :Trace( NombreDeJoursOuvrés("20210101", "20210131", [6,7]) )// Calculer le nombre de jours ouvrables entre le 01/01/2021 et le 31/01/2021 pour une semaine travaillée du lundi au vendredi :Trace( NombreDeJoursOuvrés("20210101", "20210131", [7]) )// Calculer le nombre de jours ouvrés entre le 09/01/2021 et le 27/01/2021 pour une semaine travaillée du mardi au samedi :Trace( NombreDeJoursOuvrés("20210109", "20210127", [1,7]) )
PROCÉDURE TraitementDeTexteRemplace(LOCALE sSource est une chaîne, LOCALE sCible est une chaîne, LOCALE taMots est un tableau associatif de chaîne) : booléen// Copier le fichier Source vers le fichier CibleSI fFichierExiste(sSource) _ET_ fCopieFichier(sSource, sCible) _ET_ fFichierExiste(sCible) ALORSSELON Minuscule(fExtraitChemin(sCible, fExtension))CAS ".doc", ".docx" : // Word Microsoft OfficeQUAND EXCEPTION DANSautWorddoc est un objet Automation "Word.Application"autWorddoc>>documents>>Open(sCible)autWorddoc>>visible = FauxautWorddoc>>SelectionPOUR TOUT ELEMENT sMot, sCle DE taMots// http://sepia.developpez.com/office/word/rechercherremplacer/sMot = Remplace(sMot, RC, "^p")sMot = Remplace(sMot, TAB, "^t")autWorddoc>>Selection>>Find>>Execute(sCle, Faux, Vrai, Faux, Faux, Faux, Vrai, 1, Faux, sMot, 2)FINautWorddoc>>ActiveDocument>>SaveAs(sCible, 16) // http://msdn.microsoft.com/en-us/library/office/bb238158%28v=office.12%29.aspxautWorddoc>>ActiveDocument>>Close()RENVOYER VraiFAIRESI (autWorddoc <> Null) ALORSautWorddoc>>ActiveDocument>>Close()FINFINCAS ".odt" : // OpenOffice ; LibreOffice ; etc...QUAND EXCEPTION DANS// Création d'un service OpenOffice si nécessairepautServiceManager est un objet OLE dynamique = allouer un objet OLE ("com.sun.star.ServiceManager")pautDesktop est un objet OLE dynamique = pautServiceManager>>createInstance("com.sun.star.frame.Desktop")pautDocument est un objet OLE dynamiquepautRecherche est un objet OLE dynamiquetabNoArgs_ est un tableau de 0 Variant = allouer un tableau dynamique de 0 VarianttabNoArgs est un tableau de 1 objet Automation dynamiquesCheminFormate est une chaîne = "file:///"+Remplace(sCible, "\", "/") // Formatage du chemin du fichier// Ouverture du fichier dans OpenOffice Writer// Traitement de la visibilité du documenttabNoArgs[1] = pautServiceManager>>Bridge_GetStruct("com.sun.star.beans.PropertyValue")tabNoArgs[1]>>Name = "Hidden"tabNoArgs[1]>>Value = VraipautDocument = pautDesktop>>LoadComponentFromURL(sCheminFormate, "_blank", 0, tabNoArgs)SI (pautDocument <> Null) ALORS//oDocument = oDesktop>>getCurrentComponent()POUR TOUT ELEMENT sMot, sCle DE taMots// Créer un objet JeCherche qui contiendra tous les paramètres nécessaires à ce remplacementpautRecherche = pautDocument>>createReplaceDescriptor()// Définir la balise à rechercher dans le document OpenOffice WordpautRecherche>>SearchString = sCle// Définir la valeur de remplacementpautRecherche>>ReplaceString = sMot// Distinguer les majuscules des minuscules dans la recherchepautRecherche>>SearchCaseSensitive = Vrai// Ne rechercher que des motspautRecherche>>SearchWords = Faux// Rechercher à reculonspautRecherche>>SearchBackwards = Faux// Faire une recherche avec la méthode des expressions régulièrespautRecherche>>SearchRegularExpression = Faux// Rechercher des paragraphes d’un style donné par SearchStringpautRecherche>>SearchStyles = Faux// Rechercher un texte similaire au texte cherchépautRecherche>>SearchSimilarity = Faux// Remplacer toutes les balisespautDocument>>replaceAll(pautRecherche)FIN// Enregistrement sous... du document (https://wiki.openoffice.org/wiki/FR/Documentation/BASIC_Guide/Saving_a_document)pautDocument>>storeToURL(sCheminFormate, tabNoArgs_)// Fermer le documentpautDocument>>Store()pautDocument>>close(Vrai)pautDesktop>>Terminate()RENVOYER VraiFINFAIRESI (pautDocument <> Null) ALORS// Fermer le documentpautDocument>>Store()pautDocument>>close(Vrai)pautDesktop>>Terminate()FINFINAUTRE CAS :FIN// Si échec du rechercher/remplacer alors supprimer le fichier "Cible"SI fFichierExiste(sCible) ALORSfSupprime(sCible, frLectureSeule)FINFINRENVOYER Faux
Un exemple d'utilisation :
sModeleDoc est une chaîne = ComplèteRep(fDisqueEnCours())+"Modele_TraitementDeTexte.doc"sNouveauDoc est une chaîne = ComplèteRep(fDisqueEnCours())+"Doc_TraitementDeTexte.doc" // ou bien ComplèteRep(fDisqueEnCours())+"Doc_TraitementDeTexte.odt"taMotsARemplacer est un tableau associatif de chaînetaMotsARemplacer["<Mot_a_trouver_1>"] = "Mot 1 a remplacer"taMotsARemplacer["<Mot_a_trouver_2>"] = "Mot 2 a remplacer"taMotsARemplacer["<Date_Du_Jour>"] = DateVersChaîne(DateSys(), "JJ/MM/AAAA")SI TraitementDeTexteRemplace(sModeleDoc, sNouveauDoc, taMotsARemplacer) ALORSLanceAppliAssociée(sNouveauDoc)FIN
Depuis la version 22 de WINDEV® et grâce au nouveau type de variable Document :
sModeleDoc est une chaîne = ComplèteRep(fDisqueEnCours())+"Modele_TraitementDeTexte.docx"sNouveauDoc est une chaîne = ComplèteRep(fDisqueEnCours())+"Doc_TraitementDeTexte.doc" // ou bien ComplèteRep(fDisqueEnCours())+"Doc_TraitementDeTexte.odt"taMotsARemplacer est un tableau associatif de chaînetaMotsARemplacer["<Mot_a_trouver_1>"] = "Mot 1 a remplacer"taMotsARemplacer["<Mot_a_trouver_2>"] = "Mot 2 a remplacer"taMotsARemplacer["<Date_Du_Jour>"] = DateVersChaîne(DateSys(), "JJ/MM/AAAA")docT2T est un Document = DocOuvre(sModeleDoc)SI PAS ErreurDétectée() ALORSPOUR TOUT ELEMENT sMot, sCle DE taMotsARemplacerDocRemplace(docT2T, sCle, sMot)FINSI DocSauve(docT2T, sNouveauDoc) ALORSDocFerme(docT2T)LanceAppliAssociée(sNouveauDoc)FINFIN
Il existe plusieurs approches pour savoir si un nombre particulier est contenu dans une chaîne (une liste de nombres séparés par un séparateur commun).
// La liste de nombres séparés par un séparateur communsListe_IDSOCIETE est une chaîne = "4;8;15;16;23;42"// Le nombre particulier à rechercher dans la chaînesUnIDSOCIETE est une chaîne = "2"bContient est un booléen// Code le plus simple ...// ... en utilisant la fonction Contient()bContient = Contient(";"+sListe_IDSOCIETE+";", ";"+sUnIDSOCIETE+";")Trace("Contient", bContient)// ... en utilisant la fonction Position()bContient = (Position(";"+sListe_IDSOCIETE+";", ";"+sUnIDSOCIETE+";") > 0)Trace("Position", bContient)// Code le plus rapide grâce à l'opérateur de comparaison [=]bContient = (";"+sListe_IDSOCIETE+";" [=] ";"+sUnIDSOCIETE+";")Trace("[=]", bContient)// Code le plus sûrtabEntier est un tableau de entierChaîneVersTableau(sListe_IDSOCIETE, tabEntier, ";")bContient = (TableauCherche(tabEntier, tcLinéaire, Val(sUnIDSOCIETE)) <> -1)Trace("TableauCherche", bContient)
Lors de la recherche sur les chaînes, les concaténations du séparateur (";") sont obligatoires sinon le nombre à rechercher ("2") est trouvé dans les nombres "23" et "42".
Si le développeur ne maitrise pas le contenu de la chaîne (exemples: sListe_IDSOCIETE = "4; 8;15;16;23;42" ou sListe_IDSOCIETE = "4;08;15;16;23;42") alors le code est plus sûr en utilisant un tableau.
PROCÉDURE VérifierCalcul(LOCALE sCalcul est une chaîne) : (booléen, numérique (*))sSource est une chaîne = [i est un numérique (*) = %1RENVOYER i]bResultatValide est un booléenxResutatDuCalcul est un numérique (*)SI (Compile("CalculerFormule", ChaîneConstruit(sSource, sCalcul)) = "") ALORSQUAND EXCEPTION DANSxResutatDuCalcul = ExécuteTraitement("CalculerFormule", trtProcédure)bResultatValide = VraiFAIREFINFINRENVOYER (bResultatValide, xResutatDuCalcul)
Un exemple d'utilisation :
Trace( VérifierCalcul("(1+2.5-0.25)") )Trace( VérifierCalcul("( 3 * 0.5) / 2") )Trace( VérifierCalcul("1 / 0") )
// PROCÉDURE INTERNE piDemandeConfirmationFermeture()// sNomFenêtre est un Champ <- mafenetre// si (sNomFenêtre..nom [~ "FEN_") _ou_ (sNomFenêtre..Nom [~ "FI_") ALORS // Pour ne pas récupérer les fenêtres personnalisées (WINDEV®®MessageBox, WinDevMessageBox, etc...)// SI (OuiNon(ChaîneConstruit("Etes-vous sûr de vouloir fermer la fenêtre %1 ?", sNomFenêtre..Titre)) = Oui) ALORS// Ferme()// sinon// RepriseSaisie(sNomFenêtre)// FIN// FIN// FINPROCÉDURE INTERNE piEvtFenetre(nMessage, wParam <utile>, lParam <utile>)SI (nMessage = 1) ALORS // WM_CREATEQUAND EXCEPTION DANSsNomFenêtre est un Champ <- MoiMêmeSI (FenEtat(sNomFenêtre..Nom) <> Inexistant) ALORS// ... Traitement à faire// exemple 1 : sNomFenêtre..CouleurFond=BleuPastel// exemple 2 : sNomFenêtre..Traitement[trtFermeture]..Avant = piDemandeConfirmationFermetureFINFAIREFINFINFINEvénement(piEvtFenetre, "*.", 1) // WM_CREATE : Evénement appelé à chaque ouverture d'une fenêtre.// Cela peut être utile pour une adaptation de la charte graphique, une traduction programmée, une gestion de droits utilisateur, etc...
// La colonne du champ table doit être d'un type numérique (entier, monétaire, etc...)<NomTable>.<NomColonne>[ligneTotal]
Il est également possible de récupérer un compteur (ligneComptage), un maximum (ligneMaximum), un minimum (ligneMinimum) et une moyenne (ligneMoyenne) :
Programmation des calculs dans les champs table
sTexte est une chaîne = [http://www.google.fr c'est le lien web http vers le moteur de recherche googleet https://doc.pcsoft.fr/et un autre lien https://www.google.com/q=toto aussi]sRegex est une chaîne = "(http|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])"tabLiens est un tableau de chaîneRegexCherche(sTexte, sRegex, tabLiens)POUR TOUT sUnLien DE tabLiensTrace(sUnLien)FIN
PROCÉDURE fVérifieChecksum(sCheminFichier est une chaîne, sChecksum est une chaîne, nTypeAlgo est un entier) : booléenSI HashVérifieFichier(nTypeAlgo, sCheminFichier, sChecksum) ALORSRENVOYER VraiFINsChecksum = Majuscule(sChecksum)buffHash est un Buffer = HashFichier(nTypeAlgo, sCheminFichier)sHexa est une chaîne = BufferVersHexa(buffHash, SansRegroupement, SansLigne)RENVOYER (sHexa = sChecksum)
Un exemple d'utilisation :
SI fVérifieChecksum("vlc-3.0.21-win64.exe", "9742689a50e96ddc04d80ceff046b28da2beefd617be18166f8c5e715ec60c59", HA_SHA_256) ALORSInfo("Checksum ok")SINONErreur("Le checksum ne correspond pas")FIN
PROCÉDURE PUBLIQUE GLOBALE ChaineExtrait_Numeriques(sUneChaîne est une chaîne) : chaînesNumeriques est une chaînesNumeriques = SansCaractère(ChaîneFormate(sUneChaîne, ccMinuscule+ccSansAccent+ccSansPonctuationNiEspace), "abcdefghijklmnopqrstuvwxyz", sscTout)RENVOYER sNumeriques
Un exemple d'utilisation :
sNumeriques est une chaînesNumeriques = ChaineExtrait_Numeriques("1 naissance, le 23/12/2026")Trace(sNumeriques) // Affiche "123122026"
Pour rappel, pour vérifier l'égalité de variables de type simple (booléen, numérique, chaîne, ...), utiliser l'opérateur de comparaison = .
PROCÉDURE PUBLIQUE GLOBALE VariablesEgales(LOCALE v1 est un Variant, LOCALE v2 est un Variant) : booléenbuff1, buff2 est un Buffer = ("1", "2")QUAND EXCEPTION DANSSérialise(v1, buff1, psdJSON+psdMinifie)Sérialise(v2, buff2, psdJSON+psdMinifie)FAIREErreurDéclenche(1, "Erreur sur la comparaison")FINRENVOYER (buff1 = buff2)
| Non optimisé | Optimisé |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| → De préférence, utiliser une requête SQL plutôt que les fonctions H*. → De préférence, utiliser les fonctions H* plutôt que les fonctions POUR TOUT. |
|
|
|
| → De préférence, utiliser une variable de type champ plutôt que les indirections de champs. | |
|
|
| → De préférence, typer toutes les indirections. | |
|
|
| → De préférence, utiliser les propriétés plutôt que les fonctions. | |
|
|
| → De préférence, utiliser les opérateurs de comparaison plutôt que les fonctions. | |
|
|
|
|
|
|
|
|
|
|
| → Le déclenchement du traitement d'exception spécifique QUAND EXCEPTION DANS (try ... catch) peut être relativement lent. Essayer de sécuriser au maximum le contenu pour éviter de rentrer dans le code de traitement de l'exception. | |
Lors de l'appel à une fonction WLangage®, tout un mécanisme se lance dans la machine virtuelle :
- recherche dans quel fichier DLL se trouve cette fonction
- vérification du chargement du fichier DLL
- recherche de la fonction
- empilement des paramètres
- appel de la fonction
- dépilement de la valeur de retour
- remontée jusqu’au WLangage®
A contrario, lors de l'utilisation d'un opérateur, celui-ci est directement dans la machine virtuelle. Le temps de traitement est donc réduit :
- l’opération est exécutée et le résultat renvoyé
Donc, si un opérateur existe, utilisez-le.
Par exemple, vous pouvez remplacer :
- la fonction Gauche() par l’opérateur [=
- la fonction ChaîneFinitPar() par l’opérateur ~] (termine par sans casse)
L'addition logique optimisée _OU_ ne doit pas être utilisée si une des expressions à comparer utilise le résultat d'une fonction pouvant renvoyer NULL.
https://doc.pcsoft.fr/?1512003&name=operateurs_logiques
PROCÉDURE INTERNE piInit(LOCALE nEntier est un entier)// Si la valeur du paramètre nommé "nEntier" est impair alors renvoyer null sinon renvoyer 2RENVOYER EstImpair(nEntier) ? Null SINON 2FIN// Avec _OU_ : le résultat de la trace vaut "OK" alors qu'elle devrait être "KO"SI (piInit(1) = 3) _OU_ (piInit(2) = 4) ALORSTrace("OK")SINONTrace("KO")FIN// Avec OU : le résultat de la trace vaut "KO" et c'est bien le résultat souhaitéSI (piInit(1) = 3) OU (piInit(2) = 4) ALORSTrace("OK")SINONTrace("KO")FIN
Avant pour désactiver le filtre déjà existant des codes précédents.
Après pour désactiver le filtre pour les codes suivants.
HDésactiveFiltre(NomTableBDD)POUR TOUT NomTableBDD AVEC "condition(s)"... // InstructionsSORTIRFINHDésactiveFiltre(NomTableBDD)
Depuis la version 24 de WINDEV® avec le mot clé optionnel SANSSAUVEPOSITION :
POUR TOUT NomTableBDD AVEC "condition(s)" SANSSAUVEPOSITION... // InstructionsSORTIRFIN
Avant pour libérer les ressources de la requête SQL des codes précédents.
Après pour libérer les ressources (espace mémoire) de la requête SQL pour les codes suivants.
HAnnuleDéclaration(REQ_SELECT_SOCIETE)HExécuteRequête(REQ_SELECT_SOCIETE)POUR TOUT REQ_SELECT_SOCIETE... // TraitementFINHAnnuleDéclaration(REQ_SELECT_SOCIETE)
Attention à ne pas libérer la requête SQL trop tôt !
HAnnuleDéclaration(REQ_SELECT_SOCIETE)HExécuteRequête(REQ_SELECT_SOCIETE)TableAffiche(NomChampTable, taInit)HAnnuleDéclaration(REQ_SELECT_SOCIETE)
Dans le code ci-dessus, après la fonction TableAffiche() la fonction HAnnuleDéclaration() est appelée trop tôt et le champ n'affichera pas la totalité des enregistrements.
sdReq est une Source de donnéessReq est une chaîne// Le code suivant n'est pas sécurisé :sReq = ChaîneConstruit("SELECT * FROM SITE WHERE Libelle LIKE '%1'", "Paris")HExécuteRequêteSQL(sdReq, hRequêteDéfaut, sReq)// Les requêtes préparées permettent de sécuriser contre les failles de sécurité (exemple: injection SQL)sReq = "SELECT * FROM SITE WHERE Libelle LIKE {pLibelle}"sdReq.pLibelle = "Paris"HExécuteRequêteSQL(sdReq, hRequêteDéfaut, sReq)
HChangeLocalisation("*", hDisque)
EXTERNE "WINCONST.wl" // Constantes standard de WindowsEXTERNE "KEYCONST.wl" // Constantes standard de Windows utilisées pour les touches du clavierEXTERNE "EXCEPT.wl" // Constantes utilisées pour la gestion des exceptionsEXTERNE "LIMITES.wl" // Constantes correspondant aux limites des types de données WINDEV®EXTERNE "ListeDefinitionHF.wl" // Constantes HFSQL utilisées pour la journalisation//threadMultiProcesseur : Les threads sont automatiquement répartis entre les différents processeurs.//threadSectionCritique : Chaque procédure pourra être exécutée par plusieurs threads simultanément.// Il est nécessaire de protéger les accès aux ressources partagées entre les différents threads par des sections critiques.ThreadMode(threadMultiProcesseur + threadSectionCritique)// Nouveau mode d'exécution à appliquerModeExécution(modeNormal + AppelsExternesOptimisés)// Modifie la priorité de l'application en cours d'exécutionExePriorite(ExeDonnePID(exePID), exePrioritéSupérieureNormale)SI (ExePriorite(ExeDonnePID(exePID)) <> exePrioritéSupérieureNormale) ALORSExePriorite(ExeDonnePID(exePID), exePrioritéHaute)FIN//http://faq.pcsoft.fr/8865-champ_oauth_activex_assemblage_ole_automation_coinitializeex-read.awp :// Que faire si l'utilisation d'un module externe impacte des fonctionnalités d'une application WINDEV® ?// Gestion du Drag and Drop // Connecteur Natif SQL Server : Spécificités et remarques// Lors de l'utilisation de le Connecteur Natif SQL Server via SQLnCli, certaines fonctionnalités peuvent ne pas fonctionner.// Pour retrouver un fonctionnement correct, il est conseillé d'ajouter ces lignes de code dans l'initialisation du projet :SI (ChargeDLL("OLE32") <> 0) ALORSSELON API("OLE32", "CoInitializeEx", Null, 2)CAS 0 : // OKCAS 1 :API("OLE32", "CoUninitialize")SI (API("OLE32", "CoInitializeEx", Null, 2) <> 0) ALORS... // Erreur("Echec de CoInitializeEx", ErreurInfo())FINAUTRE CAS :... // Erreur("Echec de CoInitializeEx", ErreurInfo())FINFIN//ChargeDLL("ole32")//API("ole32", "CoInitializeEx", 0, 2)// Gestion des effetsSI EnModeTSE() ALORS// Pour désactiver des effets non supportés en TSEFenDésactiveEffet(effetAnimation + effetCadreTranslucide + effetGFI + effetHalo)SINON// Animation des champs, leurs effets de transitionsAnimationMinFPS(24)// Les fenêtres ayant un cadre translucide sont affichées avec cet effetStyleDessin(styleCadreFenTranslucide, Vrai)// Chargement rapide : le temps de chargement des images est prioritaire sur leur qualitéStyleDessin(styleImageFaibleQualite, Vrai)// Les icônes, images des boutons grisés sont affichées en niveau de gris.// Si ce mode est sélectionné, l'affichage peut prendre un plus de temps mais le rendu est meilleurStyleDessin(stylePictoGriseDegrade, Vrai)FIN// Aperçu avant impressioniParamètreAperçu(iBoutonTous - iBoutonHtml - iBoutonXml, 150)// Afficher le volet des miniatures dans l'aperçu avant impressioniParamètreAperçu(iVoletMiniatures, Vrai)// Génération PDFiParamètrePDF("", "", iQualitéMaximale + iPDFUnicode)// Génération XLSiParamètreXLS(iAvecMiseEnForme)// Paramétrer l'impression de l'état (et notamment la conservation de la mise en forme des cellules)ParamètreFAA(faaImprimeEtatSurTable, 1)// Génération pour le champ "table" XLS / Word / XMLParamètreFAA(faaTableVersExcel, taAvecMiseEnForme + taColonneOrdreAffiche + taTitreColonnes)ParamètreFAA(faaTableVersWord, taAvecMiseEnForme + taColonneOrdreAffiche + taTitreColonnes)ParamètreFAA(faaTableVersXML, taAvecMiseEnForme + taColonneOrdreAffiche + taTitreColonnes)// Désactivation ReconnaissanceVocaleDésactiveFAA(faaReconnaissanceVocale)// Active la vérification d'orthographe pour toute l'applicationParamètreOrthographe(orthographeActif, Vrai)// Sélectionne le dictionnaire du langage en coursParamètreOrthographe(orthographeNation, SysNation())// Gestion des jours fériésJourFériéSupprimeTout()SELON SysNation()CAS nationFrançais :// Initialisation des 11 jours fériés communs aux départements français et DOM/TOMJourFériéAjoute("0101") // 1er JanvierJourFériéAjoute(jfLundiDePâques) // Lundi de PâquesJourFériéAjoute("0501") // 1er MaiJourFériéAjoute("0508") // 8 MaiJourFériéAjoute(jfJeudiDeLAscension) // Jeudi de l'AscensionJourFériéAjoute(jfLundiDePentecôte) // Lundi de PentecôteJourFériéAjoute("0714") // 14 JuilletJourFériéAjoute("0815") // 15 Août (Assomption)JourFériéAjoute("1101") // ToussaintJourFériéAjoute("1111") // 11 NovembreJourFériéAjoute("1225") // NoëlAUTRE CAS :FIN// Délai à attendre avant l'affichage des bulles d'aideBulleDélai(bulleDuréeAvantOuverture, -1) // Valeur par défaut gérée par Windows// Durée d'affichage des bulles d'aide des champsBulleDélai(bulleDuréeAffichage, 32s) // Valeur maximale : 32,6s// Initialisation du générateur de nombres aléatoiresInitHasard()// Règle le timeout pour les fonctions WLangage® utilisant le protocole HTTPHTTPTimeOut(10s)