După un concediu înfiorător de relaxant și o săptămână groaznică de acomodare, astăzi nu mi-am propus dar am reușit să încep cu ”motoarele în flăcări”. :)
Se face că un bun prieten are o mică problemă de rezolvat în SharePoint și anume aceea de validare a unor CNP-uri introduse într-o listă. Ce ar fi putut fi mai simplu, nu? :)
Ca să ajungi la o coloană calculată în SharePoint trebuie să ai ceva cunoștințe de Excel… așa că am pornit în realizarea formulei întâi în Excel.
Am aflat de un miraculos număr: 279146358279 pe care mulți colegi tehnici nu îl înțeleg dar pentru care am găsit o explicație pe comunitatea utilizatorilor de FoxPro:
”Scopul cifrelor de control este să semnaleze dacă vreuna din cifrele utile a fost schimbată. Există o întreagă terorie a cifrelor de control și o gramada de algoritmi cu diferite toleranțe. In cazul codurilor până la 10 cifre algoritmul respectiv folosește numerele prime de o cifră in ordine descrescăstoare: 7, 5, 3, 2, 1, după care se repetă până se acoperă lungimea codului. Este un algoritm cu o toleranță foarte mică la erori.
In cazul codurilor mai mari de 10 cifre se folosește un algoritm mai complicat ținându-se cont și de alte elemente, cum ar fi în cazul CNP faptul că cifrele de pe anumite poziții nu pot avea orice valoare. Totuși algoritmul nu este perfect, se poate vedea clar că cifra de control este 1 în cazul în care restul împărțirii la 11 este 1 sau 10. Cu alte cuvinte CNP-urile 1640228240011 și 2640228240011 sunt amandouă valide deși diferă doar o cifră, deci un baiat ar putea fi confundat cu o fată fără ca eroarea să fie sesizată de un computer.”
Pentru cei care nu cunosc structura CNP se pot informa la adresa: http://www.hangman.ro/cnp/. Tot la această adresă mai explicată odată constanta de verificare.
Varianta de lucru în Excel
Să revenim la modelul de validare în Excel. Descărcați fișierul Validare CNP. În prima foaie de calcul există un model descompus al metodei de calcul:
În foaia a doua, este un tabel care face o îmbinare a validărilor din celulele S, T, U si V.
Pentru cei care nu pot descărca fișierul formula de calcul este:
=IF(AND(INT(MID([@CNP];13;1))=IF(MOD(2*INT(MID([@CNP];1;1))+7*INT(MID([@CNP];2;1))+9*INT(MID([@CNP];3;1))+1*INT(MID([@CNP];4;1))+4*INT(MID([@CNP];5;1))+6*INT(MID([@CNP];6;1))+3*INT(MID([@CNP];7;1))+5*INT(MID([@CNP];8;1))+8*INT(MID([@CNP];9;1))+2*INT(MID([@CNP];10;1))+7*INT(MID([@CNP];11;1))+9*INT(MID([@CNP];12;1));11)=10;1;MOD(2*INT(MID([@CNP];1;1))+7*INT(MID([@CNP];2;1))+9*INT(MID([@CNP];3;1))+1*INT(MID([@CNP];4;1))+4*INT(MID([@CNP];5;1))+6*INT(MID([@CNP];6;1))+3*INT(MID([@CNP];7;1))+5*INT(MID([@CNP];8;1))+8*INT(MID([@CNP];9;1))+2*INT(MID([@CNP];10;1))+7*INT(MID([@CNP];11;1))+9*INT(MID([@CNP];12;1));11));INT([@CNP])>0);”CNP CORECT”;”CNP GRESIT”)
Adaptare în SharePoint
După ce am obținut formula concatenată în Excel, implementarea în SharePoint este doar o adaptare a acesteia.
Se crează așadar o listă simplă personalizată în care am schimbat coloana Title cu CNP și am mai adăugat o coloană nouă Stare de tip calculated column. Valoare coloanei calculate este:
=IF(AND(INT(MID(CNP,13,1))=IF(MOD(2*INT(MID(CNP,1,1))+7*INT(MID(CNP,2,1))+9*INT(MID(CNP,3,1))+1*INT(MID(CNP,4,1))+4*INT(MID(CNP,5,1))+6*INT(MID(CNP,6,1))+3*INT(MID(CNP,7,1))+5*INT(MID(CNP,8,1))+8*INT(MID(CNP,9,1))+2*INT(MID(CNP,10,1))+7*INT(MID(CNP,11,1))+9*INT(MID(CNP,12,1)),11)=10,1,MOD(2*INT(MID(CNP,1,1))+7*INT(MID(CNP,2,1))+9*INT(MID(CNP,3,1))+1*INT(MID(CNP,4,1))+4*INT(MID(CNP,5,1))+6*INT(MID(CNP,6,1))+3*INT(MID(CNP,7,1))+5*INT(MID(CNP,8,1))+8*INT(MID(CNP,9,1))+2*INT(MID(CNP,10,1))+7*INT(MID(CNP,11,1))+9*INT(MID(CNP,12,1)),11)),INT(CNP)>0),”CNP CORECT”,”CNP GRESIT”)
Izbitor de asemănător, nu? :)
Rezultatul:
În cazul în care vă propuneți să realizați formula în InfoPath pentru validarea funcției trebuie să știm că există o serie de diferențe printre care: funcția MID() este înlocuită cu funcția substring(), funcția MOD() nu există ci este înlocuită de operatorul mod care nu funcționează la fel ca cel din Excel, și altele printre care inexistența atât de utilului IF-THEN-ELSE.
Evaluarea CNP-ului în timp real
Să trecem la puțină treabă de MVP :)
Așadar, ”clientul” dorește ca după ce a completat câmpul de CNP să-i apară în mod automat, fără să dea submit, ca în exemplul anterior, dacă CNP-ul a fost completat corect sau nu:
În ecranul curent apar pe lângă starea de validare încă două variabile de lucru.
Starea este calculată în InfoPath prin compararea stării unor câmpuri calculate cu xPath. După cum spuneam în paragraful anterior în xPath nu avem IF-THEN-ELSE. În schimb în articolul Conditional Default Values putem vedea mai multe metode de înlocuire a IF-ului.
Personal am testat și utilizat metoda:
concat(
substring(TrueResult, 1, (BoolCondition) * string-length(TrueResult)),
substring(ElseResult, 1, (not(BoolCondition)) * string-length(ElseResult)))
Ca să ajung în schimb la rezultatul final, trebuie menționat că xPath nu suportă funcții logice imbircate (IF-uri în IF-uri) de aceea a trebuit să separ într-o variabilă de lucru denumită nan2 rezultatul unei funcții logice intermediare:
NAN2:
substring(CNP; 13; 1) = concat(substring(1; 1; (nan = 10) * string-length(1)); substring(nan; 1; (not(nan = 10)) * string-length(nan)))
nan-ul în formulă este de faptu modul calculat de interpretare a formulei de validare a CNP-ului.
NAN:
(2 * substring(CNP; 1; 1) + 7 * substring(CNP; 2; 1) + 9 * substring(CNP; 3; 1) + 1 * substring(CNP; 4; 1) + 4 * substring(CNP; 5; 1) + 6 * substring(CNP; 6; 1) + 3 * substring(CNP; 7; 1) + 5 * substring(CNP; 8; 1) + 8 * substring(CNP; 9; 1) + 2 * substring(CNP; 10; 1) + 7 * substring(CNP; 11; 1) + 9 * substring(CNP; 12; 1)) – 11 * (ceiling((2 * substring(CNP; 1; 1) + 7 * substring(CNP; 2; 1) + 9 * substring(CNP; 3; 1) + 1 * substring(CNP; 4; 1) + 4 * substring(CNP; 5; 1) + 6 * substring(CNP; 6; 1) + 3 * substring(CNP; 7; 1) + 5 * substring(CNP; 8; 1) + 8 * substring(CNP; 9; 1) + 2 * substring(CNP; 10; 1) + 7 * substring(CNP; 11; 1) + 9 * substring(CNP; 12; 1)) / 11) – 1)
Starea finală este determinată printr-un alt șir de evaluare care are legătură cu NAN2.
Starea:
concat(substring(„CNP CORECT”; 1; (nan2 = „true”) * string-length(„CNP CORECT”)); substring(„CNP GRESIT”; 1; (not(nan2 = „true”)) * string-length(„CNP GRESIT”)))
Concluzii
Câteva ore bune de muncă dar o statisfacție pozitivă că dacă îți pui ceva în cap doar lenea te poate ține departe de rezultate.
Sper să fie util cuiva!