专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »VB教程 » 数据库字段:VB中超长OLE数据库字段的操纵思路方法 »正文

数据库字段:VB中超长OLE数据库字段的操纵思路方法

来源: 发布时间:星期四, 2009年1月15日 浏览:26次 评论:0
  现在,多数数据库都支持OLE类型数据库字段,利用这种字段,可以存放Word文档和Excel表格等任何种类文件,而且,使用OLEAutomation思路方法,可直接激活文件原始编辑器,也就是它们OLEServer.这样,我们就有了个安全可靠保存各类重要文件思路方法.但是,这些文件常常是很大,几十K,甚至上百K,就要求我们有种切实可行操纵思路方法,实现对这种字段存取.

  VB为员提供了数据库Control控件Data,使用它,可以方便地操纵数据库,如浏览数据库,增加新记录,编辑且更新现存记录,删除记录等.但这些功能是对普通数据库而言,当数据库中有超长OLE字段时,仅仅使用Data则不能完成上述操作了.此时,需要解决 2个问题:第,如何存取OLE字段中内容;第 2,如何同步存取DataControl控件所显示记录中OLE字段和其它字段内容.

  针对上述 2个问题,介绍种解决思路方法.

  第、如何存取OLE字段中内容.

  VB提供了文件存取思路方法,利用这种思路方法我们可以方便地存取OLE数据库字段.下面给出就利用文件存取思路方法,实现了对OLE数据库字段存取操作.这里,使用Get、Put、Seek等语句,以 2进制形式打开个临时文件,把它作为OLE字段和OLEControl控件中间缓冲器,当从OLE字段向OLEControl控件中读数据时,先将OLE字段数据写入临时文件,再将临时文件用OLEControl控件OLE_LOAD_FROM_FILE动作插入OLEControl控件;当把OLEControl控件数据写入OLE字段时,则先用OLEControl控件OLE_SAVE_TO_FILE动作,将其存入临时文件,再将临时文件写入OLE字段.这里,以固定块长方式读写OLE字段和临时文件.这些都没有检测部分.

  下面所有例子使用都是Access2.0数据库.

  变量声明:

OptionExplicit
ConstOLE_SAVE_TO_FILE=11'OLEAction常量
ConstOLE_LOAD_FROM_FILE=12'OLEAction常量
ConstCHUNK_SIZE=32000'文件读写块大小
下面将Access1.x数据库中OLE字段内容取出并插入OLE2Control控件中.

FunctionAccessFieldToOLE
(oleObjectAsControl,fdObjectAsField)
DimeErrorAsInteger
DimiFileNumberAsInteger
DimwOffToObjectAsInteger
iFileNumber=FreeFile
'获取文件号
OpenApp.Path&"OLE.TMP"ForBinaryAsiFileNumber
'创建临时文件
eError=FieldToFileStream(iFileNumber,fdObject)
'将字段内容写到文件中
GetiFileNumber,3,wOffToObject
'获得Object偏移地址
SeekiFileNumber,wOffToObject1
'到object起始位置
oleObject.FileNumber=iFileNumber
'将OLEcontrol指向临时文件
oleObject.Action=OLE_LOAD_FROM_FILE
'从文件中取出OLEobject
CloseiFileNumber
'关闭临时文件
KillApp.Path&"OLE.TMP"
'删除临时文件
AccessFieldToOLE=0
'返回
EndFunction
下面将OLE字段中内容写到临时文件中.

FunctionFieldToFileStream
(iFileNumberAsInteger,fdObjectAsField)AsInteger
DimsChunkHolderAsString
DimlChunkCountAsLong
DimlChunkRederAsLong
DimIAsLong
lChunkCount=fdObject.FieldSizeCHUNK_SIZE
'获得文件块数
lChunkReder=fdObject.FieldSizeModCHUNK_SIZE
'整块后余下数据
ForI=0TolChunkCount-1
sChunkHolder=fdObject.GetChunk
(I*CHUNK_SIZE,CHUNK_SIZE)
'取
PutiFileNumber,,sChunkHolder
'将块写入临时文件
Next
IflChunkReder>0Then
sChunkHolder=fdObject.GetChunk
(lChunkCount*CHUNK_SIZE,lChunkReder)
'取余下数据
PutiFileNumber,,sChunkHolder
'将其写入临时文件
EndIf
FieldToFileStream=0
'返回
EndFunction
下面将OLE2数据库字段内容取出并插入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
下面将临时文件写入数据库OLE2字段中.

FunctionFileStreamToField
(iFileNumberAsInteger,fdObjectAsField)AsInteger
DimsChunkHolderAsString
DimlChunkCountAsLong
DimlChunkRederAsLong
DimIAsLong
sChunkHolder=Space$(CHUNK_SIZE)
'临时存贮块
lChunkCount=(LOF(iFileNumber)-Seek(iFileNumber)1)
CHUNK_SIZE'取块数
lChunkReder=(LOF(iFileNumber)-Seek
(iFileNumber)1)ModCHUNK_SIZE
'取整块后余下数据
ForI=1TolChunkCount
GetiFileNumber,,sChunkHolder
'从文件中取出
fdObject.AppendChunk(sChunkHolder)
'将块写入字段中
Next
IflChunkReder>0Then
sChunkHolder=Space$(lChunkReder)
'临时存贮块
GetiFileNumber,,sChunkHolder
'取出该块
fdObject.AppendChunk(sChunkHolder)
'写入字段中
EndIf
FileStreamToField=0
'返回
EndFunction
下面将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
上述思路方法十分简单,下面两个子给出了例子.

  将OLE2字段中内容取出并插入OLEControl控件中

