mercredi 2 janvier 2008

RIBControl : Saisie et validation d'un RIB

RIBControl est un contrôle Suneido permettant la saisie et la validation d'un Relevé d'Identité Bancaire.

Le code de RIBControl

PatternControl
{
Name: "RIB"
New(width= 23, mandatory= false)
{
super('>>>>> >>>>> >>>>>>>>>>> ##',
width : width,
mandatory : mandatory,
status: 'RIB')
.mandatory = mandatory
}
Valid?()
{
value = .Get()
if (.mandatory is false and value is '')
return true
return super.Valid?() and RIBValid?(value)
}
}

Le code de RIBValid ?

function (rib)
{
rib = rib.Tr(" " )
dict = #("0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9, A:1, B:2, C:3, D:4, E:5, F:6, G:7, H:8, I:9,J:1, K:2, L:3, M:4, N:5, O:6, P:7, Q:8, R:9,S:2, T:3, U:4, V:5, W:6, X:7, Y:8, Z:9)
num = ""
for (i=0; i<= rib.Size()-1; ++i)
{
num $= dict[rib.Substr(i,1)]
}
cle = num.Substr(-2)
if (Number(cle)<1 or Number(cle)>97)
{
return false
}
a = num.Substr(0,7)
b = num.Substr(7,7)
c = num.Substr(14,7)
verifcle = 97-((62*a+34*b+3*c)%97)
return Number(cle) == verifcle
}


Le code code de RIBValidTest

Test
{
Test_main()
{
AssertEq(RIBValid?('15459 45000 0411700920U 62'),true)
AssertEq(RIBValid?('10207 00026 04026011770 83'),true)
AssertEq(RIBValid?('30002 06971 0000072002D 05'),false)
}
}

Explications

RIBControl est un PatternControl avec comme masque de saisie >>>>> >>>>> >>>>>>>>>>> ## ou > représente un chiffre ou une lettre majuscule et # un chiffre.

Les données entrées avec ce masque sont alors vérifiées avec la fonction RIBValid?

function (rib)


RIBValid ? est une fonction prenant en paramètre d'entrée un RIB

{
rib = rib.Tr(" " )


on enlève du RIB tous les espaces

dict = #("0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9,A:1, B:2, C:3, D:4, E:5, F:6, G:7, H:8, I:9,J:1, K:2, L:3, M:4, N:5, O:6, P:7, Q:8, R:9,S:2, T:3, U:4, V:5, W:6, X:7, Y:8, Z:9)


On créé un dictionnaire nommé dict contenant la correspondance entre chaque caractère possible du RIB avec une valeur numérique

num = ""


On initialise la variable num

for (i=0; i<= rib.Size()-1; ++i)

Pour chaque caractère du RIB

{
num $= dict[rib.Substr(i,1)]


On concatène à num la valeur correspondante du caractère encours dans le dictionnaire (par ex : U donne 4)

}
cle = num.Substr(-2)


On détermine la clé (ce sont les deux derniers caractères du RIB d'où le -2)

if (Number(cle)<1 or Number(cle)>97)


Si la clé n'est pas comprise entre 1 et 97 alors le RIB n'est pas valide

{
return false
}


Sinon, on décompose le nouveau « RIB » entièrement numérique num en tois partie de 7 caractères

a = num.Substr(0,7)
b = num.Substr(7,7)
c = num.Substr(14,7)


On calcule la clé de vérification verifcle

verifcle = 97-((62*a+34*b+3*c)%97)

Le RIB est juste si la clé du RIB est égale à verifcle (on utilise Number(cle) pour convertir la clé qui est une sous chaîne de la chaîne RIB en valeur numérique, sinon il y a un conflit de type)

return Number(cle) == verifcle
}


Et voilà votre RIB est validé.

Et Comme d'habitude on met en place un ensemble de tests pour valider le tout :

Test
{
Test_main()
{
AssertEq(RIBValid?('15459 45000 0411700920U 62'),true)
AssertEq(RIBValid?('10207 00026 04026011770 83'),true)
AssertEq(RIBValid?('30002 06971 0000072002D 05'),false)
}
}


Les RIB testés ci-dessus ne sont plus actifs, mais si vous voulez faire un gros virement sur un RIB actif, je peut vous communiquer le mien ,-)

lundi 24 décembre 2007

Joyeux Noël et bonne année

Joyeux Noël et bonne année 2008 à tous.

J'espère terminer le transfert de l'ancien SuneiDojo bientôt. et J'espère surtout à la communauté Suneido francophone de faire grandir ce site à la mesure du site Anglophone ;-)

lundi 26 novembre 2007

Field_naf : un champ donnant le code et le libellé d'un NAF

Field_naf permet la recherche d'un code NAF (Nomenclature d'Activités Française) dans la base de donnée INSEE (NAF rév. 1, 2003) et l'affichage de la désignation complète de celui-ci.

