2 回答

TA貢獻1796條經驗 獲得超4個贊
---- 開 放 數 據 庫 互 連(ODBC) 已 經 成 為Client /Server 數 據 庫 應 用 系 統 中 訪 問 遠 程 數 據 庫 的 一 個 標 準。 做 為 強 大 的 前 端 開 發 工 具,MS Visual Basic 為 開 發 者 提 供 了 多 種 訪 問ODBC 數 據 源 的 途 徑, 如JET 數 據 庫 引 擎、ODBC API 函 數、RDO 接 口 等。 比 較 而 言, 直 接 使 用ODBC API 函 數 的 編 程 難 度 最 大, 但 由 此 獲 得 的 存 取 數 據 庫 的 性 能 也 是 最 佳。 誠 然,VB 4.0 企 業 版 提 供 的RDO 接 口 的 性 能 已 經 接 近ODBC API, 但 是 遺 憾 的 是, 這 個 接 口 只 能 在32 位Windows 環 境 中 運 行, 而ODBC API 函 數 則 沒 有 這 個 限 制。
---- ODBC API 函 數 的 聲 明 方 法
---- 與 使 用 其 它 動 態 庫 函 數 一 樣, 在VB 中 使 用ODBC API 函 數 之 前, 必 須 事 先 聲 明 將 要 使 用 的 函 數、 常 量 和 數 據 結 構。ODBC API 函 數 駐 留 在ODBC 運 行 動 態 庫ODBC.DLL(16 位) 或ODBC32.DLL(32 位) 中, 該 動 態 庫 位 于Windows 子 目 錄system 中。 通 常 做 法 是 在VB 項 目 中 單 獨 使 用 一 個 模 塊 文 件, 然 后 將ODBC API 聲 明 語 句 加 入 其 中, 如 下 所 示, 就 是 本 文 實 例 中 使 用 的 模 塊 文 件module1.bas 的 內 容:
Declare Function SQLAllocEnv Lib "
odbc32.dll" (phenv&) As Integer
Declare Function SQLAllocConnect Lib "
odbc32.dll" (ByVal henv&, phdbc&) As Integer
Declare Function SQLAllocStmt Lib "
odbc32.dll" (ByVal hdbc&, phstmt&) As Integer
Declare Function SQLConnect Lib "
odbc32.dll" (ByVal hdbc&, ByVal szDSN$,
ByVal cbDSN%, ByVal szUID$, ByVal cbUID%,
ByVal szAuthStr$, ByVal cbAuthStr%) As Integer
Declare Function SQLColAttributesString Lib "
odbc32.dll" Alias "SQLColAttributes"
(ByVal hstmt&, ByVal icol%, ByVal fDescType%,
ByVal rgbDesc As String, ByVal cbDescMax%,
pcbDesc%, pfDesc&) As Integer
Declare Function SQLDisconnect Lib "
odbc32.dll" (ByVal hdbc&) As Integer
Declare Function SQLExecDirect Lib "
odbc32.dll" (ByVal hstmt&, ByVal
szSqlStr$, ByVal cbSqlStr&) As Integer
Declare Function SQLFetch Lib "
odbc32.dll" (ByVal hstmt&) As Integer
Declare Function SQLFreeConnect Lib "
odbc32.dll" (ByVal hdbc&) As Integer
Declare Function SQLFreeEnv Lib "
odbc32.dll" (ByVal henv&) As Integer
Declare Function SQLFreeStmt Lib "
odbc32.dll" (ByVal hstmt&, ByVal fOption%) As Integer
Declare Function SQLGetData Lib "
odbc32.dll" (ByVal hstmt&, ByVal icol%,
ByVal fCType%, ByVal rgbValue As String,
ByVal cbValueMax&, pcbValue&) As Integer
Declare Function SQLNumResultCols Lib "
odbc32.dll" (ByVal hstmt&, pccol%) As Integer
Global Const SQL_C_CHAR As Long = 1
Global Const SQL_COLUMN_LABEL As Long = 18
Global Const SQL_DROP As Long = 1
Global Const SQL_ERROR As Long = -1
Global Const SQL_NO_DATA_FOUND As Long = 100
Global Const SQL_SUCCESS As Long = 0
---- 需 要 說 明 的 是, 在 函 數 聲 明 時, 應 該 根 據 程 序 的 運 行 環 境 選 擇 相 應 的 動 態 庫。 在VB 子 目 錄samples\remauto\db_odbc 中 有 兩 個 正 文 文 件ODBC16.TXT 和ODBC32.TXT, 分 別 存 有 所 有16 位 和32 位ODBC API 函 數、 常 量 和 數 據 結 構 的 聲 明 語 句, 編 程 時 可 以 從 中 拷 貝 所 需 的 聲 明 語 句。
---- 使 用ODBC API 的 編 程 方 法
---- 在VB 中 調 用ODBC API 函 數 訪 問ODBC 數 據 庫, 代 碼 編 制 一 般 是 按 照 下 列 過 程 進 行 的:
---- 一、 初 始 化ODBC
---- 在 這 個 過 程 中, 應 用 程 序 將 通 過 調 用SQLAlloEnv 函 數 初 始 化ODBC 接 口, 獲 取ODBC 環 境 句 柄。ODBC 環 境 句 柄 是 其 它 所 有ODBC 資 源 句 柄 的 父 句 柄, 因 此 無 論 程 序 將 建 立 多 少 個ODBC 連 接, 這 個 過 程 只 需 執 行 一 次 即 可。 例 如:
Dim rc As Integer 'ODBC函數的返回碼
Dim henv As Long 'ODBC環境句柄
rc = SQLAllocEnv(henv) '獲取ODBC環境句柄
---- 二、 與ODBC 數 據 源 建 立 連 接
---- 這 個 過 程 由 下 列 兩 個 步 驟 組 成:
---- 1、 調 用SQLAllocConnect 函 數 獲 取 連 接 句 柄。 例 如:
Dim hdbc As Long '連接句柄
rc = SQLAllocConnect(henv, hdbc) '獲取連接句柄
---- 2、 建 立 連 接。 這 個 步 驟 可 以 通 過 多 種 方 法 實 現, 最 簡 單 直 觀 的 方 法 是 調 用SQLConnect 函 數。 例 如:
Dim DSN As String, UID As String, PWD As String
DSN = "DataSourceName" 'ODBC數據源名稱
UID = "UserID" '用戶帳號
PWD = "Password" '用戶口令
rc = SQLConnect(hdbc, DSN, Len(DSN), UID,
Len(UID), PWD, Len(PWD)) '建立連接
---- 三、 存 取 數 據
---- 用 戶 對ODBC 數 據 源 的 存 取 操 作, 都 是 通 過SQL 語 句 實 現 的。 在 這 個 過 程 中, 應 用 程 序 將 通 過 連 接 向ODBC 數 據 庫 提 交SQL 語 句, 以 完 成 用 戶 請 求 的 操 作。 具 體 步 驟 如 下:
---- 1、 調 用SQLAllocStmt 函 數 獲 取 語 句 句 柄。 例 如:
Dim hstmt As Long
rc = SQLAllocStmt(hdbc, hstmt)
---- 2、 執 行SQL 語 句。 執 行SQL 語 句 的 方 法 比 較 多, 最 簡 單 明 了 的 方 法 是 調 用SQLAllocStmt 函 數, 例 如:
Dim SQLstmt As String
SQLstmt = "SELECT * FROM authors"
rc = SQLExecDirect(hstmt, SQLstmt, Len(SQLstmt))
---- 四、 檢 索 結 果 集
---- 如 果SQL 語 句 被 順 利 提 交 并 正 確 執 行, 那 么 就 會 產 生 一 個 結 果 集。 檢 索 結 果 集 的 方 法 有 很 多, 最 簡 單 最 直 接 的 方 法 是 調 用SQLFetch 和SQLGetData 函 數。SQLFetch 函 數 的 功 能 是 將 結 果 集 的 當 前 記 錄 指 針 移 至 下 一 個 記 錄,SQLGetData 函 數 的 功 能 是 提 取 結 果 集 中 當 前 記 錄 的 某 個 字 段 值。 通 常 可 以 采 用 一 個 循 環 以 提 取 結 果 集 中 所 有 記 錄 的 所 有 字 段 值, 該 循 環 重 復 執 行SQLFetch 和SQLGetData 函 數, 直 至SQLFetch 函 數 返 回SQL_NO_DATA_FOUND, 這 表 示 已 經 到 達 結 果 集 的 末 尾。
Dim ColVal As String * 225
ColVal = String(255, 0)
Do Until SQLFetch(hstmt) = SQL_NO_DATA_FOUND
rc = SQLGetData(hstmt, i, SQL_C_CHAR, ColVal,
Len(ColVal), SQL_NULL_DATA)
Loop
---- 五、 結 束 應 用 程 序
---- 在 應 用 程 序 完 成 數 據 庫 操 作, 退 出 運 行 之 前, 必 須 釋 放 程 序 中 使 用 的 系 統 資 源。 這 些 系 統 資 源 包 括: 語 句 句 柄、 連 接 句 柄 和ODBC 環 境 句 柄。 完 成 這 個 過 程 的 步 驟 如 下:
---- 1、 調 用SQLFreeStmt 函 數 釋 放 語 句 句 柄 及 其 相 關 的 系 統 資 源。 例 如:rc = SQLFreeStmt(hstmt, SQL_DROP)
---- 2、 調 用SQLDisconnect 函 數 關 閉 連 接。 例 如:
rc = SQLDisconnect(hdbc)
---- 3、 調 用SQLFreeConnect 函 數 釋 放 連 接 句 柄 及 其 相 關 的 系 統 資 源。 例 如:
rc = SQLFreeConnect(hdbc)
---- 4、 調 用SQLFreeEnv 函 數 釋 放 環 境 句 柄 及 其 相 關 的 系 統 資 源, 停 止ODBC 操 作。 例 如:
rc = SQLFreeEnv(henv)
---- 此 外, 在 編 制 程 序 時 還 有 一 個 需 要 重 點 考 慮 的 問 題, 這 就 是 錯 誤 處 理。 所 有ODBC API 函 數, 若 在 執 行 期 間 發 生 錯 誤, 都 將 返 回 一 個 標 準 錯 誤 代 碼SQL_ERROR。 一 般 來 講, 在 每 次 調 用ODBC API 函 數 之 后, 都 應 該 檢 查 該 函 數 返 回 值, 確 定 該 函 數 是 否 成 功 地 執 行, 再 決 定 是 否 繼 續 后 續 過 程。 而 詳 細 的 錯 誤 信 息, 可 以 調 用SQLError 函 數 獲 得。SQLError 函 數 將 返 回 下 列 信 息: 標 準 的ODBC 錯 誤 狀 態 碼
ODBC 數 據 源 提 供 的 內 部 錯 誤 編 碼
錯 誤 信 息 串
---- 簡 單 應 用 實 例
---- 本 實 例 將 編 制 一 個 客 戶 機 端VB 應 用 程 序, 通 過Windows NT 局 域 網 查 詢 服 務 器 端MS SQL Server 6.5 樣 板 數 據 庫PUBS 中 的AUTHORS 數 據 表, 并 在 一 個Grid 控 件 中 顯 示 查 詢 結 果。 首 先, 使 用Windows 控 制 面 板 中 的ODBC 驅 動 管 理 器 新 建 一 個ODBC 數 據 源, 定 義 數 據 源 名 稱 為ODBC_API_DEMO, 定 義 登 錄 數 據 庫 為PUBS, 其 它 信 息 應 根 據 用 戶 的 環 境 正 確 設 置。 然 后, 啟 動VB, 新 建 一 個 項 目Project1, 在 缺 省 窗 體Form1 中 加 入 一 個Grid 控 件Grid1、 兩 個CommandButton 控 件cmdQuery 和cmdClose, 在Project1 中 插 入 一 個 模 塊Module1, 將 前 面 列 舉 的 聲 明 語 句 加 入 其 中

