Thursday, February 17, 2011

SAS Transport Files and .NET

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:

  • Download and install the SAS Universal Viewer from the SAS support site
  • Create a new project in Visual Studio
  • Add a reference from the SAS Universal Viewer install files to the following 2 dlls
  •    SAS.UV.Transport
  •    SAS.UV.Utility
  • Use the following C# code (adapt as needed):
TransportFile tf = new TransportFile(@"x:\temp\sample.xpt");
var x = tf.Datasets;

Your dataset will be in variable x

UPDATED: 11/8/2017

[NOTE: I have also created a direct reader for the XPT binary format. That took a long time (a week, maybe). Contact me if you need that]

Complete code:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SAS.UV.Transport;

namespace ReadSasXportFiles
{
    class Program
    {

        static void Main(string[] args)
        {
            var tf = new TransportFile(@"x:\temp\shoes.xpt");
            var x = tf.Datasets;
         }
     }
}

IMPORTANT NOTE: Make sure your build is set for x64 and not Any CPU. You will see a warning:

Warning There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "SAS.UV.Transport", "AMD64".

Thursday, February 10, 2011

RegexBuddy and Automated Emails

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.'.

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.

What was the response?

"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."

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.

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.

Ok, off of my soapbox.

Sunday, November 28, 2010

SAS-X Blog Aggregator

Tal Galili has started up a SAS blog aggregator. The more folks involved in SAS, the better, as far as I am concerned.

You can find it at:

SAS-X

Sunday, November 07, 2010

Getting SAS/IntrNet Operational on IIS7

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.

How do you get SAS/IntrNet operational.

1. Enable CGI Role on Server through the Server Manager.

2. Add in your website in IIS. Right-click the scripts or cgi-bin directory where
the broker.exe is located and select Convert to Application.

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 --> Request restrictions --> Mapping --> Invoke --> File or Folder, Access --> Execute.

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.

5. Optional: set up a host header.

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).


See here for more details:

http://www.wrensoft.com/zoom/support/faq_cgi_iis.html

Good luck and contact me if you have issues.

Alan

Wednesday, March 17, 2010

Excel Pivot Tables and Filtering

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.

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.

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:


private static void HandlePivotTableChanges(string p)
{
FindProcessInstances();
Console.WriteLine("Starting Excel. Please be patient while it loads.");
string format = "'Product_Container_Release_Metrics_Workbook.xls'!Format_Workbook";
Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();
ExcelApp.DisplayAlerts = false;
Console.WriteLine("Opening workbook.");
Workbook wb = ExcelApp.Workbooks.Open(p, m, m, m, m, m, m, m, m, m, m, m, m, m, m);
Console.WriteLine("Running macro.");
ExcelApp.RunMacro(format);
Worksheet ws = (Worksheet)wb.Worksheets["Pivot Tables"];
string pivotTable = "Forecast to Go";
PivotTable pt = (PivotTable)ws.PivotTables(pivotTable);
pt.ManualUpdate = true;
PivotField pf = (PivotField)pt.PivotFields("Release (A)");
PivotItems items = (PivotItems)pf.PivotItems(m);

foreach (PivotItem item in items)
{
if (item.Value != string.Empty) // <--- CRITICAL LINE. Filters must have at least 1 value selected. Exception otherwise.
((PivotItem) items.Item(item.Value)).Visible = false;
}

pt.ManualUpdate = false;
ExcelApp.Calculation = XlCalculation.xlCalculationAutomatic;
Console.WriteLine("Saving workbook.");
wb.Save();
wb.Close(false, m, m);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wb);
Console.WriteLine("Closing Excel.");
ExcelApp.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ExcelApp);
}

private static void FindProcessInstances()
{
Console.WriteLine("Finding open processes.");
KillProcesses("Excel");
KillProcesses("PowerPnt");
}

private static void KillProcesses(string processName)
{
Process[] processes = Process.GetProcessesByName(processName);
if (processes.Length > 0)
{
foreach (var p in processes)
{
p.Kill();
}
}
}

public static void RunMacro(this Application app, string macro)
{
app.Run(macro,
m, m, m, m, m, m, m, m, m, m,
m, m, m, m, m, m, m, m, m, m,
m, m, m, m, m, m, m, m, m, m
);
}

Wednesday, March 03, 2010

SaviDataSet 1.0.0.5 Released

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 & 2007).

Please see the Help File in the Savian--> SaviDataSet --> Help.txt folder for instructions.

I will be incorporating a write feature in at some point but it is more complex since variables need to be defined.

The latest release can be found here:

SaviDataSet 1.0.0.5

Saturday, February 06, 2010

SaviDataSet Alpha 1.0 On the Web

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
here.

A sample .NET console application can be found in the program file entries after the installation.


Update 2/13/2010:


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.

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.

[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.

Update 2/29/2010

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.

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.

SAS throwing RPC error

If you are doing code in C#  and get this error when creating a LanguageService: The RPC server is unavailable. (Exception from HRESULT:...