SAS: Acquire new database(1)

Prelude

I always find interesting when I have a business case or project where the business requirements involves technical development even in the smallest way.

I’m working at a reporting unit of the institution. We used to have an application maintained for this function unit for their reporting and query needs. As the business grows, the function unit decided to purchase a new third party software to capture its business transactions and reporting needs.  My department was not involved in the business decision.

The third party application is web based. Because the users want to analyze the data, the vendor provided a simple query interface through the application so the users can extract the data that meets certain criteria.  First of all, the query interface was poorly designed where tables can be viewed awkwardly and the relationship between the tables were not presented in an explicit way. Secondly, the query grid has many limitations regarding the type of the criteria setting and has no capacity to incorporate calculated field to the query criteria. The vendor also provide a sql query tool through the interface, but since the users are not technical savvy and the query interface assumes users have comprehensive knowledge of the underlying database structure and relationships between the tables, the sql query interface wasn’t utilized as intended.

Later my department was asked to produce the statistic report of that function unit, we couldn’t do it because the old database is not maintained and does not have the updated data. We also found out that the third party software can not be easily integrate to meet the institution’s reporting needs. In order to re-establish the reporting function for the new databases, I asked the function unit to contact the vendor to provide me the access to the software as well as establish the back-end access to the data tables through the help of our IT people.  Later, I got access to the back-end tables through Mysql ODBC.

I was using MS Access as an intermediate tool to view the tables because I wasn’t provide with any information on the third party software, not on the  table and fields structure, not on the business process and flow or the relationship between the tables. Basically, it is self-direct investigation.  From the more than 200 tables, I narrow down about 30 tables I would need to produce reports based on an iterative discussion with the function unit on what kind of report and data they want. As a temporary solution, I used Access to understand the database and develop the queries and reports for users to verify.  The next task will be set up the database and develop reports on SAS platform.

 

Misc: Open EML files without launch mail system

One of my co-worker was sent about 30 EML files and each has attachment that needs to be saved to the hard drive.  If you click the eml file, the mail system will launch and then you need to type in the user name and password to open each eml file.  I was looking into ways can save time  to access the attachment and make the process more efficient. I came across this software EML File Viewer on the developer’s website http://www.freeviewer.org/eml/ that does exactly the work I was looking for.  The view can search the eml files on your drive and identify and preview the attachment for each in separate window.  There is a free version you can download to try out.

 

SAS: data extraction and merge routine (1)

/*select data from raw data set*/

data x;

set y;

where var1 = ‘xxx’ and var2 = ‘yyy’;

run;

/*check frequency on variables of interest*/

proc freq;

tables var1 var2;

run;

/*merge to get additional variables needed for analysis*/

proc sort data = x;

by var3;

proc sort data =z;

by var3;

data xz;

merge x (in =a) z;

by var3;

if a;

run;

 

Access VBA – conditional change decimal place for report fields

The “Terms to Graduation” data is given 2 decimal places to help identify the small differences from year to year, while the data of the rest of the report are in integers.

VBA coding:

Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
If Me![Table Name].Value = “F. Terms to Graduation (Calendar Year)” Then
Me.[2008].DecimalPlaces = “2”
Me.[2009].DecimalPlaces = “2”
Me.[2010].DecimalPlaces = “2”
Me.[2011].DecimalPlaces = “2”
Me.[2012].DecimalPlaces = “2”
Me.[2013].DecimalPlaces = “2”
Me.[2014].DecimalPlaces = “2”
Else
Me.[2008].DecimalPlaces = “0”
Me.[2009].DecimalPlaces = “0”
Me.[2010].DecimalPlaces = “0”
Me.[2011].DecimalPlaces = “0”
Me.[2012].DecimalPlaces = “0”
Me.[2013].DecimalPlaces = “0”
Me.[2014].DecimalPlaces = “0”
End If
End Sub

Report results:

access2-1

Y. I. An

Use Filter Property in Access Report

To filter the report content in Access, one way is to develop the report on a query results and every time that you want to filter the report, just modify the query to include the filter criteria in the design view, then save the query, and the record source of the report will be automatically narrow down from the query results.  This way has many benefits because you don’t have to create many reports with similar structure and your database looks cleaner.  Sometime you do need to frequently produce reports for specific department, region or product.  In that case besides the general report, you may want to make a copy of the report and use filter on load option for that specific product or department so you don’t have to go back and forth with the query.

Here is an example.

access1-1

The report is for all the department, but I need to frequently print for 2 departments, so I put the department_ID in the property for filter. Notice the table name or the query name of the field needs to be filter is referenced as well.  Also the Filter On Load property needs to be Yes.

Y. I. An

 

 

Access VBA Recordset Diagnosis

Objective: Print Access report by defined query results and generate pdf report for each selected record.

Reference: http://www.utteraccess.com/wiki/index.php/Recordsets_for_Beginners