TA貢獻1784條經驗 獲得超7個贊
VLOOKUP函數
在表格或數值數組的首列查找指定的數值,并由此返回表格或數組中該數值所在行中指定列處的數值。
這里所說的“數組”,可以理解為表格中的一個區域。數組的列序號:數組的“首列”,就是這個區域的第一縱列,此列右邊依次為第2列、3列……。假定某數組區域為B2:E10,那么,B2:B10為第1列、C2:C10為第2列……。
語法:
VLOOKUP(查找值,區域,列序號,邏輯值)
“查找值”:為需要在數組第一列中查找的數值,它可以是數值、引用或文字符串。
“區域”:數組所在的區域,如“B2:E10”,也可以使用對區域或區域名稱的引用,例如數據庫或數據清單。
“列序號”:即希望區域(數組)中待返回的匹配值的列序號,為1時,返回第一列中的數值,為2時,返回第二列中的數值,以此類推;若列序號小于1,函數VLOOKUP 返回錯誤值 #VALUE!;如果大于區域的列數,函數VLOOKUP返回錯誤值 #REF!。
“邏輯值”:為TRUE或FALSE。它指明函數 VLOOKUP 返回時是精確匹配還是近似匹配。如果為 TRUE 或省略,則返回近似匹配值,也就是說,如果找不到精確匹配值,則返回小于“查找值”的最大數值;如果“邏輯值”為FALSE,函數 VLOOKUP 將返回精確匹配值。如果找不到,則返回錯誤值 #N/A。如果“查找值”為文本時,“邏輯值”一般應為 FALSE 。另外:
·如果“查找值”小于“區域”第一列中的最小數值,函數 VLOOKUP 返回錯誤值 #N/A。
·如果函數 VLOOKUP 找不到“查找值” 且“邏輯值”為 FALSE,函數 VLOOKUP 返回錯誤值 #N/A。
下面舉例說明VLOOKUP函數的使用方法。
假設在Sheet1中存放小麥、水稻、玉米、花生等若干農產品的銷售單價:
A B
1 農產品名稱 單價
2 小麥 0.56
3 水稻 0.48
4 玉米 0.39
5 花生 0.51
…………………………………
100 大豆 0.45
Sheet2為銷售清單,每次填寫的清單內容不盡相同:要求在Sheet2中輸入農產品名稱、數量后,根據Sheet1的數據,自動生成單價和銷售額。設下表為Sheet2:
A B C D
1 農產品名稱 數量 單價 金額
2 水稻 1000 0.48 480
3 玉米 2000 0.39 780
…………………………………………………
在D2單元格里輸入公式:
=C2*B2 ;
在C2單元格里輸入公式:
=VLOOKUP(A2,Sheet1!A2:B100,2,FALSE) 。
如用語言來表述,就是:在Sheet1表A2:B100區域的第一列查找Sheet2表單元格A2的值,查到后,返回這一行第2列的值。
這樣,當Sheet2表A2單元格里輸入的名稱改變后,C2里的單價就會自動跟著變化。當然,如Sheet1中的單價值發生變化,Sheet2中相應的數值也會跟著變化。
其他單元格的公式,可采用填充的辦法寫入。
VLOOKUP函數使用注意事項
說到VLOOKUP函數,相信大家都會使用,而且都使用得很熟練了。不過,有幾個細節問題,大家在使用時還是留心一下的好。
一.VLOOKUP的語法
VLOOKUP函數的完整語法是這樣的:
VLOOKUP(lookup_value,table_array,col_index_num,range_lookup)
1.括號里有四個參數,是必需的。最后一個參數range_lookup是個邏輯值,我們常常輸入一個0字,或者False;其實也可以輸入一個1字,或者true。兩者有什么區別呢?前者表示的是完整尋找,找不到就傳回錯誤值#N/A;后者先是找一模一樣的,找不到再去找很接近的值,還找不到也只好傳回錯誤值#N/A。這對我們其實也沒有什么實際意義,只是滿足好奇而已,有興趣的朋友可以去體驗體驗。
2.Lookup_value是一個很重要的參數,它可以是數值、文字字符串、或參照地址。我們常常用的是參照地址。用這個參數時,有兩點要特別提醒:
A)參照地址的單元格格式類別與去搜尋的單元格格式的類別要一致,否則的話有時明明看到有資料,就是抓不過來。特別是參照地址的值是數字時,最為明顯,若搜尋的單元格格式類別為文字,雖然看起來都是123,但是就是抓不出東西來的。
而且格式類別在未輸入數據時就要先確定好,如果數據都輸入進去了,發現格式不符,已為時已晚,若還想去抓,則需重新輸入。
B)第二點提醒的,是使用時一個方便實用的小技巧,相信不少人早就知道了的。我們在使用參照地址時,有時需要將lookup_value的值固定在一個格子內,而又要使用下拉方式(或復制)將函數添加到新的單元格中去,這里就要用到“$”這個符號了,這是一個起固定作用的符號。比如說我始終想以D5格式來抓數據,則可以把D5弄成這樣:$D$5,則不論你如何拉、復制,函數始終都會以D5的值來抓數據。
3.Table_array是搜尋的范圍,col_index_num是范圍內的欄數。Col_index_num 不能小于1,其實等于1也沒有什么實際用的。如果出現一個這樣的錯誤的值#REF!,則可能是col_index_num的值超過范圍的總字段數。
二.VLOOKUP的錯誤值處理。
我們都知道,如果找不到數據,函數總會傳回一個這樣的錯誤值#N/A,這錯誤值其實也很有用的。比方說,如果我們想這樣來作處理:如果找到的話,就傳回相應的值,如果找不到的話,我就自動設定它的值等于0,那函數就可以寫成這樣:
=if(iserror(vlookup(1,2,3,0))=true,0,vlookup(1,2,3,0))
這句話的意思是這樣的:如果VLOOKUP函數返回的值是個錯誤值的話(找不到數據),就等于0,否則,就等于VLOOKUP函數返回的值(即找到的相應的值)。
這里面又用了兩個函數。
第一個是iserror函數。它的語法是iserror(value),即判斷括號內的值是否為錯誤值,如果是,就等于true,不是,就等于false。
第二個是if函數,這也是一個常用的函數的,后面有機會再跟大家詳細講解。它的語法是if(條件判斷式,結果1,結果2)。如果條件判斷式是對的,就執行結果1,否則就執行結果2。舉個例子:=if(D2=””,”空的”,”有東西”),意思是如D2這個格子里是空的值,就顯示文字“空的”,否則,就顯示“有東西”。(看起來簡單吧?其實編程序,也就是這樣子判斷來判斷去的。)
三.含有VLOOKUP函數的工作表檔案的處理。
一般來說,含有VLOOKUP函數的工作表,如果又是在別的檔案里抓取數據的話,檔案往往是比較大的。尤其是當你使用的檔案本身就很大的時候,那每次開啟和存盤都是很受傷的事情。
有沒有辦法把文件壓縮一下,加快開啟和存盤的速度呢。這里提供一個小小的經驗。
在工作表里,點擊工具——選項——計算,把上面的更新遠程參照和儲存外部連結的勾去掉,再保存檔案,則會加速不少,不信你可以試試。
下面詳細的說一下它的原理。
1.含有VLOOKUP函數的工作表,每次在保存檔案時,會同時保存一份其外部連結的檔案。這樣即使在單獨打開這個工作表時,VLOOKUP函數一樣可以抓取到數值。
2.在工作表打開時,微軟會提示你,是否要更新遠程參照。意思是說,你要不要連接最新的外部檔案,好讓你的VLOOKUP函數抓到最新的值。如果你有足夠的耐心,不妨試試。
3.了解到這點,我們應該知道,每次單獨打開含有VLOOKUP函數的工作表時,里面抓取外部檔案的數值,只是上次我們存盤時保存的值。若要連結最新的值,必須要把外部檔案同時打開。
添加回答
舉報