现在,多数数据库都支持OLE类型
![](/icons/75437de.gif)
数据库字段,利用这种字段,可以存放Word文档和Excel表格等任何种类
![](/icons/75437de.gif)
文件,而且,使用OLEAutomation思路方法,可直接激活文件
![](/icons/75437de.gif)
原始编辑器,也就是它们
![](/icons/75437de.gif)
OLEServer.这样,我们就有了
![](/icons/75437yi.gif)
个安全可靠
![](/icons/75437de.gif)
保存各类重要文件
![](/icons/75437de.gif)
思路方法.但是,
![](/icons/75437yinwei.gif)
这些文件常常是很大,几十K,甚至上百K,就要求我们有
![](/icons/75437yi.gif)
种切实可行
![](/icons/75437de.gif)
操纵思路方法,实现对这种字段
![](/icons/75437de.gif)
存取.
VB为
![](/icons/75437chengxu.gif)
员提供了数据库Control控件Data,使用它,可以方便地操纵数据库,如浏览数据库,增加新记录,编辑且更新现存
![](/icons/75437de.gif)
记录,删除记录等.但这些功能是对普通
![](/icons/75437de.gif)
数据库而言
![](/icons/75437de.gif)
,当数据库中有超长
![](/icons/75437de.gif)
OLE字段时,仅仅使用Data则不能完成上述操作了.此时,需要解决 2个问题:第
![](/icons/75437yi.gif)
,如何存取OLE字段中
![](/icons/75437de.gif)
内容;第 2,如何同步存取DataControl控件所显示记录中OLE字段和其它字段
![](/icons/75437de.gif)
内容.
针对上述 2个问题,介绍
![](/icons/75437yi.gif)
种解决思路方法.
第
![](/icons/75437yi.gif)
、如何存取OLE字段中
![](/icons/75437de.gif)
内容.
VB提供了文件存取
![](/icons/75437de.gif)
思路方法,利用这种思路方法我们可以方便地存取OLE数据库字段.下面给出
![](/icons/75437de.gif)
![](/icons/75437hanshu.gif)
就利用文件存取
![](/icons/75437de.gif)
思路方法,实现了对OLE数据库字段
![](/icons/75437de.gif)
存取操作.这里,使用Get、Put、Seek等语句,以 2进制形式打开
![](/icons/75437yi.gif)
个临时文件,把它作为OLE字段和OLEControl控件
![](/icons/75437de.gif)
中间缓冲器,当从OLE字段向OLEControl控件中读数据时,先将OLE字段
![](/icons/75437de.gif)
数据写入临时文件,再将临时文件用OLEControl控件
![](/icons/75437de.gif)
OLE_LOAD_FROM_FILE动作插入OLEControl控件;当把OLEControl控件
![](/icons/75437de.gif)
数据写入OLE字段时,则先用OLEControl控件
![](/icons/75437de.gif)
OLE_SAVE_TO_FILE动作,将其存入临时文件,再将临时文件写入OLE字段.这里,以固定块长
![](/icons/75437de.gif)
方式读写OLE字段和临时文件.这些
![](/icons/75437hanshu.gif)
都没有
![](/icons/75437cuowu.gif)
检测部分.
下面所有例子使用
![](/icons/75437de.gif)
都是Access2.0数据库.
变量声明:
OptionExplicit
ConstOLE_SAVE_TO_FILE=11'OLEAction常量
ConstOLE_LOAD_FROM_FILE=12'OLEAction常量
ConstCHUNK_SIZE=32000'文件读写块
大小
下面
![](/icons/75437de.gif)
![](/icons/75437hanshu.gif)
将Access1.x数据库中OLE字段
![](/icons/75437de.gif)
内容取出并插入OLE2Control控件中.
FunctionAccessFieldToOLE
(oleObjectAsControl,fdObjectAsField)
DimeErrorAsInteger
DimiFileNumberAsInteger
DimwOff
ToObjectAsInteger
iFileNumber=FreeFile
'获取文件号
OpenApp.Path&"OLE.TMP"ForBinaryAsiFileNumber
'创建临时文件
eError=FieldToFileStream(iFileNumber,fdObject)
'将字段
内容写到文件中
GetiFileNumber,3,wOff
ToObject
'获得Object
偏移地址
SeekiFileNumber,wOff
ToObject1
'到object
起始位置
oleObject.FileNumber=iFileNumber
'将OLEcontrol指向临时文件
oleObject.Action=OLE_LOAD_FROM_FILE
'从文件中取出OLEobject
CloseiFileNumber
'关闭临时文件
KillApp.Path&"OLE.TMP"
'删除临时文件
AccessFieldToOLE=0
'返回
EndFunction
下面
![](/icons/75437de.gif)
![](/icons/75437hanshu.gif)
将OLE字段中
![](/icons/75437de.gif)
内容写到临时文件中.
FunctionFieldToFileStream
(iFileNumberAsInteger,fdObjectAsField)AsInteger
DimsChunkHolderAsString
DimlChunkCountAsLong
DimlChunkRe
derAsLong
DimIAsLong
lChunkCount=fdObject.FieldSize
CHUNK_SIZE
'获得文件
块数
lChunkRe
der=fdObject.FieldSize
ModCHUNK_SIZE
'整块后余下
数据
ForI=0TolChunkCount-1
sChunkHolder=fdObject.GetChunk
(I*CHUNK_SIZE,CHUNK_SIZE)
'取
块
PutiFileNumber,,sChunkHolder
'将块写入临时文件
Next
IflChunkRe
der>0Then
sChunkHolder=fdObject.GetChunk
(lChunkCount*CHUNK_SIZE,lChunkRe
der)
'取余下
数据
PutiFileNumber,,sChunkHolder
'将其写入临时文件
EndIf
FieldToFileStream=0
'返回
EndFunction
下面
![](/icons/75437de.gif)
![](/icons/75437hanshu.gif)
将OLE2数据库字段
![](/icons/75437de.gif)
内容取出并插入OLE2Control控件中.
FunctionFieldToOLE
(oleObjectAsControl,fdObjectAsField)
DimeErrorAsInteger
DimiFileNumberAsInteger
iFileNumber=FreeFile
'获取文件号
OpenApp.Path&"OLE.TMP"ForBinaryAsiFileNumber
'创建临时文件
eError=FieldToFileStream(iFileNumber,fdObject)
'将字段
内容写到临时文件中
SeekiFileNumber,1
'到object
起始位置
oleObject.FileNumber=iFileNumber
'OLEControl控件指向临时文件
oleObject.Action=OLE_LOAD_FROM_FILE
'从文件中取出OLEobject
CloseiFileNumber
'关闭临时文件
KillApp.Path&"OLE.TMP"
'删除临时文件
FieldToOLE=0
'返回
EndFunction
下面
![](/icons/75437de.gif)
![](/icons/75437hanshu.gif)
将临时文件写入数据库
![](/icons/75437de.gif)
OLE2字段中.
FunctionFileStreamToField
(iFileNumberAsInteger,fdObjectAsField)AsInteger
DimsChunkHolderAsString
DimlChunkCountAsLong
DimlChunkRe
derAsLong
DimIAsLong
sChunkHolder=Space$(CHUNK_SIZE)
'临时存贮块
lChunkCount=(LOF(iFileNumber)-Seek(iFileNumber)1)
CHUNK_SIZE'取块数
lChunkRe
der=(LOF(iFileNumber)-Seek
(iFileNumber)1)ModCHUNK_SIZE
'取整块后余下
数据
ForI=1TolChunkCount
GetiFileNumber,,sChunkHolder
'从文件中取出
块
fdObject.AppendChunk(sChunkHolder)
'将块写入字段中
Next
IflChunkRe
der>0Then
sChunkHolder=Space$(lChunkRe
der)
'临时存贮块
GetiFileNumber,,sChunkHolder
'取出该块
fdObject.AppendChunk(sChunkHolder)
'写入字段中
EndIf
FileStreamToField=0
'返回
EndFunction
下面
![](/icons/75437de.gif)
![](/icons/75437hanshu.gif)
将OLE2Object从OLE2Control控件中取出,并存入数据库字段中.
FunctionOLEToField(oleObjectAsControl,
fdObjectAsField)AsInteger
DimeErrorAsInteger
DimiFileNumberAsInteger
iFileNumber=FreeFile
'获取文件号
OpenApp.Path&"OLE.TMP"ForBinaryAsiFileNumber
'创建临时文件
oleObject.FileNumber=iFileNumber
'OLEControl控件指向临时文件
oleObject.Action=OLE_SAVE_TO_FILE
'将字段
内容写到临时文件中
SeekiFileNumber,1
'到object
起始位置
fdObject=""清空OLE2字段
eError=FileStreamToField(iFileNumber,fdObject)
'将文件写入OLE2字段中
CloseiFileNumber
'关闭临时文件
KillApp.Path&"OLE.TMP"
'删除临时文件
OLEToField=0'返回
EndFunction
上述
![](/icons/75437hanshu.gif)
![](/icons/75437de.gif)
![](/icons/75437diaoyong.gif)
思路方法十分简单,下面
![](/icons/75437de.gif)
两个子
![](/icons/75437chengxu.gif)
给出了
![](/icons/75437diaoyong.gif)
例子.
将OLE2字段中
![](/icons/75437de.gif)
内容取出并插入OLEControl控件中
SubGetOLEObject![](/icons/75437kh.gif)
DimeErrorAsInteger
'将OLE字段File_Cont中
内容取出并插入OLEControl控件OLE1中
eError=FieldToOLE(OLE1,tbOLEObjects("File_Cont"))
EndSub
将OLE2Control控件中
内容写入OLE2字段
SubPutOLEObject![](/icons/75437kh.gif)
DimeErrorAsInteger
tbOLEObjects.Edit'修改OLEObjects
工作方式
eError=OLEToField(OLE1,tbOLEObjects("File_Cont"))
'保存OLEControl控件OLE1中
内容
tbOLEObjects.Update'更新tbOLEObjects
DoEvents
EndSub
![](/icons/75437yinwei.gif)
Access1.x
![](/icons/75437de.gif)
OLE字段格式和OLE2字段
![](/icons/75437de.gif)
格式区别,所以,若是OLE2字段,在读取字段内容时,应使用FieldToOLE
![](/icons/75437hanshu.gif)
;若是Access1.x
![](/icons/75437de.gif)
OLE字段,应使用AccessFieldToOLE
![](/icons/75437hanshu.gif)
.这两种格式OLE字段
![](/icons/75437de.gif)
存贮过程是相同
![](/icons/75437de.gif)
.当使用Access2.0建立数据库并存贮OLE字段时,它是OLE2格式
![](/icons/75437de.gif)
,应使用FieldToOLE
![](/icons/75437hanshu.gif)
.用VB3编程时,系统中应安装VB/Access2.0兼容层,否则无法操纵Access2.0数据库.
第 2、如何使DataControl控件显示
![](/icons/75437de.gif)
记录和OLE字段
![](/icons/75437de.gif)
内容同步.
这个问题是
![](/icons/75437yinwei.gif)
DataControl控件不支持超长
![](/icons/75437de.gif)
OLE字段引起
![](/icons/75437de.gif)
.对于普通
![](/icons/75437de.gif)
数据库字段,把显示该字段内容Control控件
![](/icons/75437de.gif)
DataSource和DataField属性分别置为DataControl控件和数据库
![](/icons/75437de.gif)
字段名,就可以由DataControl控件正确地显示数据库记录
![](/icons/75437de.gif)
字段内容.而用于显示OLE2字段内容
![](/icons/75437de.gif)
OLEControl控件
![](/icons/75437de.gif)
数据是无法用DataControl控件来存取
![](/icons/75437de.gif)
,必须用上面提供
![](/icons/75437de.gif)
![](/icons/75437hanshu.gif)
来存取.这时,关键问题是使OLEControl控件显示
![](/icons/75437de.gif)
内容是DataControl控件所在记录中OLE字段
![](/icons/75437de.gif)
内容,也就是OLEControl控件要和DataControl控件同步.
实现思路方法:
声明
![](/icons/75437yi.gif)
Dyna
![](/icons/75437set.gif)
类型
![](/icons/75437de.gif)
Object:tbOLEObjects.
在Form_Load事件
![](/icons/75437de.gif)
执行
![](/icons/75437chengxu.gif)
中,将Data1.RecordSet赋给tbOLEObjects,并记录tbOLEObjects中
![](/icons/75437de.gif)
记录数.
在Data1_Validate事件
![](/icons/75437de.gif)
执行
![](/icons/75437chengxu.gif)
中,使tbOLEObjects执行
![](/icons/75437de.gif)
动作和Data1
![](/icons/75437yi.gif)
致,即:在Data1
![](/icons/75437de.gif)
Data1_Validate事件执行
![](/icons/75437chengxu.gif)
中,当Data1执行Data1.RecordSet.MoveNext或Data1.RecordSet.MoveFirst时,tbOLEObjects也要执行tbOLEObjects.MoveNext或tbOLEObjects.MoveFirst.实现时,先保存当前OLEControl控件中
![](/icons/75437de.gif)
内容,然后执行tbOLEObjects.MoveNext或tbOLEObjects.MoveFirst思路方法,再取出OLE字段中
![](/icons/75437de.gif)
内容,插入到OLEControl控件中.
当系统执行了
![](/icons/75437yi.gif)
个SQL语句后,Data1显示
![](/icons/75437de.gif)
记录直接跳到某
![](/icons/75437yi.gif)
记录,对tbOLEObjects来说,则要执行
![](/icons/75437yi.gif)
查找过程,使得tbOLEObjects
![](/icons/75437de.gif)
当前记录和Data1
![](/icons/75437de.gif)
当前记录
![](/icons/75437yi.gif)
致.实现时,先保存当前OLEControl控件中
![](/icons/75437de.gif)
内容,再在tbOLEObjects中查找Data1
![](/icons/75437de.gif)
当前记录,找到后,将其OLE字段中
![](/icons/75437de.gif)
内容取出并插入到OLEControl控件中.
下面给出
![](/icons/75437de.gif)
实现例子是从本人编写
![](/icons/75437de.gif)
![](/icons/75437yi.gif)
个软件Software中摘录出来
![](/icons/75437de.gif)
,它介绍说明了具体
![](/icons/75437de.gif)
实现思路方法,但不可以直接使用,要结合自己
![](/icons/75437de.gif)
![](/icons/75437chengxu.gif)
,加上其它必要
![](/icons/75437de.gif)
部分.例子中
![](/icons/75437de.gif)
数据库是
![](/icons/75437yi.gif)
个公文数据库,保存用户
![](/icons/75437de.gif)
重要公文,其中
![](/icons/75437de.gif)
OLE字段保存
![](/icons/75437de.gif)
就是Word文档,名字为File_Cont,其它字段是文档
![](/icons/75437de.gif)
相关信息,如文档
![](/icons/75437de.gif)
标题(File_Title)、等级(File_Class)、关键字(File_Keyword)和ID号(File_ID)等.
变量介绍说明:
OptionExplicit
DimtbOLEObjectsAsDyna![](/icons/75437set.gif)
DimnRecordCountAsInteger'tbOLEObjects
记录数
DimnRecordNumberAsInteger'tbOLEObjects
记录指针
DimbBusyAsInterger'防止重入标志
DimbUpdatedAsInteger'OLEControl控件
内容发生变化
标志
下面
![](/icons/75437de.gif)
过程要在窗口
![](/icons/75437de.gif)
Form_Load事件中执行,完成对tbOLEObjects赋值并计算出tbOLEObjects中
![](/icons/75437de.gif)
记录数.
SubRefreshForm![](/icons/75437kh.gif)
DimeErrorAsInteger
NoRecord=False
Data1.RecordSource="SELECT*fromOwnFileorderbyFile_ID"
Data1.Refresh
SettbOLEObjects=Data1.Record
.Clone![](/icons/75437kh.gif)
'给tbOLEObjects赋值
'下面这两条语句是必须
![](/icons/75437de.gif)
,否则无法求出tbOLEObjects中
![](/icons/75437de.gif)
记录数
tbOLEObjects.MoveLast
tbOLEObjects.MoveFirst
nRecordCount=tbOLEObjects.RecordCount
'保存tbOLEObjects
记录数
nRecordNumber=1
'使记录
指针在第
个记录上
'设置各Control控件
DataField属性,以显示其字段
内容.
txtTitle.DataField="File_Title"
txtClass.DataField="File_Class"
txtFileID.DataField="File_ID"
txtKeyWord.DataField="File_KeyWord"
'将OLE字段File_Cont中
内容取出并插入OLEControl控件OLE1中
eError=FieldToOLE(OLE1,tbOLEObjects("File_Cont"))
'将Data1指向第
个记录
IfData1.Record
.RecordCount>1ThenData1.Record
.MoveFirst
EndSub
下面是如何在Data1_Validate事件中加入对tbOLEObjects操作代码
![](/icons/75437de.gif)
例子.
SubData1_Validate(ActionAsInteger,SaveAsInteger)
DimeErrorAsInteger
SelectCaseAction
Case1'Data1执行MoveFirst
IfNotbBusyThen
bBusy=True
Screen.MousePo
er=11
DoEvents
IfbUpdatedThen
'如果OLE1中
内容发生了变化
CallPutOLEObject
'保存OLE1中
内容
DoEvents
bUpdated=False
EndIf
IfnRecordNumber>1Then
tbOLEObjects.MoveFirst'到Data1所指向
记录
nRecordNumber=1'修改tbOLEObjects
指针
'取出当前记录OLE字段
内容
eError=FieldToOLE(OLE1,tbOLEObjects("File_Cont"))
DoEvents
EndIf
Screen.MousePo
er=0
bBusy=False
EndIf
Case2'Data1执行了MovePrevious
IfNotbBusyThen'用于防止
重入
bBusy=True'
Screen.MousePo
er=11
DoEvents
IfbUpdatedThen'如果OLE1中
内容发生变化
CallPutOLEObject'保存OLE1中
内容
DoEvents
bUpdated=False
EndIf
IfnRecordNumber>1Then
tbOLEObjects.MovePrevious'到Data1所指向
记录
nRecordNumber=nRecordNumber-1'修改tbOLEObjects
指针
'取出当前记录OLE字段
内容
eError=FieldToOLE(OLE1,tbOLEObjects("File_Cont"))
DoEvents
EndIf
Screen.MousePo
er=0
bBusy=False
EndIf
Case3'MoveNext
......
Case4'MoveLast
......
Case5'增加
个新记录
IfNotbBusyThen
bBusy=True
Screen.MousePo
er=11
DoEvents
IfbUpdatedThen
CallPutOLEObject
'保存当前OLEControl控件中
内容
DoEvents
bUpdated=False
EndIf
'执行tbOLEObjects.AddNew,修改tbOLEObjects
![](/icons/75437de.gif)
记录数、指针等
'本例子中未给出这部分代码,
![](/icons/75437chengxu.gif)
中在增加按钮
![](/icons/75437de.gif)
Click事件中执行
Screen.MousePo
er=0
bBusy=False
EndIf
Case6'更新数据库
IfSave=TrueThen
IfMsgBox
("保存所做
修改?",MSGBOX_TYPE)<>YESThen
Action=0:Save=False
EndIf
Case7
'删除记录,和增加记录
过程作同样
考虑
......
Case8
......
Case9
......
Case10'关闭数据库
IfSave=TrueThen
IfMsgBox
("关闭数据库前,保存所做
修改?",MSGBOX_TYPE)
<>YESThen
Save=False
EndIf
EndSelect
EndSub
下面
![](/icons/75437de.gif)
过程是用户用OutlineControl控件查找数据库中
![](/icons/75437de.gif)
Word文档,每
![](/icons/75437yi.gif)
个记录对应
![](/icons/75437yi.gif)
个Outline条目,当用户在Outline
![](/icons/75437de.gif)
某
![](/icons/75437yi.gif)
条目上作Click动作时,系统就显示出该记录
![](/icons/75437de.gif)
所有内容,包括OLE字段
![](/icons/75437de.gif)
内容.这里,tbOLEObjects在查找记录时,使用
![](/icons/75437de.gif)
是顺序查找思路方法,读者若要加快查找
![](/icons/75437de.gif)
速度,可采用其它
![](/icons/75437de.gif)
查找思路方法.
SubOutline1_Click![](/icons/75437kh.gif)
DimstLNameAsString,stTmp$,eError%
DimstFNameAsString
IfOutline1.Indent(Outline1.ListIndex)=2Then
stTmp$=Outline1.List(Outline1.ListIndex)
stLName=stGetToken$(stTmp$,",")'读取该记录
标志
IfnRecordCount>1Then
tbOLEObjects.MoveFirst
nRecordNumber=1'到第
个记录
DoWhileTrim$(tbOLEObjects!File_ID)<>stLName
'开始查找该记录
nRecordNumber=nRecordNumber1
tbOLEObjects.MoveNext
Loop
Data1.Record
.FindFirst"File_ID='"stLName"'"
'DataControl控件也要到该记录
eError=FieldToOLE(OLE1,tbOLEObjects("File_Cont"))
'取出OLE字段
内容
Outline1.SetFocus
'将焦点放在OutlineControl控件上
ElseIfnRecordCount=1Then
Data1.Record
.FindFirst"File_ID='"stLName"'"
eError=FieldToOLE(OLE1,tbOLEObjects("File_Cont"))
Outline1.SetFocus
EndIf
EndIf
EndSub
最后,介绍说明
![](/icons/75437yi.gif)
点:以上
![](/icons/75437de.gif)
![](/icons/75437chengxu.gif)
都是在Windows3.2中文版和VB3环境下实现
![](/icons/75437de.gif)
,若在Windows环境下,用VB4编写这种
![](/icons/75437chengxu.gif)
,上面
![](/icons/75437de.gif)
![](/icons/75437chengxu.gif)
要作改动,不能直接应用.VB4中,DataControl控件理论上是支持OLE数据库字段
![](/icons/75437de.gif)
,但这样使用时,每次执行MoveFirst或MoveNext等类似动作,都会产生
![](/icons/75437yi.gif)
个没有
![](/icons/75437cuowu.gif)
号
![](/icons/75437de.gif)
"OLEAutomation"
![](/icons/75437cuowu.gif)
,笔者没有找到产生这个问题
![](/icons/75437de.gif)
原因和解决思路方法,如果有朋友告知解决思路方法,笔者十分感谢.