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函数的工作表时,里面抓取外部档案的数值,只是上次我们存盘时保存的值。若要连结最新的值,必须要把外部档案同时打开。
添加回答
举报