SubGetOLEObject
DimeErrorAsInteger
'将OLE字段File_Cont中内容取出并插入OLEControl控件OLE1中
eError=FieldToOLE(OLE1,tbOLEObjects("File_Cont"))
EndSub
将OLE2Control控件中内容写入OLE2字段
SubPutOLEObject
DimeErrorAsInteger
tbOLEObjects.Edit'修改OLEObjects工作方式
eError=OLEToField(OLE1,tbOLEObjects("File_Cont"))
'保存OLEControl控件OLE1中内容
tbOLEObjects.Update'更新tbOLEObjects
DoEvents
EndSub
Access1.xOLE字段格式和OLE2字段格式区别,所以,若是OLE2字段,在读取字段内容时,应使用FieldToOLE;若是Access1.xOLE字段,应使用AccessFieldToOLE.这两种格式OLE字段存贮过程是相同.当使用Access2.0建立数据库并存贮OLE字段时,它是OLE2格式,应使用FieldToOLE.用VB3编程时,系统中应安装VB/Access2.0兼容层,否则无法操纵Access2.0数据库.

  第 2、如何使DataControl控件显示记录和OLE字段内容同步.

  这个问题是DataControl控件不支持超长OLE字段引起.对于普通数据库字段,把显示该字段内容Control控件DataSource和DataField属性分别置为DataControl控件和数据库字段名,就可以由DataControl控件正确地显示数据库记录字段内容.而用于显示OLE2字段内容OLEControl控件数据是无法用DataControl控件来存取,必须用上面提供来存取.这时,关键问题是使OLEControl控件显示内容是DataControl控件所在记录中OLE字段内容,也就是OLEControl控件要和DataControl控件同步.

  实现思路方法:

  声明Dyna类型Object:tbOLEObjects.

  在Form_Load事件执行中,将Data1.RecordSet赋给tbOLEObjects,并记录tbOLEObjects中记录数.

  在Data1_Validate事件执行中,使tbOLEObjects执行动作和Data1致,即:在Data1Data1_Validate事件执行中,当Data1执行Data1.RecordSet.MoveNext或Data1.RecordSet.MoveFirst时,tbOLEObjects也要执行tbOLEObjects.MoveNext或tbOLEObjects.MoveFirst.实现时,先保存当前OLEControl控件中内容,然后执行tbOLEObjects.MoveNext或tbOLEObjects.MoveFirst思路方法,再取出OLE字段中内容,插入到OLEControl控件中.

  当系统执行了个SQL语句后,Data1显示记录直接跳到某记录,对tbOLEObjects来说,则要执行查找过程,使得tbOLEObjects当前记录和Data1当前记录致.实现时,先保存当前OLEControl控件中内容,再在tbOLEObjects中查找Data1当前记录,找到后,将其OLE字段中内容取出并插入到OLEControl控件中.

  下面给出实现例子是从本人编写个软件Software中摘录出来,它介绍说明了具体实现思路方法,但不可以直接使用,要结合自己,加上其它必要部分.例子中数据库是个公文数据库,保存用户重要公文,其中OLE字段保存就是Word文档,名字为File_Cont,其它字段是文档相关信息,如文档标题(File_Title)、等级(File_Class)、关键字(File_Keyword)和ID号(File_ID)等.

  变量介绍说明:

OptionExplicit
DimtbOLEObjectsAsDyna
DimnRecordCountAsInteger'tbOLEObjects记录数
DimnRecordNumberAsInteger'tbOLEObjects记录指针
DimbBusyAsInterger'防止重入标志
DimbUpdatedAsInteger'OLEControl控件内容发生变化标志
下面过程要在窗口Form_Load事件中执行,完成对tbOLEObjects赋值并计算出tbOLEObjects中记录数.

SubRefreshForm
DimeErrorAsInteger
NoRecord=False
Data1.RecordSource="SELECT*fromOwnFileorderbyFile_ID"
Data1.Refresh
SettbOLEObjects=Data1.Record.Clone
'给tbOLEObjects赋值
'下面这两条语句是必须,否则无法求出tbOLEObjects中记录数

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操作代码例子.

SubData1_Validate(ActionAsInteger,SaveAsInteger)
DimeErrorAsInteger
SelectCaseAction
Case1'Data1执行MoveFirst
IfNotbBusyThen
bBusy=True
Screen.MousePoer=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.MousePoer=0
bBusy=False
EndIf
Case2'Data1执行了MovePrevious
IfNotbBusyThen'用于防止重入
bBusy=True'
Screen.MousePoer=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.MousePoer=0
bBusy=False
EndIf
Case3'MoveNext
......
Case4'MoveLast
......
Case5'增加个新记录
IfNotbBusyThen
bBusy=True
Screen.MousePoer=11
DoEvents
IfbUpdatedThen
CallPutOLEObject
'保存当前OLEControl控件中内容
DoEvents
bUpdated=False
EndIf
'执行tbOLEObjects.AddNew,修改tbOLEObjects记录数、指针等

  '本例子中未给出这部分代码,中在增加按钮Click事件中执行

Screen.MousePoer=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
下面过程是用户用OutlineControl控件查找数据库中Word文档,每个记录对应个Outline条目,当用户在Outline条目上作Click动作时,系统就显示出该记录所有内容,包括OLE字段内容.这里,tbOLEObjects在查找记录时,使用是顺序查找思路方法,读者若要加快查找速度,可采用其它查找思路方法.

SubOutline1_Click
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
最后,介绍说明点:以上都是在Windows3.2中文版和VB3环境下实现,若在Windows环境下,用VB4编写这种,上面要作改动,不能直接应用.VB4中,DataControl控件理论上是支持OLE数据库字段,但这样使用时,每次执行MoveFirst或MoveNext等类似动作,都会产生个没有"OLEAutomation",笔者没有找到产生这个问题原因和解决思路方法,如果有朋友告知解决思路方法,笔者十分感谢.

0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: