搬家第41天-citect2018使用cicode脚本动态创建ODBC连接
前面几天练习了如何使用ODBC方式连接Access数据库,以便后来的数据表操作。当时做练习的目的是学习数据表的读写。实际项目中,项目文件夹的位置不是固定的,最好是根据项目文件夹的位置自动的匹配。为了达到这个目的,我特意的做了练习,把思路和解决办法记录在下面。
首先手动创建一个ODBC链接,名字叫做myaccess,连接上某个Access数据库。打开注册表文件,搜索myaccess关键字,可以看到在下面的位置。
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess]
"Driver"="C:\\Windows\\system32\\odbcjt32.dll"
"DBQ"="E:\\Citect2018Prj\\Citect2018ReportBaseOnAccess\\report.mdb"
"Description"="连接access数据库"
"DriverId"=dword:00000019
"FIL"="MS Access;"
"SafeTransactions"=dword:00000000
"UID"=""
[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess\Engines]
[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess\Engines\Jet]
"ImplicitCommitSync"=""
"MaxBufferSize"=dword:00000800
"PageTimeout"=dword:00000005
"Threads"=dword:00000003
"UserCommitSync"="Yes"
[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ODBC Data Sources]
"myaccess"="Microsoft Access Driver (*.mdb)"
这些注册表信息包含了创建ODBC时各个选项的值。接下来就是想办法在项目运行初期,能够自动的创建这样的注册表文件,尤其是关于access数据库的路径要动态的生成,后台导入注册表,不要人工干预操作。
新建一个内部变量mypath,用于存放项目路径
新建一个cicode函数,代码如下
FUNCTION CreateODBCLink()
INT sfile,FileClosed,runregfile,sfile1,FileClosed1
FileClosed=10
FileClosed1=10
STRING prjpath,prjfileinreg,regfile,strDBQ,batfile
prjpath=PathToStr("[run]")
regfile=prjpath+"\createODBC.reg"
prjfileinreg=StrReplace(prjpath,"","\")+"report.mdb"
strDBQ="^"DBQ^"=^"" +prjfileinreg+"^""
IF FileExist(regfile) THEN //判断该文件存在是否存在
FileDelete(regfile) //删除该文件
END
sfile=FileOpen(regfile,"a+")
WHILE NOT FileExist(regfile) DO
//循环等待批处理文件生成,但是一个空文件
END
//写注册表文件,配置ODBC连接,自动生成用户DSN
//[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess]
FileWrite(sfile,"[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess]")
FileWrite(sfile,"^r^n")
//"Driver"="C:\\Windows\\system32\\odbcjt32.dll"
FileWrite(sfile,"^"Driver^"=^"C:\\Windows\\system32\\odbcjt32.dll^"")
FileWrite(sfile,"^r^n")
FileWrite(sfile,strDBQ)
FileWrite(sfile,"^r^n")
//"Description"="连接access数据库"
FileWrite(sfile,"^"Description^"=^"连接access数据库^"")
FileWrite(sfile,"^r^n")
//"DriverId"=dword:00000019
FileWrite(sfile,"^"DriverId^"=dword:00000019")
FileWrite(sfile,"^r^n")
//"FIL"="MS Access;"
FileWrite(sfile,"^"FIL^"=^"MS Access;^"")
FileWrite(sfile,"^r^n")
//"SafeTransactions"=dword:00000000
FileWrite(sfile,"^"SafeTransactions^"=dword:00000000")
FileWrite(sfile,"^r^n")
//"UID"=""
FileWrite(sfile,"^"UID^"=^"^"")
FileWrite(sfile,"^r^n")
//[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess\Engines]
FileWrite(sfile,"[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess\Engines]")
FileWrite(sfile,"^r^n")
//[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess\Engines\Jet]
FileWrite(sfile,"[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\myaccess\Engines\Jet]")
FileWrite(sfile,"^r^n")
//"ImplicitCommitSync"=""
FileWrite(sfile,"^"ImplicitCommitSync^"=^"^"")
FileWrite(sfile,"^r^n")
//"MaxBufferSize"=dword:00000800
FileWrite(sfile,"^"MaxBufferSize^"=dword:00000800")
FileWrite(sfile,"^r^n")
//"PageTimeout"=dword:00000005
FileWrite(sfile,"^"PageTimeout^"=dword:00000005")
FileWrite(sfile,"^r^n")
//"Threads"=dword:00000003
FileWrite(sfile,"^"Threads^"=dword:00000003")
FileWrite(sfile,"^r^n")
//"UserCommitSync"="Yes"
FileWrite(sfile,"^"UserCommitSync^"=^"Yes^"")
FileWrite(sfile,"^r^n")
//[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ODBC Data Sources]
FileWrite(sfile,"[HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ODBC Data Sources]")
FileWrite(sfile,"^r^n")
//"myaccess"="Microsoft Access Driver (*.mdb)"
FileWrite(sfile,"^"myaccess^"=^"Microsoft Access Driver (*.mdb)^"")
FileWrite(sfile,"^r^n")
FileClosed=FileClose(sfile)
//注册表文件生成完毕,关闭它
WHILE FileClosed<>0 DO
//循环等待文件完全关闭
END
batfile=prjpath+"\importReg.bat"
IF FileExist(batfile) THEN //判断该文件存在是否存在
FileDelete(batfile) //删除该文件
END
sfile1=FileOpen(batfile,"a+")
WHILE NOT FileExist(batfile) DO
//循环等待批处理文件生成,但是一个空文件
END
FileWrite(sfile1,"reg import "+prjpath+"createODBC.reg")
FileClosed1=FileClose(sfile1)
WHILE FileClosed1<>0 DO
//循环等待文件完全关闭
END
END
上述函数会获取当前项目的路径,在其下生成一个CreateODBC.REG的注册表文件。还会生成一个importReg.bat批处理文件,其作用是导入CreateODBC.REG文件,不受人工干预,不需要点击确认。项目程序文件夹下需要人工新建一个带有宏的excel文件,RunBat.xlsm。我用的是excel2016,默认的状态是没有启用VBA功能的,需要在菜单文件-选项-自定义功能区中启用“开发工具”。

启用后在菜单栏可以看到开发工具菜单,选择visual basic

就可以写vba代码了。在thisworkbook点击鼠标右键,选择“查看代码”,选择worbook的open事件,表示在工作簿打开的时候执行代码,写以下代码
Private Sub Workbook_Open()
Dim mypath As String
mypath = Application.ActiveWorkbook.Path
Shell mypath & "\importReg.bat", vbMinimizedFocus
End Sub
代码中项目路径也是动态的,就不用担心项目文件夹移动位置了。
前述cicode程序制定一个函数主要是文件读写操作,还包含了双引号字符,回车换行字符,练习的时候这里很是花了点心思。注册表文件生成后,本想通过exec函数来执行,但始终无法执行,返回值是276,说权限不够,我也不知道为什么,也找不到答案。于是转变思路,设计一个excel文件进程,在这个进程里面通过VBA来导入注册表文件。
新建一个citectVBA程序,代码如下:
Sub RunExcelFile()
Dim xlApp As Application
Dim objwb As Object
Set xlApp=CreateObject("excel.application")
xlApp.Visible=false
'打开带有宏的excel文件,宏运行后会自动创建ODBC
Set objwb = xlapp.WorkBooks.Open(prjpath & "RunBatfile.xlsm")
xlApp.Workbooks.Close
xlApp.Quit
Set xlApp=Nothing
End Sub
页面添加一个按钮,按钮的鼠标点击事件写以下脚本
CreateODBCLink()
civba call RunExcelFile()
保存编译,运行后点击这个按钮,就会先创建注册表文件和批处理文件,然后后台执行带宏命令的excel文件,创建用户ODBC了。也可以在项目中创建一个新的页面start,页面尺寸设置为10*10,页面打开事件写入
CreateODBCLink()
civba call RunExcelFile()
pagedisplay("main","cluster1")
将项目启动页面设置为start,这样项目运行时,会首先初始化设置ODBC,然后跳转到main画面,并且不再回到start页面,一次设置,不再重复设置,也不用人工点击按钮了。
补充一下,由于博客后台的代码是html,博客内容的一些字符可能会冲突,造成最终的文字与实际代码不一致,后面几天整理好后会把代码截图附上,程序也放入网盘。

浙公网安备 33010602011771号