如何在VC++6.O下動態(tài)加載ODBC數(shù)據(jù)源
如何在VC++6.O 下動態(tài)加載 ODBC數(shù)據(jù)源
SQLConfigDataSource()
SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft FoxPro Driver (*.dbf)",
"DSN=MYDB"
"DefaultDir=c:mydir"
"FIL=FoxPro 2.5"
"DriverId=280"))
在注冊DSN時,SQLConfigDataSource函數(shù)的第二個參數(shù)應(yīng)該是ODBC_ADD_DSN,第三個參數(shù)指定了ODBC驅(qū)動程序,它的寫法可以參照ODBC管理器的驅(qū)動程序頁。第四個參數(shù)說明了數(shù)據(jù)源的各種屬性,它是由一系列子串構(gòu)成,每個子串的末尾必須有一個“”。最重要的屬性是“DSN=數(shù)據(jù)源名”,其它屬性包括缺省目錄以及驅(qū)動程序版本信息。在上例中,使用FoxPro 2.5的版本,所以DriverId應(yīng)該是280,對應(yīng)地,F(xiàn)oxPro 2.6的DriverId是536,F(xiàn)oxPro 2.0的是24。
如果讀者對SQLConfigDataSource函數(shù)的第四個參數(shù)的設(shè)置方法不清楚,那么可以打開Windows的注冊表看一看已注冊過的DSN的各項屬性。運行RegEdit可以打開注冊表,然后依次打開HKEY_CURRENT_USER->Software->ODBC->ODBC.INI,就可以看到已注冊的DSN,打開各DSN,則可以看到該DSN的各項屬性,讀者可以仿照DSN屬性來設(shè)置第四個參數(shù)。
的名字必須唯一,因此如果要注冊的DSN已被注冊過,那么SQLConfigDataSource就修改原來DSN的屬性。
一、ODBC
開放數(shù)據(jù)庫連接ODBC(Open Database Connec-tivity)是微軟開放服務(wù)結(jié)構(gòu)WOSA中關(guān)于數(shù)據(jù)庫的一
個重要部分,它允許應(yīng)用程序通過ODBCAPI訪問不同數(shù)據(jù)資源中的數(shù)據(jù),從而為數(shù)據(jù)庫編程提供了
一個標(biāo)準(zhǔn)接口。ODBC是對SQL Access Group的CLI標(biāo)準(zhǔn)的一種實現(xiàn),它允許應(yīng)用程序訪問范圍很廣
的數(shù)據(jù)庫(從簡單的ASCII文本到復(fù)雜的主框架數(shù)據(jù)庫),除了Windows平臺外,ODBC還可以在其
他諸如UNIX等的操作平臺上使用,因此ODBC獲得了世界上大多數(shù)領(lǐng)先的數(shù)據(jù)庫和應(yīng)用程序開發(fā)商
的廣泛支持。
ODBC主要包括了四層結(jié)構(gòu):最上層是應(yīng)用程序,第二層是驅(qū)動程序管理器,第三層是不同的驅(qū)
動程序,對應(yīng)不同的數(shù)據(jù)庫,最底層是具體的數(shù)據(jù)源。每個不同的數(shù)據(jù)資源類型由一個ODBC驅(qū)動程
序支持,這個驅(qū)動程序完成了ODBC API程序的核心,而且與數(shù)據(jù)庫通訊。
二、一般加表數(shù)據(jù)源的方法
通常,開發(fā)ODBC應(yīng)用程序之前必須要手動加入所用的數(shù)據(jù)源,利用位于控制面板中的ODBC管
理器可以方便地實現(xiàn)數(shù)據(jù)庫加載。雙擊控制面板中32-bit ODBC的圖標(biāo)就會出現(xiàn)管理器對話框,點擊
Add按鈕加人數(shù)據(jù)源,選擇使用的驅(qū)動程序、數(shù)據(jù)庫名稱、服務(wù)器地址或其他缺省設(shè)置后就把數(shù)據(jù)源
加載到ODBC管理器中了。ODBC管理器負(fù)責(zé)安裝驅(qū)動程序、管理數(shù)據(jù)源,幫助程序員跟蹤ODBC的函
數(shù)調(diào)用,并能將應(yīng)用程序的SQL語句及其他消息傳遞給驅(qū)動程序,而驅(qū)動程序則負(fù)責(zé)將結(jié)果集傳回應(yīng)
用程序。
利用VC++6.0的AppWizard創(chuàng)建一個基于單文檔的工程,選擇數(shù)據(jù)庫支持并根據(jù)提示加人所需
數(shù)據(jù)庫,這樣就可以在應(yīng)用程序中實現(xiàn)對該數(shù)據(jù)源的增加、修改和刪除等操作了。
毫無疑問,采用上述方法就能方便地對指定數(shù)據(jù)庫進(jìn)行操作。但是,實際運用中,用戶往往要求
在同一個應(yīng)用程序中能任意訪問不同的數(shù)據(jù)源,開發(fā)人員無法確定要加載的數(shù)據(jù)源,采用一般的加載
方法就有了無法克服的缺陷。顯然,這時就要求動態(tài)地進(jìn)行ODBC數(shù)據(jù)源加載,用戶只要選擇所需的
數(shù)據(jù)源,應(yīng)用程序就會自動地把它裝載到ODBC管理器。 "
三、動態(tài)加載數(shù)據(jù)庫
創(chuàng)建ODBC數(shù)據(jù)源可以調(diào)用Windows系統(tǒng)子目錄下的動態(tài)鏈接庫Odbcint.dll中的函數(shù)SQLConfigDataSource()
該函數(shù)可以動態(tài)地增加、修改和刪除數(shù)據(jù)源。
lQLConfigDataSource()函數(shù)
SQLConfigDataSource()的原型如下:
BOOLSQLConfigDataSource(HWND hwndParent, UINT
fRequest,LPCSTR IpszDriver, LPCSTR IpszAttributes);
其中四個參數(shù)的用法如下:
●參數(shù)hwndPwent是父級窗口句柄。如果句柄為NULL,將不會顯示一些有關(guān)的對話框。
如果參數(shù) IpszAttributes提供的信息不夠完善,在創(chuàng)建過程中就會出現(xiàn)對話框要求用戶提供相應(yīng)信息。
●參數(shù)fRequest可以設(shè)置為下面的數(shù)值之一:
ODBC_ADD_DSN: 增加_個新數(shù)據(jù)源
ODBC_CONHG_DSN: 配置(修改)一個已經(jīng)存在的數(shù)據(jù)源
ODBC_REMOVE_DSN: 刪除一個已經(jīng)存在的數(shù)據(jù)源
ODBC_ADD_SYS_DSN:. 增加一個新的系統(tǒng)數(shù)據(jù)源
ODBC_CONFIG—SYS—DSN: 更改一個已經(jīng)存在的系統(tǒng)數(shù)據(jù)源
ODBC_REMOVE_SYS_DSN:. 刪除一個已經(jīng)存在的系統(tǒng)數(shù)據(jù)源
●參數(shù)lpszDriver是數(shù)據(jù)庫引擎名稱,可以參見
ODBC管理器中對ODBC驅(qū)動程序的描述。比如要加
載的是Excel數(shù)據(jù)庫,那么數(shù)據(jù)庫引擎名稱就為Microsoft Excel Driver(*.xls)
●參數(shù)lpszAttributes為一連串的"KeyName=value"
字符串,每兩個KeyName值之間用""字符隔開。KeyName主要是新數(shù)據(jù)源缺省的驅(qū)動程序注冊說明,其中最主要的關(guān)鍵字是"DSN"----- 新數(shù)據(jù)源的名稱,其余關(guān)鍵字則根據(jù)不同的數(shù)據(jù)源有不同要求。關(guān)于lpszAttributes參數(shù)的具體設(shè)置,詳細(xì)可以參考Windows系統(tǒng)目錄下幫助文件Odbcjtn.hlp主題目錄標(biāo)簽中的"ODBC API函數(shù)改變|SQLConfigDatasource"條目。
2.SqlConfigDataSource的應(yīng)用條件
使用SqlConfigDataSource函數(shù)之前,必須把
ODBCINST.H文件包含在工程頭文件中,將ODBC-
CP32.LIB加人工程,同時保證ODBCCP32.DLL運行時處于系統(tǒng)子目錄下。
3.SqlConfigDataSource的應(yīng)用示例
以下的例子采用SQLConfigDataSource ODBC API函數(shù)在VC++6.0下動態(tài)加載任意一個Excel數(shù)
據(jù)源。
由于要求是動態(tài)地加載數(shù)據(jù)源,事先沒法手動向ODBC管理器加載數(shù)據(jù)源,因此無法選擇數(shù)據(jù)庫
支持,不能建立基于單文檔或多文檔的應(yīng)用程序。啟動VC++6.0,利用AppWizard建立一個基于對
話框的應(yīng)用程序,工程名稱為"My"。在對話框模板上放置一個按鈕,其ID號為IDC-GETDATA,
Caption為"調(diào)數(shù)據(jù)源"。再派生出一個基于CFile-Doialg類的新類CMyFileDialog,以標(biāo)準(zhǔn)文件對話框
方式選擇打開文件,具體做法請參閱有關(guān)資料,這里不作說明。
由于應(yīng)用程序沒有對數(shù)據(jù)庫的支持,故必須手工在STDAFX.H文件中加入對數(shù)據(jù)庫的支持,添加有
數(shù)據(jù)庫支持的STDAFX.H文件清單如下所示:
#define VC-EXTRALEAN
/ / Exclude rarely-used stuff from Windows headers
#include <afxwin. h>
//MFC core and standard components
#include <afxext. h> // MFC extensions
#include <afxdb. h //MFC database classes
#include <afxdisp. h> // MFC OLE automation classes
#ifndef _AFX_NO_AFXCMN- SUPPORT
#include <afxcmn. h>
// MFC support for Windows Common Controls
#endif//- AFX-NO_AFXCMN_SUPPORT
//{{AFX_Insert_LOCATION}}
#endif
利用classwizard給按紐添加函數(shù)OnGetData,定位到該函數(shù)并添加SqlConfigDataSource()以動態(tài)調(diào)用數(shù)據(jù)源,值得指出的是,對于要加載的excel數(shù)據(jù)源的lpszAttributes參數(shù)中有個關(guān)鍵字必須要說明,數(shù)據(jù)源名稱:"DSN"
主程序如下
#include"odbcinst.h"
#include"string.h"
#include"stdafx.h"
#include"my.h"
#include"mydlg.h"
IMPLEMENT_DYNAMIC ( CMyFileDialog ,CFileDialog)
CMyFileDialog:: CMyFileDialog ( BOOL bOpenFileDialog,
LPCTSTR lpszDefExt, LPCTSTR lpszFileName,DWORD
dwFlags, LPCTSTR lpszFilter, CWnd * pParentWnd):
CFileDialog (bOpenFileDialog lpszDefExt, lpszFileName,
dwFlags, lpszFilter, pParentWnd)
{}
//CAboutDlg dialog used for App About
class CAboutDlg :public CDialog
public:
CAboutDlg ();
// Dialog Data
/ / { { AFX DATA I CAboutDlg)
enum { IDD = IDDABOUTBOX };
//} }AFX_DATA
/ / ClassWizard generated virtual function overrides
/ / { {AFX VIRTUAL CAboutDlg)
protected:
/ / Implementation
protected:
/ / {AFX_MSG (CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGEMAP()
CAboutDlg: : CAboutDlg() : CDialog(CAboutDlg: : IDD)
//{{AFX_DATA_INIT(CAboutDlg)
//})AFX_DATA_INIT
void CAboutDlg: : DoDataExchange ( CDataExchange * pDX)
{
CDialog:: DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGiN_MESSAGEMAP ( CAboutDlg, CDialog)
// ( {AFX_MSG_MAP(CAboutDlg)
/ / No message handlers
//}}AFX_MSG_MAP
END_MESSAGEMAP()
/ / CMyDlg dialog
CMyDlg: : CMyDlg(CWnd* pParent / * =NULL* /)
CDialog(CMyDlg: : IDD, pParent)
{
//{{AFX_DATA_INIT(CMyDlg)
// NOTE: the ClassWizard will add member
initialization here
//}}AFX_DATA_NIT
m_hlcon =AfxGetApp()->Loadlcon(IDR_MAINFRAME);
}
void CMyDlg: : DoDataExchange ( CDataExchange * pDX)
I
{ CDialog:: DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//})AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
//{{AFX_MSG_MAP(CMyDIg)
ON WM_SYSCOMMAND()
ON_WMPAINT()
ON WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_GETDATA, OnGetdata)
//}}AFX_MSG_MAP
END_MESSAGEMAP()
/ / CMyDlg message handlers
BOOL CMyDlg: : OnlnitDialog()
{
CDialog: : OnlnitDialog ();
ASSERT( (IDM_ABOUTBOX& OxFFFO) = =IDM_ABOUTBOX);
ASSERT(IDMABOUTBOX < OxF000);
CMenu * pSysMenu = GetSystemMenu ( FALSE);
if(pSysMenu!=NULL)
{CString strAboutMenu;
strAbooutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m.hlcon, TRUE); // Set big icon
SetIcon ( m.hlcon, FALSE); / / Set small icon
/ / TODO: Add extra initialization here
return TRUE; / / return TRUE unless you set the focus to a control
}
void CMyDlg:: OnSysCommand( UINT nlD, LPARAM
lParam)
{ if ((nID & OxFFFO) = = 1DM_ABOUTBOX)
{ CAboutDlg dlgAbout;
dlgAbout. DoModal ();
}
else
{CDialog: : OnSysCommand(nID, lParam);}
}
void CMyDlg: : OnPaint()
{if (lslconic0)
{CPaintDC dc (this); / / device context for painting
SendMessage (WM_ICONERASEBKGND, (WPARAM)
dc.GetSafeHdc0, 0);
/ / Center icon in client rectangle
int cxIcon = GetSystemMetrics ( SMCXICON);
int cyIcon = GetSystemMetrics ( SMCYICON);
CRect rect;
GetClientRect( & rect);
int x = (rect.Width() -cxlcon + 1) / 2;
int y = (rect. Height()-cylcon + 1) / 2;
// Draw the icon
dc.Drawlcon(x, y, m_hlcon);
}
else
{CDiaLog: : OnPaint();}
}
HCURSOR CMyDlg: : OnQueryDraglcon()
{return (HCURSOR) m_hIcon;}
void CMyDlg: OnGetdata ()
/ / TODO: Add your control notification handler code here
CMyFileDialog filedlg (TRUE);
filedlg. DoModal (); / /彈出打開對話框
CString drivername;//數(shù)據(jù)庫引擎名稱
CString filetitle = filedlg. GetFileTitle ();
//取得指定文件名(不包含后綴)
CString extention =filedlg. GetFileExt();
/ /取得后綴
if(extention = = "xls")
drivername = "Microsoft Excel Driver (* xis) ";}
char str[50];
strcpy(str, "DSN =");
CString keyname = strcat( str, filetitle);
//keyname 指明了數(shù)據(jù)源名稱
if (FALSE = = SQLConfigDataSource (NULL, ODBC_
ADD_DSN, drivername, keyname)
{MessageBox("加載失敗");}
else
{MessageBox("成功將數(shù)據(jù)源加載到管理器");}
}
進(jìn)行上述編程之后,用戶只要點擊"調(diào)數(shù)據(jù)源"按鈕,在對話框里任意選擇所需Excel數(shù)據(jù)源,程序就會自動把數(shù)據(jù)源加載到ODBC管理器而不再需要手動加入,用戶可以通過雙擊"控制面板"中的32位ODBC圖據(jù),查看"用戶DSN"一欄,即可看見數(shù)據(jù)源己經(jīng)自動加載到ODBC管理器了。利用動態(tài)加載數(shù)據(jù)庫,用戶還可以多次加載所需數(shù)據(jù)源,操作起來非常方便靈活,應(yīng)用程序的處理能力也大大增強(qiáng)了。
SQLConfigDataSource()
SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft FoxPro Driver (*.dbf)",
"DSN=MYDB"
"DefaultDir=c:mydir"
"FIL=FoxPro 2.5"
"DriverId=280"))
在注冊DSN時,SQLConfigDataSource函數(shù)的第二個參數(shù)應(yīng)該是ODBC_ADD_DSN,第三個參數(shù)指定了ODBC驅(qū)動程序,它的寫法可以參照ODBC管理器的驅(qū)動程序頁。第四個參數(shù)說明了數(shù)據(jù)源的各種屬性,它是由一系列子串構(gòu)成,每個子串的末尾必須有一個“”。最重要的屬性是“DSN=數(shù)據(jù)源名”,其它屬性包括缺省目錄以及驅(qū)動程序版本信息。在上例中,使用FoxPro 2.5的版本,所以DriverId應(yīng)該是280,對應(yīng)地,F(xiàn)oxPro 2.6的DriverId是536,F(xiàn)oxPro 2.0的是24。
如果讀者對SQLConfigDataSource函數(shù)的第四個參數(shù)的設(shè)置方法不清楚,那么可以打開Windows的注冊表看一看已注冊過的DSN的各項屬性。運行RegEdit可以打開注冊表,然后依次打開HKEY_CURRENT_USER->Software->ODBC->ODBC.INI,就可以看到已注冊的DSN,打開各DSN,則可以看到該DSN的各項屬性,讀者可以仿照DSN屬性來設(shè)置第四個參數(shù)。
的名字必須唯一,因此如果要注冊的DSN已被注冊過,那么SQLConfigDataSource就修改原來DSN的屬性。
一、ODBC
開放數(shù)據(jù)庫連接ODBC(Open Database Connec-tivity)是微軟開放服務(wù)結(jié)構(gòu)WOSA中關(guān)于數(shù)據(jù)庫的一
個重要部分,它允許應(yīng)用程序通過ODBCAPI訪問不同數(shù)據(jù)資源中的數(shù)據(jù),從而為數(shù)據(jù)庫編程提供了
一個標(biāo)準(zhǔn)接口。ODBC是對SQL Access Group的CLI標(biāo)準(zhǔn)的一種實現(xiàn),它允許應(yīng)用程序訪問范圍很廣
的數(shù)據(jù)庫(從簡單的ASCII文本到復(fù)雜的主框架數(shù)據(jù)庫),除了Windows平臺外,ODBC還可以在其
他諸如UNIX等的操作平臺上使用,因此ODBC獲得了世界上大多數(shù)領(lǐng)先的數(shù)據(jù)庫和應(yīng)用程序開發(fā)商
的廣泛支持。
ODBC主要包括了四層結(jié)構(gòu):最上層是應(yīng)用程序,第二層是驅(qū)動程序管理器,第三層是不同的驅(qū)
動程序,對應(yīng)不同的數(shù)據(jù)庫,最底層是具體的數(shù)據(jù)源。每個不同的數(shù)據(jù)資源類型由一個ODBC驅(qū)動程
序支持,這個驅(qū)動程序完成了ODBC API程序的核心,而且與數(shù)據(jù)庫通訊。
二、一般加表數(shù)據(jù)源的方法
通常,開發(fā)ODBC應(yīng)用程序之前必須要手動加入所用的數(shù)據(jù)源,利用位于控制面板中的ODBC管
理器可以方便地實現(xiàn)數(shù)據(jù)庫加載。雙擊控制面板中32-bit ODBC的圖標(biāo)就會出現(xiàn)管理器對話框,點擊
Add按鈕加人數(shù)據(jù)源,選擇使用的驅(qū)動程序、數(shù)據(jù)庫名稱、服務(wù)器地址或其他缺省設(shè)置后就把數(shù)據(jù)源
加載到ODBC管理器中了。ODBC管理器負(fù)責(zé)安裝驅(qū)動程序、管理數(shù)據(jù)源,幫助程序員跟蹤ODBC的函
數(shù)調(diào)用,并能將應(yīng)用程序的SQL語句及其他消息傳遞給驅(qū)動程序,而驅(qū)動程序則負(fù)責(zé)將結(jié)果集傳回應(yīng)
用程序。
利用VC++6.0的AppWizard創(chuàng)建一個基于單文檔的工程,選擇數(shù)據(jù)庫支持并根據(jù)提示加人所需
數(shù)據(jù)庫,這樣就可以在應(yīng)用程序中實現(xiàn)對該數(shù)據(jù)源的增加、修改和刪除等操作了。
毫無疑問,采用上述方法就能方便地對指定數(shù)據(jù)庫進(jìn)行操作。但是,實際運用中,用戶往往要求
在同一個應(yīng)用程序中能任意訪問不同的數(shù)據(jù)源,開發(fā)人員無法確定要加載的數(shù)據(jù)源,采用一般的加載
方法就有了無法克服的缺陷。顯然,這時就要求動態(tài)地進(jìn)行ODBC數(shù)據(jù)源加載,用戶只要選擇所需的
數(shù)據(jù)源,應(yīng)用程序就會自動地把它裝載到ODBC管理器。 "
三、動態(tài)加載數(shù)據(jù)庫
創(chuàng)建ODBC數(shù)據(jù)源可以調(diào)用Windows系統(tǒng)子目錄下的動態(tài)鏈接庫Odbcint.dll中的函數(shù)SQLConfigDataSource()
該函數(shù)可以動態(tài)地增加、修改和刪除數(shù)據(jù)源。
lQLConfigDataSource()函數(shù)
SQLConfigDataSource()的原型如下:
BOOLSQLConfigDataSource(HWND hwndParent, UINT
fRequest,LPCSTR IpszDriver, LPCSTR IpszAttributes);
其中四個參數(shù)的用法如下:
●參數(shù)hwndPwent是父級窗口句柄。如果句柄為NULL,將不會顯示一些有關(guān)的對話框。
如果參數(shù) IpszAttributes提供的信息不夠完善,在創(chuàng)建過程中就會出現(xiàn)對話框要求用戶提供相應(yīng)信息。
●參數(shù)fRequest可以設(shè)置為下面的數(shù)值之一:
ODBC_ADD_DSN: 增加_個新數(shù)據(jù)源
ODBC_CONHG_DSN: 配置(修改)一個已經(jīng)存在的數(shù)據(jù)源
ODBC_REMOVE_DSN: 刪除一個已經(jīng)存在的數(shù)據(jù)源
ODBC_ADD_SYS_DSN:. 增加一個新的系統(tǒng)數(shù)據(jù)源
ODBC_CONFIG—SYS—DSN: 更改一個已經(jīng)存在的系統(tǒng)數(shù)據(jù)源
ODBC_REMOVE_SYS_DSN:. 刪除一個已經(jīng)存在的系統(tǒng)數(shù)據(jù)源
●參數(shù)lpszDriver是數(shù)據(jù)庫引擎名稱,可以參見
ODBC管理器中對ODBC驅(qū)動程序的描述。比如要加
載的是Excel數(shù)據(jù)庫,那么數(shù)據(jù)庫引擎名稱就為Microsoft Excel Driver(*.xls)
●參數(shù)lpszAttributes為一連串的"KeyName=value"
字符串,每兩個KeyName值之間用""字符隔開。KeyName主要是新數(shù)據(jù)源缺省的驅(qū)動程序注冊說明,其中最主要的關(guān)鍵字是"DSN"----- 新數(shù)據(jù)源的名稱,其余關(guān)鍵字則根據(jù)不同的數(shù)據(jù)源有不同要求。關(guān)于lpszAttributes參數(shù)的具體設(shè)置,詳細(xì)可以參考Windows系統(tǒng)目錄下幫助文件Odbcjtn.hlp主題目錄標(biāo)簽中的"ODBC API函數(shù)改變|SQLConfigDatasource"條目。
2.SqlConfigDataSource的應(yīng)用條件
使用SqlConfigDataSource函數(shù)之前,必須把
ODBCINST.H文件包含在工程頭文件中,將ODBC-
CP32.LIB加人工程,同時保證ODBCCP32.DLL運行時處于系統(tǒng)子目錄下。
3.SqlConfigDataSource的應(yīng)用示例
以下的例子采用SQLConfigDataSource ODBC API函數(shù)在VC++6.0下動態(tài)加載任意一個Excel數(shù)
據(jù)源。
由于要求是動態(tài)地加載數(shù)據(jù)源,事先沒法手動向ODBC管理器加載數(shù)據(jù)源,因此無法選擇數(shù)據(jù)庫
支持,不能建立基于單文檔或多文檔的應(yīng)用程序。啟動VC++6.0,利用AppWizard建立一個基于對
話框的應(yīng)用程序,工程名稱為"My"。在對話框模板上放置一個按鈕,其ID號為IDC-GETDATA,
Caption為"調(diào)數(shù)據(jù)源"。再派生出一個基于CFile-Doialg類的新類CMyFileDialog,以標(biāo)準(zhǔn)文件對話框
方式選擇打開文件,具體做法請參閱有關(guān)資料,這里不作說明。
由于應(yīng)用程序沒有對數(shù)據(jù)庫的支持,故必須手工在STDAFX.H文件中加入對數(shù)據(jù)庫的支持,添加有
數(shù)據(jù)庫支持的STDAFX.H文件清單如下所示:
#define VC-EXTRALEAN
/ / Exclude rarely-used stuff from Windows headers
#include <afxwin. h>
//MFC core and standard components
#include <afxext. h> // MFC extensions
#include <afxdb. h //MFC database classes
#include <afxdisp. h> // MFC OLE automation classes
#ifndef _AFX_NO_AFXCMN- SUPPORT
#include <afxcmn. h>
// MFC support for Windows Common Controls
#endif//- AFX-NO_AFXCMN_SUPPORT
//{{AFX_Insert_LOCATION}}
#endif
利用classwizard給按紐添加函數(shù)OnGetData,定位到該函數(shù)并添加SqlConfigDataSource()以動態(tài)調(diào)用數(shù)據(jù)源,值得指出的是,對于要加載的excel數(shù)據(jù)源的lpszAttributes參數(shù)中有個關(guān)鍵字必須要說明,數(shù)據(jù)源名稱:"DSN"
主程序如下
#include"odbcinst.h"
#include"string.h"
#include"stdafx.h"
#include"my.h"
#include"mydlg.h"
IMPLEMENT_DYNAMIC ( CMyFileDialog ,CFileDialog)
CMyFileDialog:: CMyFileDialog ( BOOL bOpenFileDialog,
LPCTSTR lpszDefExt, LPCTSTR lpszFileName,DWORD
dwFlags, LPCTSTR lpszFilter, CWnd * pParentWnd):
CFileDialog (bOpenFileDialog lpszDefExt, lpszFileName,
dwFlags, lpszFilter, pParentWnd)
{}
//CAboutDlg dialog used for App About
class CAboutDlg :public CDialog
public:
CAboutDlg ();
// Dialog Data
/ / { { AFX DATA I CAboutDlg)
enum { IDD = IDDABOUTBOX };
//} }AFX_DATA
/ / ClassWizard generated virtual function overrides
/ / { {AFX VIRTUAL CAboutDlg)
protected:
/ / Implementation
protected:
/ / {AFX_MSG (CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGEMAP()
CAboutDlg: : CAboutDlg() : CDialog(CAboutDlg: : IDD)
//{{AFX_DATA_INIT(CAboutDlg)
//})AFX_DATA_INIT
void CAboutDlg: : DoDataExchange ( CDataExchange * pDX)
{
CDialog:: DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGiN_MESSAGEMAP ( CAboutDlg, CDialog)
// ( {AFX_MSG_MAP(CAboutDlg)
/ / No message handlers
//}}AFX_MSG_MAP
END_MESSAGEMAP()
/ / CMyDlg dialog
CMyDlg: : CMyDlg(CWnd* pParent / * =NULL* /)
CDialog(CMyDlg: : IDD, pParent)
{
//{{AFX_DATA_INIT(CMyDlg)
// NOTE: the ClassWizard will add member
initialization here
//}}AFX_DATA_NIT
m_hlcon =AfxGetApp()->Loadlcon(IDR_MAINFRAME);
}
void CMyDlg: : DoDataExchange ( CDataExchange * pDX)
I
{ CDialog:: DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//})AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
//{{AFX_MSG_MAP(CMyDIg)
ON WM_SYSCOMMAND()
ON_WMPAINT()
ON WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_GETDATA, OnGetdata)
//}}AFX_MSG_MAP
END_MESSAGEMAP()
/ / CMyDlg message handlers
BOOL CMyDlg: : OnlnitDialog()
{
CDialog: : OnlnitDialog ();
ASSERT( (IDM_ABOUTBOX& OxFFFO) = =IDM_ABOUTBOX);
ASSERT(IDMABOUTBOX < OxF000);
CMenu * pSysMenu = GetSystemMenu ( FALSE);
if(pSysMenu!=NULL)
{CString strAboutMenu;
strAbooutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m.hlcon, TRUE); // Set big icon
SetIcon ( m.hlcon, FALSE); / / Set small icon
/ / TODO: Add extra initialization here
return TRUE; / / return TRUE unless you set the focus to a control
}
void CMyDlg:: OnSysCommand( UINT nlD, LPARAM
lParam)
{ if ((nID & OxFFFO) = = 1DM_ABOUTBOX)
{ CAboutDlg dlgAbout;
dlgAbout. DoModal ();
}
else
{CDialog: : OnSysCommand(nID, lParam);}
}
void CMyDlg: : OnPaint()
{if (lslconic0)
{CPaintDC dc (this); / / device context for painting
SendMessage (WM_ICONERASEBKGND, (WPARAM)
dc.GetSafeHdc0, 0);
/ / Center icon in client rectangle
int cxIcon = GetSystemMetrics ( SMCXICON);
int cyIcon = GetSystemMetrics ( SMCYICON);
CRect rect;
GetClientRect( & rect);
int x = (rect.Width() -cxlcon + 1) / 2;
int y = (rect. Height()-cylcon + 1) / 2;
// Draw the icon
dc.Drawlcon(x, y, m_hlcon);
}
else
{CDiaLog: : OnPaint();}
}
HCURSOR CMyDlg: : OnQueryDraglcon()
{return (HCURSOR) m_hIcon;}
void CMyDlg: OnGetdata ()
/ / TODO: Add your control notification handler code here
CMyFileDialog filedlg (TRUE);
filedlg. DoModal (); / /彈出打開對話框
CString drivername;//數(shù)據(jù)庫引擎名稱
CString filetitle = filedlg. GetFileTitle ();
//取得指定文件名(不包含后綴)
CString extention =filedlg. GetFileExt();
/ /取得后綴
if(extention = = "xls")
drivername = "Microsoft Excel Driver (* xis) ";}
char str[50];
strcpy(str, "DSN =");
CString keyname = strcat( str, filetitle);
//keyname 指明了數(shù)據(jù)源名稱
if (FALSE = = SQLConfigDataSource (NULL, ODBC_
ADD_DSN, drivername, keyname)
{MessageBox("加載失敗");}
else
{MessageBox("成功將數(shù)據(jù)源加載到管理器");}
}
進(jìn)行上述編程之后,用戶只要點擊"調(diào)數(shù)據(jù)源"按鈕,在對話框里任意選擇所需Excel數(shù)據(jù)源,程序就會自動把數(shù)據(jù)源加載到ODBC管理器而不再需要手動加入,用戶可以通過雙擊"控制面板"中的32位ODBC圖據(jù),查看"用戶DSN"一欄,即可看見數(shù)據(jù)源己經(jīng)自動加載到ODBC管理器了。利用動態(tài)加載數(shù)據(jù)庫,用戶還可以多次加載所需數(shù)據(jù)源,操作起來非常方便靈活,應(yīng)用程序的處理能力也大大增強(qiáng)了。
文章版權(quán)歸西部工控xbgk所有,未經(jīng)許可不得轉(zhuǎn)載。