Tout d'abord nous devons définir une table qui importera la Nomenclature d'Activités Française Niveau 700 (la plus détaillée, voir le site de l'INSEE pour plus de détail)

Définition de la table NAF700


Database("ensure naf700 (naf_code, naf_libelle) key(naf_code) index(naf_libelle)" )
File("naf/naf_700.txt" )
{ |f|
while (false isnt (ligne = f.Readline()))
{
enr = Record()
valeurs = ligne.Split('\t')
for (i in valeurs.Members())
enr[champs1[i]] = valeurs[i]
QueryOutput ("naf700", enr)
}
}
Cette fonction définie la table naf700 qui est composée des colonnes naf_code et naf_libelle et à comme clé primaire naf_code.

Nous définissons ensuite un paramètre de champs pour un fichier d'import et importons dans la table naf700 les données du fichier naf/naf_700.txt.

Définition du champs naf700

Field_string
{
Prompt: 'NAF'
Control: (Key 'naf700' field:'naf_code', width: 4)
Format: (Text width: 4)
}
Le champ naf est défini comme un champ string qui est basé sur un contrôle Key prenant en paramètre la table naf700.

Exemple dans Suneido:

Une petite fonction pour convertir une somme en toutes lettres

Une petite fonction utilisant le méthode EnFrancais pour écrire une somme en euro et toute lettre.

Le code

function(somme)
{
return (somme.Int().EnFrancais()) $ " euro"
$ ((somme.Int())>1? "s" : "" )
$ (somme.Frac() == 0? ( "" ) : ( " et "
$ ((somme.Frac())*100).Round(0).EnFrancais()
$ " centime" $ (((somme.Frac())*100)>1? "s" : "" )))
}


Explications

On décompose la somme en sa partie entière et sa partie décimale :
-Partie entière : somme.Int()
-Partie décimale : somme.Frac()

On applique la méthode EnFrancais à ces deux parties.

On rassemble le tout en tenant compte :
-du pluriel de euro : somme.Int()>1? "s" : ""
-de l'affichage ou nom de centime : somme.Frac()==0?"": ...
-du pluriel de centime : somme.Frac()*100>1? "s" : ""

Utiliser Browse dans un Access pour les liaisons Entête Lignes (Parent Enfants, ...)

Par Jeff Ferguson Suneido Software
Traduit par Jean Charles Hoarau

Vous avez une table Entête avec une ou plusieurs tables Ligne qui ont une clé étrangère vers la table Entête et vous voulez permettre la saisie de données Lignes dans la fenêtre Entête;

Nous allons utiliser l'exemple d'une facture. La facture aura des lignes normales ainsi que des lignes de port. Voici les tables :

facture (fact_num, fact_date, fact_tiers)
Key(fact_num)

fact_ligne (ligne_num, fact_num, ligne_desc, ligne_montant)
Key(ligne_num)
Index(fact_num) in facture

fact_port(port_num, fact_num, extra_desc, extra_montant)
Key(port_num)
Index(fact_num) in facture

Pour gérer les clés des tables, nous définissons des règles qui retournent un Timestamp (tampon horaire). Ceci assurera que la valeur du champ est unique. De plus les clés seront renommées de façon à prévenir l'exécution des règles sur les clés étrangères des tables de détail.

Rule_fact_num_new
function()
{
return Timestamp()
}

Rule_ligne_num_new
function()
{
return Timestamp()
}

Rule_port_num_new
function()
{
return Timestamp()
}

Il est important de définir les Champs pour les clés pour s'assurer qu'elles seront traité comme des dates.

Field_fact_num
Field_num
{
}

Field_fact_num_new
Field_fact_num
{
}

Field_ligne_num_new
Field_num
{
}

Field_port_num
Field_num
{
}

Nous avons aussi besoin de dupliquer fact_num. Nous avons besoins de fact_num_new2 parce que nous avons deux contrôles (des BrowseControl) avec le même nom dans RecordControl, les contrôles étant reconnu par leur nom.

Rule_fact_num2
function()
{
return .fact_num_new
}

Maintenant nous devons pouvoir définir un Access pour entrer nos factures :

FactureAccess
#(Access "facture rename fact_num to fact_num_new"
(Vert
fact_date
fact_tiers
(Browse "fact_ligne rename ligne_num to ligne_num_new"
columns: (ligne_desc, ligne_montant)
linkField: "invoice_num",
name: "fact_num_new")
(Browse "fact_port rename port_num to port_num_new"
columns: (port_desc, port_montant)
linkField: "invoice_num",
name: "fact_num_new2")
)
)

l'argument 'name' de Browse doit être un champ ou une règle de la requette maître. l'argument 'linkField' doit être un champ de la requette détail.

Maintenant vous pouvez accéder à l'Access en lançant dans le WorkSpace :

Window(FactureAccess)

vendredi 23 novembre 2007

Obtenir les lignes selectionnées d'un BrowseControl

Par Jenebelle
Traduit par Jean-Charles Hoarau

Ingrédient : BrowseControl

Comment obtenir l'enregistrement correspondant à la ligne sélectionnée d'un BrowseControl

Pour obtenir l'enregistrement de la ligne sélectionnée :

