FELIZ ANO NOVO!
Olá pessoal,
Desejo a todos um próspero ANO NOVO, muita saúde, dinheiro!!
E vamos todos juntos nesse ano aprender mais e mais sobre o gigantesco mundo que é o AX!!
E QUE VENHAM OS DESAFIOS!
[]‘s,
Peterson Ferreira
Olá pessoal,
Desejo a todos um próspero ANO NOVO, muita saúde, dinheiro!!
E vamos todos juntos nesse ano aprender mais e mais sobre o gigantesco mundo que é o AX!!
E QUE VENHAM OS DESAFIOS!
[]‘s,
Peterson Ferreira
Boa tarde pessoal,
Estava navegando nos blogs sobre AX espalhados pela internet, e achei uma solução muito interessante e resolvi colocar aqui pra vocês.
Sabe aquelas classes que são feitas para ficar rodadando todas as noites para corrigir ou atualizar algo, e quando você chega no outro dia a classe deu erro e você não sabe porque?
Você pode utilizar este job para colocar em sua classe escrever o erro ou algum aviso no event viewer do windows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | //Inicio <DynamicsAxBR> static void eventViwerLog(Args _args) { System.Diagnostics.EventLog eventLog; LogText nameLog = "Dynamics AX Brasil"; LogText sourceLog = "Log de Teste"; ; if(!System.Diagnostics.EventLog::SourceExists(sourceLog)) { System.Diagnostics.EventLog::CreateEventSource(sourceLog, nameLog); } eventlog = new System.Diagnostics.EventLog(); eventlog.set_Source(sourceLog); //Colocando uma mensagem no log eventlog.WriteEntry("Testando log no event viewer!"); //Colocando mensagem de error no log eventlog.WriteEntry("Erro! Teste de error. \n\n" + con2str(xSession::xppCallStack()), System.Diagnostics.EventLogEntryType::Error); //Colocando aviso no log eventlog.WriteEntry("Fim de teste" , System.Diagnostics.EventLogEntryType::Warning); info("Olhe no seu event viewer!"); } //Fim <DynamicsAxBR> |
É isso pessoal, se restou alguma dúvida sobre a utilidade deste job ou algo técnico, COMENTEM…
Abraços, e até a próxima!
Referência: http://www.artofcreation.be
Boa noite pessoal…
Depois de quase duas semanas sem postar, hoje vou colocar no post um assunto bem interessante sobre Reflections, que rolou enquanto eu e meus amigos de trampo estavamos tendo treinamento de Ax em julho desse ano.
A cada noite de treinamento tínhamos um desafio, e o desafio dessa noite era: Como listar todos os objetos de um projeto utilizando reflection ? Chegamos muito perto mas não conseguimos, assim o instrutor que no dia era o Leonardo Monteiro nos mandou o .xpo da resolução, que por sinal muito inteligente.
Ai essa semana perguntei para ele se eu poderia colocar o projeto no blog pro pessoal estudar, e ele liberou…
Então todos os créditos ao Leonardo Monteiro.
let`s go !
Nesse job foi utilizada um função recursiva, para caso os objetos estejam separados pro grupos, assim como manda as boas práticas de desenvolvimento do AX.
Foi utilizado também alguns recursos de reflection do AX, exemplo: TreeNodeIterator…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | //Inicio <DynamicsAxBR> static void listAllObjectosFromProject(Args _args) { //Pega o nome do Projeto ProjName projName = "ListProjectNode_MSBS"; //Aonde está seu projeto? Shared ou Private... ProjectListNode list = infolog.projectRootNode().AOTfindChild("Shared"); //Instância um TreeNodeIterator para percorrer os projetos TreeNodeIterator ir = list.AOTiterator(); ProjectNode pnProj; ProjectNode pn = list.AOTfindChild(projName); void searchAllObj(projectNode rootNode) { #TreeNodeSysNodeType TreeNode childNode; TreeNodeIterator rootNodeIterator; ; if (rootNode) { rootNodeIterator = rootNode.AOTiterator(); childNode = rootNodeIterator.next(); while (childnode) { // Verifica se o elemento possui filhos, se tiver chama novamento o método if (childNode.AOTgetNodeType() == #NT_PROJECT_GROUP) searchAllObj(childNode); // Senão mostra nome do elemento else info(strfmt("Grupo:%1 - Objeto: %2", rootNode.AOTname(), childNode.AOTname())); childNode = rootNodeIterator.next(); } } } ; if (pn) { info(strFmt("Projeto %1:", projName)); pnProj = pn.loadForInspection(); searchAllObj(pnProj); pnproj.treeNodeRelease(); } else info("Projeto não encontrado"); } //Fim <DynamicsAxBR> |
Para realizar o teste eu seu ambiente de desenvolvimento basta copiar o código mudar o nome do projeto e onde ele está na árvore de projetos (Private ou Shared).
Era isto pessoal, bem simples e muito interessante, queria agradecer a Léo mais uma vez !!!
Espero que tenham gostado, qualquer dúvida COMENTEM…E até a próxima !
Fala pessoal…
Continuando o útlimo post (Importação e Exportação utilizando a classe CommaIO (Parte 1)) , irei postar hoje como importar um arquivo utilizando a classe CommaIO.
Vamos lá…
O arquivo que vocês exportaram utilizando as dicas do último post, com o código abaixo vocês irão importar esse arquivo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | //Inicio <DynamicsAxBR> static void commaIoRead(Args _args) { #File Dialog dialog = new Dialog("Importar"); DialogField dialogFieldCaminho; CommaIo commaIo; FileIoPermission fileIoPermission; Container filtro = ["txt", #AllFilesName+#txt], readCon; TimesFutebol timesFutebol; //Table Buffer ; dialog.filenameLookupFilter(filtro); dialogFieldCaminho = dialog.addField(TypeId(FileNameOpen), "Selecione o arquivo"); if(dialog.run()) { fileIoPermission = new fileIoPermission(dialogFieldCaminho.value(), #io_read); fileIoPermission.assert(); commaIo = new CommaIo(dialogFieldCaminho.value(), #io_read); commaIo.inFieldDelimiter(";"); if(commaIo) { try { while(commaIo.status() == IO_Status::Ok) { readCon = commaIo.read(); if(conlen(readCon) > 0) { ttsbegin; timesFutebol.IdTime = conpeek(readCon, 1); timesFutebol.NomeTime = conpeek(readCon,2); timesFutebol.insert(); ttscommit; } } info("Arquivo importado com sucesso!"); } catch(Exception::Error) { throw error("Erro ao importar o arquivo!"); } } } } //Fim <DynamicsAxBR> |
Bom galera era isso, se restou alguma dúvida que eu não expliquei, por favor comentem que irei tentar responder para vocês.
Abraço e até a próximaaa !
Fala pessoal…
Hoje e amanhã irei falar de uma classe muito interessante que o AX nos oferece, a classe “CommaIO”, com ela é possível que você escreva em arquivos que estão fora do AX, por exemplo arquivos do word, txt entre outros.
Hoje irei colocar um exemplo de exportação utilizando a classe “CommaIO”, e amanhã irei colocar o exemplo de importação continuando o exemplo, vamos lá…
Primeiramente eu criei uma tabela com 2 campos, e populei essa tabela veja:
Tabela de exemplo CommaIO

Agora vamos criar o job que exporta os dados da tabela para um arquivo “.txt”, separando os arquivos com “;”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | //Inicio <DynamicsAxBR> static void commaIoWrite(Args _args) { #File Dialog dialog = new Dialog("Exportar"); DialogField dialogFieldCaminho; CommaIo commaIo; FileIoPermission fileIoPermission; Container filtro = ["txt", #AllFilesName+#txt], readCon; TimesFutebol timesFutebol; //Table Buffer ; dialog.filenameLookupFileName('arquivo'); dialog.filenameLookupFilter(filtro); dialogFieldCaminho = dialog.addField(TypeId(FileNameSave), "Salvar como"); if(dialog.run()) { fileIoPermission = new fileIoPermission(dialogFieldCaminho.value(), #io_write); fileIoPermission.assert(); commaIo = new CommaIo(dialogFieldCaminho.value(), #io_write); commaIo.outFieldDelimiter(';'); if(commaIo) { try { while select timesFutebol { readCon = [timesFutebol.IdTime, timesFutebol.NomeTime]; commaIo.writeExp(readCon); } info("Arquivo criado com sucesso!"); } catch(Exception::Error) { throw error("Erro ao exportar o arquivo!"); } } } } //Fim <DynamicsAxBR> |
Nesse job você seleciona o local do arquivo para onde ele será exportado, qualquer dúvida comentem !!
PS: Amanhã, irei colocar o exemplo de importação…AGUARDEM!!
Abraços.
Fala pessoal…
Uma função muito legal do Ax é a “Number Sequence Framework”, que atribui automaticamente um ID a um registro automaticamente, sempre que criado. Mas para utilizar é preciso que você configure antes.
Vamos lá…
A number sequence é atribuída de acordo com o módulo do AX com que você está trabalhando. Depois de identificar o módulo é possível você escolher a classe que irá implementar a sua number sequence.
A classe responsável por implementar automaticamente a number sequence é a NumberSeqReference. Mas como falei, cada módulo possui a sua classe, no meu caso irei usar a classe NumberSeqReference_Customer, que referência ao Cliente.
IMPORTANTE: Cada number sequence é atrubuída a um EDT do tipo string, portanto o campo que você quer que sua number sequence seja atribuída deverá estar utilizando este EDT.
Abra a classe e o método loadModule() que é de onde o AX busca a number sequence. Lá estarão várias referências ja criadas, você irá apenas adicionar a sua.
Copie o código abaixo fazendo as alterações necessárias:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //Inicio <DynamicsAxBR> protected void loadModule() { //EDT do seu campo numRef.dataTypeId = typeId2ExtendedTypeId(typeid(DynamicsAxBr_Cliente)); numRef.referenceHelp = literalStr("Cliente DynamicsAxBr"); numRef.wizardContinuous = false; numRef.wizardManual = NoYes::No; numRef.wizardAllowChangeDown = NoYes::No; numRef.wizardAllowChangeUp = NoYes::No; numRef.wizardHighest = 999999; //Veja o código acima, e adicione o próximo número numRef.sortField = 1; this.create(numRef); } //Fim <DynamicsAxBR> |
Feito isso, vá ao menu Básico> Configuração> Sequências Numéricas> Sequências Numéricas
Irá abrir um formulário com todas as number sequences ja registradas no AX, para incluir a sua clique no botão “Assistente” e siga as instruções.
Está quase pronto, sua number sequence ja foi registrada no AX. Agora você só precisar configurá-la para atribuir automaticamente em sua tabela, mas esta parte é fácil (não que o resto não tenha sido).
Va na sua tabela, e subtitua o método initValue(), e coloque o código abaixo:
1 2 3 4 5 6 7 8 9 10 | //Inicio <DynamicsAxBR> public void initValue() { super(); if(NumberSequenceReference::find(typeId2ExtendedTypeId(typeid(DynamicsAxBr_Cliente))).NumberSequence) { this.SeuCampo = NumberSeq::newGetNum(NumberSequenceReference::find(typeId2ExtendedTypeId(typeid(DynamicsAxBr_Cliente)))).num(); } } //Fim <DynamicsAxBR> |
Pronto, após ter feito isso toda vez que um novo registro for criado em sua tabela um novo ID será atribuido automaticamenteirá.
Bom pessoal é isso, qualquer dúvida só comentar!!!
Abraços…
Fala galera…
Essa noite eu estava fuçando a internet, em um dos blogs que falam sobre as novidades do Dynamics AX, e encontrei uma característica muito interessante e atraente principalmente para os desenvolvedores que estão vindo do .NET para o AX.
É o famoso LINQ, que permite você busque dados de fontes diferentes como: DB, XML.
É possível pegar uma versão TRIAL no site da empresa que desenvolveu, LINK
Para utilizar o LINQ será necessário que o .NET Business Conector esteja configurado e no projeto, seja incluída a DLL no cabeçalho.
Abaixo um exemplo da utilização do LINQ para Dynamics AX:
Tenho certeza que para os desenvolvedores .NET essa é uma ótima notícia, pois ja estão acostumados com a linguagem, ja para o nativos do X++ pode não ser tão atrativo mas aconselho darem a uma olhada.
Abraços e até a próxima.
Referência: http://www.littlebeacon.com/Products/DYNAMICS%20MODULES/LINQ%20DYNAMICS%20AX.aspx
Fala galera…vamos a mais um post, hoje vamos falar de um método de substituição chamado jumpRef();
Ele é simplesmente aquela função tão útil que temos em um campo…”Ir para o formulário da tabela principal”.
Essa semana no trampo precisei colocar esse tal “Ir para o formulário da tabela principal” em um campo que não tinha essa funcionalidade. Como eu e um colega do trampo demoramos um pouco para achar, resolvi postar aqui pois pode ser bem útil. Vamos lá…
O exemplo será bem simples, irei implementar esse método e ele irá chamar um formulário, criando um “Ir para o formulário da tabela principal” no campo.
1 2 3 4 5 6 7 8 9 10 | //Inicio <DynamicsAxBR> public void jumpRef() { MenuFunction menu = new MenuFunction(menuItemDisplayStr(CustTable), MenuItemType::Display); ; //super(); menu.run(); } //Fim <DynamicsAxBR> |
No exemplo acima, este método chamará no seu campo o formulário “CustTable”.
Caso você queira retirar o “Ir para o formulário da tabela principal” de seu campo basta comentar o super(); como no exemplo abaixo.
1 2 3 4 5 6 7 | //Inicio <DynamicsAxBR> public void jumpRef() { ; //super(); } //Fim <DynamicsAxBR> |
Bom galera essa foi uma dúvida que surgiu e espero que eu possa ter ajudado.
falou, e até a próxima…
Fala galera do Dynamics…
Começa neste dia 14, o AX Decision 2009. Muitos de vocês devem estar se perguntando oque é? Vamos lá…
AX Decisions 2009
AX Decisions 2009 é uma conferência virtual para profissionais Microsoft Dynamics AX buscando estratégias de implementação, o pensamento liderança, e as melhores práticas para maximizar o valor e a eficácia da plataforma de sua organização.
Oque será abordado na edição 2009
Confira melhor a programação : http://axdecisions.com/program
Palestrantes
Além dos temas muito interessantes teremos ótimos palestrantes…
Ainda da tempo para você fazer a sua incrição…
Link: http://axdecisions.com
Até a próxima…Abraços
Fala galera…
Um brother que trampa comigo postou um material muito bom sobre Enterprise Portal.
Vem dando uma visão geral sobre oque é Enterprise Portal, falando também um pouco sobre a arquitetura, segurança, acesso de usuário do EP.
What is Enterprise Portal ? (Parte1)
What is Enterprise Portal ? (Parte2)
Espero que gostem! COMENTEM!