Dynamics AX Blog - Axapta 3.0 - Seite 6
RSS-Feed dieser Version
Einfache str2html-Funktion
29.10.2007Microsoft Dynamics AX (Axapta)
Meines Wissens nach gibt es in AX 3.0 keine Möglichkeit, Text in (halbwegs) validen HTML-Code umzuwandeln. Deshalb habe ich mir die nachstehende Methode geschrieben, die zumindest die meisten möglichen Zeichen in ihre entsprechenden HTML-Entities umwandelt. Ich muß aber gleich vorwegnehmen, diese Methode ist ein "Schnellschuß", d.h. sie ist weder gewissenhaft geprüft noch hinsichtlich Performance optimiert worden. Wer dies nachholen möchte, möge mir seine Ergebisse mitteilen ;-) static str str2html(str _input, boolean _createParagraphs = false) { map entitiesMap = new Map(types::String, types::String); mapiterator it; str ret; ; // Benannte Zeichen für HTML-eigene Zeichen entitiesmap.insert("\"", """); entitiesmap.insert("&", "&"); entitiesmap.insert("<", "<"); entitiesmap.insert(">", ">"); entitiesmap.insert("", " "); entitiesmap.insert("¡", "¡"); entitiesmap.insert("¢", "¢"); entitiesmap.insert("£", "£"); entitiesmap.insert("¤", "¤"); entitiesmap.insert("¥", "¥"); entitiesmap.insert("¦", "¦"); entitiesmap.insert("§", "§"); entitiesmap.insert("¨", "¨"); entitiesmap.insert("©", "©"); entitiesmap.insert("ª", "ª"); entitiesmap.insert("«", "«"); entitiesmap.insert("¬", "¬"); entitiesmap.insert("", ""); entitiesmap.insert("®", "®"); entitiesmap.insert("¯", "¯"); entitiesmap.insert("°", "°"); entitiesmap.insert("±", "±"); entitiesmap.insert("²", "²"); entitiesmap.insert("³", "³"); entitiesmap.insert("´", "´"); entitiesmap.insert("µ", "µ"); entitiesmap.insert("¶", "¶"); entitiesmap.insert("·", "·"); entitiesmap.insert("¸", "¸"); entitiesmap.insert("¹", "¹"); entitiesmap.insert("º", "º"); entitiesmap.insert("»", "»"); entitiesmap.insert("¼", "¼"); entitiesmap.insert("½", "½"); entitiesmap.insert("¾", "¾"); entitiesmap.insert("¿", "¿"); entitiesmap.insert("À", "À"); entitiesmap.insert("Á", "Á"); entitiesmap.insert("Â", "Â"); entitiesmap.insert("Ã", "Ã"); entitiesmap.insert("Ä", "Ä"); entitiesmap.insert("Å", "Å"); entitiesmap.insert("Æ", "Æ"); entitiesmap.insert("Ç", "Ç"); entitiesmap.insert("È", "È"); entitiesmap.insert("É", "É"); entitiesmap.insert("Ê", "Ê"); entitiesmap.insert("Ë", "Ë"); entitiesmap.insert("Ì", "Ì"); entitiesmap.insert("Í", "Í"); entitiesmap.insert("Î", "Î"); entitiesmap.insert("Ï", "Ï"); entitiesmap.insert("Ð", "Ð"); entitiesmap.insert("Ñ", "Ñ"); entitiesmap.insert("Ò", "Ò"); entitiesmap.insert("Ó", "Ó"); entitiesmap.insert("Ô", "Ô"); entitiesmap.insert("Õ", "Õ"); entitiesmap.insert("Ö", "Ö"); entitiesmap.insert("×", "×"); entitiesmap.insert("Ø", "Ø"); entitiesmap.insert("Ù", "Ù"); entitiesmap.insert("Ú", "Ú"); entitiesmap.insert("Û", "Û"); entitiesmap.insert("Ü", "Ü"); entitiesmap.insert("Ý", "Ý"); entitiesmap.insert("Þ", "Þ"); entitiesmap.insert("ß", "ß"); entitiesmap.insert("à", "à"); entitiesmap.insert("á", "á"); entitiesmap.insert("â", "â"); entitiesmap.insert("ã", "ã"); entitiesmap.insert("ä", "ä"); entitiesmap.insert("å", "å"); entitiesmap.insert("æ", "æ"); entitiesmap.insert("ç", "ç"); entitiesmap.insert("è", "è"); entitiesmap.insert("é", "é"); entitiesmap.insert("ê", "ê"); entitiesmap.insert("ë", "ë"); entitiesmap.insert("ì", "ì"); entitiesmap.insert("í", "í"); entitiesmap.insert("î", "î"); entitiesmap.insert("ï", "ï"); entitiesmap.insert("ð", "ð"); entitiesmap.insert("ñ", "ñ"); entitiesmap.insert("ò", "ò"); entitiesmap.insert("ó", "ó"); entitiesmap.insert("ô", "ô"); entitiesmap.insert("õ", "õ"); entitiesmap.insert("ö", "ö"); entitiesmap.insert("÷", "÷"); entitiesmap.insert("ø", "ø"); entitiesmap.insert("ù", "ù"); entitiesmap.insert("ú", "ú"); entitiesmap.insert("û", "û"); entitiesmap.insert("ü", "ü"); entitiesmap.insert("ý", "ý"); entitiesmap.insert("þ", "þ"); entitiesmap.insert("ÿ", "ÿ"); // Benannte Zeichen für diverse Symbole (unvollständig) entitiesmap.insert("•", "•"); entitiesmap.insert("™", "™"); entitiesmap.insert("€", "€"); // Benannte Zeichen lateinisch erweitert entitiesmap.insert("Œ", "Œ"); entitiesmap.insert("œ", "œ"); entitiesmap.insert("Š", "Š"); entitiesmap.insert("š", "š"); entitiesmap.insert("Ÿ", "Ÿ"); entitiesmap.insert("ƒ", "ƒ"); // Benannte Zeichen für Interpunktion entitiesmap.insert("–", "–"); entitiesmap.insert("—", "—"); entitiesmap.insert("‘", "‘"); entitiesmap.insert("’", "’"); entitiesmap.insert("‚", "‚"); entitiesmap.insert("“", "“"); entitiesmap.insert("”", "”"); entitiesmap.insert("„", "„"); entitiesmap.insert("†", "†"); entitiesmap.insert("‡", "‡"); entitiesmap.insert("…", "…"); entitiesmap.insert("‰", "‰"); entitiesmap.insert("‹", "‹"); entitiesmap.insert("›", "›"); // Benannte Zeichen für diakritische Zeichen entitiesmap.insert("ˆ", "ˆ"); entitiesmap.insert("˜", "˜"); it = new mapIterator(entitiesMap); ret = _input; while (it.more()) { ret = strReplace(ret, it.key(), it.value()); it.next(); } // Zeilenumbrüche if ( _createParagraphs ) { ret = strReplace(ret, '\n\n', ''); ret = strReplace(ret, '\n', ''); } return ret; } |
e-Mail-Validierung in MS Dynamics AX
18.10.2007Microsoft Dynamics AX (Axapta)
Manchmal ist es notwendig, eingegebene E-Mail-Adressen auf deren Syntax hin zu überprüfen. Genau für dieses Zweck habe ich die nachfolgende Methode geschrieben. Schliesslich verfügt MS Dynamics AX erst ab Version 4.0 über eine entsprechende eigene Methode (SysEmailDistributor.validateEmail). static boolean isValidMailAddress(str _mailAddress, str 2 _separator4MultipleAddresses = ";") { // Prüft Mail-Adressen auf ihre Gültigkeit. // Es können auch mehrere Adressen auf einmal geprüft werden, dabei ist der Parameter _separator4MultipleAddresses zu verwenden boolean ret = true; int i = 0; str 1 buchstabe, firstZeichen = '', firstDomainZeichen; int firstAT = 0, firstDot = 0, lastDot = 0; str errorText = ''; int z, x, y; email SubMailAddr; container SubMailAddrContainer, c; container str2conLocal(str _value, str 10 _sep = ',') // str2con von AX30 ist fehlerhaft, wenn der ein Teilstring mit einer { // Zahl beginnt und als Separatir , verwendet wird int length = strlen(_value); int u = 1; int j = strscan(_value, _sep, 1, length); container retContainer; while (j) { retContainer+=(substr(_value, u, j-u)); u = j+1; j = strscan(_value, _sep, u, length); } retContainer+=(substr(_value, u, length-u+1)); return retContainer; } ; if(strLen(_MailAddress) == 0) { return true; } SubMailAddrContainer = str2conLocal(_MailAddress, _separator4MultipleAddresses); for(z=1;z<=ConLen(SubMailAddrContainer);z++){ SubMailAddr = ConPeek(SubMailAddrContainer,z); if(subMailAddr == '') { continue; } // Variablen initieren i=0; firstzeichen=''; firstDomainZeichen=''; lastdot=0; firstDot=0; firstAT=0; buchstabe=''; errorText = StrFmt('Die E-Mail-Adresse "%1" wurde falsch eingegeben', subMailAddr) + '. '; // ###### Start der Prüfung ########### lastDot = strFind(SubMailAddr, '.', strLen(SubMailAddr), -1 * strLen(SubMailAddr)); // @ muß zumindest einmal vorkommen firstAT = StrScan(SubMailAddr, '@', 1, strLen(SubMailAddr)); if(firstAT == 0) { return checkFailed(errorText + 'In der Mail-Adresse muß zumindest ein @-Zeichen vorkommen'); } // @ darf nur einmal vorkommen if(StrScan(SubMailAddr, '@', firstAT + 1, strLen(SubMailAddr)) != 0) { return checkFailed(errorText + 'Das @-Zeichen darf nur einmal vorkommen'); } // . muß zumindest einmal vorkommen firstDot = StrScan(SubMailAddr, '.', 1, strLen(SubMailAddr)); if(firstDot == 0) { return checkFailed(errorText + 'In der Mail-Adresse muß zumindest ein Punkt vorkommen'); } // nach dem @ muß zumindest 1 punkt kommen if(StrScan(SubMailAddr, '.', firstAT, strLen(SubMailAddr)) == 0) { return checkFailed(errorText + 'Nach dem @-Zeichen muss zumindest ein Punkt vorkommen'); } // nach dem letzten punkt darf nur 2 bis 4 zeichen kommen if(StrLen(SubStr(SubMailAddr,lastDot +1,strLen(SubMailAddr))) > 4 || StrLen(SubStr(SubMailAddr,lastDot +1,strLen(SubMailAddr))) < 2) { return checkFailed(errorText + 'Die Domän-Endung muss aus mindestens 2 und maximal 4 Zeichen bestehen'); } // Sub-Domänen müssen zumindest 2 Stellen gross sein und müssen mit A-Z oder 0-9 anfangen c = str2conLocal(SubStr(SubMailAddr, firstAT + 1, strLen(SubMailAddr)), "."); for (x=1; x<=conLen(c); x++) { firstDomainZeichen = SubStr(conPeek(c,x), 1,1); if( !( ( char2num(firstDomainZeichen,1) >= 97 && char2num(firstDomainZeichen,1) <= 122 ) || ( char2num(firstDomainZeichen,1) >= 48 && char2num(firstDomainZeichen,1) <= 57 ) || ( char2num(firstDomainZeichen,1) >= 65 && char2num(firstDomainZeichen,1) <= 90 ) ) ) { return checkFailed(errorText + 'Jede Subdomäne muss mit einem Buchstaben oder einer Zahl beginnen'); } if(strLen(conPeek(c,x)) < 2) { return checkFailed(errorText + 'Jede Subdomöne muss aus zumindest 2 Zeichen bestehen'); } // Subdomänen dürfen nur aus A-Z 0-9 oder - bestehen for(y=1;y<=strLen(conPeek(c,x));y++) { buchstabe = SubStr(conPeek(c,x),y,1); if( !(char2num(buchstabe,1) == 45 || // - ( char2num(buchstabe,1) >= 97 && char2num(buchstabe,1) <= 122 ) || ( char2num(buchstabe,1) >= 48 && char2num(buchstabe,1) <= 57 ) || ( char2num(buchstabe,1) >= 65 && char2num(buchstabe,1) <= 90 ) ) ) { return checkFailed(errorText + strFmt('In der Subdomäne "%1" ist das Zeichen "%2" nicht erlaubt!',conPeek(c,x),buchstabe)); } } } // Text vor dem @ (durch Punkte getrennt) muss mindestens 1 Stelle lang sein c = ConNull(); c = str2conLocal(SubStr(SubMailAddr, 1, firstAT-1), "."); for (x=1; x<=conLen(c); x++) { if(strLen(conPeek(c,x)) < 1) { return checkFailed(errorText + 'Der Text vor dem @-Zeichen ist ungültig'); } } // muß mit a-z oder A-Z oder 0-9 beginnen firstZeichen = SubStr(SubMailAddr, 1,1); if( !(( char2num(firstZeichen,1) >= 97 && char2num(firstZeichen,1) <= 122 ) || ( char2num(firstZeichen,1) >= 48 && char2num(firstZeichen,1) <= 57 ) || ( char2num(firstZeichen,1) >= 65 && char2num(firstZeichen,1) <= 90 )) ) { return checkFailed(errorText + 'Die Mailadresse muss mit einem Buchstaben oder einer Zahl beginnen'); } // Gültiges Zeichen i = 0; for(i=1;i<=StrLen(SubMailAddr);i++) { buchstabe = SubStr(SubMailAddr,i,1); if( !(char2num(buchstabe,1) == 46 || // . char2num(buchstabe,1) == 45 || // - char2num(buchstabe,1) == 95 || // _ char2num(buchstabe,1) == 64 || // @ char2num(buchstabe,1) == 228 || // ä char2num(buchstabe,1) == 252 || // ü char2num(buchstabe,1) == 246 || // ö char2num(buchstabe,1) == 196 || // Ä char2num(buchstabe,1) == 220 || // Ü char2num(buchstabe,1) == 214 || // Ö ( char2num(buchstabe,1) >= 97 && char2num(buchstabe,1) <= 122 ) || ( char2num(buchstabe,1) >= 48 && char2num(buchstabe,1) <= 57 ) || ( char2num(buchstabe,1) >= 65 && char2num(buchstabe,1) <= 90 ) ) ) { return checkFailed(errorText + strFmt('Ungültiges Zeichen "%1" in der Mail-Adresse', buchstabe)); } } } return true; } Obiger Code sollte in allen AX-Versionen funktionieren. Verwendung natürlich auf eigene Gefahr. |
Fehlerhafte str2con-Funktion
17.10.2007Microsoft Dynamics AX (Axapta)
Wer schon mal versucht hat in Dynamics AX 2.x einen String in einen Container umzuwandeln, der hat recht bald entdecken müssen, daß es - anders als in den meisten anderen Programmiersprachen - in X++ der Version 2.x keine entsprechende Funktion dafür gibt und man sich eine solche selbst schreiben muß. static container str2con(str _value, str 10 _sep = ',') { int length = strlen(_value); int i = 1; int j = strscan(_value, _sep, 1, length); container ret; void add2Ret(str _current) { // v-artemt, 26 Jul 2004, PS#: 1741 if (match('<:d+>', _current)) ret += str2int(_current); else ret += _current; } ; while (j) { add2Ret(substr(_value, i, j-i)); i = j+1; j = strscan(_value, _sep, i, length); } add2Ret(substr(_value, i, length-i+1)); return ret; } |
|
|
|
|
|
|
Eine der Neuerungen von AX 4.0, die jedem Benutzer sofort ins Auge fällt, ist das links angedockte, umgestaltete Hauptmenü. Bestandteil, dieses Menüs ist u.a. auch ein Bereich der sich "Eigene Favoriten" nennt. Hier kann sich jeder Benutzer per Drag&Drop seine meist verwendeten Menüpunkte hineinziehen.
Daß es diese Favoriten in einer ähnlichen Form aber bereits in AX 3.0 gab, ist nur wenigen bekannt. Und zwar kann sich jeder Benutzer über Datei - Neu - Benutzermenü ein eigenes Menü zusammenstellen. In diesem Menü kann er nach Belieben Registerkarten erstellen, löschen und umbenennen und ebenfalls per Drag&Drop sich all jene Menüpunkte aus dem "normalen" Hauptmenü an jene Stelle seines eigenen Menüs ziehen, wo es ihm am sinnvollsten erscheint.
Dieses Menü kann anschließend jederzeit über Datei - Öffnen - Menü - "Menüname" geöffnet werden. Wer darauf Zugriff hat, verlinkt sich idealerweise sein eigenes Menü in den Benutzereinstellungen unter Werkzeuge - Optionen im Feld Startmenü. Dann öffnet sich AX in Zukunft standardmässig mit dem selbst kreierten Menü, das bisherige Hauptmenü beibt ja sowieso jederzeit über die Toolbar erreichbar.
Tip: Wer das Menü der Version 4.0 so genau als möglich kopieren möchte, braucht ja nur den ersten Register "Meine Favoriten" taufen und sich alle anderen Menüpunkte vom Hauptmenü in sein eigenes ziehen (Registerkarten können leider nicht per Drag&Drop kopiert werden, diese muß man vorher ggf. selbst erstellen).
Benutzermenü erstellen
Namen für das neue Menü vergeben
Registerkarten bearbeiten