简介
程序员常问哪一种语言能访问sas,那就是用sas的it机制,它容许开发式客户访问sas,程序员能用不同的语言快速的建立同sas交互的强壮的应用,此文主要介绍大家如何用vb同sas交互
读前需知
该文假设读者对vb/com/sas知识有一定的了解
sas it的组件
sas it是一个中间件,是为用户提供访问sas和呈现数据的接口,它包含下面功能
1、ldap(轻量级目录访问协议)目录集成
ldap是一个分布式存储数据的工业标准,程序员可以使用微软的adsi(动态目录服务接口)访问ldap目录,你可以把ldap认为一个可以通过tcp/ip访问的数据库,通常,一个组织会有一个单一的ldap 服务器,并被该组织的所有机器共享
2、发布/订阅
这种积极的信息传送机制能使你制造sas输出(发布者)到那些对这些输出感兴趣的人(订阅者)
这种机制是由iom(整合对象模型)接口、sas语言调用语法和ldap对象组成并协同工作的
3、消息队列
sas可以把输出信息输出到消息队列,这样客户端没有必要等待sas执行完成
关于消息队列的详细用法情参考:
http://www.sas.com/rnd/itech/doc/messageq/index.htm
4、iom(综合对象模型)
iom是一组com对象的集合,其中大多数通常被vb使用
sas it比以前版本提供的ole接口的优势
it是以前ole的延伸,下面比较一下三种主要的不同
1、it提供了多层次的接口,而ole只提供了单一的接口
2、it是跨平台(sas所能支持的平台,如:win/unix/os等)的,vb应用能通过远端调用it对象,而ole只能运行于win平台
3、it对象容许sas 程序异步运行,而ole不能
注:it对象的根对象为“sas.workspace” ,其对应了ole的 “sas.application”对象
vb程序员的it工具
包含iom、sas workspace manager、iom数据提供者、iom bridge for com、scripto
iom
客户端可以通过多种连接方式连接到iom 服务器,如corba/jdbc/com/omg等,而没有必要附加代码到客户端
iom是一个对象模型,因为它暴露了一组对象供用户使用
这些对象可以用来实现2个目标:提交代码给sas和获得sas的输出
在所以iom对象中,数组被广泛的使用,所以所有请求是被同时返回的
所需注意的是:如果没有sas it产品的授权,iom接口只能被本地com使用,如过有授权,则可以通过网络访问远端的iom接口
iom对象层次上的根对象是workspace,每个这样的对象都有它自己的work库
workspace对象提供了下面可用的对象
dataservice对象:返回一个操作sas库的接口,它同时也提供了一个读写sas数据的接口,但vb程序员不能直接使用,只能通过sas 数据提供者间接调用
fileservice对象:返回一个读写sas服务器文件和文件引用的接口
getapplication对象:返回一个有sas/af建立的自定义接口
languageservice 对象:返回一个提交sas代码并获得输出的接口
iom使用例子
假设下面代码已经被执行
dim obwsmgr as new _
sasworkspacemanager.workspacemanager
dim obsas as sas.workspace
dim xmlinfo as string
' this creates a sas server running on the
' local machine
set obsas = obwsmgr.workspaces.createworkspacebyserver ("", visibilitynone, nothing, "", "", xmlinfo)
例子1:提交代码
有2种方式可以提交代码到sas server
方式1:使用languageservice
obsas.languageservice.submit _
"data a; do x= 1 to 10; y=x*x*x;" & _
"output;end;run;"
msgbox obsas.languageservice.flushlog(100000)
方式2:使用 storedprocessservice
这种方式请求sas文件存放在已知的目录中,且能过通过宏的方式传参数给文件,而在sas文件中要想接收参数信息,需使用这样的语法:
*processbody;
它会自动把传入的参数转换为宏
如有多个参数,在传入的时候用【空格】分隔
例如:
' run the sas program at c:/temp/looper.sas
dim obstoredprocessservice as _
sas.storedprocessservice
set obstoredprocessservice = _
obsas.languageservice.storedprocessservice
obstoredprocessservice.repository = _
"file:c:/temp"
obstoredprocessservice.execute "looper", _
"looptimes=10"
msgbox obsas.languageservice.flushlog(100000)
looper.sas文件内容如下:
%let looptimes=3;
*processbody;
data a;
do x= 1 to &looptimes;
y=x*x*x;
output;
end;
run;
例子2:执行代码
async属性:如果为false,则为同步执行,否,为异步执行,可以通过事件获得是否已成功执行完成
如下定义一个错误发生事件:
public withevents obsaslanguage as _ sas.languageservice
' to enable events, you must associate the
' obsaslanguage
' interface with the same languageservice
' interface used to make calls.
set oblanguage = obsas.languageservice
oblanguage.submit "this is an error;run;"
private sub oblanguage_steperror()
' an error has occurred. dump the log
debug.print oblanguage.flushlog(100000)
end sub
例子3:获得输出
sas会输出多种类型的信息供用户使用,如下
iom data provider 能够提供二进制数据访问给用户
languageservice的flushlist flushlistlines方法可以获得sas的窗口输出
如果想获得ods输出,可以通过文件引用的方式,sas提供的fileservice提供这样的服务
下面演示如何通用fileservice方式获得输出
dim obfileref as sas.fileref
dim obtextstream as sas.textstream
dim obfilesystem as new scripting.filesystemobject
dim obfile as scripting.textstream
set obfile = obfilesystem.createtextfile ("c:/temp/sasoutput.htm", true)
obsas.languageservice.submit "filename fref temp;" & "ods html body=fref;" & "proc corr data=sashelp.class;" & "run;" & "ods html close;"
set obfileref = obsas.fileservice.usefileref("fref")
set obtextstream = obfileref.opentextstream (streamopenmodeforreading, 10000)
sodsoutput = obtextstream.read(100000)
while (len(sodsoutput) > 0)
' do something with the read text here
obfile.write sodsoutput
sodsoutput = obtextstream.read(100000)
wend
webbrowser1.navigate "c:/temp/sasoutput.htm"
其实在单机环境中就没有必要这样做了 :)
使用resultpackageservice也可获得输出,它可以通过workspace.utilities.resultpackageservice引用
你可以使用resultpackageservice提供的接口建立resultpackage,当然也可以通过sas语言的call语法
一个resultpackage可以是任意的sas输出,如文件,数据集,ods输出、图片等
下面这个例子显示如何建立一个 resultpackage
%macro checkrc(rc);
if rc ne 0 then do;
msg = sysmsg();
put msg;
abort;
end;
%mend;
data _null_;
call package_begin(pid, desc, nameval, rc);
%checkrc(rc);
call insert_file(pid, 'fileref:fref',
"text", "text/html", "some ods output",
'', rc);
%checkrc(rc);
/* nothing in the package actually gets
* written out until we call publish.
* so, if you modify any filerefs after
* calling insert but before calling
* this, then you will get the
* modified fileref.*/
call package_publish(pid, "to_archive", rc,
"archive_path, archive_name", "c:/temp",
"archive");
%checkrc(rc);
/* you could call package_publish as many
* times as you want for any given package,
* as long as you
* do so before calling package_end. */
call package_end(pid, rc);
%checkrc(rc);
run;
下面显示如何读这个 resultpackage
dim props() as string
dim obresultpackage as sas.resultpackage
dim obfileentry as sas.resultpackagefileentry
dim obrps as sas.resultpackageservice
set obrps = obsas.utilities.resultpackageservice
set obresultpackage = obrps.browseresultpackage( "archive", "c:/temp/archive.spk", props)
set obfileentry = obresultpackage.getentry(0)
set obtextstream = obfileentry.open (streamopenmodeforreading, 100000)
sodsoutput = obtextstream.read(100000)
while (len(sodsoutput) > 0)
' do something with the read text here
obfile.write sodsoutput
sodsoutput = obtextstream.read(100000)
wend
webbrowser1.navigate "c:/temp/sasoutput.htm"
关于sas workspace manager
它是一个完成下面功能的activex控件
1、它同sas建立连接,并返回工作空间
2、它提供了一个池保证每个工作空间在web环境中是安全的
3、自动保持同sas的连接
你可以使用以下2种方式建立同sas的连接
非被管理模式(所有连接信息保留在客户端)
被管理模式 (所以连接信息保留在文件或者ldap中)
这些连接信息包含 连接到哪台机器、用什么协议、使用什么端口或者服务名字、用户名、用户id等,同时dcom或者iom支持加密的session
例子1:建立连接,非被管理模式
dim obwsmgr as new _
sasworkspacemanager.workspacemanager
dim obsas as sas.workspace
dim xmlinfo as string
dim observer as new _
sasworkspacemanager.serverdef
observer.machinednsname = "remote.sas.com"
set obsas = _
obwsmgr.workspaces.createworkspacebyserver _
("", visibilitynone, observer, "", "", _
xmlinfo)
xmlinfo参数返回服务器实际上使用的值
关于iom data provider
iom data provider是一个使用iom dataservice读写数据的ole db的数据提供者
你可以使用ado读写数据
例如:
set obsas = _
obwsmgr.workspaces.createworkspacebyserver _
("",visibilityprocess,observer,"","", _
xmlinfo)
dim obconnection as new adodb.connection
obconnection.open _
"provider=sas.iomprovider.1;" & _
"sas workspace id=" & obsas.uniqueidentifier
dim obrs as new adodb.recordset
obrs.open "sashelp.class", obconnection, _
adopendynamic, adlockreadonly, _
adcmdtabledirect
set mschart1.datasource = obrs
关于iom com桥
当sas运行window上时,你可以使用com或者dcom,然而当sas运行于unix或者os上时,则不能使用com技术调用sas,sas提供了iom com桥,它一方便呈现com接口给客户端,一方面使用tcp/ip跟sas进行通信
关于scripto
scripto 是一个用于脚本应用的acitvex对象,其使用解决了脚本同sas组件对象交互使用的几个限制,如vbscript只能返回一个单一参数;vbscript请求所有变量为variant,故数祖也被处理为variant,scripto就解决这2个问题,容许返回多个参数,可以使用数组进行传输
' scripto will do 2 things:
' 1) it will convert the 3 returned arrays to arrays of variants instead of arrays of
' longs so vbscript can handle them
' 2) it allows more than 1 return parameter
set obsas = createobject("sas.workspace")
set obscripto = _
createobject("sasscripto.scripto")
obsas.languageservice.submit _
"proc options;run;"
obscripto.setinterface obsas.languageservice
' obsas.languageservice.flushloglines 1000, carriagecontrols, linetypes, loglines
dim flushloglinesparams(3)
flushloglinesparams(3) = 1000
obscripto.invokemethod "flushloglines", _
flushloglinesparams
' flushloglinesparams(0) now has loglines
' flushloglinesparams(1) has linetypes
' flushloglinesparams(2) has carriagectrls
' this prints the first line
wscript.echo flushloglinesparams(0)(0)
关于it客户端
你需要在客户端安装和注册几个文件
it客户端的必要文件是自动安装执行的,通过调用inttech.exe,其会安装必要的文件通过网络