Reference: http://www.utteraccess.com/wiki/index.php/RunSQL_vs_Execute

Reference:https://msdn.microsoft.com/en-us/library/office/ff192065.aspx

Basic coding:

Dim rst As DAO.Recordset

If you run into an error of “User-defined type not defined, you need to add “Microsoft DAO 3.6 object Library” to the reference library under “Tools” menu and then “Reference” item.  Refer https://support.microsoft.com/en-us/kb/289664 for details.

DAO (Data Access Object) is different from ADO (Active Data Object). Both are types of recordsets.  If the VBA is just used in Access only, it is good to use DAO.

Set rst currentDb. OpenRecordset (“Select ID from ids”)

To set a recordset object, using the OpenRecordset method of a database object.

The “… ” referred to above can be one of three things, passed as a literal string or a variable:

  • a Table Name
  • a Query Name
  • an SQL string that returns records (not an Action Query)

rst.close

Set rst= Nothing

“Clean up a recordset object.

These closing lines are very important and MUST be run (we include them in an exit procedure in case we have an error to ensure that the recordset is always closed and the object is dereferenced). Failure to do so may induce some very hard to track bugs.

With a recordset, we need to explicitly open it, and therefore it needs to be explicitly closed before the object pointer is destroyed.

If you used an object variable for the Database, you should also set this to Nothing (but, as it did not need to be “opened”, we need not “close” it).

VBA is supposed to automatically do this for us in case we don’t get it ourselves, but it doesn’t always catch it, and wierd things start happening when they are not caught.”– www.utteraccess.com

EOF

Do While rst.EOF = False

“Cursors and Position

BOF (beginning of file) and EOF (end of file) are always there. Records may not be. So, the first thing to do when opening a recordset is generally to check and make sure there are records in it. IF there are records, the RecordCount property of the recordset will return a nonzero value (not always the number of records though). Or, you can determine this by checking the BOF and EOF properties… if they are both true, there are no records.” –– www.utteraccess.com

Do loop until the end of the file. If the cursor reaches the end the file, the loop will be ended.

DoCmd.OutputTo acOutputReport, stDocName, acFormatPDF, PdfFileNameToStore, False

Syntax: DoCmd.OutputTo(ObjectType, ObjectName, OutputFormat, OutputFile, AutoStart, TemplateFile, Encoding, OutputQuality)

“You can use the OutputTo method to output the data in the specified Access database object (a datasheet, form, report, module, data access page) to several output formats.” -msdn.microsoft

acOutputReport is an ObjectType Parameter.  The types of object to output also includes acOutputForm, acOutputFunction, acOutputModule, acOutputQuery, acOutputserverView, acOutputStoredProcedure and acOutputTable.

stDocName is an ObjectName Parameter. “A string expression that’s the valid name of an object of the type selected by the ObjectType argument.”-msdn.sicrosoft

acFormatPDF is an OutputFormat Parameter.   “An AcFormat constant that specifies the output format. If you omit this argument, Access prompts you for the output format. It can be one of the following AcFormat constants: acFormatASP, acFormatDAP, acFormatHTML, acFormatIIS, acFormatRTF, acFormatSNP, acFormatTXT, acFormatXLS” -msdn.microsoft

PdfFileNameToStore is an OutputFile Parameter.  “A string expression that’s the full name, including the path, of the file you want to output the object to. If you leave this argument blank, Access prompts you for an output file name.” -msdn.microsoft

False is an AutoStart Parameter. “Use True (–1) to start the appropriate Microsoft Windows–based application immediately, with the file specified by the OutputFile argument loaded. Use False (0) if you don’t want to start the application. ” -msdn.microsoft

rst.MoveNext

This is the code to move the cursor.  Similar codes like rst.MoveFirst, rst. MoveLast, rst.MoveNext, rst.MoveRrevious, rst.Move can move the cursor between the BOF and EOF.  “By default, a recordset is opened with the cursor on the first record if there are records in the set. It is a good idea to check the BOF or EOF properties before navigating towards either one. “-– www.utteraccess.com

Here is a complete example:

Private Sub print_cpr()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strinsert As String
Dim mypath As String
Dim mypdf As String
Dim temp As String
Dim myReport As String

mypath = “X:\Work\CPR\1415\”
myReport = “rep_undergrad”
Set db = DBEngine.OpenDatabase(“X:\Work\AAP\Database\1415\1415 AAPR Undergraduate.mdb”)
Set rs = db.OpenRecordset(“Select * from tblCPR1415”, dbOpenSnapshot)

Do While Not rs.EOF

temp = rs(“Program_short”)
Debug.Print “The value of varialble temp is ” & temp
mypdf = rs(“Program_short”) & “.pdf”
DoCmd.OpenReport myReport, acViewPreview, , “[program_short]='” & temp & “‘”
DoCmd.OutputTo acOutputReport, “”, acFormatPDF, mypath & mypdf
DoCmd.Close acReport, myReport
DoEvents

