<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-20769129</id><updated>2011-12-27T09:52:18.475-08:00</updated><category term='ASP.NET AJAX'/><category term='sas7bdat c# .net reader writer'/><category term='SAS'/><category term='sas obs length observation variable'/><category term='Web Services'/><title type='text'>SAS from Out in Left Field</title><subtitle type='html'>This blog is designed to show various ways to use SAS with Microsoft technologies. Hopefully, I can illustrate ways to make these 2 technologies work together and help users out with integration concerns.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://savian.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>57</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-20769129.post-8943455180122606144</id><published>2011-12-27T09:52:00.000-08:00</published><updated>2011-12-27T09:52:18.491-08:00</updated><title type='text'>SAS Macro to Make Tiny URLs</title><content type='html'>Someone on SAS-L wanted a piece of SAS code to convert a long url to a short one. Well, here you go:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;filename in "x:\temp\in";&lt;br /&gt;filename out "x:\temp\out.txt";&lt;br /&gt;&lt;br /&gt;%macro MakeTiny(longUrl=);&lt;br /&gt; data _null_;&lt;br /&gt;    file in lrecl=1028;&lt;br /&gt;    put "url=&amp;amp;longUrl" ;&lt;br /&gt;    run;&lt;br /&gt;&lt;br /&gt;    proc http in=in out=out url="http://tinyurl.com/api-create.php"&lt;br /&gt;      method="post"&lt;br /&gt;      ct="application/x-www-form-urlencoded";&lt;br /&gt; run;&lt;br /&gt;&lt;br /&gt; data _null_ ;&lt;br /&gt;    infile out;&lt;br /&gt;    input tinyUrl :$1024. ;&lt;br /&gt;    call symput('tinyUrl',tinyUrl);&lt;br /&gt;    %global tinyUrl ;&lt;br /&gt;    run;&lt;br /&gt;&lt;br /&gt;%mend makeTiny;&lt;br /&gt;&lt;br /&gt;%MakeTiny(longUrl=www.savian.net);&lt;br /&gt;&lt;br /&gt;%put &amp;amp;tinyUrl ;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8943455180122606144?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8943455180122606144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8943455180122606144' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8943455180122606144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8943455180122606144'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/12/sas-macro-to-make-tiny-urls.html' title='SAS Macro to Make Tiny URLs'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-6535651008739880320</id><published>2011-07-21T13:26:00.000-07:00</published><updated>2011-10-18T05:03:35.688-07:00</updated><title type='text'>WCF and PROC SOAP</title><content type='html'>&lt;div&gt;Adam Bullock in SAS Tech Support has become a superstar in my book. I don't send him tickets directly but the area I am working in always seems to find him.&lt;br /&gt;&lt;br /&gt;The latest issue was consuming a WCF service. This was different since Microsoft uses interfaces in WCF vs the old way of doing it. I didn't catch that but Adam did. Here is working SAS code for handling it:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: lightgrey; border: solid black; font-size: 14px; word-wrap: break-word;"&gt;FILENAME REQUEST 'C:\temp\REQUEST.xml';&lt;br /&gt;FILENAME RESPONSE 'C:\temp\RESPONSE.xml';&lt;br /&gt;&lt;br /&gt;data _null_;&lt;br /&gt;file request;&lt;br /&gt;input;&lt;br /&gt;put _infile_;&lt;br /&gt;datalines4;&lt;br /&gt;&amp;lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/"&amp;gt;&lt;br /&gt;   &amp;lt;soapenv:Header/&amp;gt;&lt;br /&gt;   &amp;lt;soapenv:Body&amp;gt;&lt;br /&gt;      &amp;lt;tem:DoWork&amp;gt;&lt;br /&gt;         &amp;lt;!--Optional:--&amp;gt;&lt;br /&gt;         &amp;lt;tem:p&amp;gt;Test&amp;lt;/tem:p&amp;gt;&lt;br /&gt;      &amp;lt;/tem:DoWork&amp;gt;&lt;br /&gt;   &amp;lt;/soapenv:Body&amp;gt;&lt;br /&gt;&amp;lt;/soapenv:Envelope&amp;gt;&lt;br /&gt;;;;;&lt;br /&gt;run;&lt;br /&gt;&lt;br /&gt;%let RESPONSE=RESPONSE;&lt;br /&gt;&lt;br /&gt;proc soap in=REQUEST&lt;br /&gt;out=&amp;amp;RESPONSE&lt;br /&gt;url="http://prognos2.savian.net/SampleServices/cdmAlive.svc"&lt;br /&gt;soapaction="http://tempuri.org/ICdmAlive/DoWork"&lt;br /&gt;;&lt;br /&gt;run;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Adam used SoapUI to track it down and was nice enough to send a picture of where he saw the interface call:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-xqfbgeaDIgI/Tih4so80yvI/AAAAAAAAADM/nvRrim7CwcY/s1600/SoapUI.JPG"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5631884042328918770" src="http://1.bp.blogspot.com/-xqfbgeaDIgI/Tih4so80yvI/AAAAAAAAADM/nvRrim7CwcY/s320/SoapUI.JPG" style="cursor: pointer; height: 146px; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-6535651008739880320?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/6535651008739880320/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=6535651008739880320' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6535651008739880320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6535651008739880320'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/07/wcf-and-proc-soap.html' title='WCF and PROC SOAP'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-xqfbgeaDIgI/Tih4so80yvI/AAAAAAAAADM/nvRrim7CwcY/s72-c/SoapUI.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-843345362808020355</id><published>2011-06-20T20:14:00.000-07:00</published><updated>2011-06-20T20:30:23.048-07:00</updated><title type='text'>Wix and InStyler</title><content type='html'>This isn't a SAS post even though SAS is on the periphery of this one. This post is designed to help other developers in a similar boat if they get a hit on the error message verbiage.&lt;br /&gt;&lt;br /&gt;The standard MS Installer is going away (next year, I believe), and a lot of people are converting to WIX (Windows Installer XML). On my latest project, I needed a custom installer. Now anyone who has ever worked with custom installers should be able to tell you what an absolute pain it is, how hard it is to debug, hard to put in custom screens, etc.&lt;br /&gt;&lt;br /&gt;This seemed like an opportune time to jump over to WIX, especially when I needed a lot more than what the custom dialogs could provide under the standard Windows installer technology inside of Visual Studios. InstallShield was NOT an option. They want way, way too much money for their product and I am not a fan from days of yore.&lt;br /&gt;&lt;br /&gt;WIX is very flexible but it is also hard to work with. There are no GUIs, per se, for it which means a lot of manual coding. My current WIX file, code generated, is weighing in at 900+ lines of XML. That and looking up the GUIDs for products, etc. meant a lot of manual effort and lots of places for mistakes.&lt;br /&gt;&lt;br /&gt;I found a product on the web called Instyler Setup. Not sure how well supported it is, and it has a number of bugs, but it mostly writes the WIX for you. Two of the most annoying bugs I wanted to describe so others can seee them on the web:&lt;br /&gt;&lt;br /&gt;1. "Error 2834:  The next pointers on the dialog ErrorPopup do not form a single loop"&lt;br /&gt;&lt;br /&gt;...when running the installer is caused by the text label on the ErrorPopup dialog having a tabstop set to true. MSI is very, very picky about everything which is why it is a nightmare to debug.&lt;br /&gt;&lt;br /&gt;2. "Error 1723. There is a problem with this Windows Installer package."&lt;br /&gt;&lt;br /&gt;...make sure you reference the CA dll instead of teh normal dll on your custom action.&lt;br /&gt;&lt;br /&gt;3. To make working with WIX a lot easier, download and install the DTF package:&lt;br /&gt;&lt;br /&gt;http://wix.sourceforge.net/&lt;br /&gt;&lt;br /&gt;4. Turn on MSI debugging in your local group policy. this makes like a lot easier to track things down.&lt;br /&gt;&lt;br /&gt;I hope these get picked up in the search engines and helps some other dev out at some point.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-843345362808020355?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/843345362808020355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=843345362808020355' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/843345362808020355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/843345362808020355'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/06/wix-and-instyler.html' title='Wix and InStyler'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-8257713280308703215</id><published>2011-06-17T23:24:00.000-07:00</published><updated>2011-06-17T23:25:13.628-07:00</updated><title type='text'>IIS 7.5 and SAS DCOM: ACCESS DENIED, ACCESS DENIED, ACCESS DENIED</title><content type='html'>And the joy of being a pathfinder continues ;-]&lt;br /&gt;&lt;br /&gt;IIS 7.5 has now changed the game. No longer do we play with NETWORK SERVICES to get SAS operational. Now it is a new user IIS APPPOOL\DefaultAppPool. Security has now been taken from NETWORK SERVICES, which covered the website, to specific security by the AppPools. I am not a security expert but that is my understanding.&lt;br /&gt;&lt;br /&gt;So I took my happy little web services project (WCF) that worked fine in Visual Studio 2010 (Cassini), built a Web Setup for it, and deployed  it to localhost. Then spent the next 7 hours staring at the same error: ACCESS DENIED. This was occurring on CreateObjectByServer. ACCESS DENIED, ACCESS DENIED, ACCESS DENIED, over and over again. I spent so much time in DCOMCNFG even going so far as to enable the Administrator account as the launching account, open up everything I could, and still ACCESS DENIED.&lt;br /&gt;&lt;br /&gt;This morning I spoke to Bubba in SAS Tech Support. Great guy. He didn’t know this area but diligently was tossing out terms on tech notes he saw. He finally tossed out “enable 32-bit apps” and I keyed in on that one immediately. Well, I did a bit of investigation and have now made it far enough along for a blog post:&lt;br /&gt;&lt;br /&gt;In IIS 7.5, get your application in place under a Virtual Directory:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-C2_vzYKiZJA/TfxBa9j-LQI/AAAAAAAAACc/puflIwpRDYI/s1600/pic2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 287px;" src="http://4.bp.blogspot.com/-C2_vzYKiZJA/TfxBa9j-LQI/AAAAAAAAACc/puflIwpRDYI/s320/pic1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5619438366509378818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Set up whatever app pool you are using. In this case, it is DefaultAppPool. Click on the Application Pools under the directory. Now here is where you have a choice. You can use the DefaultAppPool for everything but that also means giving it access to every library location, file, whatever. I opted to instead set up a new account called ‘WebService”.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-SrEgr0P88Jc/TfxCRao7WjI/AAAAAAAAACk/jMJ2hETg_HM/s1600/pic2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 206px;" src="http://3.bp.blogspot.com/-SrEgr0P88Jc/TfxCRao7WjI/AAAAAAAAACk/jMJ2hETg_HM/s320/pic2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5619439302027729458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p/&gt;&lt;br /&gt;&lt;br /&gt;Now it needs to be associated with the access rights for each directory and file. This is standard Windows stuff. Click on a directory and add the new username:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-SMcE8pa37aU/TfxCq1Ooo6I/AAAAAAAAACs/TYgkTuQNTxc/s1600/pic3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 285px; height: 320px;" src="http://2.bp.blogspot.com/-SMcE8pa37aU/TfxCq1Ooo6I/AAAAAAAAACs/TYgkTuQNTxc/s320/pic3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5619439738661938082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In IIS, change the App Pool to use the new identity:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-p2tEj8-7xJo/TfxDTWmGypI/AAAAAAAAAC0/Yma-PU9MrS0/s1600/pic4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 160px;" src="http://2.bp.blogspot.com/-p2tEj8-7xJo/TfxDTWmGypI/AAAAAAAAAC0/Yma-PU9MrS0/s320/pic4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5619440434813520530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here are the settings and the ones to be concerned with:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-g6t_QUpfXRI/TfxDgZ3RIXI/AAAAAAAAAC8/eNDITR63rlE/s1600/pic5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 262px; height: 320px;" src="http://1.bp.blogspot.com/-g6t_QUpfXRI/TfxDgZ3RIXI/AAAAAAAAAC8/eNDITR63rlE/s320/pic5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5619440659029107058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Enable 32-bit applications and set the identity as needed. By default, it will be the name of your app pool. We will use our newly created name of WebService.&lt;br /&gt;&lt;br /&gt;Now, time to go into DCOMCNFG (Start --&gt; Run --&gt; DCOMCNFG and fix the DCOM entry for the SAS Workspace:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-w8e_H6SyLiI/TfxD3ORu6dI/AAAAAAAAADE/wvWKTDwh-q4/s1600/pic6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 242px; height: 320px;" src="http://1.bp.blogspot.com/-w8e_H6SyLiI/TfxD3ORu6dI/AAAAAAAAADE/wvWKTDwh-q4/s320/pic6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5619441051055876562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Finally, change your code to the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;                ObjectFactory factory = new ObjectFactory();&lt;br /&gt;                ServerDef server = new ServerDef();&lt;br /&gt;                SasWorkSpace = (Workspace)factory.CreateObjectByServer("ws", true, server, "WebService", "MyPassword");&lt;br /&gt;                var id = SasWorkSpace.UniqueIdentifier;&lt;br /&gt;                SasLanguageService = SasWorkSpace.LanguageService;&lt;br /&gt;                keeper = new ObjectKeeper();&lt;br /&gt;                keeper.AddObject(1, "SASServer", SasWorkSpace);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No more ACCESS DENIED.&lt;br /&gt;&lt;br /&gt;Thanks Bubba. I think we p*wned it.&lt;br /&gt;&lt;br /&gt;…not really but it works good enough for me for now ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8257713280308703215?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8257713280308703215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8257713280308703215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8257713280308703215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8257713280308703215'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/06/iis-75-and-sas-dcom-access-denied.html' title='IIS 7.5 and SAS DCOM: ACCESS DENIED, ACCESS DENIED, ACCESS DENIED'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-C2_vzYKiZJA/TfxBa9j-LQI/AAAAAAAAACc/puflIwpRDYI/s72-c/pic1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-9049395561174997954</id><published>2011-05-17T08:49:00.000-07:00</published><updated>2011-05-17T09:05:14.106-07:00</updated><title type='text'>SAS StoredProcessService events</title><content type='html'>If you encounter the following error when using SAS's StoredProcessService events:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;event invocation for COM objects requires event to be attributed with DispIdAttribute&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Roll your project back from .NET 4.0 to .NET 3.5. This may only be applicable to the web services code.&lt;br /&gt;&lt;br /&gt;Example code:&lt;br /&gt;&lt;br /&gt;class Program&lt;br&gt;{&lt;br&gt;static void Main(string[] args)&lt;br&gt;{&lt;br&gt;&lt;br /&gt;Workspace ws = new Workspace();&lt;br&gt;SAS.LanguageService ls = ws.LanguageService;&lt;br&gt;&lt;FONT style="BACKGROUND-COLOR: yellow"&gt;ls.StepError += new CILanguageEvents_StepErrorEventHandler(ls_StepError); &lt;---- ERROR OCCURS HERE&lt;/font&gt; &lt;br&gt;ls.Submit("data test; abort; run;");&lt;br&gt;}&lt;br&gt;static void ls_StepError()&lt;br&gt;{&lt;br&gt;Console.WriteLine("Bingo!");&lt;br&gt;Console.ReadLine();&lt;br&gt;}&lt;br&gt;}&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-9049395561174997954?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/9049395561174997954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=9049395561174997954' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/9049395561174997954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/9049395561174997954'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/05/sas-storedprocessservice-events.html' title='SAS StoredProcessService events'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-9181949785295214175</id><published>2011-05-13T21:32:00.000-07:00</published><updated>2011-05-13T21:50:33.965-07:00</updated><title type='text'>Flush with excitement...errr, logs</title><content type='html'>Well, it is Friday night, I am back from the doctor with antibiotics due to a possible spider bite (love those little guys), and I decide to track down some performance issues with the SAS StoredProcessService (or Microsoft's Cassini). Somewhere, someone is responsible. Set up my little test bed to see it all work:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;SAS.Workspace ws = new Workspace();&lt;br /&gt;LanguageService ls = ws.LanguageService;&lt;br /&gt;StoredProcessService sp = ls.StoredProcessService;&lt;br /&gt;sp.Repository = @"file:" + @"x:\temp";&lt;br /&gt;sp.Execute("test.sas", string.Empty);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;All is well and good. Life is happy, kids are playing, sunshine is everywhere.&lt;br /&gt;&lt;br /&gt;Wait! We need to see if the code ran. let's check the log:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;string log = ls.FlushLog(1000);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;AHHHH!!!! It never comes back. Where is my string!?!?&lt;br /&gt;&lt;br /&gt;Turns out that if the FlushLog int amount EXCEEDS the total number of chars in the log, you go to a happy place called infinity. Less than the total chars and all is well.&lt;br /&gt;&lt;br /&gt;I decided to test this a few times and was able to get a picture of my CPU utilization:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-ATVhAMqMhlY/Tc4HoaNwhqI/AAAAAAAAABY/IH8gVBNZPw8/s1600/CPU.png"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 160px; FLOAT: left; HEIGHT: 212px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5606426976936036002" border="0" alt="" src="http://2.bp.blogspot.com/-ATVhAMqMhlY/Tc4HoaNwhqI/AAAAAAAAABY/IH8gVBNZPw8/s320/CPU.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-am4iVOcn6V4/Tc4HgJmCRTI/AAAAAAAAABQ/75odGoKUu7s/s1600/CPU.png"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This does not happen when using the LanguageService directly, only when using the StoredProcessService. Time to wrap up this blog, pull back from the black hole of infinite loops, and go issue a bug report with SAS R&amp;amp;D.&lt;br /&gt;&lt;br /&gt;If any SAS R&amp;amp;D folks in this area read this blog, let me know if I missed something. Right now, it seems like I have been bitten twice today by bugs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-9181949785295214175?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/9181949785295214175/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=9181949785295214175' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/9181949785295214175'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/9181949785295214175'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/05/flush-with-excitementerrr-logs.html' title='Flush with excitement...errr, logs'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-ATVhAMqMhlY/Tc4HoaNwhqI/AAAAAAAAABY/IH8gVBNZPw8/s72-c/CPU.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-8162543831958729420</id><published>2011-04-18T22:08:00.000-07:00</published><updated>2011-04-18T22:17:24.118-07:00</updated><title type='text'>3-fer on StoredProcessService</title><content type='html'>Ok, well the major issues have been tackled except 1. How do you handle spaces in your NameValuePairs? Well, without the single quotes below, it kept splitting the values between the Sample and the Data. The single quotes hold it together.&lt;br /&gt;&lt;br /&gt;Check this out:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;br /&gt;string[] parms = new string[2]&lt;br /&gt;        {&lt;br /&gt;         "outdata=WORK.ALAN_20110418_070053",&lt;br /&gt;         @"datalib='X:\Data\Prognos\DemandForecasting\Sample Data'",&lt;br /&gt;        };&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Notice the single quotes around the value? It took a long time to track that one down (thanks ThotWave). &lt;br /&gt;&lt;br /&gt;Now it is simple to submit to SAS:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;br /&gt;string newParms = string.Empty;&lt;br /&gt;if (parms != null)&lt;br /&gt;   {&lt;br /&gt;     newParms = String.Join(" ", parms);&lt;br /&gt;   }&lt;br /&gt;StoredProcessService sp = Common.SasLanguageService.StoredProcessService;&lt;br /&gt;sp.Repository = storedProcLibrary;&lt;br /&gt;sp.Execute(storedProcedureName, newParms);&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I would ask R&amp;D a simple question which is why isn't there an option on the SPS to specify the delimiter or am I missing a flag somewhere?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8162543831958729420?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8162543831958729420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8162543831958729420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8162543831958729420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8162543831958729420'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/04/3-fer-on-storedprocessservice.html' title='3-fer on StoredProcessService'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-5721829771940496174</id><published>2011-04-18T21:29:00.000-07:00</published><updated>2011-04-18T22:03:13.984-07:00</updated><title type='text'>Our journey with SAS's StoredProcessService object continues...</title><content type='html'>Check out this code:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;br /&gt;string newParms = "outdata=WORK.TEST";&lt;br /&gt;Common.SasLanguageService.Async = true;&lt;br /&gt;StoredProcessService sp = Common.SasLanguageService.StoredProcessService;&lt;br /&gt;sp.Repository = storedProcLibrary;&lt;br /&gt;sp.Execute(storedProcedureName, newParms);&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Standard stuff when working with the stored process server through VB or C# (or any other means of hitting these dlls).&lt;br /&gt;&lt;br /&gt;Funny thing is the SAS log shows that the macro assignment of newParms never takes place. Hence, &amp;outdata is undefined:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;SYMBOLGEN:  Macro variable OUTDATA resolves to &lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Commenting out the Async makes this all work:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;SYMBOLGEN:  Macro variable OUTDATA resolves to WORK.ALAN_20110418_070053&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Now, even wiring up the event handlers for SubmitComplete do not fix the issue. Seems like a bug but I'll let the guys in R&amp;D figure it out. If you have to waste a lot of time on it, however, keep in mind the nuances here until SAS R&amp;D dives in.&lt;br /&gt;&lt;br /&gt;Well, back out to the far left field where I hang out. Time to work on the business problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-5721829771940496174?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/5721829771940496174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=5721829771940496174' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5721829771940496174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5721829771940496174'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/04/our-journey-with-sass-storedprocess.html' title='Our journey with SAS&apos;s StoredProcessService object continues...'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-3144145683445548913</id><published>2011-04-18T13:01:00.000-07:00</published><updated>2011-04-18T13:17:00.228-07:00</updated><title type='text'>This one is a real Keeper</title><content type='html'>So, if you ever get this error while trying to work with OleDb and SAS IOM:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;The object ... could not be found; make sure it was previously added to the object keeper&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Make sure that you include the following lines (the lack of a Keeper is what causes this error):&lt;br /&gt;&lt;br /&gt;ObjectFactory factory = new ObjectFactory();&lt;br /&gt;ServerDef server = new ServerDef();&lt;br /&gt;Workspace ws = (Workspace)factory.CreateObjectByServer("ws", true, server, "", "");&lt;br /&gt;&lt;strong&gt;ObjectKeeper keeper = new ObjectKeeper();&lt;br /&gt;keeper.AddObject(1, "SASServer", ws);&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;That whole ObjectKeeper is missing from a number of examples that I have seen and it is critical for everything to function. It becomes apparent when trying to get the data from an OleDb DataAdaptor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-3144145683445548913?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/3144145683445548913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=3144145683445548913' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3144145683445548913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3144145683445548913'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/04/this-one-is-real-keeper.html' title='This one is a real Keeper'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-5666383290278532464</id><published>2011-02-20T22:28:00.000-08:00</published><updated>2011-02-20T22:44:16.707-08:00</updated><title type='text'>Wufoo and REST API</title><content type='html'>Wufoo (&lt;a href="http://www.wufoo.com/"&gt;http://www.wufoo.com/&lt;/a&gt;) is a great service for creating user forms and getting input. Build a form interactively, let people fill it out, and Wufoo collects the results. If you haven't checked it out before, I highly recommend this great service.&lt;br /&gt;&lt;br /&gt;I was simply parsing the emails when they were sent upon form completion but that is a real hassle due to HTML. However, Wufoo has a really good REST API so I started playing around with it. Here, in C#, is how I used their API to get my data. This can easily be converted into SAS as well:&lt;br /&gt;&lt;br /&gt;The HttpGet:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: lightgray; border: solid black;word-wrap: break-word;font-size:14px;"&gt;&lt;br /&gt;internal static string HttpGet(string uri, string apiKey)&lt;br /&gt;{&lt;br /&gt;    var pairs = new StringBuilder();&lt;br /&gt;    var req = WebRequest.Create(uri) as HttpWebRequest;&lt;br /&gt;    req.Timeout = 300000;&lt;br /&gt;    req.Credentials = new NetworkCredential(apiKey, string.Empty);&lt;br /&gt;    req.UserAgent = "AlanC";&lt;br /&gt;    req.ContentType = "text/html";&lt;br /&gt;    req.Method = "GET";&lt;br /&gt;&lt;br /&gt;    // Get response&lt;br /&gt;&lt;br /&gt;    using (var response = req.GetResponse() as HttpWebResponse)&lt;br /&gt;    {&lt;br /&gt;        if (response != null)&lt;br /&gt;        {&lt;br /&gt;            WebResponse resp = req.GetResponse();&lt;br /&gt;            if (resp != null)&lt;br /&gt;            {&lt;br /&gt;                var sr = new StreamReader(resp.GetResponseStream());&lt;br /&gt;                return sr.ReadToEnd().Trim();&lt;br /&gt;            }&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    return null;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The call to the method:&lt;/p&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;XDocument xd = XDocument.Parse(HttpGet(@"https://xxxxxxx.wufoo.com/api/v3/forms/xxxxx3/entries.xml", "XXXX-XXXX-XXXX-XXXX"));&lt;br /&gt;&lt;br /&gt;The https://xxxxx would correspond to your domain on wufoo.&lt;br /&gt;The xxxxx after forms in the uri would be the form id assigned by Wufoo.&lt;br /&gt;The XXX-XXXX-etc. is the API Key assigned by Wufoo.&lt;br /&gt;&lt;br /&gt;The above can be found on the Wufoo site. Just look at the Wufoo API information to find out how to obtain it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-5666383290278532464?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/5666383290278532464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=5666383290278532464' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5666383290278532464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5666383290278532464'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/02/wufoo-and-rest-api.html' title='Wufoo and REST API'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-3396363360226171206</id><published>2011-02-17T09:32:00.000-08:00</published><updated>2011-02-17T09:43:59.183-08:00</updated><title type='text'>SAS Transport Files and .NET</title><content type='html'>Well, someone contacted me about the Data Management Utilities. they loved them (thank you) but wanted to know about reading SAS Transport Files. Well, after fiddling with the localProvider a bit and getting nowhere, I stumbled onto something cool:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Download and install the SAS Universal Viewer from the SAS support site&lt;/li&gt;&lt;li&gt; Create a new project in Visual Studio&lt;/li&gt;&lt;li&gt; Add a reference from the SAS Universal Viewer install files to the following 2 dlls&lt;/li&gt;&lt;li&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;SAS.UV.Transport&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;SAS.UV.Utility&lt;/li&gt;&lt;li&gt; Use the following C# code (adapt as needed):&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;&lt;pre&gt;TransportFile tf = new TransportFile(@"x:\temp\sample.xpt");&lt;br /&gt;var x = tf.Datasets;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Your dataset will be in variable x&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Don't forget to add the using statement to the top of your code for the SAS.UV.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-3396363360226171206?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/3396363360226171206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=3396363360226171206' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3396363360226171206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3396363360226171206'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/02/sas-transport-files-and-net.html' title='SAS Transport Files and .NET'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-8899515961242547616</id><published>2011-02-10T18:31:00.001-08:00</published><updated>2011-02-10T23:03:17.017-08:00</updated><title type='text'>RegexBuddy and Automated Emails</title><content type='html'>So, I am going to help out with a computer club at my kids middle school. Since a topic was needed to start it all off, I said 'hey! regular expressions are used everywhere, why not start there. Plus, it is very useful.'.&lt;br /&gt;&lt;br /&gt;So, I sent JGSoft (the owner of RegexBuddy) an email and explained the situation. How they were kids, we needed a limited version or a free one for a certain time, the kids may purchase it after the class, etc.&lt;br /&gt;&lt;br /&gt;What was the response?&lt;br /&gt;&lt;br /&gt;&lt;em&gt;"We indeed do not offer a free trial version of RegexBuddy for download on our web site.  At RegexBuddy's low price point and with our solid 3-month money-back guarantee, you can buy the full version of RegexBuddy entirely risk-free."&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;All of the supportive messages for RegexBuddy on SAS-L and other places and the best they can do is some automated response saying all of the kids need to cough up the 40 dollars to use their product. This is a fine way to get a bad reputation IMO.&lt;br /&gt;&lt;br /&gt;Now I need to go get a free regex editor to show the kids despite RegexBuddy being the premiere product on the market. I am trying to turn them into kids interested in the product so they can go home and dazzle mom and dad who will then pay the fee.&lt;br /&gt;&lt;br /&gt;Ok, off of my soapbox.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8899515961242547616?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8899515961242547616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8899515961242547616' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8899515961242547616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8899515961242547616'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2011/02/regexbuddy-and-automated-emails.html' title='RegexBuddy and Automated Emails'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-8495448575388298268</id><published>2010-11-28T14:17:00.000-08:00</published><updated>2010-11-28T14:21:26.314-08:00</updated><title type='text'>SAS-X Blog Aggregator</title><content type='html'>Tal Galili has started up a SAS blog aggregator. The more folks involved in SAS, the better, as far as I am concerned.&lt;br /&gt;&lt;br /&gt;You can find it at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.sas-x.com/"&gt;SAS-X&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8495448575388298268?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8495448575388298268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8495448575388298268' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8495448575388298268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8495448575388298268'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2010/11/sas-x-blog-aggregator.html' title='SAS-X Blog Aggregator'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-738799771935694888</id><published>2010-11-07T09:27:00.000-08:00</published><updated>2010-11-07T09:42:59.874-08:00</updated><title type='text'>Getting SAS/IntrNet Operational on IIS7</title><content type='html'>IIS7 is a major change in IIS. Don Henderson contacted me and asked if I could help get it working. It really isn't hard but involves a few steps.&lt;br /&gt;&lt;br /&gt;How do you get SAS/IntrNet operational.&lt;br /&gt;&lt;br /&gt;1. Enable CGI Role on Server through the Server Manager.&lt;br /&gt;&lt;br /&gt;2. Add in your website in IIS. Right-click the scripts or cgi-bin directory where &lt;br /&gt;the broker.exe is located and select Convert to Application.&lt;br /&gt;&lt;br /&gt;3. While still having the scripts/cgi-bin folder selected, double-click on the handler mappings icon on the right-hand side. There should already be a listing for *.cgi at the top. Double-click on it --&gt; Request restrictions --&gt; Mapping --&gt; Invoke --&gt; File or Folder, Access --&gt; Execute.&lt;br /&gt;&lt;br /&gt;4. Click on the machine name in IIS. Click on ISAPI and CGI restrictions. Click on Add..., specify the full path to the broker.exe. &lt;br /&gt;&lt;br /&gt;5. Optional: set up a host header.&lt;br /&gt;&lt;br /&gt;Click on the Default website or on the website name. On the far right-hand side of the screen, click on bndings. Specify a host header (demos.savian.net, for example).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;See here for more details:&lt;br /&gt;&lt;br /&gt;http://www.wrensoft.com/zoom/support/faq_cgi_iis.html&lt;br /&gt;   &lt;br /&gt;Good luck and contact me if you have issues.&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-738799771935694888?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/738799771935694888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=738799771935694888' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/738799771935694888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/738799771935694888'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2010/11/getting-sasintrnet-operational-on-iis7.html' title='Getting SAS/IntrNet Operational on IIS7'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-2473815307267947296</id><published>2010-03-17T11:56:00.000-07:00</published><updated>2010-03-17T12:40:39.468-07:00</updated><title type='text'>Excel Pivot Tables and Filtering</title><content type='html'>So I get a post this morning from my client saying everything looks great and they can't find any issues with the latest release. Happy moment, cigar time.&lt;br /&gt;&lt;br /&gt;Well, at this point I am over on the project and am working on my own time. That's fine considering that there might be future business there. Ok, so they mention 2 minor items that are annoyances that would be perfect. No obligation to do them but I have a few minutes so I dive in.&lt;br /&gt;&lt;br /&gt;5 hours later I have it working. What was the issue? Pivot Tables in Excel and setting their filter values. For those poor saps who have to deal with it in the future, here is some C# code to hopefully save you some time:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: lightgray; border: solid black;word-wrap: break-word;font-size:14px;"&gt;&lt;br /&gt;        private static void HandlePivotTableChanges(string p)&lt;br /&gt;        {&lt;br /&gt;            FindProcessInstances();&lt;br /&gt;            Console.WriteLine("Starting Excel. Please be patient while it loads.");&lt;br /&gt;            string format = "'Product_Container_Release_Metrics_Workbook.xls'!Format_Workbook";&lt;br /&gt;            Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();&lt;br /&gt;            ExcelApp.DisplayAlerts = false;&lt;br /&gt;            Console.WriteLine("Opening workbook.");&lt;br /&gt;            Workbook wb = ExcelApp.Workbooks.Open(p, m, m, m, m, m, m, m, m, m, m, m, m, m, m);&lt;br /&gt;            Console.WriteLine("Running macro.");&lt;br /&gt;            ExcelApp.RunMacro(format);&lt;br /&gt;            Worksheet ws = (Worksheet)wb.Worksheets["Pivot Tables"];&lt;br /&gt;            string pivotTable = "Forecast to Go";&lt;br /&gt;            PivotTable pt = (PivotTable)ws.PivotTables(pivotTable);&lt;br /&gt;            pt.ManualUpdate = true;&lt;br /&gt;            PivotField pf = (PivotField)pt.PivotFields("Release (A)");&lt;br /&gt;            PivotItems items = (PivotItems)pf.PivotItems(m);&lt;br /&gt;&lt;br /&gt;            foreach (PivotItem item in items)&lt;br /&gt;            {&lt;br /&gt;                    if (item.Value != string.Empty)  // &lt;--- CRITICAL LINE. Filters must have at least 1 value selected. Exception otherwise.&lt;br /&gt;                        ((PivotItem) items.Item(item.Value)).Visible = false;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            pt.ManualUpdate = false;&lt;br /&gt;            ExcelApp.Calculation = XlCalculation.xlCalculationAutomatic;&lt;br /&gt;            Console.WriteLine("Saving workbook.");&lt;br /&gt;            wb.Save();&lt;br /&gt;            wb.Close(false, m, m);&lt;br /&gt;            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wb);&lt;br /&gt;            Console.WriteLine("Closing Excel.");&lt;br /&gt;            ExcelApp.Quit();&lt;br /&gt;            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ExcelApp);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void FindProcessInstances()&lt;br /&gt;        {&lt;br /&gt;            Console.WriteLine("Finding open processes.");&lt;br /&gt;            KillProcesses("Excel");&lt;br /&gt;            KillProcesses("PowerPnt");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void KillProcesses(string processName)&lt;br /&gt;        {&lt;br /&gt;            Process[] processes = Process.GetProcessesByName(processName);&lt;br /&gt;            if (processes.Length &gt; 0)&lt;br /&gt;            {&lt;br /&gt;                foreach (var p in processes)&lt;br /&gt;                {&lt;br /&gt;                    p.Kill();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static void RunMacro(this Application app, string macro)&lt;br /&gt;        {&lt;br /&gt;            app.Run(macro,&lt;br /&gt;                    m, m, m, m, m, m, m, m, m, m,&lt;br /&gt;                    m, m, m, m, m, m, m, m, m, m,&lt;br /&gt;                    m, m, m, m, m, m, m, m, m, m&lt;br /&gt;                );&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-2473815307267947296?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/2473815307267947296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=2473815307267947296' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2473815307267947296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2473815307267947296'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2010/03/excel-pivot-tables-and-filtering.html' title='Excel Pivot Tables and Filtering'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-5077661394377268046</id><published>2010-03-03T13:22:00.000-08:00</published><updated>2010-03-03T13:27:23.041-08:00</updated><title type='text'>SaviDataSet 1.0.0.5 Released</title><content type='html'>I just posted the latest version of the SaviDataSet reader/writer. The latest version allows for its use from the command line for converting SAS datasets to delimited, XML, and Excel files (2003 &amp;amp; 2007).&lt;br /&gt;&lt;br /&gt;Please see the Help File in the Savian--&gt; SaviDataSet --&gt; Help.txt folder for instructions.&lt;br /&gt;&lt;br /&gt;I will be incorporating a write feature in at some point but it is more complex since variables need to be defined.&lt;br /&gt;&lt;br /&gt;The latest release can be found here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cid-8bca55fbca813d37.skydrive.live.com/self.aspx/Applications/SaviDataSet.zip"&gt;SaviDataSet 1.0.0.5&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-5077661394377268046?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/5077661394377268046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=5077661394377268046' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5077661394377268046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5077661394377268046'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2010/03/savidataset-1005-released.html' title='SaviDataSet 1.0.0.5 Released'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-2784811511962246279</id><published>2010-02-06T21:20:00.001-08:00</published><updated>2010-03-01T07:24:17.762-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sas7bdat c# .net reader writer'/><title type='text'>SaviDataSet Alpha 1.0 On the Web</title><content type='html'>&lt;span style="font-family:arial;"&gt;I am finally ready with my SAS dataset reader/writer for .NET. It is written in 100% managed code using .NET 3.5. The dlls can be found&lt;br /&gt;&lt;a href="http://cid-8bca55fbca813d37.skydrive.live.com/self.aspx/Applications/SaviDataSet.zip?ccr=1994"&gt;here.&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;A sample .NET console application can be found in the program file entries after the installation.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#ff0000;"&gt;&lt;strong&gt;Update 2/13/2010:&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I am now testing this against a real-world project so I am finding little bugs here and there. These are being addressed for version 1.0.0.1. If you need a build sooner than it is released, let me know.&lt;/p&gt;&lt;p&gt;I have also found that you need at around 100+ observations for this to work correctly. I am investigating but keep that in mind while testing.&lt;/p&gt;&lt;p&gt;[LATE BREAKING] I fixed the obs issue so I went ahead and uploaded the fixed version. Watch for breaking changes which are in the Readme.txt file. &lt;/p&gt;&lt;p&gt;&lt;span style="color:#ff0000;"&gt;&lt;strong&gt;Update 2/29/2010&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Based upon Chris' work, I added in a console application that exposed my existing work. It allows for export of the sas7bdat to Excel, delimited, and XML. I will add in import at some point and have designed the interface as such. For example, I put the parms in an XML file to provide enough flexibility to accomplish everything. That has pros and cons but I figured the pros outweighed the cons.&lt;/p&gt;&lt;p&gt;I am also doing something I have meant to do for a long time which is to build a data viewer. Hence, I don't want an interim release but will bundle it all together. I have spent some time this weekend starting that process. All of the components are here but I have to pull them together which I am hoping to do this week.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-2784811511962246279?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/2784811511962246279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=2784811511962246279' title='26 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2784811511962246279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2784811511962246279'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2010/02/savidataset-alpha-10-on-web.html' title='SaviDataSet Alpha 1.0 On the Web'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>26</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-6767265503661733707</id><published>2010-01-15T17:12:00.000-08:00</published><updated>2010-01-15T17:22:34.386-08:00</updated><title type='text'>SaviCellsPro and Exciting Changes</title><content type='html'>Well, it was hectic week. I went back to work again (on a cool project) and spent a lot of personal time on SaviCellsPro. Specifically on a new utility that I think is pretty darn exciting.&lt;br /&gt;&lt;br /&gt;In the past, when you used SCP, you needed to write the XML for the product. Now, the XML is well-documented and I have provided help files and samples to make it easy but, let's face it, a lot of people are uncomfortable with XML.&lt;br /&gt;&lt;br /&gt;A suggestion was made by a friend of mine at SAS to have a utility that would take an existing Excel spreadsheet and automatically generate the beginning XML so it doesn't have to be done from scratch. Well, I scratched my head and few times and decided, over the Christmas holiday, that this might be doable. Well, it was. SCP now has an XML creator that can take an existing workbook and describe it in XML. A SAS programmer can then use that as a basis and incorporate their data into the SCP XML. It makes it much easier to get started.&lt;br /&gt;&lt;br /&gt;The utility supports cell values, styles (fonts, font sizes, borders, italics, bolds, etc.), formulas, graphs, images, print settings, and more. I will continue to add to it as demand is shown.&lt;br /&gt;&lt;br /&gt;Expect a rollout next week on SAS-L, sasCommunity, and probably this blog. I have some testers looking at it first but I think this really rounds out SCP nicely. I will probably add in OLAP support and more robust graphing but for now, it is a cool utility that makes it easy to generate native Excel, PDF, and HTML files of your SAS data (or any other data for that matter). Since it uses XML, it can be run on any computer that produces text.&lt;br /&gt;&lt;br /&gt;Look for my presentation at SGF on SaviCellsPro and how to use it. It is on Tues at 1:30.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-6767265503661733707?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/6767265503661733707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=6767265503661733707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6767265503661733707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6767265503661733707'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2010/01/savicellspro-and-exciting-changes.html' title='SaviCellsPro and Exciting Changes'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-6172848851064830334</id><published>2010-01-04T21:04:00.000-08:00</published><updated>2010-01-04T23:46:29.031-08:00</updated><title type='text'>.NET Coders and the sas7bdat dll</title><content type='html'>I have been spending the last week working on how the interface to the sas dataset can be used by a .NET developer. It is of particular concern because once the initial dll is released, it will be hard to change it. Getting the interface 'mostly' correct is important. &lt;br /&gt;&lt;br /&gt;After a lot of thought, here is what I have so far:&lt;br /&gt;&lt;br /&gt;//Initiate logging&lt;br /&gt;&lt;br /&gt;Savian.SaviDataSet.Logging.StartLog(@"c:\temp\SaviDataSetErrors.log");&lt;br /&gt;&lt;br /&gt;//Create SAS dataset object&lt;br /&gt;&lt;br /&gt;SasDataSet ds = new SasDataSet();&lt;br /&gt;&lt;br /&gt;//Add 4 variables&lt;br /&gt;&lt;br /&gt;ds.AddVariable("AA1", "Var1");&lt;br /&gt;ds.AddVariable("AA2", "Var2");&lt;br /&gt;ds.AddVariable("AA3", "Var3", 10, SasVariableType.Character,"$5.","$7.");&lt;br /&gt;ds.AddVariable("AA4", "Var4", 10, SasVariableType.Character);&lt;br /&gt;&lt;br /&gt;//Add observations&lt;br /&gt;//Bulk insertion&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &lt; 1000; i++)&lt;br /&gt;   {&lt;br /&gt;     object[] values = new object[] {1, 2, "Test_" + (i + 1).ToString("00#"), "Test2", "Test3", "Test4", "Test5"}; &lt;br /&gt;     ds.AddObservation(i, values );&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;//Modify observation - Similar to a .NET dataset&lt;br /&gt;&lt;br /&gt;ds.Observations[0]["AA1"].Value = "Test";&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//Write dataset&lt;br /&gt;&lt;br /&gt;ds.WriteDataSet("TEMP", @"c:\temp\test.sas7bdat");&lt;br /&gt;&lt;br /&gt;//Stop logging&lt;br /&gt;&lt;br /&gt;Savian.SaviDataSet.Logging.CloseLog();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The area that was a challenge was adding observations since they are really an array across existing variable metadata.&lt;br /&gt;&lt;br /&gt;The other area I am focused on is keeping the wording the same as how SAS would refer to things. Hence, observation instead of row and variable instead of column. &lt;br /&gt;&lt;br /&gt;I have also been working on validation so that invalid data does not make it into the dataset. I can't prevent everything, but I am making a good faith effort to minimize it. Also, formats/informats have to be checked, name lengths, length values, dataset name, etc. all have to be verified to make sure they comply. So far, so good but more checking is underway.&lt;br /&gt;&lt;br /&gt;While working on this, you realize how much effort has been put into the dataset by SAS over the years and how much work they have to go through to make things compliant and workable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-6172848851064830334?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/6172848851064830334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=6172848851064830334' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6172848851064830334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6172848851064830334'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2010/01/net-coders-and-sas7bdat-dll.html' title='.NET Coders and the sas7bdat dll'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-179441837778366927</id><published>2009-12-28T23:14:00.000-08:00</published><updated>2009-12-28T23:21:21.281-08:00</updated><title type='text'>Progress on the sas7bdat</title><content type='html'>It is tough at times to be a consultant and get those side projects out of the way. That said, I finally had a chance to really work on the sas7bdat some more over the holidays. Not too much since my personal focus is my kids. &lt;br /&gt;&lt;br /&gt;A really tough project interfered since the last time I played with it in September so I was looking forward to the holidays to pass another milestone.&lt;br /&gt;&lt;br /&gt;Well, I just managed to create a 100 record dataset with 7 variables, char and numeric. My little Christmas gift to myself.&lt;br /&gt;&lt;br /&gt;When I first started work on this project many moons back, I never expected that writing a dataset would be much more difficult than reading one. That was a major mistake. However, the writing has made me really discover a lot more about the structure and how it works plus I have had to step up my coding skills a bit to make it through.&lt;br /&gt;&lt;br /&gt;Long road but finally happy to be here after so much time.&lt;br /&gt;&lt;br /&gt;Happy New Year everyone.&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-179441837778366927?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/179441837778366927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=179441837778366927' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/179441837778366927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/179441837778366927'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/12/progress-on-sas7bdat.html' title='Progress on the sas7bdat'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-6864047327564646753</id><published>2009-11-10T05:33:00.000-08:00</published><updated>2009-11-10T05:38:42.310-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sas obs length observation variable'/><title type='text'>Calculate a SAS Observation Length</title><content type='html'>Well, I couldn't find this documented anywhere (someone correct me if I missed it) but the question for the day was how to calculate the SAS Observation Length. After some investigation, here is how it is done (pseudocode):&lt;br /&gt;&lt;br /&gt;obsLength = Sum of all of your character lengths + Sum of all of your variable lengths;&lt;br /&gt;&lt;br /&gt;if any numeric variables have a length of 8 then &lt;br /&gt;   round the obsLength to the nearest factor of 8.&lt;br /&gt;   &lt;br /&gt;Since the default for numeric variables is a length of 8, the rounding will almost always occur but it is not a guarantee.&lt;br /&gt;&lt;br /&gt;I hope this helps others who may need to calculate this value for storage or performance reasons.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-6864047327564646753?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/6864047327564646753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=6864047327564646753' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6864047327564646753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6864047327564646753'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/11/calculate-sas-observation-length.html' title='Calculate a SAS Observation Length'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-1904157943412409217</id><published>2009-08-27T19:23:00.000-07:00</published><updated>2009-08-27T19:33:37.116-07:00</updated><title type='text'>What next?</title><content type='html'>As I can see that shimmer of light at the end of the tunnel I have to start thinking "what do I do with a binary SAS reader/writer?"&lt;br /&gt;&lt;br /&gt;I originally started down this path with the goal of avoiding having to read/write SAS using XML Now that I am nearing the finish, I am trying to determine what comes after this (other than a quiet, non-working evening).&lt;br /&gt;&lt;br /&gt;Where I am leaning right now is an Excel add-in or something in that space. I think Excel/SAS is one of the biggest areas of opportunity and an area that frankly does not get enough attention, IMO. SQL Server add-ins are another possible option so SAS can be supported in SSIS. It is early in this mulling period though so I would appreciate any thoughts people have on what they would like to see.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-1904157943412409217?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/1904157943412409217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=1904157943412409217' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/1904157943412409217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/1904157943412409217'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/08/what-next.html' title='What next?'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-2103969104310031451</id><published>2009-07-26T19:06:00.001-07:00</published><updated>2009-08-27T19:17:09.862-07:00</updated><title type='text'>Created my first SAS dataset without using SAS</title><content type='html'>Well, around 14 months ago, I started on a journey to understand the SAS dataset so I could read and write one independently. Originally, I needed the functionality for a client but it became an obsession to figure it out. Client work and personal matters interfered non-stop but I have finally written my first SAS dataset using C# and .NET.&lt;br /&gt;&lt;br /&gt;It isn't pretty (no data is in it) but it is a dataset and that is what matters. Putting data in is minor so I am not concerned about that.&lt;br /&gt;&lt;br /&gt;A lot of effort still remains to get it all worked out but I am happy to be at this position. After cleaning the code up and finishing it, I plan on making interoperability tools to simplify interfacing with SAS, expecially in areas where SAS needs help (i.e. SSIS, MS Office).&lt;br /&gt;&lt;br /&gt;It is a good day but it has taken a brutal amount of hours to accomplish this feat. I would not suggest to others to spend this amount of time on this issue: it is simply mind-numbing.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;[Update 07/27/2009]&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I just wrote my first data into the dataset. It is only numerics right now but it is a start.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;[Update 07/29/2009, 3AM]&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I just created a dataset that contains text fields. I had an extraneous bug that made me think it was failing when it wasn't. Such is the life of a coder. Anyway, on to cleaning up code that I left hard-coded and making the system a bit more robust.&lt;br /&gt;&lt;br /&gt;Let me be clear: I am tired of looking at hex code. &lt;br /&gt;476F6F646E69676874&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;[Update 08/27/2009]&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Progress continues. After I created my first dataset, the goal was to get rid of any hard-coded values and make it more dynamic. While doing that work, I hit a major logic issue and had to focus on figuring that out. I have made it through that and am now mopping up the remnants and tightening up the logic. Since the goal is to ship a .NET dll for developers, I also need to consider how a developer codes to the dll. Basically, I am in cleanup mode and testing additional variables, labels, etc. to see where things break or do not work as intended. &lt;br /&gt;&lt;br /&gt;Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-2103969104310031451?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/2103969104310031451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=2103969104310031451' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2103969104310031451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2103969104310031451'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/07/created-my-first-sas-dataset-without.html' title='Created my first SAS dataset without using SAS'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-1693680502303351405</id><published>2009-07-15T09:53:00.000-07:00</published><updated>2009-07-15T09:56:54.583-07:00</updated><title type='text'>PM Stories</title><content type='html'>These are stories I have collected over the years. i hope people enjoy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Project Managers In Practice (PIMP…sorry, PMIP)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Our first story involves a young PM, new to the project and not very technical&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Ok, so I (senior consultant guy) have a project and there are 3 changes requested by the team:&lt;br /&gt;&lt;br /&gt;1. Change a label (minor)&lt;br /&gt;2. Allow a user to save their selections made on dropdowns (these select what displays in a grid)&lt;br /&gt;3. Allow a user to change a grid and submit the values to another program&lt;br /&gt;&lt;br /&gt;That’s all fine and good. I bid 44 hours to make the changes.&lt;br /&gt;&lt;br /&gt;Team now wants a user to not only make the grid changes (#3) but save those changes as well. So PM says change 2 &amp;amp; 3 are now merged. We need to save selections and grid entries.&lt;br /&gt;&lt;br /&gt;I said, OK, slight increase in scope, 50 hours total.&lt;br /&gt;&lt;br /&gt;PM says, wait, we merged 2 &amp;amp; 3 together so now we only have 2 changes not 3 so it should be a decrease in hours.&lt;br /&gt;&lt;br /&gt;PM survival tip #1: Reduce scope by merging letters on the plan and hope no one notices.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 2 involves 4 experienced PMs&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Project is in a major crisis. High-demanding customer, a lot of screaming, no time to deliver on time. Save team is called in to try and pull it out. Atmosphere is very tense.&lt;br /&gt;&lt;br /&gt;Some of the project members (developer/consultants) have to work on all 4 segments of the overall project simultaneously. Each segment is given a PM. Customer wants to know what is happening all of the time so PMs demand status reports at least twice a day. For consultants working on all segments that is 8 status reports per day. When complaints are lodged, developers are told that it has to be that way and why aren’t we getting the work done.&lt;br /&gt;&lt;br /&gt;Revolt of developers / consultants ensues after months of this activity.&lt;br /&gt;&lt;br /&gt;PM survival tip #2: if you flood your customer with progress reports they will think you are doing your job. See tip #4 below.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 3 involves a fixed bid contract and some super savvy consultants&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Two senior consultants figure out a clever way around a major stumbling block on a late project. They can change the process agreed upon slightly and save time, money, effort, AND bring in a late project on time. The customer also wants it done since the new process has a lot of compelling advantages.&lt;br /&gt;&lt;br /&gt;Guess who says no? That’s right, our friendly neighborhood PM. It seems that the PM has decided that the original project, as scoped and laid out, is immutable for all time. No changes are allowed from the project plan WHATSOEVER.&lt;br /&gt;&lt;br /&gt;PM Survival Tip #3: Minimize risk by making no changes. No changes, no new plans to build. Voila!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 4 involves a PM with a dangerous weapon…Outlook&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A project, as usual, is in crisis. The PM decides that their main role is to send out emails…lots and lots of emails. On the day of ‘the incident’, the PM has sent close to 50 emails since 8am.&lt;br /&gt;&lt;br /&gt;Then it happens…just before lunch. The PM sends an email saying that people are sending way too many emails.&lt;br /&gt;&lt;br /&gt;Consultants laugh and break for lunch.&lt;br /&gt;&lt;br /&gt;PM sends 10 more before they get back….&lt;br /&gt;&lt;br /&gt;PM survival tip #4: Forward everything, comment on everything, make up stuff. The success of a PM is ultimately measured by the suffering of others.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 5 involves a PM with no sense what a PM does&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;So, the PM contacts the lead on a project and tells the lead that there are too many emails about the project and could the lead please summarize all of the open issues and assign priorities…&lt;br /&gt;&lt;br /&gt;…isn’t this what a PM does?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 6 involves a PM…again…&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The developer has been waiting on getting access to the client’s machine for almost a week. Technical issues, blah, blah, blah.&lt;br /&gt;&lt;br /&gt;After the week is up, the PM wants to know timelines (this is good, they are doing their job). Developer says the development has been pushed by 3 days. The PM, who has been copied on every email between the client and the developer, says that they don’t understand why the project is delayed because of a lack of access…&lt;br /&gt;&lt;br /&gt;Rule #1 in computers: it is hard to use them if you can’t access them.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 7 Guess who…&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This story involves, SURPRISE, a PM who we will affectionately call Rum. Now Rum is a great PM because Rum thinks that EVERY piece of email and/or communication must flow through him. Rum insists that no direct communication happen between the technical people or the customer and that he will just forward on what is relevant.&lt;br /&gt;&lt;br /&gt;I…AM…IRON MAN…DO, DO, DO DUH DO…&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 8 Who wants it early?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;So, the consultant finishes the application early (1 week) but they can’t test it because it isn’t scheduled to be deployed until the following week. They are told to wait until the project scheduled date so they meet the schedule.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Story 9 This is a loving one that I just title ‘Make the Sh*&amp;amp; up’&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Well, the customer wants a project plan. Enter our superhero ‘The PM’. Rather than getting requirements or design done first, the PM decides ‘hey, let me have fun with little chain icons and links and just create a project plan! Oh boy!’.&lt;br /&gt;&lt;br /&gt;So a project plan is created, with no document saying what needs to be done and no involvement from the programmers. Developers finally start working on the project and are told you must meet this date for this functionality. Programmers say WTF!?!? Where did this come from.&lt;br /&gt;&lt;br /&gt;Well, it is in the project plan that we designed w/o any involvement from the people who do the work…&lt;br /&gt;&lt;br /&gt;PM Survival Tip #5: When in doubt, just SWAG the dates and blame the developers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-1693680502303351405?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/1693680502303351405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=1693680502303351405' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/1693680502303351405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/1693680502303351405'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/07/pm-stories.html' title='PM Stories'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-6963183179245520168</id><published>2009-03-11T17:26:00.000-07:00</published><updated>2009-03-11T17:30:08.553-07:00</updated><title type='text'>Windows 7</title><content type='html'>Ok, I am testing out Windows 7 and it seems great...except it didn't recognize my printer and wouldn't let me install the driver. It errored out with:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Unable to Install Printer. The printer driver is not compatible with a policy enabled on your computer that blocks Windows NT 4.0 drivers.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Ok, the solution (as is often the case under Vista) is to disable UAC. Don't go looking for a policy setting (it isn't there that I could find and I scoured all of them), don't try to install a local port like Microsoft advices for Windows Server 2003. Just disable UAC and you are good to go.&lt;br /&gt;&lt;br /&gt;I know this one isn't SAS related but people really rely on some tips like these when they are beating their heads against the wall.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-6963183179245520168?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/6963183179245520168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=6963183179245520168' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6963183179245520168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6963183179245520168'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/03/windows-7.html' title='Windows 7'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-7026376700771581119</id><published>2009-02-24T19:33:00.001-08:00</published><updated>2009-02-24T19:44:37.630-08:00</updated><title type='text'>Opportunity</title><content type='html'>It will be very rare when I criticize a SAS PR release but this one was a bad release, in my opinion:&lt;br /&gt;&lt;br /&gt;http://www.sas.com/news/preleases/AberdeenReport.html?utm_medium=RSS&amp;utm_source=Corp_PressRelease&lt;br /&gt;&lt;br /&gt;It infers that only mid-size businesses use spreadsheets and that it shows a level of immaturity. My current client, a SAS user, is 15x the size of SAS and uses a lot of spreadsheets. Why? because it is easy and it works. Also, let's not use a generic term spreadsheets. EVERYONE uses Excel so put a name on the usage and don't generalize. &lt;br /&gt;&lt;br /&gt;I found this sentence the most galling:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Hatch said that the most successful midsized enterprises are much more likely to be using powerful and relevant technologies such as those from SAS, the leader in business analytics software and services. &lt;/em&gt;&lt;br /&gt;&lt;br /&gt;A business can use SAS and be relevant while also using Excel. Trying to say that someone needs to use SAS end-to-end is the major issue I have today with SAS. SAS is extremely powerful but to say that their interfaces have to be the vehicle for BI is nonsense. Excel is a fantastic delivery mechanism for SAS BI.&lt;br /&gt;&lt;br /&gt;Bad press release, IMO. I am unsure who it targets. The 'unsuccessful' midsized enterprises who love Excel and just want SAS to work with it or the ferociously succesful large businesses who have melded the 2 sides and view them as compatible.&lt;br /&gt;&lt;br /&gt;Sell SAS guys but do so with an understanding of what clients want: SAS to work with Microsoft and display data in Excel, Word, Project, Powerpoint, SharePoint, etc. No need for a rift when the 2 sides work well together.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-7026376700771581119?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/7026376700771581119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=7026376700771581119' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/7026376700771581119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/7026376700771581119'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/02/opportunity.html' title='Opportunity'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-8270996271094448745</id><published>2009-02-17T18:21:00.001-08:00</published><updated>2009-02-17T18:35:34.574-08:00</updated><title type='text'>Microsoft Project and Inserting Columns</title><content type='html'>I am doing a LOT of work right now with SAS and Microsoft Project using the Microsoft Project interop, Base SAS, and SAS/IntrNet. One of the client requirements was to add in additional columns to the default MS Project columns. Well, I searched high and low and couldn't figure out how to do it. After some slogging, here is what I came up with:&lt;br /&gt;&lt;br /&gt;&lt;pre style="color:blue;font-size: 2 em;"&gt;&lt;br /&gt;&lt;br /&gt;    class MsProjectTest&lt;br /&gt;    {&lt;br /&gt;        Project p ;&lt;br /&gt;        object m = Missing.Value;&lt;br /&gt;        string file = @"c:\temp\test.mpp";&lt;br /&gt;&lt;br /&gt;        public void Process()&lt;br /&gt;        {&lt;br /&gt;            Application app = new Application();&lt;br /&gt;            app.Alerts(false);&lt;br /&gt;            p = app.Projects.Add(m,m,m);&lt;br /&gt;            Task t = p.Tasks.Add("Test", m);&lt;br /&gt;            t.Name = "Test Node";&lt;br /&gt;            t.Start = "03/20/2009";&lt;br /&gt;            t.Start7 = "03/31/2009";&lt;br /&gt;            p.Application.TableEdit("Entry", true, m, m, m, m,&lt;br /&gt;            "Start7", "Start Test", 10, PjAlignment.pjLeft, &lt;br /&gt;            true, true, 255, 1, 4, 1, m, m);&lt;br /&gt;            p.Application.TableApply("Entry");&lt;br /&gt;            p.SaveAs(file, PjFileFormat.pjMPP, m, m, m, m, &lt;br /&gt;                     m, m, m, m, m, m, m, m, m);&lt;br /&gt;            app.Quit(PjSaveType.pjDoNotSave);&lt;br /&gt;&lt;br /&gt;            System.Diagnostics.Process.Start(file);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I hope this helps some other interop developer out &lt;br /&gt;there struggling with the same issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8270996271094448745?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8270996271094448745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8270996271094448745' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8270996271094448745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8270996271094448745'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/02/microsoft-project-and-inserting-columns.html' title='Microsoft Project and Inserting Columns'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-3912396480033025809</id><published>2009-01-06T22:57:00.000-08:00</published><updated>2009-01-06T23:05:19.134-08:00</updated><title type='text'>Silverlight, WCF, SAS, and Demos</title><content type='html'>I had a client ask, very nicely, if I could showcase some of my work to help make their internal sale. Well, this is all good to me since I could possible get some business in 2009 and I needed to do it anyway.&lt;br /&gt;&lt;br /&gt;Well, the only time available was the holiday season so I cranked out a lot of code, learned a LOT about WCF and Silverlight, but was able to get my demo site built.&lt;br /&gt;&lt;br /&gt;The site utilizes WCF to talk to SAS on the backend and expose SAS out as a service on the front-end. Things are very secure right now so I have held a lot of the 'what is possible' back so that I don't expose a security hole.&lt;br /&gt;&lt;br /&gt;Here is the site:&lt;br /&gt;&lt;br /&gt;http://demos.savian.net&lt;br /&gt;&lt;br /&gt;Silverlight has been the most challenge simply because the tools are still a bit immature and the coding examples are thin, thin, thin but I love the possibilities. The more I work with Silverlight, the more I like it even if the syntax leaves me scratching my head at times. &lt;br /&gt;&lt;br /&gt;The examples I put on the web use SAS as a local resource but SAS could easily be sitting on another server and be exposed via IOM or IntrNet (REST).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-3912396480033025809?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/3912396480033025809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=3912396480033025809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3912396480033025809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3912396480033025809'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/01/silverlight-wcf-sas-and-demos.html' title='Silverlight, WCF, SAS, and Demos'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-4442809185435757623</id><published>2009-01-06T22:40:00.000-08:00</published><updated>2009-01-06T22:56:13.258-08:00</updated><title type='text'>Consultants, Idealism, and the Real World</title><content type='html'>Today, I hit an absolute programming wall. I was deep into my code, client asking for a deliverable date, and I hit a deal-breaker coding moment. I think, we have all had those things happen. You're there in the bowels and suddenly find some code that simply is not going to work and may jeopardize the entire design. &lt;br /&gt;&lt;br /&gt;What to do? Well, Google and hope for a miracle. In this case, i got fortunate and finally stumbled onto a solution late into the evening. &lt;br /&gt;&lt;br /&gt;However, the issue made me start doing some more research into the particular area I had struggled with and was reading a lot about static vs dynamic languages (this post is not about that). C$ 4.0 recognizes this dilemma and is implementing it but it isn't available now. However, what a firestorm on the web over the addition of dynamic capabilities.&lt;br /&gt;&lt;br /&gt;What I realized is how far off the idealists / zealots are from the consultant/business coder. &lt;br /&gt;&lt;br /&gt;If I tell my client that I have to rearchitect the 100s of hours of coding, what are they supposed to say? Instead of that Feb 1 deadline, I need to redo everything and deliver it in June? They will drop my contract and possible pursue action. Reality will sink in...quickly...&lt;br /&gt;&lt;br /&gt;In the world of consulting, it is critical to deliver projects on time and to estimate accurately. When you hit those walls, there isn't a lot of time to debate the nuances of static/dynamic languages: I just have to have something that works...and NOW. Customers have a real allergy to paying a lot more money on top of what they already paid.&lt;br /&gt;&lt;br /&gt;I dogged this problem, like always, and found an answer so I dodged a bullet: sometimes you aren't so lucky. There are times when you, as a consultant, have to take it in the shorts and I have done my time there. However, to ask a a client to pay because 'it isn't perfect' ignores the fact that nothing in computing is perfect: just make it work.&lt;br /&gt;&lt;br /&gt;So, at the end of the day I will take tools that focus more on getting the job done than being perfect in theory. And I will also say an extra thank-you tonight for finding that one blog posting I really, really needed...&lt;br /&gt;&lt;br /&gt;Catching pop flys,&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-4442809185435757623?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/4442809185435757623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=4442809185435757623' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/4442809185435757623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/4442809185435757623'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2009/01/consultants-idealism-and-real-world.html' title='Consultants, Idealism, and the Real World'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-8706957575884150646</id><published>2008-11-18T07:38:00.000-08:00</published><updated>2008-11-18T08:07:31.119-08:00</updated><title type='text'>SAS and Microsoft: Different Worlds</title><content type='html'>Well, first of all, sorry I haven't written recently. My time has been taken up by some great SAS work but it is under wraps for the time being.&lt;br /&gt;&lt;br /&gt;I was chatting with a SAS buddy of mine recently and I started to comment on the differences between the SAS and Microsoft development communities. I like them both but they each have the pros and cons.&lt;br /&gt;&lt;br /&gt;The Microsoft community travels fast, I mean lightening fast. There are constant updates, massive 3rd party support, great forums, blogs, etc. from the Microsoft developers to always keep people updated. Best of all, the constant changes means that it is always exciting and new. Like getting several Christmas's a year. Cool new technologies like Silverlight (WOW!!), C# 4.0, Office 2007, Windows 7, LINQ, etc. On the 3rd party front, I have dozens of graphing toolsets I can use. Dozens of databases, etc.&lt;br /&gt;&lt;br /&gt;That is also their con which is that you always have to be learning and never catch up. It also leads to a lot more uncertainty with how things work which can be a detriment when building enterprise systems.&lt;br /&gt;&lt;br /&gt;The SAS community is much slower to change. Part of this is due to the Institute which doesn't release software very often and keeps the software fairly static. &lt;br /&gt;I like that I can count on Base SAS to work each and every time. It is still the best way of manipulating data that I know of. Also, the user community (SAS-L, mainly) is a club with the same players each year. I like the steadiness of the SAS community and the software. When I go to a SAS conference, I know people. The Microsoft conferences tend to be a madhouse and you have to arrange to meet people you might know. &lt;br /&gt;&lt;br /&gt;The con with SAS is that steadiness. The lack of change means that people still use older technologies such as DDE and do not explore further. So often, I see the same way of doing things being recommended rather than people stepping back and asking if there is a better way. The insularity of the community tends to hold back innovation, IMO. SAS does not have a 3rd party ecosystem so you don't have other companies being encouraged to develop new ways of using SAS. &lt;br /&gt;&lt;br /&gt;At the end of the day, though, I like SAS and Microsoft. Each has strengths and weaknesses. &lt;br /&gt;&lt;br /&gt;Lastly, I would encourage SAS developers to find dual interests simply to see alternate ways of doing things. Not everyone needs to embrace Microsoft but I see a great positive in adopting multiple technologies simply to change the view of the world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8706957575884150646?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8706957575884150646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8706957575884150646' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8706957575884150646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8706957575884150646'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2008/11/sas-and-microsoft-different-worlds.html' title='SAS and Microsoft: Different Worlds'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-3640932168967414904</id><published>2008-08-12T21:49:00.000-07:00</published><updated>2010-03-31T11:17:58.540-07:00</updated><title type='text'>SAS Integration Technologies and Vista</title><content type='html'>Ok, I am sure that I will get some grief about this but I needed to submit my SAS code from a .NET application. this was on my new PC which is running Vista 32. Anyway, no matter what I did, I kept getting the following error:&lt;br /&gt;&lt;br /&gt;"Retrieving the COM class factory for component with CLSID {440196D4-90F0-11D0-9F41-00A024BB830C} failed due to the following error: 80040154."&lt;br /&gt;&lt;br /&gt;Well, normally that is addressed by simply installing the IntTech client and setting permissions to None in dcomcnfg. It didn't work this time.&lt;br /&gt;&lt;br /&gt;Here is what i did to fix it (people can try these in isolation to see which one is the root):&lt;br /&gt;&lt;br /&gt;1. Right-click on the the inttech.exe file and run it in compatibility mode for Win XP SP2&lt;br /&gt;&lt;br /&gt;2. Go into dcomcnfg and set every single SAS DCOM object with permissions of None.&lt;br /&gt;&lt;br /&gt;I could play with this some more but I am now behind.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update 3/31/2010&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This worked for me on Windows 7 64 and when the dcom stuff failed:&lt;br /&gt;&lt;br /&gt;To register the IOM server,&lt;br /&gt;&lt;br /&gt;1)  Copy SASVRSRV.DLL from !SASROOT\CORE\SASEXE which can be found on&lt;br /&gt;    the SAS System CD or a Network copy of SAS to your Client&lt;br /&gt;    !SASROOT\CORE\SASEXE directory.&lt;br /&gt;&lt;br /&gt;2)  From a command prompt run !SASROOT\SAS.EXE /REGSERVER&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-3640932168967414904?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/3640932168967414904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=3640932168967414904' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3640932168967414904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3640932168967414904'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2008/08/sas-integration-technologies-and-vista.html' title='SAS Integration Technologies and Vista'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-8014192453306806651</id><published>2008-05-06T20:32:00.000-07:00</published><updated>2008-05-06T20:39:16.060-07:00</updated><title type='text'>Microsoft Project Files, SAS, and .NET</title><content type='html'>Ok, another fun, fun time with SAS and an obscure area. Here's the scenario, the client needs data from an MPP file (Microsoft Project) converted into a SAS dataset. I tried lots of routes, all to no avail. As usual, I get to go through the mess of COM interop, lack of documentation on the web, and SAS not supporting write access in the local data provider. Ahhhh, the joys of consulting ;-]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I finally got the following C# code operational and it writes the data into a SAS-friendly XML format. I hope this helps someone else:&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Data.OleDb;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;using Microsoft.Office.Interop.MSProject;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using Savian.Core;&lt;br /&gt;using Savian.DataManagement.Delimited;&lt;br /&gt;&lt;br /&gt;namespace Client.ReadProjectFile&lt;br /&gt;{&lt;br /&gt;    public class Main&lt;br /&gt;    {&lt;br /&gt;        List&lt;ProjectInfo&gt; tasks = new List&lt;ProjectInfo&gt;();&lt;br /&gt;&lt;br /&gt;        public void Process(string file)&lt;br /&gt;        {&lt;br /&gt;            ReadMppFile(file);&lt;br /&gt;            ConvertFileToSas();&lt;br /&gt;            Console.ReadLine();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void ConvertFileToSas()&lt;br /&gt;        {&lt;br /&gt;            DateTime start = DateTime.Now;&lt;br /&gt;            Console.WriteLine("Start converting to SAS..." + start.ToShortTimeString());&lt;br /&gt;            DataTable dt = tasks.ToDataTable("TABLE");&lt;br /&gt;            dt.WriteXml(@"c:\temp\Client.xml");&lt;br /&gt;            DateTime end = DateTime.Now;&lt;br /&gt;            Console.WriteLine("Finished conversion..." + end.ToShortTimeString());&lt;br /&gt;            Console.WriteLine("Elapsed time: " + (end - start).TotalSeconds + " seconds");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void ReadMppFile(string file)&lt;br /&gt;        {&lt;br /&gt;            ApplicationClass app = new ApplicationClass();&lt;br /&gt;            app.DisplayAlerts = false;&lt;br /&gt;            app.ScreenUpdating = false;&lt;br /&gt;            app.Visible = false;&lt;br /&gt;            app.MacroVirusProtection = false;&lt;br /&gt;            app.FileOpen(file, Missing.Value, Missing.Value, Missing.Value, Missing.Value,&lt;br /&gt;                                              Missing.Value, Missing.Value, Missing.Value, Missing.Value,&lt;br /&gt;                                              Missing.Value, Missing.Value, PjPoolOpen.pjDoNotOpenPool,&lt;br /&gt;                                              Missing.Value, Missing.Value, Missing.Value, Missing.Value);&lt;br /&gt;            var mppTasks = app.ActiveProject.Tasks;&lt;br /&gt;            int i = 0;&lt;br /&gt;            DateTime start = DateTime.Now;&lt;br /&gt;            Console.WriteLine("Start creating records..." + start.ToShortTimeString());&lt;br /&gt;            foreach (Task task in mppTasks)&lt;br /&gt;            {&lt;br /&gt;                ProjectInfo pi = GetProjectInfo(task);&lt;br /&gt;                tasks.Add(pi);&lt;br /&gt;                i++;&lt;br /&gt;                if (i % 100 == 0)&lt;br /&gt;                {&lt;br /&gt;                    Console.Write("Records created: " + i);&lt;br /&gt;                    Console.SetCursorPosition(0, 1);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            Console.WriteLine("Records created: " + i);&lt;br /&gt;            DateTime end = DateTime.Now;&lt;br /&gt;            Console.WriteLine("Record read completed..." + end.ToShortTimeString());&lt;br /&gt;            Console.WriteLine("Elapsed time: " + (end-start).TotalSeconds + " seconds");&lt;br /&gt;            app.FileClose(PjSaveType.pjDoNotSave, Missing.Value);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static ProjectInfo GetProjectInfo(Task task)&lt;br /&gt;        {&lt;br /&gt;            ProjectInfo pi = new ProjectInfo();&lt;br /&gt;            AssignFields(ref pi, task);&lt;br /&gt;            return pi;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void AssignFields(ref ProjectInfo pi, Task t)&lt;br /&gt;        {&lt;br /&gt;            pi.Name = t.Name;&lt;br /&gt;            pi.Start = (DateTime)t.Start;&lt;br /&gt;            pi.Finish = (DateTime)t.Finish;&lt;br /&gt;            pi.Id = t.ID;&lt;br /&gt;            pi.PercentComplete = Extensions.GetIntValue(t.PercentComplete);&lt;br /&gt;            pi.Duration = Extensions.GetIntValue(t.Duration);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;    class ProjectInfo&lt;br /&gt;    {&lt;br /&gt;        public int Id { get; set; }&lt;br /&gt;        public string Name { get; set; }&lt;br /&gt;        public DateTime Start { get; set; }&lt;br /&gt;        public DateTime Finish { get; set; }&lt;br /&gt;        public int? PercentComplete { get; set; }&lt;br /&gt;        public int? Duration { get; set; }&lt;br /&gt;    }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-8014192453306806651?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/8014192453306806651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=8014192453306806651' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8014192453306806651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/8014192453306806651'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2008/05/microsoft-project-files-sas-and-net.html' title='Microsoft Project Files, SAS, and .NET'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-2851384523329376434</id><published>2008-03-23T07:32:00.001-07:00</published><updated>2008-03-29T15:25:49.344-07:00</updated><title type='text'>Silverlight Lessons Learned</title><content type='html'>After a shotgun week of Silverlight 2.0, I thought I would share a few lessons learned.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Blank page&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;If you get a blank page after uploading your xap file, make sure that NETWORK SERVICE is in the security accounts.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;XAP File&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;XAP is the only file that needs to be moved typically. As you do your code updates, just move the XAP file into place.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Dynamic XAML&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Dynamic XAML requires a namespace attribute now:&lt;br /&gt;&lt;br /&gt;     &amp;ltGrid xmlns="http://schemas.microsoft.com/client/2007"&amp;gt&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Timing Issues&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There seems to be a timing issue in Silverlight that is causing an event to get triggered before the data streams down from a site. This still requires investigation.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Visual Studio 2008 and Silverlight Debugging&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;For some reason, if a serious Silverlight error occurs, debugging will be disabled in the web application. This may make it seem like events are not firing when they are, just that the debugger is broken. Right-click properties on the web application --&gt; Start Options --&gt; Debuggers --&gt; Check Silverlight&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Overall&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Overall, I love XAML and Silverlight. It was absolutely incredible to work with but it took a lot of time due to minimla information on the web right now. Hopefully, this post will help some other folks out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-2851384523329376434?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/2851384523329376434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=2851384523329376434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2851384523329376434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/2851384523329376434'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2008/03/silverlight-lessons-learned.html' title='Silverlight Lessons Learned'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-52265205816440917</id><published>2008-03-07T06:04:00.000-08:00</published><updated>2008-03-27T19:10:26.444-07:00</updated><title type='text'>Microsoft Silverlight</title><content type='html'>I have been in Vegas all week at the Microsoft MIX08 conference for the rollout of Silverlight 2.0. It is so revolutionary that it really got me thinking. That and SAS Global Forum made me mull a few thoughts:&lt;br /&gt;&lt;br /&gt;1. Silverlight is going to revolutionize the world. Bold statement, I know.However, what I saw, as a web developer, absolutely stunned me. If you don't believe me, see what NBC will do with the Olympics. 2200 hours of hi-def video, 4 channels per user, VOD, and just much, much more.&lt;br /&gt;&lt;br /&gt;However, check this out for something live now:&lt;br /&gt;&lt;br /&gt;http://memorabilia.hardrock.com/&lt;br /&gt;&lt;br /&gt;Data visualization and BI will move toward Silverlight. SAS should move there as well. as quickly as possible. SAS should be a leader here and not follow the inevitable.&lt;br /&gt;&lt;br /&gt;2. Microsoft is innovating at an amazing pace. Windows Server 2008, Silverlight, Surface, Vista, IE8, IIS7, and on and on. Meanwhile we await a .07 release from SAS that is languishing once again. Basic project management:  reduce scope, increase budget, adjust timeframes...hmmm, it seems like the only option at SAS is the latter and I honestly don't understand it. Hopefully, SAS Global Forum will provide some answers.&lt;br /&gt;&lt;br /&gt;3. Silverlight controls are being released open source. Office formats are now open, the .NET source code has been released open source. I think SAS can learn from this and realize that money can be made without keeping everything tight to the vest.&lt;br /&gt;&lt;br /&gt;4. Integration Technologies should be bundled with Base. All of this new technology requires it so why, as a customer, do I have to have a separate line item? Put SAS/IntrNet in that category as well. Why does web enablement cost extra from SAS. Pay more and realize it is 2008 and web enablement is part of Base SAS.&lt;br /&gt;&lt;br /&gt;5. Microsoft actively encourages blogging even if it is critical of the company. People should be trusted and I have found most use discretion, especially if they are employees. Blogging and active user participation helps sell the company message and actively engages the user community. A once a year conference is not enough in today's fast-paced world. SAS Forums are fine, SAS-L operates via 'birdies' but wouldn't it be great to have blogs from Paul, Vince, Chris, Eric, etc. out in the wild? Open and free, give and take, user comments...&lt;br /&gt;&lt;br /&gt;As a SAS advocate, user, former employee, and partner, I am asking for change. More openness, more releases, more interaction. Simple stuff that is doable today.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-52265205816440917?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/52265205816440917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=52265205816440917' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/52265205816440917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/52265205816440917'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2008/03/microsoft-silverlight.html' title='Microsoft Silverlight'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-6629901256341509900</id><published>2008-02-06T21:40:00.000-08:00</published><updated>2008-02-06T21:53:46.154-08:00</updated><title type='text'>SAS LanguageService and You</title><content type='html'>For those of us who work with SAS LanguageService on a regular basis, it is frustrating. The entire SAS COM interface is very poorly documented and is light on functionality. It gets better over time but it would be much nicer to have a .NET interface so we don't have 50 COM nulls in a single method call.&lt;br /&gt;&lt;br /&gt;Ok, that all said, I just came off of a marathon (10+ hours) bug fix that damn near drove me mad.&lt;br /&gt;&lt;br /&gt;I was submitting a simple query via the Language Service:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;proc sql;&lt;br /&gt;     create outdata.test as&lt;br /&gt;     select *&lt;br /&gt;     from DICTIONARY.COLUMNS&lt;br /&gt;     where …some criteria…&lt;br /&gt;   ;&lt;br /&gt;quit;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Ok, no problem. I could submt the query within the SAS Editor and it would work fine. However, DEPENDING ON WHERE I WAS IN MY .NET CODE, it would return 0 rows. Huh!?!? It wasn't the dataset, it wasn't the syntax for the call, it was where the call occured at during processing. Holy smokes Batman! That's a bear of a bug to catch.&lt;br /&gt;&lt;br /&gt;You do the normal stuff and isolate, isolate, isolate. Well, it took a long time to isolate that it was where it was being called. Damn, damn, damn...one of the toughest bugs I have hit in years.&lt;br /&gt;&lt;br /&gt;My answer for how to solve it:&lt;br /&gt;&lt;br /&gt;Common.SAS.LanguageService.Reset();&lt;br /&gt;&lt;br /&gt;(I am using a static class called Common).&lt;br /&gt;&lt;br /&gt;Will this answer stand the test of time? Not sure. I have asked my buddy at SAS whether I am on the right track.&lt;br /&gt;&lt;br /&gt;Back to the first point: better documentation would be welcome. Even better, an ADO.NET data provider WITHIN Base SAS. Don't make me buy IOM to use SQL processing.&lt;br /&gt;&lt;br /&gt;Ah well, back out to the far corners of the ballpark I go...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-6629901256341509900?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/6629901256341509900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=6629901256341509900' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6629901256341509900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/6629901256341509900'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2008/02/sas-languageservice-and-you.html' title='SAS LanguageService and You'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-5209902073196536458</id><published>2007-12-07T03:44:00.000-08:00</published><updated>2007-12-07T04:19:30.967-08:00</updated><title type='text'>SAS and LINQ - Part 1</title><content type='html'>So, I am just getting my feet wet with LINQ, the new integrated query language within .NET. There are loads of articles on LINQ elsewhere. What I want to do is to illustrate LINQ with SAS and this is my starting point.&lt;br /&gt;&lt;br /&gt;Look at the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-size:10px"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Xml.Linq;&lt;br /&gt;using System.Windows.Forms;&lt;br /&gt;&lt;br /&gt;namespace WindowsFormsApplication2&lt;br /&gt;{&lt;br /&gt;    public partial class Form1 : Form&lt;br /&gt;    {&lt;br /&gt;        public Form1()&lt;br /&gt;        {&lt;br /&gt;            InitializeComponent();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void btnGetData_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            XElement table =XElement.Parse(&lt;br /&gt;               @"&amp;ltTABLE&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt Alfred &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 14 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 69 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 112.5 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt Henry &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 14 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 63.5 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 102.5 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt James &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 12 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 57.3 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 83 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt Jeffrey &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 13 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 62.5 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 84 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt John &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 12 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 59 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 99.5 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt Philip &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 16 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 72 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 150 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt Robert &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 12 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 64.8 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 128 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt Ronald &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 15 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 67 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 133 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt Thomas &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 11 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 57.5 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 85 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;ltCLASS&amp;gt&lt;br /&gt;                  &amp;ltName&amp;gt William &amp;lt/Name&amp;gt&lt;br /&gt;                  &amp;ltSex&amp;gt M &amp;lt/Sex&amp;gt&lt;br /&gt;                  &amp;ltAge&amp;gt 15 &amp;lt/Age&amp;gt&lt;br /&gt;                  &amp;ltHeight&amp;gt 66.5 &amp;lt/Height&amp;gt&lt;br /&gt;                  &amp;ltWeight&amp;gt 112 &amp;lt/Weight&amp;gt&lt;br /&gt;               &amp;lt/CLASS&amp;gt&lt;br /&gt;               &amp;lt/TABLE&amp;gt");&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            var obs = (from o in table.Elements("CLASS")&lt;br /&gt;                       where (string)o.Element("Sex") == " M "&lt;br /&gt;                       select new&lt;br /&gt;                           { &lt;br /&gt;                               Name = (string) o.Element("Name"),&lt;br /&gt;                               Age = (string) o.Element("Age")&lt;br /&gt;                           }&lt;br /&gt;                       );&lt;br /&gt;            List&lt;string&gt; observations = new List&lt;string&gt;();&lt;br /&gt;            foreach (var ob in obs)&lt;br /&gt;            {&lt;br /&gt;                observations.Add(ob.Name) ;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above is C# code. &lt;br /&gt;&lt;br /&gt;Notice that the input data is a SAS XML representation (I am doing it inline right now as a demo. It could easily come from a file)? Notice the SQL-like code toward the bottom? That is LINQ.&lt;br /&gt;&lt;br /&gt;One of the oft-used criticisms of low-level languages is that they were fine for a lot of things except processing data. For that, we needed languages such as SAS or SQL. LINQ doesn't substitute for the database but what it does do is enable us to combine data processing with the full-blown power of a language like C#. The syntax isn't as elegant as SAS (by any means) but what it does provide is a way to juice up the power of data processing against SAS data when needed.&lt;br /&gt;&lt;br /&gt;SAS is OleDb and ODBC compliant. As of yet, Microsoft has not provided support for either one within LINQ. When it does, I will post examples of using LINQ against a SAS dataset directly rather than via XML.&lt;br /&gt;&lt;br /&gt;The above represents a fraction of the power of LINQ and it is in its first iteration. Using the same query language against any data source (SAS, XML, SQL Server, etc.) and then combine that with the power of a language such as C# holds a lot of potential. Power SAS users, especially on the ETL side, should keep an eye on LINQ because it offers up a great way to do data processing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-5209902073196536458?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/5209902073196536458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=5209902073196536458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5209902073196536458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/5209902073196536458'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2007/12/sas-and-linq-part-1.html' title='SAS and LINQ - Part 1'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-4973045256143612202</id><published>2007-11-26T06:59:00.000-08:00</published><updated>2007-11-26T07:21:58.046-08:00</updated><title type='text'>Demarcation</title><content type='html'>Good systems practice is to have demarcations between systems layers. This involves separation of the following layers (at a minimum):&lt;br /&gt;&lt;br /&gt;Application&lt;br /&gt;Business logic&lt;br /&gt;Data access&lt;br /&gt;Data&lt;br /&gt;&lt;br /&gt;SAS programmers though tend to muddle all together:&lt;br /&gt;&lt;br /&gt;libname indata ...;   &lt;strong&gt;&lt;-- Data Access&lt;/strong&gt;&lt;br /&gt;data mydata...; &lt;strong&gt;&lt;--- Business Logic&lt;/strong&gt;&lt;br /&gt;ods html; proc report...; &lt;strong&gt;&lt;--- Application Layer / UI&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A better way to handle is to treat all layers as standalone and get them out of each other's space. The easiest way for a SAS coder to accomplish this is to use macro libraries to get it all started:&lt;br /&gt;&lt;br /&gt;%GetFinanceData() ; &lt;br /&gt;%DetermineProfit() ;&lt;br /&gt;%OutputResults() ;&lt;br /&gt;&lt;br /&gt;However, even this is constrained since everything is called together and a single program controls what happens top-to-bottom. Rather than doing the final piece as a part of the batch job, consider doing it on demand and perhaps through other means:&lt;br /&gt;&lt;br /&gt;%GetFinanceData() ; &lt;br /&gt;%DetermineProfit() ;&lt;br /&gt;&lt;br /&gt;...wait until use requests information....&lt;br /&gt;&lt;br /&gt;Get information on demand and make the presentation logic extraneous to SAS. Someone could even keep it in SAS ODS but the idea would be to pull it out to an application layer that is completely separated from how the information was formulated.&lt;br /&gt;&lt;br /&gt;SAS programmers would be better off putting in extremely strong lines of demarcations between layers. This makes code easier to maintain, easier to change, and easier to understand. &lt;br /&gt;&lt;br /&gt;Longer term, web service calls will simplify this even more but the concept of processing silos can be done now. Break your code apart so everything isn't glued together so tightly that code reuse is hard and code libraries are non-existent or little used.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-4973045256143612202?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/4973045256143612202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=4973045256143612202' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/4973045256143612202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/4973045256143612202'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2007/11/demarcation.html' title='Demarcation'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-4040058659511299625</id><published>2007-11-26T04:11:00.000-08:00</published><updated>2007-11-26T04:19:19.072-08:00</updated><title type='text'>C# and DBF files</title><content type='html'>I have a client that asked me to read DBF files generated by their SAS application. Well, this posting is to explain to someone what i have learned in reading DBF files using C#. The main thing I learned was &lt;strong&gt;no spaces in the file path&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Here is the code that worked for me:&lt;br /&gt;&lt;br /&gt;            string connectionString = "Driver={Microsoft dBase Driver (*.dbf)};SourceType=DBF;SourceDB=C:\projects\Client\Data\WeeklyAvailableComparison;Exclusive=No; Collate=Machine;NULL=NO;DELETED=NO;BACKGROUNDFETCH=NO;";&lt;br /&gt;            string selectCommand = @"SELECT * FROM C:\projects\Client\Data\WeeklyAvailableComparison\ac_141.dbf";&lt;br /&gt;            DataTable dt = new DataTable();&lt;br /&gt;&lt;br /&gt;            OdbcConnection oConn = new OdbcConnection();&lt;br /&gt;            oConn.ConnectionString = connectionString;&lt;br /&gt;            oConn.Open();&lt;br /&gt;            OdbcCommand oCmd = oConn.CreateCommand();&lt;br /&gt;            oCmd.CommandText = selectCommand;&lt;br /&gt;&lt;br /&gt;            dt.Load(oCmd.ExecuteReader());&lt;br /&gt;&lt;br /&gt;I tried doing a 8.3 conversion and it wouldn't work for the select clause. &lt;br /&gt;&lt;br /&gt;I hope this helps someone.&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-4040058659511299625?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/4040058659511299625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=4040058659511299625' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/4040058659511299625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/4040058659511299625'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2007/11/c-and-dbf-files.html' title='C# and DBF files'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-3394945189767603799</id><published>2007-07-11T16:33:00.000-07:00</published><updated>2007-07-11T17:02:19.001-07:00</updated><title type='text'>Using SAS\Share and C#</title><content type='html'>Ok, I went a little crazy getting SAS\Share working with OleDb from C#. Since I got it figured out, someone else may have the same issue.&lt;br /&gt;&lt;br /&gt;Here is how I did it. First of all, make sure you client machine and the SAS\Share server can talk to each other. I tested from a development machine that has SAS on it. Otherwise, a test app will have to be built.&lt;br /&gt;&lt;br /&gt;In the web.config, I have these settings:&lt;br /&gt;&lt;br /&gt;&amp;lt;add key=\"ShareConnectionString\" value=\"Provider=sas.ShareProvider.1;Data Source=share1;Location=192.168.1.199;User ID=Administrator;Password=&amp;lt;span color=\"&amp;gt;&lt;span style="color:#ff0000;"&gt;*****&lt;/span&gt;&amp;lt;/span&amp;gt;;Mode=ReadShare Deny None\"/&amp;gt;&lt;br /&gt;&amp;lt;add key=\"SasLibrary\" value=\"demo\"&amp;gt;&lt;br /&gt;&amp;lt;add key=\"SasDataSet\" value=\"user_info\"&amp;gt;&lt;br /&gt;&lt;br /&gt;Here is the C# code:&lt;br /&gt;&lt;br /&gt;private static DataTable LoadSasDataSet()&lt;br /&gt;{&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;string library = ConfigurationManager.AppSettings["SasLibrary"] ;&lt;br /&gt;string dataset = ConfigurationManager.AppSettings["SasDataSet"] ;&lt;br /&gt;string conn = ConfigurationManager.AppSettings["ShareConnectionString"];&lt;br /&gt;&lt;br /&gt;DataSet sasDs = new DataSet();&lt;br /&gt;OleDbConnection sas = new OleDbConnection(conn);&lt;br /&gt;sas.Open();&lt;br /&gt;&lt;br /&gt;OleDbCommand sasCommand = sas.CreateCommand();&lt;br /&gt;sasCommand.CommandType = CommandType.TableDirect;&lt;br /&gt;sasCommand.CommandText = library + "." + dataset;&lt;br /&gt;&lt;br /&gt;OleDbDataAdapter da = new OleDbDataAdapter(sasCommand);&lt;br /&gt;da.Fill(sasDs);&lt;br /&gt;sas.Close();&lt;br /&gt;&lt;br /&gt;return sasDs.Tables[0];&lt;br /&gt;}&lt;br /&gt;catch (Exception ex)&lt;br /&gt;{&lt;br /&gt;Common.AddLogEntry("ERROR", "Unable to load SAS dataset", "", DateTime.Now, ex.ToString());&lt;br /&gt;return null;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Keep in mind that there is also SQL capability within Share so that would be an option as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-3394945189767603799?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/3394945189767603799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=3394945189767603799' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3394945189767603799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/3394945189767603799'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2007/07/using-sasshare-and-c.html' title='Using SAS\Share and C#'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-922125392011065797</id><published>2007-02-13T10:01:00.000-08:00</published><updated>2007-03-03T09:48:17.105-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SAS'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET AJAX'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Services'/><title type='text'>SAS, ASP.NET AJAX, Web Services</title><content type='html'>In preparation for SAS Global Forum 2007, I have posted 2 videos showing 1) How to set up a web service to read a SAS dataset, 2) How to consume that service in an ASP.NET AJAX page. Simple demos but they should help get people started:&lt;br /&gt;&lt;br /&gt;There are several videos demonstrating the concepts involved. They can be found here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://utilities.savian.net"&gt;http://utilities.savian.net&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Look under the video tab.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-922125392011065797?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/922125392011065797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=922125392011065797' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/922125392011065797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/922125392011065797'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2007/02/sas-aspnet-ajax-web-services.html' title='SAS, ASP.NET AJAX, Web Services'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-116922456241441040</id><published>2007-01-19T08:20:00.000-08:00</published><updated>2007-01-19T08:36:02.430-08:00</updated><title type='text'>Code generation, macros, et al</title><content type='html'>As a SAS programmer evolves, they start to think:&lt;br /&gt;&lt;br /&gt;"Hey, I can create SAS code using data step or macros!"&lt;br /&gt;&lt;br /&gt;So they start to go down the happy path of code generation:&lt;br /&gt;&lt;br /&gt;data _null_;&lt;br /&gt;   file "myplace";&lt;br /&gt;   put   "data test ;&lt;br /&gt;       / "   set a; "&lt;br /&gt;       / "   x = wereHavingFunFunc(y)" ;&lt;br /&gt;   ... etc. &lt;br /&gt;run;&lt;br /&gt;&lt;br /&gt;...and pretty soon they have elaborate SAS code in macros, etc. that does nothing but generate code. If you don't use my utility SasEncase to help you do this, you are doing a LOT of extra work but that is another story.&lt;br /&gt;&lt;br /&gt;Well, I think the next level of thought (at least for me) was:&lt;br /&gt;&lt;br /&gt;"Hey! Why can't I just use ANY programming language to generate SAS code"&lt;br /&gt;&lt;br /&gt;Now, think about that for a sec. ANY programming language can be used to generate SAS code.&lt;br /&gt;&lt;br /&gt;The reason why SAS is an entry into this area is because that is what all of us know and love. But, don't confine yourself to just using SAS for code generation. Instead, pick other languages as the need arises.&lt;br /&gt;&lt;br /&gt;public void CreateSomeSasCode()&lt;br /&gt;   {&lt;br /&gt;      StreamWriter sw = new StreamWriter(@"c:\temp\mySasCode.sas") ;&lt;br /&gt;      sw.WriteLine("data test;") ;&lt;br /&gt;      ....&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;Now, that's better, a little C# to play with.&lt;br /&gt;&lt;br /&gt;Ok, so you would have to wrap a lot of code. &lt;br /&gt;&lt;br /&gt;I think I have evolved. Now I actually write the SAS code with macro parms and store them on a server. Then you can just call the stored process and pass the parameters using web services:&lt;br /&gt;&lt;br /&gt;DataSet ds = SasServer.Services.ExecuteStoredProcedure("mySasCode.sas", @"%let outdata = 'c:\temp'");&lt;br /&gt;&lt;br /&gt;Now, I think we have nirvana: SAS doing what it does best being driven by a modern OOP environment. &lt;br /&gt;&lt;br /&gt;Dropping flyballs in left field,&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-116922456241441040?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/116922456241441040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=116922456241441040' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/116922456241441040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/116922456241441040'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2007/01/code-generation-macros-et-al.html' title='Code generation, macros, et al'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-116221723183104494</id><published>2006-10-30T05:59:00.000-08:00</published><updated>2006-10-30T06:07:11.846-08:00</updated><title type='text'>Inserting records into SQL Server</title><content type='html'>99+% of the time, I read records from SQL Server into SAS. I typically use C# and do it direct in code. However, I recently needed to write records into SQL Server from the SAS side.&lt;br /&gt;&lt;br /&gt;Attempt #1 was to use PROC APPEND. This failed with the following:&lt;br /&gt;&lt;br /&gt;"ERROR: During insert:  Data was not set for one or more columns."&lt;br /&gt;&lt;br /&gt;This was failing on the identity column. &lt;br /&gt;&lt;br /&gt;Attempt #2 was to try a SQL Server insert:&lt;br /&gt;&lt;br /&gt;proc sql ;&lt;br /&gt;   insert into SqlSrvr.Test &lt;br /&gt;      select * from newdata&lt;br /&gt;    ;&lt;br /&gt;quit;&lt;br /&gt;&lt;br /&gt;ERROR: Attempt to insert fewer columns than specified after the INSERT table name.&lt;br /&gt;ERROR: Value 1 on the SELECT clause does not match the data type of the corresponding column&lt;br /&gt;       listed after the INSERT table name.&lt;br /&gt;ERROR: Value 2 on the SELECT clause does not match the data type of the corresponding column&lt;br /&gt;       listed after the INSERT table name.&lt;br /&gt;ERROR: Value 17 on the SELECT clause does not match the data type of the corresponding column&lt;br /&gt;       listed after the INSERT table name.&lt;br /&gt;&lt;br /&gt;Hmmmm, could it be a problem wit hthe identity column and me using the new XML filed type?&lt;br /&gt;&lt;br /&gt;A little bit of sleep and attempt #3 worked:&lt;br /&gt;&lt;br /&gt;libname SQLSrvr oledb provider=sqloledb init_string='Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=MyCustomer;Data Source=SERVER01' schema=dbo ;&lt;br /&gt;&lt;br /&gt;data NewData;&lt;br /&gt;   attrib platform length=$200&lt;br /&gt;          periodicity length=$200&lt;br /&gt;    level0-level10 length=$200 &lt;br /&gt;    image length=$1024&lt;br /&gt;    data length=$1024&lt;br /&gt;    help length=$1024&lt;br /&gt;    ;&lt;br /&gt;   DateTime = DateTime() ;&lt;br /&gt;   Platform = "MVS" ;&lt;br /&gt;   Periodicity = "Daily" ;&lt;br /&gt;   Level0 = "CPU Utilization" ;&lt;br /&gt;   Image = "c:\temp\myimage.jpg" ;&lt;br /&gt;   Data = "&lt;?xml version=""1.0""?&gt;&lt;Options&gt;&lt;/Options&gt;" ;&lt;br /&gt;   Help = "c:\temp\myhelp.doc" ;&lt;br /&gt;run;&lt;br /&gt;&lt;br /&gt;proc sql ;&lt;br /&gt;   insert into SqlSrvr.Test &lt;br /&gt;      select * from newdata&lt;br /&gt;    ;&lt;br /&gt;quit;&lt;br /&gt;&lt;br /&gt;proc sql ;&lt;br /&gt;   insert into SqlSrvr.Test (datetime,platform, periodicity, level0, image, data, help) &lt;br /&gt;      select datetime, platform, periodicity, level0, image, data, help from newdata&lt;br /&gt;    ;&lt;br /&gt;quit;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-116221723183104494?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/116221723183104494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=116221723183104494' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/116221723183104494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/116221723183104494'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/10/inserting-records-into-sql-server.html' title='Inserting records into SQL Server'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-115986709995757939</id><published>2006-10-03T02:13:00.000-07:00</published><updated>2006-10-03T02:18:19.966-07:00</updated><title type='text'>SAS and AJAX</title><content type='html'>SAS has no built in support for AJAX at this time. However, you can hack up some of it by using enabling technologies such as ASP.NET or just code it yourself in JavaScript.&lt;br /&gt;&lt;br /&gt;However, I have coded AJAX bits in JavaScript using SAS/IntrNet and found the experience less than desirable. A better way to make this happen, IMO, is to use the new Atlas framework from Microsoft:&lt;br /&gt;&lt;br /&gt;http://atlas.asp.net/Default.aspx?tabid=47&lt;br /&gt;&lt;br /&gt;It's quick and easy and makes coding AJAX much easier. JavaScript is god-awful due to lack of true debugging support but it works. Make it easier though by focusing on doing the AJAX piece in Atlas and let them handle the JavaScript bits. My $0.01.&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-115986709995757939?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/115986709995757939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=115986709995757939' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115986709995757939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115986709995757939'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/10/sas-and-ajax.html' title='SAS and AJAX'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-115706352325230759</id><published>2006-08-31T15:29:00.000-07:00</published><updated>2006-08-31T15:32:03.273-07:00</updated><title type='text'>Weird VS2005 Error</title><content type='html'>I'm posting this in case others hit the same issue.&lt;br /&gt;&lt;br /&gt;When trying to doa  ClickOnce deployment, we hit the following error:&lt;br /&gt;&lt;br /&gt;"Cannot publish because a project failed to build."&lt;br /&gt;"SignTool reported an error. "The parameter is incorrect."&lt;br /&gt;&lt;br /&gt;We switched from VB to C# and it worked fine. I'll leave this blog posting out on the net so it can help someone else out doing ClickOnce deployments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-115706352325230759?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/115706352325230759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=115706352325230759' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115706352325230759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115706352325230759'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/08/weird-vs2005-error.html' title='Weird VS2005 Error'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-115492444695910358</id><published>2006-08-06T21:19:00.000-07:00</published><updated>2006-08-06T21:21:02.866-07:00</updated><title type='text'>EG Tasks not displaying</title><content type='html'>Installed EG4.1 and no task were displayed. Here's how I fixed it (based upon an old 2.0 TS post):&lt;br /&gt;&lt;br /&gt;Go to:&lt;br /&gt;&lt;br /&gt;Tools &gt; SAS Enterprise Guide Explorer &gt; &lt;br /&gt;&lt;br /&gt;In Enterprise Guide Explorer&lt;br /&gt;&lt;br /&gt;Tools &gt; Options &gt; Uncheck Enable Task Administration&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-115492444695910358?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/115492444695910358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=115492444695910358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115492444695910358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115492444695910358'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/08/eg-tasks-not-displaying.html' title='EG Tasks not displaying'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-115492387237542275</id><published>2006-08-06T20:57:00.000-07:00</published><updated>2006-08-06T21:11:12.386-07:00</updated><title type='text'>SAS EG and .NET 2.0</title><content type='html'>Ok, so the official word is no .NET 2.0 apps in EG. I understand this position 100% and I agree with the position. Regardless, .NET 2.0 costs me 25-50% less effort than 1.1 so my goal was to see if I could hack out something that would allow me to post a 2.0 app in EG 4.1.&lt;br /&gt;&lt;br /&gt;It is a hack, it's not official, it's limited, etc. but I successfully got my 2.0 app to run under EG and had it post my code to an EG task. Here's how I did it but it is simplistic and not pretty. I share it in case you need something similar.&lt;br /&gt;&lt;br /&gt;First, create a 2.0 app. Make it a WinForm and have fun on layout, generics, etc.&lt;br /&gt;&lt;br /&gt;Then change parts of your program.cs to something like the following:&lt;br /&gt;&lt;br /&gt;            MainForm frm = new MainForm();&lt;br /&gt;            Application.Run(frm);&lt;br /&gt;            Console.WriteLine(frm.SasCode);&lt;br /&gt;&lt;br /&gt;All Winform apps can write to a console but this output goes to a standard out.&lt;br /&gt;&lt;br /&gt;Then change your EG add-in to support it:&lt;br /&gt;&lt;br /&gt;public SAS.Shared.AddIns.ShowResult Show(System.Windows.Forms.IWin32Window Owner)&lt;br /&gt;{&lt;br /&gt;        Process proc ;&lt;br /&gt;        proc = new Process() ;&lt;br /&gt; proc.StartInfo.UseShellExecute = false ;&lt;br /&gt; proc.StartInfo.RedirectStandardOutput = true ;&lt;br /&gt; proc.StartInfo.RedirectStandardError = true ;&lt;br /&gt; proc.StartInfo.CreateNoWindow = true ;&lt;br /&gt; proc.StartInfo.FileName = "AnalystToolkit.exe";&lt;br /&gt; proc.Start() ;&lt;br /&gt; proc.WaitForExit() ;&lt;br /&gt; sasCode = proc.StandardOutput.ReadToEnd() ;&lt;br /&gt; return SAS.Shared.AddIns.ShowResult.RunLater;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;I could have done a lot more with standard out (and I probably will) but this shows you a quick and easy way to hack up a solution that works. From this standard out, you should be able to make out a way to do anything you need.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;From out in left field and having fun,&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-115492387237542275?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/115492387237542275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=115492387237542275' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115492387237542275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115492387237542275'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/08/sas-eg-and-net-20.html' title='SAS EG and .NET 2.0'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-115024679537473722</id><published>2006-06-13T17:56:00.000-07:00</published><updated>2006-06-13T17:59:55.386-07:00</updated><title type='text'>Excel 2007 and SAS Programmers</title><content type='html'>SAS-L is always having questions on Excel (and sometimes Word and PowerPoint). Office 2007 has now gone to beta 2 and should go production by the end of the year. &lt;br /&gt;&lt;br /&gt;There are some areas that might be of relevance to SAS programmers who have to interface with the new Excel 2007.&lt;br /&gt;&lt;br /&gt;- Color coding of cells by value is now very, very easy for users to do.  So easy in fact that it is 1 click for the entire sheet.&lt;br /&gt;- Cell formatting, coloring, etc. is now wide-open and very, very easy to do. &lt;br /&gt;- Color choices now expand to 16M&lt;br /&gt;- Rows go to 1M, columns to 65K&lt;br /&gt;- Pivot tables no longer expand into other columns but remain fixed in the 1 column&lt;br /&gt;- The file format for Excel files will be changing. Currently, it is binary. The new file format will be XML based, may contain multiple files, and all of them will be zipped up into a single package&lt;br /&gt;- Etc., etc.&lt;br /&gt;&lt;br /&gt;The reason I mention this is because a) it’s on my mind, b) I'm at TechEd and just saw mor eof this stuff, and c) I think it may have significant impact on SAS programmers. BTW, the beta 2 of Office may be one of the largest download activities ever seen by Microsoft (500K+ in 2 days).&lt;br /&gt;&lt;br /&gt;I can see users using Excel a lot more for data storage. Also, expect a lot more data to be displayed by color-coding rather than value-based.&lt;br /&gt;&lt;br /&gt;Why should SAS users care?&lt;br /&gt;&lt;br /&gt;It will break a lot of existing paradigms for reading Excel and from what we expect from users. Data will now be stored a lot more in unstructured forms and there will be a lot more data. Also, users will expect Excel sheets to be done nicely and not just be a data dump.&lt;br /&gt;&lt;br /&gt;The move of SAS programmers away from using DDE is long overdue. As difficult as it may be for many, the use of Excel object models will becoome more and more of a job necessity IMO. &lt;br /&gt;&lt;br /&gt;For what it's worth...&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-115024679537473722?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/115024679537473722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=115024679537473722' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115024679537473722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/115024679537473722'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/06/excel-2007-and-sas-programmers.html' title='Excel 2007 and SAS Programmers'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-114646073070630299</id><published>2006-04-30T22:09:00.000-07:00</published><updated>2006-04-30T22:18:50.716-07:00</updated><title type='text'>MHTML, AOL, C#, and the new WebBrowser</title><content type='html'>Recently, I had a customer who used AOL as their primary email account. This was a CEO so it was important to accomodate their desired email vendor. Well, AOL doesn't support MIME HTML (MHTML). Since the data being reporting was coming out of SQL Server Reporting Services, the choices for output were limited. The CEO liked the layout of the MHTML, but there was a hex dump at the end of the emails. He wanted to keep the look of the emails but without the hex dump. &lt;br /&gt;&lt;br /&gt;The solution to this problem, and I hope this helps someone else, was to write a custom C# program to rip out the meta tags in the emails. There were several tricks that needed to be applied so I will list them here for someone else.&lt;br /&gt;&lt;br /&gt;1. Switch the program.cs code to instantiate a form but don't run it directly. Make the application run a null value. This keeps the form from popping:&lt;br /&gt;&lt;br /&gt;        static void Main(string[] args)&lt;br /&gt;        {&lt;br /&gt;            Application.EnableVisualStyles();&lt;br /&gt;            Application.SetCompatibleTextRenderingDefault(false);&lt;br /&gt;            Main main = new Main(args);&lt;br /&gt;            Application.Run();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;2. Use the new webbrowser control in .NET 2.0. You can then grab the DocumentText from the browser control AFTER it finishes rendering:&lt;br /&gt;&lt;br /&gt;    class Main&lt;br /&gt;    {&lt;br /&gt;        string report;&lt;br /&gt;        string reportName;&lt;br /&gt;        string distributionList;&lt;br /&gt;        static string server = "mail.savian.net";&lt;br /&gt;        WebBrowser browser = new WebBrowser();&lt;br /&gt;&lt;br /&gt;        public Main(string[] args)&lt;br /&gt;        {&lt;br /&gt;            if (args.Length &lt; 2)&lt;br /&gt;                MessageBox.Show("Too few arguments to process");&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                distributionList = args[1];&lt;br /&gt;                ConvertReportToHtml(args[0]);&lt;br /&gt;                reportName = args[0].Substring(args[0].LastIndexOf('\\') + 1).Replace(".mhtml", "");&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void ConvertReportToHtml(string p)&lt;br /&gt;        {&lt;br /&gt;            browser.Navigate(p);&lt;br /&gt;            browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            report = browser.DocumentText;&lt;br /&gt;            StripMhtmlSection();&lt;br /&gt;            SendReport();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void StripMhtmlSection()&lt;br /&gt;        {&lt;br /&gt;            Regex regex = new Regex(@"&lt;META.+?&gt;");&lt;br /&gt;            regex.Replace(report, "");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void SendReport()&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                SmtpClient client = new SmtpClient(server);&lt;br /&gt;                MailAddress from = new MailAddress("CCLeadManagementSystem@savian.net");&lt;br /&gt;                MailAddress to = new MailAddress(distributionList);&lt;br /&gt;                MailMessage message = new MailMessage(from, to);&lt;br /&gt;                message.IsBodyHtml = true;&lt;br /&gt;                message.Subject = reportName;&lt;br /&gt;                message.Body = report;&lt;br /&gt;                client.Send(message);&lt;br /&gt;            }&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                MessageBox.Show(ex.ToString());&lt;br /&gt;            }&lt;br /&gt;            Application.Exit();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I hope this helps someone. It took a lot of time to figure this all out. I tried FileWebRequest as well to no avail. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-114646073070630299?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/114646073070630299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=114646073070630299' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/114646073070630299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/114646073070630299'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/04/mhtml-aol-c-and-new-webbrowser.html' title='MHTML, AOL, C#, and the new WebBrowser'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-114139315957210067</id><published>2006-03-02T07:38:00.000-08:00</published><updated>2006-03-03T05:39:19.640-08:00</updated><title type='text'>Web Services</title><content type='html'>When setting up web services using Visual Studios and ASP.NET, you will notice that the test page does not contain a launch button by default for testing. This is solved by going into the web.config file for the site and entering the following:&lt;br /&gt;&lt;br /&gt;&amp;lt;webservices&amp;gt;&lt;br /&gt;&amp;lt;protocols&amp;gt;&lt;br /&gt;&amp;lt;add name="HttpPost"&amp;gt;&lt;br /&gt;&amp;lt;add name="HttpGet"&amp;gt;&lt;br /&gt;&amp;lt;/protocols&amp;gt;&lt;br /&gt;&amp;lt;/webservices&amp;gt;&lt;br /&gt;&lt;br /&gt;That should get you running.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-114139315957210067?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/114139315957210067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=114139315957210067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/114139315957210067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/114139315957210067'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/03/web-services.html' title='Web Services'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-114104589585708440</id><published>2006-02-27T05:05:00.000-08:00</published><updated>2006-02-27T05:11:35.873-08:00</updated><title type='text'>RoboHelp and IIS 6.0</title><content type='html'>Ok, so for some reason, flash wasn't working on my Windows Server 2003 running IIS 6.0. This impacted me since I wanted to run RoboHelp Flash. After a lot of tinkering and searching, turns out that IIS wouldn't allow the flashhelp_default.fhs file to run because IIS wouldn't allow the MIME type of fhs to run.This is a simple fix. Go into the properties of the web server and add in the mime type of fhs with a desscription of text/xml. Voila!! life is happy again.&lt;br /&gt;&lt;br /&gt;I hope this helps someone else in this same boat.&lt;br /&gt;&lt;br /&gt;Alan&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-114104589585708440?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/114104589585708440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=114104589585708440' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/114104589585708440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/114104589585708440'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/02/robohelp-and-iis-60.html' title='RoboHelp and IIS 6.0'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-113951743011607709</id><published>2006-02-09T12:19:00.001-08:00</published><updated>2006-02-09T12:37:10.120-08:00</updated><title type='text'>Web Services and SAS</title><content type='html'>The traditional field of Application Integration (you know, creating a SAS program on Unix that creates Excel spreadsheets) has been a muddied water for a long time. People tend to stick with the tried and true and just use API-type of mentatlity for delivering information. This is problematic for a lot of reasons:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;An API has to be created and maintained over time&lt;/li&gt;&lt;li&gt;Neither application plays to its strengths but instead each one 'dumbs' down to the lowest common denominator of both applications&lt;/li&gt;&lt;li&gt;You always have to search for the specific API to use to get anything done&lt;/li&gt;&lt;li&gt;There is no central way of managing these APIs and you get a lot of code bloat&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To solve these issues, web services were born. Now web services may sound like voodoo or black magic but they are very, very simple. Everyone, and I mean everyone (including SAS), agreed to have a common means (XML) of transporting information between each other. I won't go into the ugly details of web services because the web is rife with them but let's talk about how they could be used to solve the typical SAS scenario I mentioned above.&lt;/p&gt;&lt;p&gt;You have SAS running on a Unix server and all of your users want it in Excel. &lt;/p&gt;&lt;p&gt;Old solution: Use SAS\Access to create an Excel file, use ODS to create a very bloated Excel file, write out to CSV, etc. Run the code, ftp the file to a server for delivery, have the end users read in the data and parse it themselves, or again use ODS and figure out the coding needed to create an Excel report.&lt;/p&gt;&lt;p&gt;New solution: Create a web service on Unix that reads in the SAS data using OleDB, ODBC, etc. and just expose a service (let's call it GetSasData("ExcelData"). Next have Excel consume that service and parse the data into the exact Excel report you need.&lt;/p&gt;&lt;p&gt;Ok. You may say that the new solution doesn't sound much better than the old. But wait!! Your boss now comes along and says can you please make that same data available to Lotus 1-2-3 and StarOffice. AHHHHH!!!! Under the old method you need to rewrite all of that ODS or just create an entirely new package. The boss then asks you to also support SAP and Oracle. AHHH!!&lt;/p&gt;&lt;p&gt;Ok, web services wouldn't require any changes because Oracle, SAP, etc. support web services. They can just consume that service the same as Excel. But, you claim, CSV is supported by everyone as well.&lt;/p&gt;&lt;p&gt;Actually, it isn't. Take the following CSV file:&lt;/p&gt;&lt;p&gt;Name Age Gender&lt;/p&gt;&lt;p&gt;Bill 29 M&lt;/p&gt;&lt;p&gt;Mary 32 F&lt;/p&gt;&lt;p&gt;Now is name a numeric, string, what does Name mean? CSV doesn't tell you and never will. Web services have support for typing information so you know what it is.&lt;/p&gt;&lt;p&gt;This blog merely scratches the surface. Don Henderson and I have put up some sample web services for people to play with over here:&lt;/p&gt;&lt;p&gt;&lt;a href="http://demo.savian.net/SasWebServicesDemo/Service.asmx"&gt;http://demo.savian.net/SasWebServicesDemo/Service.asmx&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I urge you to check them out and see what the possibilities are.&lt;/p&gt;&lt;p&gt;Out in left field and loving it,&lt;/p&gt;&lt;p&gt;Alan&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-113951743011607709?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/113951743011607709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=113951743011607709' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113951743011607709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113951743011607709'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/02/web-services-and-sas_09.html' title='Web Services and SAS'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-113951738986378978</id><published>2006-02-09T12:19:00.000-08:00</published><updated>2006-02-09T12:36:31.780-08:00</updated><title type='text'>Web Services and SAS</title><content type='html'>The traditional field of Application Integration (you know, creating a SAS program on Unix that creates Excel spreadsheets) has been a muddied water for a long time. People tend to stick with the tried and true and just use API-type of mentatlity for delivering information. This is problematic for a lot of reasons:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;An API has to be created and maintained over time&lt;/li&gt;&lt;li&gt;Neither application plays to its strengths but instead each one 'dumbs' down to the lowest common denominator of both applications&lt;/li&gt;&lt;li&gt;You always have to search for the specific API to use to get anything done&lt;/li&gt;&lt;li&gt;There is no central way of managing these APIs and you get a lot of code bloat&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To solve these issues, web services were born. Now web services may sound like voodoo or black magic but they are very, very simple. Everyone, and I mean everyone (including SAS), agreed to have a common means (XML) of transporting information between each other. I won't go into the ugly details of web services because the web is rife with them but let's talk about how they could be used to solve the typical SAS scenario I mentioned above.&lt;/p&gt;&lt;p&gt;You have SAS running on a Unix server and all of your users want it in Excel. &lt;/p&gt;&lt;p&gt;Old solution: Use SAS\Access to create an Excel file, use ODS to create a very bloated Excel file, write out to CSV, etc. Run the code, ftp the file to a server for delivery, have the end users read in the data and parse it themselves, or again use ODS and figure out the coding needed to create an Excel report.&lt;/p&gt;&lt;p&gt;New solution: Create a web service on Unix that reads in the SAS data using OleDB, ODBC, etc. and just expose a service (let's call it GetSasData("ExcelData"). Next have Excel consume that service and parse the data into the exact Excel report you need.&lt;/p&gt;&lt;p&gt;Ok. You may say that the new solution doesn't sound much better than the old. But wait!! Your boss now comes along and says can you please make that same data available to Lotus 1-2-3 and StarOffice. AHHHHH!!!! Under the old method you need to rewrite all of that ODS or just create an entirely new package. The boss then asks you to also support SAP and Oracle. AHHH!!&lt;/p&gt;&lt;p&gt;Ok, web services wouldn't require any changes because Oracle, SAP, etc. support web services. They can just consume that service the same as Excel. But, you claim, CSV is supported by everyone as well.&lt;/p&gt;&lt;p&gt;Actually, it isn't. Take the following CSV file:&lt;/p&gt;&lt;p&gt;Name    Age    Gender&lt;/p&gt;&lt;p&gt;Bill         29       M&lt;/p&gt;&lt;p&gt;Mary     32       F&lt;/p&gt;&lt;p&gt;Now is name a numeric, string, what does Name mean? CSV doesn't tell you and never will. Web services have support for typing information so you know what it is.&lt;/p&gt;&lt;p&gt;This blog merely scratches the surface. Don Henderson and I have put up some sample web services for people to play with over here:&lt;/p&gt;&lt;p&gt;&lt;a href="http://demo.savian.net/SasWebServicesDemo/Service.asmx"&gt;http://demo.savian.net/SasWebServicesDemo/Service.asmx&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I urge you to check them out and see what the possibilities are.&lt;/p&gt;&lt;p&gt;Out in left field and loving it,&lt;/p&gt;&lt;p&gt;Alan&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-113951738986378978?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/113951738986378978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=113951738986378978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113951738986378978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113951738986378978'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/02/web-services-and-sas.html' title='Web Services and SAS'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-113802911835694271</id><published>2006-01-23T07:03:00.000-08:00</published><updated>2006-01-23T07:11:58.370-08:00</updated><title type='text'>Convert SAS datasets to Excel</title><content type='html'>I've recently posted code samples of using VSTO and some other means of getting SAS data into Excel. I thought I would compile a list of various techniques to move data from SAS to Excel.&lt;br /&gt;&lt;br /&gt;These are the means (outside of SAS) that I am aware of using as well as pros and cons:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;XML (for Office 2000 and better)&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Pros&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Easily written&lt;/li&gt;&lt;li&gt;Works pretty fast&lt;/li&gt;&lt;li&gt;Excel not required on machine&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;Cons&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Creates enormous files. Have to open and then save as&lt;br /&gt;old Excel using COM to reduce file size&lt;/li&gt;&lt;li&gt;Hard to work with the XML model due to its top to right&lt;br /&gt;formatting. No real random cell access that I can find.&lt;br /&gt; &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;VSTO (Visual Studio Tools for Office)&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Pros&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Built-in support in Visual Studio (ie easy editing)&lt;/li&gt;&lt;li&gt;Microsoft 'direction'&lt;/li&gt;&lt;li&gt;Does not require Excel&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Cons&lt;/p&gt;&lt;ul&gt;&lt;li&gt;COM based (slow, 1 instance only)&lt;/li&gt;&lt;li&gt;Requires Visual Studio&lt;/li&gt;&lt;li&gt;Requires coding in a different language&lt;br /&gt;(VB.NET or C#)&lt;/li&gt;&lt;li&gt;Only supported on Windows&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;VBA in Excel&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Pros&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Well-documented. Fairly easy to use.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Cons&lt;/p&gt;&lt;ul&gt;&lt;li&gt;VBA will be deprecated, probably in Office 12&lt;br /&gt;coming next year&lt;/li&gt;&lt;li&gt;COM based (see above)&lt;/li&gt;&lt;li&gt;Requires Excel to run and build&lt;/li&gt;&lt;li&gt;Possibly opens up security concerns&lt;/li&gt;&lt;li&gt;Only supported on Windows&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;strong&gt;.NET using 3rd party tools (Aspose is an example)&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Pros &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Fastest generation method seen. Faster than&lt;br /&gt;COM by probably 1000x&lt;/li&gt;&lt;li&gt;Able to run simultaneous threads&lt;/li&gt;&lt;li&gt;Easy to code and edit in Visual Studios due to&lt;br /&gt;intellisense support&lt;/li&gt;&lt;li&gt;Object model is simple and easy to use&lt;/li&gt;&lt;li&gt;Random cell access&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Cons &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Requires 3rd party product ($400) plus&lt;br /&gt;Visual Studios&lt;/li&gt;&lt;li&gt;Requires a non-SAS language&lt;/li&gt;&lt;li&gt;Only supported on Windows&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Next up: web services and SAS data. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-113802911835694271?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/113802911835694271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=113802911835694271' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113802911835694271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113802911835694271'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/01/convert-sas-datasets-to-excel.html' title='Convert SAS datasets to Excel'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-113721857344620915</id><published>2006-01-13T21:39:00.000-08:00</published><updated>2006-01-13T22:02:53.470-08:00</updated><title type='text'>SAS and Processes</title><content type='html'>Most SAS folks that I have dealt think in terms of the language and how to do things easier or 'niftier' using traditional SAS. No issues there. What has intrigued me the most, though, over the past few years is to think in terms of the processes to write SAS code and whether those processes can be made easier. Also, whether the processes can be done outside of SAS and then incorporated. Well, why go out of SAS is the question. Well, oftentimes it is easier to build a GUI or to write an easy to maintain program in another language. For example, build a SAS program that reads in XML using XPath or loop through the process threads on a system looking for a file name. Well, not going to happen easily hence other languages and approaches are needed either before or after it gets into SAS.&lt;br /&gt;&lt;br /&gt;On SAS-L today was a debate over macros vs whatever else or whether a user should learn macros early, late, never, sometime. I have nothing against macros but I do have an issue with the idea that SAS code generation is exclusively the domain of macros and SCL. I also don't think users should ever be held back on what they should or should not learn. No bounds in programming is my motto and the point of this blog entry.&lt;br /&gt;&lt;br /&gt;Awhile back I wrote a program that was entirely in C# and just generated SAS format code. This provided the users with a great little graphical utility that generated valid format statements from various data sources (&lt;a href="http://savian.net/utilities"&gt;http://savian.net/utilities&lt;/a&gt;). Why? To do this in SAS would require Access engines, would not be graphically rich, and wouldn't allow the drag and drop stuff that I like.&lt;br /&gt;&lt;br /&gt;This is where I think the SAS community can benefit: asking "how do I do this today and is there a better way?". I'm not saying it's right but that it provides an alternative view for how to accomplish a given task. The more we know the more we will embrace macros, embrace perl, embrace C#, embrace wild stuff like LINQ. The more you play, the more you will be able to help the end users.&lt;br /&gt;&lt;br /&gt;Ok, I'm heading back to left field now...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-113721857344620915?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/113721857344620915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=113721857344620915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113721857344620915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113721857344620915'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/01/sas-and-processes.html' title='SAS and Processes'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-113689277693935019</id><published>2006-01-10T03:15:00.000-08:00</published><updated>2006-01-10T03:32:56.966-08:00</updated><title type='text'>Approach to Excel and SAS</title><content type='html'>Oftentimes on SAS-L, the topic of how to integrate with Excel comes up. Most SAS users take very traditional approaches to this and use DDE, ODS, Access engines, etc. I feel, though, that is is best approached from the Microsoft side of the equation. The reason is that you achieve far more control and power over the resulting sheet.&lt;br /&gt;&lt;br /&gt;The approach I typically advocate is:&lt;br /&gt;&lt;br /&gt;1. Use SAS to get your data in shape.&lt;br /&gt;&lt;br /&gt;2. Write a .NET program and use the SAS OleDB provider to read in the dataset. This sample code will turn your SAS dataset into a .NET datatable.&lt;br /&gt;&lt;br /&gt;        internal DataTable LoadSasDataSet(string sasLibrary, string sasDataSet)&lt;br /&gt;       {           &lt;br /&gt;           DataTable dt = new DataTable();           &lt;br /&gt;           OleDbConnection sas = new OleDbConnection("Provider=sas.LocalProvider; Data Source=" + sasLibrary);           &lt;br /&gt;           sas.Open();           &lt;br /&gt;           OleDbCommand sasCommand = sas.CreateCommand();&lt;br /&gt;           sasCommand.CommandType = CommandType.TableDirect;          &lt;br /&gt;           sasCommand.CommandText = sasDataSet;           &lt;br /&gt;           OleDbDataReader sasRead = sasCommand.ExecuteReader();           &lt;br /&gt;            dt.Load(sasRead);           &lt;br /&gt;            endTime = DateTime.Now;           &lt;br /&gt;            return dt;      &lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;3. Download the Aspose Excel .NET model. It can be found at www.aspose.com . While this ultimately will cost around $400, it is worth every penny if you do this a lot.&lt;br /&gt;&lt;br /&gt;4. Write your .NET code. There are loads of examples on the Aspose site.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This approach is simply fast, fast, fast and is very powerful. You have full formatting control over the sheet, random access to anywhere on the sheet, and it is simple to code once you get started. Depending on the level of formatting, sheets should be created in less than 1ms plus Excel is not needed to create the sheets.&lt;br /&gt;&lt;br /&gt;While learning 2 languages and keeping up on them has its complexities, I think you will find the above to be worth the time. What you will get out is a powerful tool to create Excel worksheets from your SAS data.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-113689277693935019?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/113689277693935019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=113689277693935019' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113689277693935019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113689277693935019'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/01/approach-to-excel-and-sas.html' title='Approach to Excel and SAS'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-113689043038369295</id><published>2006-01-10T02:50:00.000-08:00</published><updated>2006-01-10T02:54:48.026-08:00</updated><title type='text'>Visual Studio Tools for Office (VSTO) and SAS Integration</title><content type='html'>Software Used&lt;br /&gt;&lt;br /&gt;Microsoft Office 2003 SP1&lt;br /&gt;Visual Studios 2005&lt;br /&gt;SAS version 9.13&lt;br /&gt;&lt;br /&gt;Excel Project&lt;br /&gt;&lt;br /&gt;1. Start Visual Studios 2005 and create a new Office project, specifying Excel&lt;br /&gt;2. Enable VS2005 to allow access to the VBA engine (security)&lt;br /&gt;&lt;br /&gt;3. On the right hand side of the screen, right-click ThisWorkbook.cs, select View Code&lt;br /&gt;&lt;br /&gt;Here is the complete code listing. Replace the existing code in ThisWorkbook.cs with the following:&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Data.OleDb;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.Windows.Forms;&lt;br /&gt;using Microsoft.VisualStudio.Tools.Applications.Runtime;&lt;br /&gt;using Excel = Microsoft.Office.Interop.Excel;&lt;br /&gt;using Office = Microsoft.Office.Core;&lt;br /&gt;&lt;br /&gt;namespace SasToExcel&lt;br /&gt;{&lt;br /&gt;public partial class ThisWorkbook&lt;br /&gt;{&lt;br /&gt;private Excel.Worksheet xlSheet = null;&lt;br /&gt;private Excel.Chart xlChart = null;&lt;br /&gt;&lt;br /&gt;//The @ sign in front of a string means ignore special characters&lt;br /&gt;string sasLibrary = @"C:\Program Files\SAS\SAS 9.1\core\sashelp";&lt;br /&gt;string sasDataSet = "retail";&lt;br /&gt;&lt;br /&gt;private void ThisWorkbook_Startup(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;ResetWorkbook();&lt;br /&gt;DataTable dt = LoadSasDataSet();&lt;br /&gt;CreateWorksheet();&lt;br /&gt;LoadAndFormatData(dt);&lt;br /&gt;CreateChart();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void ThisWorkbook_Shutdown(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#region VSTO Designer generated code&lt;br /&gt;&lt;br /&gt;/// &lt;summary&gt;&lt;br /&gt;/// Required method for Designer support - do not modify&lt;br /&gt;/// the contents of this method with the code editor.&lt;br /&gt;/// &lt;/summary&gt;&lt;br /&gt;private void InternalStartup()&lt;br /&gt;{&lt;br /&gt;this.Startup += new System.EventHandler(ThisWorkbook_Startup);&lt;br /&gt;this.Shutdown += new System.EventHandler(ThisWorkbook_Shutdown);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;&lt;br /&gt;private void ResetWorkbook()&lt;br /&gt;{&lt;br /&gt;// Get rid of all but the original worksheet.&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;ThisApplication.DisplayAlerts = false;&lt;br /&gt;&lt;br /&gt;foreach (Excel.Worksheet ws in Globals.ThisWorkbook.Worksheets)&lt;br /&gt;if (ws != ThisApplication.ActiveSheet)&lt;br /&gt;{&lt;br /&gt;ws.Delete();&lt;br /&gt;}&lt;br /&gt;foreach (Excel.Chart cht in Globals.ThisWorkbook.Charts)&lt;br /&gt;cht.Delete();&lt;br /&gt;}&lt;br /&gt;finally&lt;br /&gt;{&lt;br /&gt;ThisApplication.DisplayAlerts = true;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private DataTable LoadSasDataSet()&lt;br /&gt;{&lt;br /&gt;DataTable dt = new DataTable();&lt;br /&gt;OleDbConnection sas = new OleDbConnection("Provider=sas.LocalProvider; Data Source=" + sasLibrary);&lt;br /&gt;sas.Open();&lt;br /&gt;OleDbCommand sasCommand = sas.CreateCommand();&lt;br /&gt;sasCommand.CommandType = CommandType.TableDirect;&lt;br /&gt;sasCommand.CommandText = sasDataSet;&lt;br /&gt;OleDbDataReader sasRead = sasCommand.ExecuteReader();&lt;br /&gt;dt.Load(sasRead);&lt;br /&gt;return dt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void CreateWorksheet()&lt;br /&gt;{&lt;br /&gt;xlSheet = (Excel.Worksheet)Globals.ThisWorkbook.Worksheets.Add(Type.Missing, Globals.ThisWorkbook.ActiveSheet,&lt;br /&gt;Type.Missing, Type.Missing);&lt;br /&gt;&lt;br /&gt;xlSheet.Name = "Sas Retail Sample";&lt;br /&gt;&lt;br /&gt;// Copy field names to Excel.&lt;br /&gt;// Bold the column headings.&lt;br /&gt;Excel.Range rng = (Excel.Range)xlSheet.Cells[1, 1];&lt;br /&gt;rng.Formula = "Year";&lt;br /&gt;rng.Font.Bold = true;&lt;br /&gt;&lt;br /&gt;rng = (Excel.Range)xlSheet.Cells[1, 2];&lt;br /&gt;rng.Formula = "Sales";&lt;br /&gt;rng.Font.Bold = true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void LoadAndFormatData(DataTable dt)&lt;br /&gt;{&lt;br /&gt;int row;&lt;br /&gt;// Copy the data in from the SqlDataReader.&lt;br /&gt;// Start at row 2.&lt;br /&gt;row = 1;&lt;br /&gt;foreach (DataRow dr in dt.Rows)&lt;br /&gt;{&lt;br /&gt;row += 1;&lt;br /&gt;xlSheet.Cells[row, 1] = dr["Year"];&lt;br /&gt;xlSheet.Cells[row, 2] = dr["Sales"];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Format the columns.&lt;br /&gt;((Excel.Range)xlSheet.Columns[1, Type.Missing]).AutoFit();&lt;br /&gt;&lt;br /&gt;Excel.Range rng = (Excel.Range)xlSheet.Columns[2, Type.Missing];&lt;br /&gt;rng.NumberFormat = "0.00";&lt;br /&gt;rng.AutoFit();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void CreateChart()&lt;br /&gt;{&lt;br /&gt;// Now create the chart.&lt;br /&gt;Excel.Chart xlChart = (Excel.Chart) Globals.ThisWorkbook.Charts.&lt;br /&gt;Add(Type.Missing, xlSheet, Type.Missing, Type.Missing);&lt;br /&gt;&lt;br /&gt;Excel.Range cellRange = (Excel.Range)xlSheet.Cells[1, 1];&lt;br /&gt;xlChart.ChartWizard(cellRange.CurrentRegion,&lt;br /&gt;Excel.Constants.xl3DBar, Type.Missing,&lt;br /&gt;Excel.XlRowCol.xlColumns, 1, 2, false,&lt;br /&gt;xlSheet.Name, Type.Missing, Type.Missing,&lt;br /&gt;Type.Missing);&lt;br /&gt;&lt;br /&gt;// Apply some formatting to the chart.&lt;br /&gt;xlChart.Name = xlSheet.Name + " Chart";&lt;br /&gt;&lt;br /&gt;Excel.ChartGroup grp = (Excel.ChartGroup)xlChart.ChartGroups(1);&lt;br /&gt;grp.GapWidth = 20;&lt;br /&gt;grp.VaryByCategories = true;&lt;br /&gt;xlChart.ChartTitle.Font.Size = 16;&lt;br /&gt;xlChart.ChartTitle.Shadow = true;&lt;br /&gt;xlChart.ChartTitle.Border.LineStyle = Excel.Constants.xlSolid;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;4. Press F5 to build and see the results&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-113689043038369295?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/113689043038369295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=113689043038369295' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113689043038369295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113689043038369295'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/01/visual-studio-tools-for-office-vsto.html' title='Visual Studio Tools for Office (VSTO) and SAS Integration'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-20769129.post-113688911646643911</id><published>2006-01-10T02:29:00.000-08:00</published><updated>2006-01-10T02:40:06.903-08:00</updated><title type='text'>Creating Excel spreadsheets using Visual Studio Express for C# and SAS datasets</title><content type='html'>These steps show you how to make an Excel sheet using the Excel COM object, SAS, and C#. There are other ways to do this but it is a good way to get started.&lt;br /&gt;&lt;br /&gt;Here are the steps needed to create the sheets:&lt;br /&gt;&lt;br /&gt;Download Visual Studios Express for C# from Microsoft’s website: it is free.&lt;br /&gt;&lt;br /&gt;&lt;a title="http://lab.msdn.microsoft.com/express/vcsharp/default.aspx" href="http://lab.msdn.microsoft.com/express/vcsharp/default.aspx"&gt;http://lab.msdn.microsoft.com/express/vcsharp/default.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Download and install the OLEDB Providers for SAS from the SAS website:&lt;br /&gt;&lt;br /&gt;&lt;a title="http://www.sas.com/apps/demosdownloads/oledbproviders_PROD_9.1.3_sysdep.jsp?packageID=" href="http://www.sas.com/apps/demosdownloads/oledbproviders_PROD_9.1.3_sysdep.jsp?packageID=000366"&gt;http://www.sas.com/apps/demosdownloads/oledbproviders_PROD_9.1.3_sysdep.jsp?packageID=000366&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Create a directory c:\temp. Copy the shoes dataset from the sashelp files (this is for testing only) and place it in temp. You can find it where sas is installed under core\sashelp.&lt;br /&gt;&lt;br /&gt;Once installed, create a new project (Fileà Newà Project). Select console type for now. After you become familiar with the steps, you can build a windows app.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You need to add in a reference to Excel. This basically is telling the project that the Excel classes will be available to your code. Look at the Solution Explorer on the right, right-click References and select Add Reference….Click on the COM tab at the top and then scroll down until you see Microsoft Excel 11.0 Object Library (you may have one slightly different such as 9.0, etc. Just select the Excel library you have).&lt;br /&gt;&lt;br /&gt;Paste the following code into the default class that appears:&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Data.OleDb;&lt;br /&gt;using System.IO;&lt;br /&gt;using System.Text;&lt;br /&gt;// using Excel = Microsoft.Office.Interop.Excel;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;namespace SASToExcel&lt;br /&gt;{&lt;br /&gt;class Program&lt;br /&gt;{&lt;br /&gt;static DataTable dt;&lt;br /&gt;static Excel.Application app = new Microsoft.Office.Interop.Excel.Application();&lt;br /&gt;static Excel.Workbook wb;&lt;br /&gt;static Excel.Worksheet ws;&lt;br /&gt;static List&lt;string&gt; regions = new List&lt;string&gt;();&lt;br /&gt;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;app.DisplayAlerts = false;&lt;br /&gt;dt = LoadSasDataSet(@"c:\temp", "shoes");&lt;br /&gt;DetermineDistinctValuesForWorksheets();&lt;br /&gt;CreateWorkbooks();&lt;br /&gt;System.Runtime.InteropServices.Marshal.ReleaseComObject(app);&lt;br /&gt;app = null;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void DetermineDistinctValuesForWorksheets()&lt;br /&gt;{&lt;br /&gt;Excel.Workbooks wbs = app.Workbooks;&lt;br /&gt;Excel.Workbook wb = wbs.Add(Type.Missing);&lt;br /&gt;&lt;br /&gt;foreach (DataRow dr in dt.Rows)&lt;br /&gt;{&lt;br /&gt;if (!regions.Contains(dr["region"].ToString()))&lt;br /&gt;{&lt;br /&gt;regions.Add(dr["region"].ToString()) ;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void CreateWorkbooks()&lt;br /&gt;{&lt;br /&gt;Excel.Workbooks wbs = app.Workbooks;&lt;br /&gt;wb = wbs.Add(Type.Missing);&lt;br /&gt;&lt;br /&gt;foreach (string region in regions)&lt;br /&gt;{&lt;br /&gt;wb.Worksheets.Add(Type.Missing, Type.Missing, Type.Missing, Type.Missing);&lt;br /&gt;ws = (Excel.Worksheet)wb.ActiveSheet;&lt;br /&gt;//Create the worksheet name but clean up invalid values at the same time&lt;br /&gt;ws.Name = region.Replace("/", " ");&lt;br /&gt;Console.WriteLine("Wroksheet added: " + region);&lt;br /&gt;DataRow[] rows = GetSelectedRegion(region);&lt;br /&gt;AddDataToSheets(rows, region);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;wb.SaveAs(@"c:\temp\SASToExcelSample.xls", Excel.XlFileFormat.xlWorkbookNormal,&lt;br /&gt;Type.Missing, Type.Missing, Type.Missing, Type.Missing,&lt;br /&gt;Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing,&lt;br /&gt;Type.Missing, Type.Missing, Type.Missing, Type.Missing);&lt;br /&gt;&lt;br /&gt;wb.Close(Type.Missing, Type.Missing, Type.Missing);&lt;br /&gt;wbs.Close();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static DataRow[] GetSelectedRegion(string region)&lt;br /&gt;{&lt;br /&gt;string selectQuery = "region='" + region + "'";&lt;br /&gt;DataRow[] subset = dt.Select(selectQuery);&lt;br /&gt;return subset;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void AddDataToSheets(DataRow[] rows, string region)&lt;br /&gt;{&lt;br /&gt;int row = 1 ;&lt;br /&gt;//Write Header records&lt;br /&gt;WriteRow(row, 1, "Product");&lt;br /&gt;WriteRow(row, 2, "Subsidiary");&lt;br /&gt;WriteRow(row, 3, "Stores");&lt;br /&gt;WriteRow(row, 4, "Sales");&lt;br /&gt;row++;&lt;br /&gt;foreach(DataRow dr in rows)&lt;br /&gt;{&lt;br /&gt;WriteRow(row, 1, dr["product"].ToString());&lt;br /&gt;WriteRow(row, 2, dr["subsidiary"].ToString());&lt;br /&gt;WriteRow(row, 3, dr["stores"].ToString());&lt;br /&gt;WriteRow(row, 4, dr["sales"].ToString());&lt;br /&gt;row++;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void WriteRow(int row, int col, string value)&lt;br /&gt;{&lt;br /&gt;Excel.Range rng = (Excel.Range)ws.Cells[row, col];&lt;br /&gt;rng.Value2 = value;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static DataTable LoadSasDataSet(string sasLibrary, string sasDataSet)&lt;br /&gt;{&lt;br /&gt;Console.WriteLine("Loading SAS data at library " + sasLibrary + ", dataset " + sasDataSet);&lt;br /&gt;DataTable dt = new DataTable();&lt;br /&gt;OleDbConnection sas = new OleDbConnection("Provider=sas.LocalProvider; Data Source=" + sasLibrary);&lt;br /&gt;sas.Open();&lt;br /&gt;OleDbCommand sasCommand = sas.CreateCommand();&lt;br /&gt;sasCommand.CommandType = CommandType.TableDirect;&lt;br /&gt;sasCommand.CommandText = sasDataSet;&lt;br /&gt;OleDbDataReader sasRead = sasCommand.ExecuteReader();&lt;br /&gt;dt.Load(sasRead);&lt;br /&gt;Console.WriteLine("Records read from SAS: " + dt.Rows.Count.ToString());&lt;br /&gt;return dt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;7. Press F5 to build and run the code. You will also have a new program called SasToExcel.exe in the project’s bin\debug folder&lt;br /&gt;&lt;br /&gt;8. View your new workbook in the temp directory. It is called SasToExcelSample.xls&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/20769129-113688911646643911?l=savian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://savian.blogspot.com/feeds/113688911646643911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=20769129&amp;postID=113688911646643911' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113688911646643911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/20769129/posts/default/113688911646643911'/><link rel='alternate' type='text/html' href='http://savian.blogspot.com/2006/01/creating-excel-spreadsheets-using.html' title='Creating Excel spreadsheets using Visual Studio Express for C# and SAS datasets'/><author><name>Alan Churchill</name><uri>http://www.blogger.com/profile/17299246950932791515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://3.bp.blogspot.com/-mKzLJmNY8gY/TiiMPSLvbBI/AAAAAAAAADU/_7cEJEZwK4M/s220/AlanSmall.jpg'/></author><thr:total>0</thr:total></entry></feed>