sel = browse.GetSelection()
Ceci retourne un objet contenant les index de la ou des lignes sélectionnées.

Pour avoir les données d'un ligne sélectionnée :

row = sel[0]
on obtient l'index de la première ligne sélectionnée si il y en a plusieurs.

data = browse.GetRow(row)
data contient toutes les valeurs de tous les champs de la ligne.

Exemple :
Controller
{
Controls: #(Vert
(Browse 'tables')
(Button "Montrer l enregistrement"))
On_Montrer_l_enregistrement()
{
browse = .Vert.Browse
selected = browse.GetSelection()
if selected.Empty?()
{
Alert("Vous n'avez pas selectionné de ligne")
return
}
if selected.Size() > 1
{
Alert("Vous ne pouvez selectionner qu'une ligne")
return
}
index = selected[0]
rec = browse.GetRow(index)
Alert('Vous avez selectionné la table ' $ Display(rec.tablename))
}
}

Utiliser Excel avec Suneido

Lire et écrire dans un document Excel à partir de Suneido (testé par moi-même (le traducteur) avec Excel 2002 sur Windows 2000)

Par Claudio Mascioni
Traduit par Jean-charles Hoarau
Ingrédients : COMobject

Recette

Pour Ouvrir une feuille excel à partir de Suneido


excelapp = COMobject("Excel.Application")
excelapp.Visible = true
// true = montre la fenetre excel
// false = cache la fenetre excel
wrkbks = excelapp.Workbooks.Open("c:/test.xls") // le fichier Excel à ouvrir
wrkbks.Release()
excelapp.Release() // pour libérer la mémoire occupée par Excel


Pour obtenir la valeur d'une cellule d'une feuille Excel


excelapp = COMobject("Excel.Application")
excelapp.Visible = false // cache la fenetre excel
wrkbks = excelapp.Workbooks.Open('c:/test.xls')
cellvalue = excelapp.Cells(2,2).Value // retourne la valeur de la cellule B2
wrkbks.Close // ferme la feuille Excel
Print(Display(cellvalue))
wrkbks.Release()
excelapp.Release()
NdT : si vous essayer de lire un nombre flottant (25.00) dans une cellule Excel vous obtiendrez une erreur car les nombres flottants ne sont pas gérés dans l'interface COM de Suneido. Il semblerait que cela ne soit pas très compliqué à mettre en œuvre (fichier sucomobject.cpp méthode com2su) mais comme mes connaissances en C sont nulles alors si cela vous tente...

Pour écrire une valeur dans une cellule d'une feuille Excel existante et sauvegarder la feuille


excelapp = COMobject("Excel.Application")
excelapp.Visible = true; // montre la fenêtre
wrkbks = excelapp.Workbooks.Open("c:\\test.xls")
excelapp.Cells(2,2).Value = Display(Timestamp()) // écrit quelque chose dans la cellule B2
wrkbks.Save
wrkbks.Close
wrkbks.Release()
excelapp.Release()


Pour écrire une valeur dans une cellule d'une nouvelle feuille Excel et la montrer

excelapp = COMobject("Excel.Application")
excelapp.Visible = true;
wrkbks = excelapp.Workbooks.Add()
excelapp.Cells(2,2).Value = Display(Timestamp())
wrkbks.Release()
excelapp.Release()
Pour écrire une valeur dans une cellule d'une nouvelle feuille Excel et enregistrer la feuille

excelapp = COMobject("Excel.Application")
excelapp.Visible = false; // cache la fenêtre
wrkbks = excelapp.Workbooks.Add()
excelapp.Cells(2,2).Value = Display(Timestamp())
wrkbks.SaveAs("c:\\testnew.xls")
wrkbks.Close
wrkbks.Release()
excelapp.Release()

Pour changer le nom des feuilles affichées dans les onglets et écrire une valeur dans chacune d'elle

Modifié car la version d'origine ne fonctionne pas sur Excel 2002/Windows 2000

excelapp = COMobject("Excel.Application")
excelapp.Visible = true;
wrkbks = excelapp.Workbooks.Add()
//
sheet1 = wrkbks.WorkSheets.Add() // original : sheet1 = wrkbks.WorkSheets.(1)
sheet1.Name = 'nameofsheet1' // change le non de la feuille
sheet1.Cells(1,1).Value = 'valuesheet1' // on écrit quelque chose
//
sheet2 = wrkbks.WorkSheets.Add() // original : sheet1 = wrkbks.WorkSheets.(2)
sheet2.Name = 'nameofsheet2'
sheet2.Cells(2,2).Value = 'valuesheet2'
//
sheet3 = wrkbks.WorkSheets.Add() // original :sheet1 = wrkbks.WorkSheets.(3)
sheet3.Name = 'nameofsheet3'
sheet3.Cells(3,3).Value = 'valuesheet3'
//
wrkbks.Release()
sheet1.Release()
sheet2.Release()
sheet3.Release()
excelapp.Release()


ps. copier et coller ce code dans votre espace de travail pour tester si cela marche chez vous.