rs.MoveNext

Loop

rs.Close
Set rs = Nothing
Set db = Nothing

End Sub

Description of the code:

The code is used to open a access database, then open a query with unique program_short value that can be passed on to the report.  The result of the query is saved temporarily in the rs variable.  The cursor starts with the first record in the rs recordset.  The value of the first record is saved as the name of the pdf file, eg. AP-UG-EN which stands for a specific Faculty undergraduate English program.  Open the undergraduate program report with the where condition of program short equal to “AP-UG-EN”.  Output the pdf report to the defined the path with AP-UG-EN.pdf as file name. Cursor then move to the next record on the rs recordset until the end of the recordset to generate individual program report and output to pdf document.  Once the cursor reaches the end of the recordset, the loop is finished and the program closes the rs recordset and  clear the memory for both the recordset and database.

Application in Work:

I have designed standardized academic program reporting in Access with 2 layouts, one for Undergraduate and one for Graduate Programs.  Use the above code and generate individual data sheets for hundreds for undergraduate and graduate programs.  Then the datasheets can be distributed to the corresponding Faculty and program Directors.

 

Y. I. An

 

 

 

SAS ODBC Driver Installation

I want to access the sas data table outside sas software and in Microsoft Access where I can edit the records more conveniently.

The version of sas I have is 9.3 and I googled the sas ODBC driver and came across the following link.

http://support.sas.com/downloads/browse.htm?cat=40#tab:2:

SAS3-1

Initially, I installed the “Aug 2014” version, but it is for SAS 9.4 and didn’t work.

I uninstalled the sas ODBC for 9.4 and then installed the “July 2011” version which didn’t work either because I have Win 7.

Then I had to uninstalled ODBC for 9.3 and download the “Dec 2011” version.

Hope this time it works but it doesn’t. 🙁

Got this error message.

SAS3-2

When launching setup.exe for ODBC installation. Got the following error message.

SAS3-3

While having no success in installing SAS ODBC 9.3,  I found some good reference resource on the website.

http://www.sascommunity.org/planet/blog/category/sql/

With some investigation, I found the odbcad32.exe hiding in a winsxs folder.

C:\Windows\winsxs\x86_microsoft-windows-m..-odbc-administrator_31bf3856ad364e35_6.1.7600.16385_none_44263d819f0aa19e

This might came from one of the windows service patch installed previously, but it is not the same ODBC administrator when I run from the “Control Panel” > “Administrative Tools”, which point to a different odbcad32.exe under C:\Windows\System32.

Apparently, the SAS ODBC 9.4 has already been recognized in the “ODBC Data Source Administrator”.  Under the “System DSN” tab, click “Add”.

SAS3-5

Find the “SAS” driver at the bottom of the list and click “Finish”.

SAS3-6

In the “SAS ODBC Driver Configuration” window, there are 3 tabs, “General”, “Servers” and “Libraries”. Notice the Server name is defined as “__5001” which is the default “Local (Single User)” and if you change the name to something else, it will cause error in connection. Click “Configure…” on the “Servers” tab.

SAS3-7

On the “Local Options” setting, check if the Path for sas.exe is correct and don’t change the default setting for “Startup parameters”.  Click “OK” to go back.

SAS3-8

Click “Library” tab and under the “Library Setting” give a Name for the library which holds the SAS data file you want to access through ODBC. In the “Host File”, provide the directory of the folder that contains the SAS data files.  You can create many libraries for different SAS folders. Click “Add” to add the library and then “OK” to go back.

SAS3-9

This completes the configuration of the “SAS ODBC Driver”.

 

 

I. A.

Renew SAS Software

Come to renew my SAS license, I was given a txt file SAS93_xxxxxx_xxxxxxxx_win_X64_Wrkstn.txt.

Click “Start” > “Program”

SAS4-1

A dialog box pops up where you can input the txt file name with the directory.

The renew license information has to match the operating system, if not, the new license will not be able to apply and change the site validation data.

For example, my computer is a ‘w32_7pro’ and the renew license’s OSNAME specifies ‘wx64-wks’, and I got the following error message.

SAS4-2

It will generate a setimit.log (c:\program Files\sashome\x86\SASfoundation)  with the detail information.

If the license file is right and you browse to the folder where it is saved.

SAS4-3

Click “Next” and a dialog box will show the SAS installation data being verified with all the dates renewed to the new dates.

SAS4-4

Then you need to identify the folder where SAS is installed. On my computer it is c:\Program Files\SASHome\x86\SASfoundation\9.3., then click “Renew”.

 

 

SAS4-5

You will get a pop up that the setinit is successfully installed.

SAS4-6

I.A.