147、资料库的导出
在很多 VB 的资料库书籍中,都会很完整的提到:如何由其他种类的文件中将资料导入资料库,但是却很少有书提到:如何将资料库中的资料,导出到各种不同的文件类型的文件中,连 VB 的 Help 中也是这样!
或许是大家都认为资料库主题的重点是在资料库本身吧!
但是,在实际的资料库程序运用中,却常常需要将资料库导出到各种不同的文件类型的文件中,这些文件可能是 DBase文件、文字文件 (.Txt)、Excel 文件、Html 文件、Access 文件或其他类型的资料库文件 (ODBC)...等。
在本专题中,考虑到并不是每一个人都有 Oracle 或 SQL Server 的环境,为了让大家都能够实作,我们将以 Access 资料库来作练习,而练习的文件也使用 VB 本身提供的 Biblio.mdb (位于各版本 VB 的目录下)。
预计要练习导出的文件类型有五种:DBase文件、文字文件 (.Txt)、Html 文件、Excel 文件、Access 文件。除了这五种之外,下面的语法可以将资料库之资料导出到任一种 VB 支援的资料库或文件中。
在练习之前,要将导出文件的 SQL 语法先说明一下:
SELECT Table.Fields INTO [dbms type;DATABASE=path].[unqualified filename] FROM [Table or Tables]
SELECT Table.Fields INTO [资料库种类;DATABASE=资料库路径].[资料库文件名称] FROM [Table or Tables]
至于【资料库种类】及【资料库路径】,视资料库或文件类型之不同而异,详见【注一】。
如果上面说的都清楚了,那我们要开始这一个练习了!
在 Form 上放置一个 CommandButton,在【专案】【设定引用项目】中加入 Microsoft DAO 3.51 Object Library,我们将使用 Biblio.mdb 的 authors Table,在 Command1_Click 中加入以下程序码:
Dim db As Database
Set db = Workspaces(0).OpenDatabase(App.Path & "\biblio.mdb")
'db.execute "SELECT Table.Fields INTO [dbms type;DATABASE=path].[unqualified filename] FROM [Table or Tables]"
在以上程序中,db.execute 指令行之指令依资料库或文件的种类说明如下:
一、DBase文件
SQL 语法:SELECT * INTO [dBase III;DATABASE=资料库路径].[dbase文件名称] FROM [authors]
db.Execute "SELECT * INTO [dBase III;DATABASE=C:\test].[authors.DBF] FROM [authors]"
注意事项:
1、authors.DBF 事先不可存在,否则会产生错误!
2、若您没有 Dbase,您可以使用 Access 来连结这个 Table,以便观察结果!
二、文本文件 (.Txt)
SQL 语法:SELECT * INTO [Text;DATABASE=文本文件路径].[文本文件名称] FROM [authors]
db.Execute "SELECT * INTO [Text;DATABASE=C:\test].[authors.TXT] FROM [authors]"
注意事项:
1、authors.TXT 事先不可存在,否则会产生错误!
2、此动作会产生的文件有二个,第一个就是文本文件 authors.TXT,第二个是 Schema.ini。
3、文本文件之格式为 CSV 之文件格式,即各栏位间以逗点分开,实际呈现方式如下:
"Au_ID","Author","Year Born"
1,"Jacobs, Russell",1950
2,"Metzger, Philip W.",1942
4、Schema.ini 若事先不存在会新产生一个,若已存在,则会在原文件后面直接 Append。
5、至于 Schema.ini 的属性为此次导出的相关资讯,格式同一般的 Ini 文件,详细属性如下:
[authors.TXT]
ColNameHeader=True
CharacterSet=OEM
Format=CSVDelimited
Col1=Au_ID Integer
Col2=Author Char Width 50
Col3="Year Born" Short
三、Html 文件
SQL 语法:SELECT * INTO [Excel 8.0;DATABASE=Html文件路径].[Html文件名称] FROM [authors]
db.Execute "SELECT * INTO [HTML Export;DATABASE=C:\test].[authors.HTM] FROM [authors]"
注意事项:
1、authors.HTM 事先不可存在,否则会产生错误!
2、此动作会产生的文件有二个,第一个就是文本文件 authors.HTM,第二个是 Schema.ini。
3、Schema.ini 若事先不存在会新产生一个,若已存在,则会在原文件后面直接 Append。
4、至于 Schema.ini 的属性为此次导出的相关资讯,格式同一般的 Ini 文件,详细属性如下:
[authors.HTM]
ColNameHeader=True
CharacterSet=ANSI
Format=HTML
Col1=Au_ID Integer
Col2=Author Char Width 50
Col3="Year Born" Short
四、Excel 文件
SQL 语法:SELECT * INTO [Excel 8.0;DATABASE=文件路径+文件名].[工作表名称] FROM [authors]
db.Execute "SELECT * INTO [Excel 8.0;DATABASE=C:\test\authors.XLS].[authors] FROM [authors]"
注意事项:
1、authors.XLS 可事先存在,也可以不存在,会自动产生一个。
2、工作表 authors 事先不可存在,否则会产生错误!
五、Access 文件
SQL 语法:SELECT * INTO [新资料库路径+文件名][新资料表名称] FROM [authors]
'导出到同一资料库 ( 新 Table 为 authors1 )
'新 Table authors1 事先不可存在,否则会产生错误!
db.Execute "SELECT * INTO [authors1] FROM [authors]"
'导出到不同的资料库 ( 新资料库为 db1,新 Table 为 authors )
'新资料库 db1事先必须存在,否则会产生错误!
'但是其中新 Table authors 事先不可存在,否则会产生错误!
db.Execute "SELECT * INTO [C:\test\db1.mdb].[authors] FROM [authors]"
注一:各种可能的资料库种类 Connect 属性设定方式:
资料库种类
资料库声明方式
资料库路径 (或加上文件名)
Microsoft Jet Database
[database];
drive:\path\filename.mdb
dBASE III
dBASE III;
drive:\path
dBASE IV
dBASE IV;
drive:\path
dBASE 5
dBASE 5.0;
drive:\path
Paradox 3.x
Paradox 3.x;
drive:\path
Paradox 4.x
Paradox 4.x;
drive:\path
Paradox 5.x
Paradox 5.x;
drive:\path
Microsoft FoxPro 2.0
FoxPro 2.0;
drive:\path
Microsoft FoxPro 2.5
FoxPro 2.5;
drive:\path
Microsoft FoxPro 2.6
FoxPro 2.6;
drive:\path
Microsoft Visual FoxPro 3.0
FoxPro 3.0;
drive:\path
Microsoft Excel 3.0
Excel 3.0;
drive:\path\filename.xls
Microsoft Excel 4.0
Excel 4.0;
drive:\path\filename.xls
Microsoft Excel 5.0 or Microsoft Excel 95
Excel 5.0;
drive:\path\filename.xls
Microsoft Excel 97
Excel 8.0;
drive:\path\filename.xls
Lotus 1-2-3 WKS and WK1
Lotus WK1;
drive:\path\filename.wk1
Lotus 1-2-3 WK3
Lotus WK3;
drive:\path\filename.wk3
Lotus 1-2-3 WK4
Lotus WK4;
drive:\path\filename.wk4
HTML Import
HTML Import;
drive:\path\filename
HTML Export
HTML Export;
drive:\path
Text
Text;
drive:\path
ODBC
ODBC;
DATABASE=database;
UID=user;
PWD=password;
DSN= datasourcename;
[LOGINTIMEOUT=seconds;]
None
Microsoft Exchange
Exchange 4.0;
MAPILEVEL=folderpath; [TABLETYPE={ 0 | 1 }];[PROFILE=profile;]
[PWD=password;]
[DATABASE=database;]
drive:\path\filename.mdb
148、模拟 Windows 的资源回收站!
您现在将屏幕上所有的视窗全部缩小,找到资源回收站,按鼠标右键,选择【属性】,便会出现【资源回收站】的属性问话框。
其中有几个选项如下:
1、不要将文件移到资源回收站,删除时立即移除文件。
2、显示删除确认对话框?
根据以上之状况,文件之删除有三种情形:
1、删除文件,出现确认对话框,文件移到资源回收站。
2、删除文件,出现确认对话框,文件不移到资源回收站。
3、删除文件,不出现确认对话框,文件也不移到资源回收站。
模拟程序如下:
'在模组的声明区中加入以下声明:
Public Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Long
hNameMappings As Long
lpszProgressTitle As Long
End Type
Public Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long
Public Const FO_DELETE = &H3
Public Const FOF_ALLOWUNDO = &H40 '可以还原
Public Const FOF_NOCONFIRMATION = &H10 '不出现确认对话框
Public Const FOF_SILENT = &H4
'在程序中之使用方法如下:
'以下之例子会出现确认对话框,文件也会移到资源回收站。
Private Sub Command1_Click()
Dim SHop As SHFILEOPSTRUCT
Dim strFile As String '要删除的文件(含全路径)
strFile = "c:\test.txt"
With SHop
.wFunc = FO_DELETE
.pFrom = strFile
.fFlags = FOF_ALLOWUNDO
End With
SHFileOperation SHop
End Sub
'若要调整,只要更改 fFlags 之值即可,如下:
.fFlags = FOF_SILENT '删除文件,出现确认对话框,文件不移到资源回收站。
.fFlags = FOF_NOCONFIRMATION '删除文件,不出现确认对话框,文件也不移到资源回收站。
149、如何得到文件路径的文件名
Dim sFilePath As String
sFilePath = "C:\Windows\System\sytem.dll"
Dim lGetLen As Long, lNum As Long
Dim sGetFile As String, sTemp As String
lGetLen = Len(sFilePath) '得到文件路径长度
sTemp = lGetLen
For lNum = 1 To lGetLen
If Left(sGetFile, 1) = "\" Then Exit For
sGetFile = Mid(sFilePath, sTemp, lNum)
sTemp = sTemp - 1
Next lNum
sGetFile = Mid(sGetFile, 2) '得到文件名
MsgBox sGetFile
150、如何用VB准确计算年龄
Function CalcAge(datEmpDateOfBirth as Variant) as Integer
CalcAge = Int(DateDiff("y",datEmpDateOfBirth,Date())/365.25)
End Function
151、如何算出屏幕的分辨率?
如果不使用 Third Party 的控制项,而希望程序的画面能随著屏幕的分辨率而自动调整各个控制项的位置及大小,其中最重要的一件事,便是算出目前执行程序的屏幕之分辨率!
而分辨率要如何算呢?看看以下的程序便可知道!
ResWidth = Screen.Width \ Screen.TwipsPerPixelX
ResHeight = Screen.Height \ Screen.TwipsPerPixelY
ScreenRes = ResWidth & "x" & ResHeight
ResWidth 就是指屏幕分辨率中的宽
ResHeight 就是指屏幕分辨率中的长
而最后算出的 ScreenRes,格式会像 800x600 一样!
除了 800x600 之外,可能还有 640x480、1024x768....等。
152、如何产生一个多行式的提示框 (ToolTipText)?
VB5 以后的 VB 版本都有提供一个属性 -- ToolTipText,目的是让使用者在执行阶段,鼠标在物件上徘徊约一秒时,就将该物件的提示字串显示在该物件下面的一个小长方形中,以协助使用者做输入动作。
有时候说明字串太长了,于是就有人想将提示字串分行显示,而且自然而然的使用 vbNewLine (=vbCrLf 或 =vbCr ) 来换行,因为根据以往的经验,VB都是这样做换行的,可是这一次很多人都踢到铁板了!
VB 用来显示 ToolTipText 的提示框,其实是一个文字框,而且 MultiLine 属性并没有设为 True,您可以自己用一个单行式的文字框来做测试,就算您用 vbCrLf 来换行也不会有作用的!
既然 VB 提供的 Default 功能不能满足我们的需求,而我们又想提供使用者多行式的提示框,那要怎么办呢?其实也不难,我们自己动手 DIY 一下就有了,而且程序码也不长!
'首先在 Form 上放一个 Timer (如果需要的话),以便于叫出突现式说明框
Private Function TimeOut(pInterval As Single)
Dim sngTimer As Single
sngTimer = Timer
Do While Timer < sngTimer + pInterval
DoEvents
Loop
End Function
'然后在 Form 上放一个 Label,取名为 lblToolTip,在 MouseMove 中加入以下程序:
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
lbltooltip.Visible = False
End Sub
'在您想显示说明框的物件加入以下程序码: ( Textbox, listbox etc. )
Private Sub Text1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
TimeOut 0.3 '鼠标移到物件上多久后,要显示提示框
lbltooltip.Caption = "大家好 !!" & vbCrLf & "" & vbCrLf & _
"您目前看到的黄色标签" & vbCrLf & "是一个多行式的提示框"
lbltooltip.Left = Text1.Left + lbltooltip.Width
lbltooltip.Top = Text1.Top + Text1.Height
lbltooltip.Visible = True
End Sub
153、如何改变屏幕的分辨率?
如果希望使用者在跑我们开发的应用程序时,看到的画面的样子和我们在 Design Time 时一样的话,我们往往需要处理屏幕分辨率的问题,才能使程序的画面能随著屏幕的分辨率而自动调整各个控制项的位置及大小,但是这样子往往会使程序复杂化!
除了以上这样子,将就使用者屏幕分辨率大小的民主式做法之外,您还有一个选择,那就是强制改掉使用者屏幕分辨率大小的暴权式做法,如果真的可以这么做,您根本就不用再去处理分辨率的问题了!
在讨论区中,不时有人问到如何改变屏幕分辨率的大小,这是因为在 VB 32位元的 API 检视员中漏掉了有关 EnumDisplaySettings、ChangeDisplaySettings 的常数及宣告。
'在模组中加入以下宣告、常数、型态:
Declare Function EnumDisplaySettings Lib "user32" Alias "EnumDisplaySettingsA" (ByVal lpszDeviceName As Long, ByVal iModeNum As Long, lpDevMode As Any) As Boolean
Declare Function ChangeDisplaySettings Lib "user32" Alias "ChangeDisplaySettingsA" (lpDevMode As Any, ByVal dwFlags As Long) As Long
Declare Function ExitWindowsEx Lib "user32" _
(ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Public Const EWX_LOGOFF = 0
Public Const EWX_SHUTDOWN = 1
Public Const EWX_REBOOT = 2
Public Const EWX_FORCE = 4
Public Const CCDEVICENAME = 32
Public Const CCFORMNAME = 32
Public Const DM_BITSPERPEL = &H40000
Public Const DM_PELSWIDTH = &H80000
Public Const DM_PELSHEIGHT = &H100000
Public Const CDS_UPDATEREGISTRY = &H1
Public Const CDS_TEST = &H4
Public Const DISP_CHANGE_SUCCESSFUL = 0
Public Const DISP_CHANGE_RESTART = 1
Type DEVMODE
dmDeviceName As String * CCDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName As String * CCFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
'假设现在我们希望将分辨率改成 800X600,但是不要改变色板 ,程序如下:
'注:色板指的就是 16色 / 256色 / High Color (16Bit) / True Color (24Bit)
Private Sub Command1_Click()
Dim DevM As DEVMODE '将取得的讯息存放在 DevM
erg& = EnumDisplaySettings(0&, 0&, DevM)
DevM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT 'Or DM_BITSPERPEL
DevM.dmPelsWidth = 800 '想要设定的屏幕宽度
DevM.dmPelsHeight = 600 '想要设定的屏幕高度
'我们不更改色板,因为一旦更改色板就必须重新开机!
'DevM.dmBitsPerPel = 32 (could be 8, 16, 32 or even 4) '此行可用于改变色板
'以下这行指令会暂时更改屏幕的分辨率,是测试性的,不一定成功,
'不过因为没将设定值写到注册表,所以虽然可能更改成功,
'但是一旦重新开机后,会自动恢复成更改前的设定值
erg& = ChangeDisplaySettings(DevM, CDS_TEST)
'上面的指令若成功,而且您想永久性的更改使用者的屏幕分辨率,
'您还必须使用下一行指令,将资料写到注册表
'erg& = ChangeDisplaySettings(DevM, CDS_UPDATEREGISTRY)
'但是如果您只是想暂时更改使用者的屏幕分辨率,就不需要了.
'当然并不是您随便设定一个值,就一定会成功的更改屏幕分辨率,
'所以还需要检查是否更改成功!下面的程序就是检查是否更改成功
Select Case erg&
Case DISP_CHANGE_RESTART
'通常如果有更改到色板,或者较老的板子,会要求重新开机
an = MsgBox("您必须重新开机!", vbYesNo + vbSystemModal, "讯息")
If an = vbYes Then
erg& = ExitWindowsEx(EWX_REBOOT, 0&)
End If
Case DISP_CHANGE_SUCCESSFUL
'如果更改成功且不需重新开机,您就可以将设定值写到注册表中
erg& = ChangeDisplaySettings(DevM, CDS_UPDATEREGISTRY)
MsgBox "分辨率更改成功!", vbOKOnly + vbSystemModal, "成功!"
Case Else
'更改不成功
MsgBox "不支持此一模式!", vbOKOnly + vbSystemModal, "错误!"
End Select
End Sub
154、如何在程序中启动 NT 的【拨号网络连接】对话框?
在【问题125】如何在程序中启动【拨号网络连接】对话框?我告诉大家如何在 VB 中用 Shell 去叫出【拨号网络连接】对话框,程序码如下:
Private Sub Command1_Click()
Dim res
res = Shell("rundll32.exe rnaui.dll,RnaDial " & "拨号网络连接名称", 1)
End Sub
但是有网友反应,用上述的方法只有在 Windows 95/98 中才行得通,一碰到 Windows NT 可就没辄了!今天,我要告诉大家在 Windows NT 中,要如何做到相同的事情。不难,方法如下:
Private Sub Command1_Click()
Dim res
res = Shell("rasphone.exe [-d 拨号网络连接名称]", 1)
End Sub
155、如何使用 ADO 來压缩或修复 Microsoft Access 文件
以前使用 DAO 時,Microsoft 有提供 CompactDatabase Method 來压缩 Microsoft Access 文件,RepairDatabase Method 來修复损坏的 Microsoft Access 文件,。可是自从 ADO 出來之后,好像忘了提供相对的压缩及修复 Microsoft Access 文件的功能。
現在 Microsoft 发现了这个问题了,也提供了解決方法,不过有版本上的限制!限制說明如下:
ActiveX Data Objects (ADO), version 2.1
Microsoft OLE DB Provider for Jet, version 4.0
這是 Microsoft 提出的 ADO 的延伸功能:Microsoft Jet OLE DB Provider and Replication Objects (JRO)
这个功能在 JET OLE DB Provider version 4.0 (Msjetoledb40.dll) 及 JRO version 2.1 (Msjro.dll) 中第一次被提出!
這些必要的 DLL 文件在您安裝了 MDAC 2.1 之后就有了,您可以在以下的网页中下载 MDAC 的最新版本!
Universal Data Access Web Site
在下载之前先到 VB6 中檢查一下,【控件】【設定引用項目】中的 Microsoft Jet and Replication Objects X.X library 如果已经是 2.1 以上的版本,您就可以不用下载了!
在您安裝了 MDAC 2.1 或以上的版本之后,您就可以使用 ADO 來压缩或修复 Microsoft Access 文件,下面的步骤告訴您如何使用 CompactDatabase Method 來压缩 Microsoft Access 文件:
1、新建一個新表单,选择功能表中的【控件】【設定引用項目】。
2、加入 Microsoft Jet and Replication Objects X.X library,其中 ( X.X 大于或等于 2.1 )。
3、在适当的地方加入以下的程序代码,記得要修改 data source 的內容及目地文件的路径:
Dim jro As jro.JetEngine
Set jro = New jro.JetEngine
jro.CompactDatabase "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\nwind2.mdb", _ '來源文件
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\abbc2.mdb;Jet OLEDB:Engine Type=4" '目的文件
在 DAO 3.60 之后,RepairDatabase Method 已经无法使用了,以上的程序代码显示了 ADO CompactDatabase Method 的用法,而它也取代了 DAO 3.5 時的 RepairDatabase method!
156、如何建立可卷动的图形框?
在各网站的讨论区中常有人问到这个问题,其实答案就在 Msdn 中!以下资料由 Msdn 节录:
除了图片方块控制项之外,也可用水平、垂直卷轴来建立可卷动的图形框应用程序。当所包含的图形超过控制项范围时,单独一个图片方块控制项无法制作卷动功能─ 因为图片方块控制项无法自动新增卷轴。应用程序使用两个图片方块。称第一个为平稳的父图片方块控制项。第二个为子图片方块控制项,它包含在父图片方块中。子图片方块中包含图形影像,可用卷轴控制项在父图片方块中搬动子图片方块。
先建立一个新工程,然后在表单上绘制两个图片方块、一个水平卷轴和一个垂直卷轴。位置随便放,这里,用表单的 Form_Load 事件设定比例模型,在父图片方块中调整子图片方块的大小,水平、垂直卷轴,搜寻并调整它们的大小,然后载入点阵图图形。将下列程序码新增到表单的 Form_Load 事件程序中:
修正:避开 Form_Resize 产生的错误,将程序模组化,并加上范例程序。
Private Sub init_object()
'初始化两个图片方块的位置。
Picture1.Move 0, 0, ScaleWidth - VScroll1.Width, ScaleHeight - HScroll1.Height
Picture2.Move 0, 0
'将水平卷轴搜寻。
HScroll1.Top = Picture1.Height
HScroll1.Left = 0
HScroll1.Width = Picture1.Width
'将垂直卷轴搜寻。
VScroll1.Top = 0
VScroll1.Left = Picture1.Width
VScroll1.Height = Picture1.Height
'设定卷轴的 Max 属性。
HScroll1.Max = Picture2.Width - Picture1.Width
VScroll1.Max = Picture2.Height - Picture1.Height
'判断子图片方块是否将充满屏幕。若如此,则无需使用卷轴。
VScroll1.Visible = (Picture1.Height < Picture2.Height)
HScroll1.Visible = (Picture1.Width < Picture2.Width)
End Sub
Private Sub Form_Load()
'设定 ScaleMode 为像素。
Form1.ScaleMode = vbPixels
Picture1.ScaleMode = vbPixels
'将 Autosize 设定为 True,以使 Picture2 的边界延伸到实际的点阵图大小。
Picture2.AutoSize = True
'将每个图片方块的 BorderStyle 属性设定为 None。
Picture1.BorderStyle = 0
Picture2.BorderStyle = 0
'载入点阵图。 此处请自行更改图片
'Picture2.Picture = LoadPicture("c:\Windows\ham.bmp")
'初始化各物件
init_object
End Sub
水平和垂直卷轴的 Change 事件,用在父图片方块中上、下、左、右移动子图片方块。请将下列程序码新增到两个卷轴控制项的 Change 事件中:
Private Sub HScroll1_Change()
Picture2.Left = -HScroll1.Value
End Sub
Private Sub VScroll1_Change()
Picture2.Top = -VScroll1.Value
End Sub
将子图片方块的 Left 和 Top 属性分别设定成水平和垂直卷轴数字的负值,这样,当上、下、左、右卷动时,图形可以正确移动。
执行阶段中,显示的图形如上图所示。
在执行阶段调整表单大小
在上例中,表单的初始大小限制图形的可视大小。在执行阶段中,当使用者调整表单大小时,为了调整图形视域应用程序的大小,可将下列程序码新增到表单的 Form_Resize 事件程序中:
Private Sub Form_Resize()
'重新初始化各物件
'避开表单最小化的情况
If Me.WindowState <> 1 Then init_object
End Sub
评论