Un petit bricolage avec l'API Google Maps/DotNet/XML qui permet de récupérer la distance entre 2 villes saisies en paramètres: à tester/adapter/détourner/améliorer
static void OBRFindKm(Args _args)
{
dialog d;
dialogField Depart,Arrivee;
Name VilleDepart,VilleArrivee;
Str url,xml;
System.Net.WebClient webClient = new System.Net.WebClient();
XMlDocument doc;
XMLNodeList Distance;
XMLNode node;
real totaldistance;
AddressZipCode AddressDepart,AddressArrivee;
AddressMap AddressMap;
;
d = new dialog();
Depart = d.addField(typeId(Name));
Depart.label("Départ");
Arrivee = d.addField(typeId(Name));
Arrivee.label("@SYS14181");
d.run();
VilleDepart = Depart.value();
VilleArrivee = Arrivee.value();
if(VilleDepart != "" && VilleArrivee != "")
{
url = "http://maps.google.com/maps/api/directions/xml?language=fr&origin="+VilleDepart+"&destination="+VilleArrivee+"&sensor=false";
xml = webClient.DownloadString(url);
doc = XMLDocument::newXml(xml);
Distance = doc.selectNodes('//distance');
node = Distance.nextNode();
if(d.closedOk())
{
while(node)
{
totalDistance = any2real(node.selectSingleNode('value').text());
node = Distance.nextNode();
}
box::info((strfmt("%1 %2 %3","Distance totale:",totalDistance/1000,"km")));
}
else
{
box::info("@SYS93289");
}
}
else
{
box::info("le point de départ et/ou le point d'arrivé sont mal renseignés");
}
}
Dynamics AX pour les nuls
Des trucs et des astuces pour les utilisateurs et développeurs Dynamics AX
vendredi 15 mars 2013
Bloquer le critère de filtre d'un formulaire
Scénario:
On a ajouté le code suivant sur la méthode executeQuery() du datasource du formulaire pour n'afficher que les articles dont le nom contient "Porte*"
this.query().dataSourceNo(1).addRange(fieldnum(InventTable, ItemId)).value('Porte*');
A l'ouverture, tout est OK sauf que si ensuite on resaisit un filtre dans les colonnes, le filtre initial disparaît. Dans ce cas de figure, pour maintenir le filtre initial, il faut ajouter le code suivant :
this.query().dataSourceNo(1).addRange(fieldnum(InventTable,ItemId)).status(rangeStatus::Locked);
On a ajouté le code suivant sur la méthode executeQuery() du datasource du formulaire pour n'afficher que les articles dont le nom contient "Porte*"
this.query().dataSourceNo(1).addRange(fieldnum(InventTable, ItemId)).value('Porte*');
A l'ouverture, tout est OK sauf que si ensuite on resaisit un filtre dans les colonnes, le filtre initial disparaît. Dans ce cas de figure, pour maintenir le filtre initial, il faut ajouter le code suivant :
this.query().dataSourceNo(1).addRange(fieldnum(InventTable,ItemId)).status(rangeStatus::Locked);
Aller à la table principale à partir du contenu d'un champ et pas du type
Pour avoir "Aller à la table principale" sur un champ sans extended Data type ou alimenté par une méthode,
il suffit d'ajouter une méthode jumpref() sur le champ en question:
public void jumpRef()
{
Args args;
MenuFunction menuFunction;
SalesTable SalesTable;
;
args = new Args();
menuFunction = new MenuFunction(menuitemDisplayStr(SalesTable), MenuItemType::Display);
args = new Args(menuFunction.object());
args.caller(element);
select SalesTable where SalesTable.SalesId == NumCommandeEnCours.text();
args.record(SalesTable);
menuFunction.run(args);
}
Explication:
on va se servir des classes Args, menuFunction et d'un buffer de la table Salestable. On récupère l'argument du No de commande affiché dans le champ NumCommandeEnCours avec la méthode text(), on la passe dans un select pour récupérer le buffer de salesTable pour la commande en cours et on lance une instance de la classe menuFunction qui va ouvrir le formulaire SalesTable filtré sur le No de commande qui nous intéresse
il suffit d'ajouter une méthode jumpref() sur le champ en question:
public void jumpRef()
{
Args args;
MenuFunction menuFunction;
SalesTable SalesTable;
;
args = new Args();
menuFunction = new MenuFunction(menuitemDisplayStr(SalesTable), MenuItemType::Display);
args = new Args(menuFunction.object());
args.caller(element);
select SalesTable where SalesTable.SalesId == NumCommandeEnCours.text();
args.record(SalesTable);
menuFunction.run(args);
}
Explication:
on va se servir des classes Args, menuFunction et d'un buffer de la table Salestable. On récupère l'argument du No de commande affiché dans le champ NumCommandeEnCours avec la méthode text(), on la passe dans un select pour récupérer le buffer de salesTable pour la commande en cours et on lance une instance de la classe menuFunction qui va ouvrir le formulaire SalesTable filtré sur le No de commande qui nous intéresse
vendredi 21 décembre 2012
mardi 18 décembre 2012
Bonjour à tous
Je me lance aujourd'hui dans un blog sur Dynamics AX, j'ai trouvé que ce serait bien de partager mes connaissances d'utilisateur et développeur sur cet ERP.
Générer un fichier Excel en X++
Voici le code pour générer un fichier Excel avec du code X++:
public void ExportXLS()
{
SysExcelApplication xlsApplication;
SysExcelWorkBooks xlsWorkBookCollection;
SysExcelWorkBook xlsWorkBook;
SysExcelWorkSheets xlsWorkSheetCollection;
SysExcelWorkSheet xlsWorkSheet;
SysExcelRange xlsRange;
CustTable CustTable;
int row = 1;
str fileName;
FileIOPermission perm;
;
fileName = "\\\\nomServeur\\dossier\\nomFichierExcel.xls";
xlsApplication = SysExcelApplication::construct();
xlsWorkBookCollection = xlsApplication.workbooks();
xlsWorkBook = xlsWorkBookCollection.add();
xlsWorkSheetCollection = xlsWorkBook.worksheets();
xlsWorkSheet = xlsWorkSheetCollection.itemFromNum(1);
//Ajoute des entêtes de colonne
xlsWorkSheet.cells().item(row,1).value("Numéro de client");
xlsWorkSheet.cells().item(row,2).value("Nom");
row++;
//Ajoute les lignes avec le no et le nom du client
while select custTable
{
xlsWorkSheet.cells().item(row,1).value(custTable.custAccount);
xlsWorkSheet.cells().item(row,2).value(custTable.name);
}
//Si le fichier existe on le supprime
if(WinApi::fileExists(fileName))
WinApi::deleteFile(fileName);
//On enregistre le fichier sous le nom contenu dans la variable filename
xlsWorkbook.saveAs(fileName);
//Fermeture de l'application (plus d'excel.exe dans le gestionnaire de tâches windows
xlsApplication.quit();
xlsApplication.finalize();
xlsApplication = null;
}
perm = new FileIOPermission(filename,'rw');
perm.assert();
à insérer après la boucle while et
CodeAccessPermission::revertAssert();
avant xlsApplication.quit();
mais ça n'a pas l'air de marcher mieux (en tout cas dans mon environnement AX 2009 sans SP1)
Si on veut ouvrir le fichier: remplacer les dernières lignes par le code suivant:
xlsApplication.visible(true);
public void ExportXLS()
{
SysExcelApplication xlsApplication;
SysExcelWorkBooks xlsWorkBookCollection;
SysExcelWorkBook xlsWorkBook;
SysExcelWorkSheets xlsWorkSheetCollection;
SysExcelWorkSheet xlsWorkSheet;
SysExcelRange xlsRange;
CustTable CustTable;
int row = 1;
str fileName;
FileIOPermission perm;
;
fileName = "\\\\nomServeur\\dossier\\nomFichierExcel.xls";
xlsApplication = SysExcelApplication::construct();
xlsWorkBookCollection = xlsApplication.workbooks();
xlsWorkBook = xlsWorkBookCollection.add();
xlsWorkSheetCollection = xlsWorkBook.worksheets();
xlsWorkSheet = xlsWorkSheetCollection.itemFromNum(1);
//Ajoute des entêtes de colonne
xlsWorkSheet.cells().item(row,1).value("Numéro de client");
xlsWorkSheet.cells().item(row,2).value("Nom");
row++;
//Ajoute les lignes avec le no et le nom du client
while select custTable
{
xlsWorkSheet.cells().item(row,1).value(custTable.custAccount);
xlsWorkSheet.cells().item(row,2).value(custTable.name);
}
//Si le fichier existe on le supprime
if(WinApi::fileExists(fileName))
WinApi::deleteFile(fileName);
//On enregistre le fichier sous le nom contenu dans la variable filename
xlsWorkbook.saveAs(fileName);
//Fermeture de l'application (plus d'excel.exe dans le gestionnaire de tâches windows
xlsApplication.quit();
xlsApplication.finalize();
xlsApplication = null;
}
NB: ce code ne semble pas fonctionner dans le cadre d'un traitement par lot, la classe WinAPI pose problème car elle n'est pas supportée dans le cadre d'un traitement de type serveur, j'ai vu dans des forums qu'il fallait plutôt utiliser la classe winAPIServer et gérer des permissions avec le code suivant:
perm = new FileIOPermission(filename,'rw');
perm.assert();
à insérer après la boucle while et
CodeAccessPermission::revertAssert();
avant xlsApplication.quit();
mais ça n'a pas l'air de marcher mieux (en tout cas dans mon environnement AX 2009 sans SP1)
Si on veut ouvrir le fichier: remplacer les dernières lignes par le code suivant:
xlsApplication.visible(true);
Inscription à :
Articles (Atom)