Create Outlook Appointment or Meeting Request using X++


If you need to create an appointment or meeting request
in Outlook using X++, just borrow the code below. Outlook client needs to be installed on the
machine where the code is run.

Here is the job.

static void OutlookAppointment(Args _args)

{

   
COM        sysOutlookCollection;

   
COM        collection;

   
COMVariant comStartDate = new COMVariant();

   
COMVariant comEndDate   = new
COMVariant();

   
COM        c;

   
#SysOutLookCOMDEF

   
#define.mapi("MAPI")

   
#define.outlook("Outlook.Application")

   
COM        sysOutlook;

   
COM        sysOutlookNameSpace;

   
COM        sysOutlookMAPIFolder;

    ;

   
sysOutlook                  = new
COM(#outlook);

   
sysOutlookNameSpace         = sysOutlook.getNamespace(#mapi);

   
sysOutlookNameSpace.logon();

   
sysOutlookMAPIFolder        =
sysOutlookNameSpace.getDefaultFolder(#OlDefaultFolders_olFolderCalendar);

   
collection                  =
sysOutlookMAPIFolder.items();

    c =
collection.add();

   
comStartDate.date(today());

   
comStartDate.time(str2Time( "12:00:00"));

   
comEndDate.date(today());

   
comEndDate.time(str2Time( "12:45:00"));

   
c.location(‘Solugenix 4th Floor Conference Room, India’);

   
c.subject(‘Meeting regd Microsoft Dynamics AX 2009’);

   
c.body(‘Lets discuss on whats new in DAX 2009’);

   
c.start(comStartDate);

   
c.end(comEndDate);

   
c.save();

    if (c)

    {

       
c.display();

       
info("The action is created in Microsoft Outlook");

    }

    else

       
throw error("@SYS31969");

       
sysOutlookNameSpace.logoff();

}

Advertisements

Problem when creating a dynamic form with ActiveX control & Solution :)

The Requirement was to connect to the web
and get the content of the web page and display it on

the form .Well, I did not want to create a
form in AOT to display the HTML content .So , I thought of dynamically creating
a form and adding the browser ActiveX Control using X++ code.

Here is the code which I pasted in the job.

 static void ActiveX_DynamicForm(Args _args)

{

    COMDispFunction         webpreviewWrite;

    COMVariant                  text = new COMVariant();

   
COM                              ctrl = new COM();

   
Form                               formBrowse;

   
FormActivexControl    activex;

   
FormRun                       formRun;

   
Args                              args;

   
int                                  handle;

   
WinInet                        wi =
new WinInet();

   
str                                  htmlContent;

    ;

    handle
= wi.internetOpenUrl(‘http://www.yahoo.com’);

    if
(handle)

    {

       
htmlContent = wi.internetReadFile(handle);

    }

 

    wi.internetCloseHandle(handle);

   
formBrowse = new Form(‘ActiveX AX Form’, true);

   
formBrowse.design().width(500);

   
formBrowse.design().height(500);

   
formBrowse.design().addControl(FormControlType::ActiveX, ‘Browser’);

    args =
new Args(formBrowse.name());

    args.name(formBrowse.name());

   
args.object(formBrowse);

   
formRun = classFactory.formRunClass(args);

   
formRun.init();

   
activex = formRun.design().controlName(‘Browser’);

   
activex.className(‘{8856F961-340A-11D0-A96B-00C04FD705A2}’);

    activex.height(1,1);

   
activex.width(1,1);

   
formRun.run();

   
ctrl.attach(activex.interface());

   
webpreviewWrite = new COMDispFunction(ctrl, ‘write’,
COMDispContext::Method);

   
text.bStr(htmlContent);

   
activex.open("");

   
webpreviewWrite.call(text);

    formRun.detach();

}

I was successful in creating the form but
strangely AX threw me an error when I ran the code. It was not supporting ‘write’ method for automatic interface
of COM object of class “IWEBBrowser2’

I did not want to create a separate form adding
an ActiveX control to achieve this.

I looked for alternatives and found one interesting
class which served my purpose.

Class Name: KMKnowledgeFunctionShow

Method : static Object show(TextBuffer   
htmlText,     Object        _formRun = null)

The show method will open the standard “KMKnowledgeAnalogMeter”
form which has an ActiveX Control added to it.

I got the content of the webpage and added it
to the TextBuffer by using settext() method and passed the TextBuffer to the
show method. I did not pass the second parameter formrun.

The idea behind this is to open the existing
Standard form which has already Browser ActiveX in it.

Here is the code

 static void ActiveX_Alternate(Args _args)

{

   
str         htmlContent;

   
TextBuffer  txtBuffer;

   
int         handle;

   
WinInet     wi = new WinInet();

    ;

    handle
= wi.internetOpenUrl(‘http://www.yahoo.com/’);

    if
(handle)

    {

        
htmlContent = wi.internetReadFile(handle);

    }

   
txtBuffer = new TextBuffer();

   
txtBuffer.setText(htmlContent);

   
KMKnowledgeFunctionShow::show(txtBuffer);

}

 Drawback: The form caption stills remains the KMKnowledgeAnalogMeter “form caption

 Attached is the error and the output of the second job

Stock Market Anlaysis(DOW JONES) using X++

As a commodities trader, I’ve never lost my fascination for the markets. This job will download
historical trading data from Yahoo Finance for any valid specified date range
and issue symbol, including indexes such as the Dow Industrials Average (that’s
"^DJI" with Yahoo).

 URL
Used :

http://finance.yahoo.com/q/hp?s=IBM&a=00&b=2&c=2004&d=04&e=8&f=2005&g=d&z=66&y=66

   * s – ticker symbol( MSFT – Microsoft,
IBM etc)
   * a – start month
   * b – start day
   * c – start year
   * d – end month
   * e – end day
   * f – end year
   * g – resolution (e.g. ‘d’ is daily,
‘w’ is weekly, ‘m’ is monthly)
   * y is the offset (cursor) from the
start date
   * z is the number of results to return
starting at the cursor (66
     maximum, apparently)

 Here is the Job:

 static void StockMarket_Analysis(Args _args)

{

   
System.Net.WebClient web = new System.Net.WebClient();

   
TextBuffer           txtBuffer =
new TextBuffer();

   
str                        result;

   
container           
recordContainer, fieldContainer;

   
str                  stockContent;

    int                  i;

   
FileName       nameOfTheFile;

   
str                  tmpContent;

    str
urlQuery         =
@"http://ichart.finance.yahoo.com/table.csv?s=MSFT&a=00&b=2&c=2007&d=04&e=8&f=2008&g=d&ignore=.csv";

   
CCHTMLString         htmlString;

   
CCHTMLString formHTML(Container hmtlContainer, int tmp = 0)

    {

       
CCHTMLString html;

       
int h;

       
str start_td_th;

       
str end_td_th;

       
str value;

        ;

        if
(tmp == 1)

        {

           
start_td_th = @"<th align = ‘center’>";

           
end_td_th = @'</th>’;

        }

       
else

        {

           
start_td_th = @"<td align = ‘center’>";

           
end_td_th = @'</td>’;

        }

       
html += ‘<tr>’;

       
for (h = 1; h <= conlen(hmtlContainer); h++)

        {

           
if (h == 6 && isInteger(conpeek(hmtlContainer, h)))

               
value = 
int2str(conpeek(hmtlContainer, h));

           
else

               
value =  conpeek(hmtlContainer,
h);

           
html += start_td_th + value + end_td_th;

         }

       
html += ‘</tr>’;

       
return html;

    }

    ;

    result
= web.DownloadString(urlQuery);

    result
= strreplace(result,"\r", "");

   
recordContainer = str2con(result,’\n’);

   
htmlString += @'<html><body><Marquee><b>Stock
Market Alert … <IMG
SRC="http://www.wharton-pec.org/conf2006/images/DowJones_Logo.jpg&quot;
HEIGHT=40 WIDTH=82

                   
</b></Marquee><CENTER><table border="1"
CELLSPACING="5" CELLPADDING="5" BGCOLOR="lightblue"
WIDTH="80%>’;

     for (i
= 1; i <= conlen(recordContainer); i++)

    {

       
tmpContent = conpeek(recordContainer, i);

       
fieldContainer = str2con(tmpContent,’,’);

        if
(i == 1)

           
stockContent += formHtml(fieldContainer, 1);

       
else

           
stockContent += formHtml(fieldContainer);

    }

   
htmlString += stockContent +
‘</table></CENTER></body></html>’;

   
txtBuffer.setText(htmlString);

   
nameOfTheFile = winApi::getTempPath() + ‘StockMarket.html’;

    txtBuffer.toFile(nameOfTheFile);

   
infolog.urlLookup(nameOfTheFile);

}

The screen shot of the output is attached below.

Weather forecasting using X++

In todays competitive business world, there are many factors which determine the profit or loss.

Climatic conditions has its own impact and is becoming increasingly important for the corporates.

Like Demand forecast, weather forecast can be very helpful in business planning.

This Job is an attempt to predict the weather conditions in advance and organize things in such a way which will help the companies not
only to optimize their resources but also maximize their profits.

In the example, I used Yahoo released rss weather feeds: http://weather.yahoo.com/rss and XML programming to get the climatic conditions

The format of the URL for the feed is:

http://xml.weather.yahoo.com/forecastrss?p=USNY0996&u=f

p is a US zip or a Yahoo! Weather location ID
u is the temp. units. ‘F’ for Fahrenheit (default) and ‘C’ for celcius

static void weatherForecast(Args _args)

{

   
XmlDocument         doc = new
XmlDocument();

   
XmlNamespaceManager ns;

   
XmlNodeList         nodes;

   
XmlNode                node;

  
//AddressZipCode     
addresszipCode;

   
container day(str _day)

    {

        ;

       
switch(_day)

        {

           
case ‘Mon’ : return [1,’Monday’];

           
case ‘Tue’ : return [2,’Tuesday’];

           
case ‘Wed’ : return [3,’Wednesday’];

           
case ‘Thu’ : return [4,’Thursday’];

           
case ‘Fri’ : return [5,’Friday’];

           
case ‘Sat’ : return [6,’Saturday’];

           
case ‘Sun’ : return [7,’Sunday’];

            
Default : return connull();

        }

    }

     ;

    //addresszipCode = _args.record();

   
doc.Load("http://xml.weather.yahoo.com/forecastrss?p=
UKXX0085&u=c"
);// +
addresszipCode.ZipCode +’&u=c’);

    // Set
up namespace manager for XPath

    ns =
new XmlNamespaceManager(doc.nameTable());

   
ns.AddNamespace("yweather", "http://xml.weather.yahoo.com/ns/rss/1.0&quot;);

    // Get
forecast with XPath

    nodes
= doc.SelectNodes("//rss/channel/item/yweather:forecast", ns);

    node =
nodes.nextNode();

   
setprefix("Weather forecast");

     while
(node)

    {

       
info("—————————————————–");

       
info(conpeek(day(node.attributes().getNamedItem("day").InnerText()),2));

       
info("—————————————————–");

       
info( node.attributes().getNamedItem("text").InnerText());

       
info(‘Min :’    +
node.attributes().getNamedItem("low").InnerText());

       
info(‘Max :’    +
node.attributes().getNamedItem("high").InnerText());

       
if(dayofwk(today()) ==
conpeek(day(node.attributes().getNamedItem("day").InnerText()),1))

        {

           
info(‘Current :’ +
node.attributes().getNamedItem("code").InnerText());

        }

       
else

        {

            
info(‘Current : NA’);

        }

       
node = nodes.nextNode();

    }

}

Note:

1) An essential pre-requisite for the code to work is the URL should not be blocked by the firewall.

2)We can directly use this job as an menuitemaction button by adding the job in menuitems under actions, Then add the button in the AddressZipcode form , for that make use of the commented code of AddressZipcode in the above Job.

Here are some example location IDs (do not include the city name) or use the existing Zipcodes of AX

  • Beijing: CHXX0008
  • Helsinki: FIXX0002
  • London: UKXX0085
  • Moscow: RSXX0063
  • Munich: GMXX0087
  • Paris: FRXX0076
  • Riyadh: SAXX0017
  • Tokyo: JAXX0085

For more details on the Yahoo! Weather RSS feed and other location IDs, please visit http://developer.yahoo.com/weather/index.html.

" Don’t bother about weather"

Create HTML using HtmlTextWriter class in x++

HtmlTextWriter class is used to output properly formed HTML
into a web page.  The
HtmlTextWriter allows the developer to code attributes, style attributes, and
tags etc.

The HtmlTextWriter class permits the developer to generate
page output in a non-browser specific way; that is to say, the burden of
developing alternative markup is typically removed by using the
HtmlTextWriter.  The HtmlTextWriter class exposes properties, fields, and
methods that permit the developer to format HTML 4.0 compliant output. 

For example, in the job below i  added static string and  an image using the HtmlTextWriter class.

static void HTMLTextWriter(Args _args)

{

    HTMLTextWriter htw = new HTMLTextWriter();

    TextBuffer     txtBuffer = new TextBuffer();

    CCHTMLString   staticString;

    ;

    staticString = @’At
Solugenix we know our success results from taking a long term view in all

    our relationships: clients,
employees, industries and technologies.’;

   
htw.renderBeginTag(HtmlTextWriterTag::table());

   
htw.renderBeginTag(HtmlTextWriterTag::tr());

   
htw.write(staticString);

   
htw.addAttribute(HtmlTextWriterAttribute::class_Attribute(), ‘ms-vb’);

   
htw.addStyleAttribute(HtmlTextWriterStyle::width(), ’26px’);

   
htw.addStyleAttribute(HtmlTextWriterStyle::padding_top(), ‘3px’);

   
htw.renderBeginTag(HtmlTextWriterTag::td());

   
htw.addAttribute(HtmlTextWriterAttribute::src(), ‘http://www.holidayegreetingssite.com/index_files/image3121.jpg&#8217;);//get
the image from web

   
htw.addStyleAttribute(HtmlTextWriterStyle::width(), ‘100’);

   
htw.addStyleAttribute(HtmlTextWriterStyle::height(), ’50’);

   
htw.renderBeginTag(HtmlTextWriterTag::img(), true);

    htw.renderEndTag();
//close <Td>

    htw.renderEndTag();
//close <Table>

   
txtBuffer.setText(htw.getHtmlString());

   
txtBuffer.toFile(‘f:\\DynamicsAX.html’);  // please provide your path to save the
file

}

The result of the above code will be –

How to write a message to the Event Log

This tiny helper function creates the entry and closes it. The "source" argument is the name of your application

static void
writeEntry_EventLog(Args _args)

{

    System.Diagnostics.EventLog oEV = new
System.Diagnostics.EventLog();

    ;

   oEV.set_Source(‘Dynamics AX’);

    oEV.WriteEntry("This is just an
information from Dynamics AX");

    oEV.Close();

}