字符串函數(shù)運(yùn)算的差異

此頁沒有內(nèi)容條目
內(nèi)容

Visual Basic for Applications (VBA) 代碼與 Access Basic 代碼相比較而言,其文本在內(nèi)存中的存儲(chǔ)格式是不同的。(Access Basic 曾經(jīng)用在早期版本的 Microsoft Access 中。)Access Basic 代碼中的文本以 ANSI 格式存儲(chǔ),而 Visual Basic 代碼中的文本以 Unicode 格式存儲(chǔ)。

Visual Basic 中使用的 Unicode 格式可以與 OLE 中文本的格式相匹配。OLE 間接地與 Visual Basic 相關(guān)。

例如,文本字符串“ABCfe140fe086fe228”在內(nèi)存中的存儲(chǔ)如下所示:

存儲(chǔ)格式

存儲(chǔ)方式

說明

Unicode

41 00 42 00 43 00 42 30 44 30 46 30

每個(gè)字符存為兩個(gè)字節(jié)。

ANSI

41 42 43 82 A0 82 A2 82 A4

ASCII 字符存為 1 個(gè)字節(jié);雙字節(jié)字符存為 2 個(gè)字節(jié)。

 

由于在內(nèi)部格式上這些不同之處,在 Access Basic 和 Visual Basic 中字符串處理函數(shù)的運(yùn)算也是有差異的。下面列出了這些運(yùn)算有差異的函數(shù)及其語句。

Asc 函數(shù)、Chr 函數(shù)、InputB 函數(shù)、InStrB 函數(shù)、LeftB 函數(shù)、LenB 函數(shù)、RightB 函數(shù)、MidB 函數(shù)和相應(yīng)的語句。

另外,Visual Basic 中又新增了 ChrB 函數(shù)和 AscB 函數(shù)。

由于這些函數(shù)和語句處理文本時(shí)均以字節(jié)為單位,所以它們在 Access Basic 和 Visual Basic 中是一樣的。但因文本的存儲(chǔ)格式不同,它們的運(yùn)算是有差異的。例如,在 Access Basic 中 LenB("A") 為 1,而在 Visual Basic 中為 2。

早期版本的 Microsoft Access 中創(chuàng)建的程序若使用以字節(jié)為單位的字符串處理函數(shù),在 Visual Basic 中必須變換成識(shí)別 Unicode 格式的源代碼。但如果用到的僅是處理字符單位的字符串處理函數(shù),如 Len 函數(shù)、Left 函數(shù)和 Right 函數(shù)等,則無需識(shí)別它們。

如果早期版本的 Microsoft Access 中創(chuàng)建的程序移植到當(dāng)前版本的 Microsoft Access 中,則應(yīng)考慮下列有關(guān)字符串處理的要點(diǎn)。

Asc 函數(shù)和 AscB 函數(shù)

該程序在早期版本的 Access 中能正常運(yùn)行,但在 Microsoft Access 中當(dāng)前版本的 Visual Basic 中會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤。

Print Asc(MidB("fe140", 2,1))

這是因?yàn)?Asc 函數(shù)中的參數(shù) MidB("fe140", 2,1) 不能返回正確的 Unicode 格式文本數(shù)據(jù)。

用下面的 AscB 函數(shù)可以使該程序在當(dāng)前版本的 Microsoft Access 中運(yùn)行:

Print AscB(MidB("fe140", 2,1))

在該程序中,返回了第二個(gè) Unicode 格式字節(jié)的值 (&H30)。

Chr 函數(shù)和 ChrB 函數(shù)

Microsoft Access 中的 Chr 函數(shù)總是返回雙字節(jié)字符。在早期版本的 Microsoft Access 中 Chr(&H41) 和 ChrB(&H41) 是相等的,而在當(dāng)前版本的 Microsoft Access 中。Chr(&H41) 和 ChrB(&H41) + ChrB(0) 才是相等的。

同樣,在早期版本的 Microsoft Access 中,“fe140”表示為 ChrB(&H82) + ChrB(&HA0),但當(dāng)前版本的 Microsoft Access 中卻表示為 ChrB(&H42) + ChrB(&H30)。

調(diào)用 Windows 應(yīng)用程序編程接口 (API)

在某些 Windows API 函數(shù)中,字符串的字節(jié)長度有特殊的含義。例如,下列程序返回一個(gè)在 Windows 中建立的文件夾。在 Microsoft Access 中,LeftB(Buffer, ret) 不能返回正確的字符串。這是因?yàn)楸M管該函數(shù)顯示了一個(gè) ANSI 字符串的字節(jié)長度,但 LeftB 函數(shù)處理的卻是 Unicode 字符串。在這種情況下可使用 InStr 函數(shù)只返回沒有空值的字符串。

Private Declare Function GetWindowsDirectory Lib "kernel32" _

    Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, _

    ByVal nSize As Long) As Long

Private Sub Command1_Click()

    Buffer$ = Space(255)

    ret = GetWindowsDirectory(Buffer$, 255)

    ' WinDir = LeftB(Buffer, ret)   '<--- Incorrect code"

    WinDir = Left(Buffer$, InStr(Buffer$, Chr(0)) - 1)

                                        '<--Correct code"

    Print WinDir

End Sub

Input 函數(shù)和 InputB 函數(shù)

在 Microsoft Access 中,Input 函數(shù)在將文本從文件讀到一個(gè) Unicode 格式字符串中時(shí)會(huì)轉(zhuǎn)換指定數(shù)量的字符,并將其作為變量讀取。而 InputB 函數(shù)卻不然,它假定數(shù)據(jù)已是二進(jìn)制,對其不加轉(zhuǎn)換即存為變量。如果讀取一個(gè)以固定長度字段存儲(chǔ)的文件時(shí)使用 InputB 函數(shù),那么該固定字節(jié)長度的數(shù)據(jù)一經(jīng)讀取便需轉(zhuǎn)換。

Open "Data.Dat" For Input As 1

dat1 = StrConv(InputB(10, 1), vbUnicode)

dat2 = StrConv(InputB(10, 1), vbUnicode)

dat3 = StrConv(InputB(10, 1), vbUnicode)

===DATA.DAT

123456789012345678901234567

Name      Address      Telephone

在 Microsoft Access 7.0 中處理 ANSI 格式字符串字節(jié)

如果必須在 Microsoft Access 中處理 ANSI 格式字符串字節(jié),可以使用 StrConv 函數(shù)。通過設(shè)置 vbUnicodevbFromUnicode 常量可在 ANSI 和 Unicode 格式之間轉(zhuǎn)換文本。如果在臨時(shí)將一個(gè) Unicode 格式字符串轉(zhuǎn)換為 ANSI 格式字符串之后處理字節(jié),處理完畢后又將其轉(zhuǎn)換回 Unicode 格式,那么使用早期版本的 Access 中的代碼要相對容易一些。

'fe141fe141fe087

   fe143fe144fe145fe146fe147fe019fe148fe149fe150fe095fe089fe095fe153fe154fe019fe155fe156fe157fe158fe160fe161fe150

ANSI fe163fe164fe165fe160fe166fe231fe093fe095fe232

dat = StrConv(dat, vbFromUnicode)

.

.

.    'fe141fe141fe087

   fe143fe144fe145fe146fe147fe019fe148fe149fe150fe167fe086fe093fe095fe232

.    'fe016fe084fe231

fe169fe170fe019fe155fe156fe146fe147fe019fe155fe156fe157fe158fe148fe149fe090fe087fe009fe093fe172fe173fe232

.

.

fe141fe141fe087

   fe143fe144fe145fe146fe147fe019fe148fe149fe150fe095fe089fe095fe153fe154fe019fe155fe156fe157fe158fe174fe161fe150

Unicode fe163fe164fe165fe160fe166fe231fe093fe095fe232

dat = StrConv(dat, vbUnicode)

執(zhí)行與 16 位字節(jié)處理函數(shù)相兼容的操作的示例函數(shù)

在 Visual Basic for Applications 中,字符串的內(nèi)部處理使用 Unicode 格式。因此 VBA 中的二進(jìn)制處理函數(shù)不同于 Access Basic 的二進(jìn)制處理函數(shù),Access Basic 曾經(jīng)用在早期版本的 Microsoft Access 中。

ANSI 函數(shù)是為保持 Access Basic 和 Visual Basic 運(yùn)算的兼容性而創(chuàng)建的。

注釋  用這些 ANSI 處理函數(shù)輸入和刪除的字符串總是 Unicode 的。在函數(shù)中會(huì)臨時(shí)轉(zhuǎn)換為 ANSI 格式字符串,但處理過程一結(jié)束便將恢復(fù) Unicode 格式。

下列代碼不能將一個(gè) DBCS 字符的第一和第二個(gè)字節(jié)合并而生成一個(gè) DBCS 字符。

AnsiMidB("fe140",1,1) + AnsiMidB("fe140",2,1)

創(chuàng)建的這些函數(shù)以字節(jié)為單位處理字符串。但是通過這種以字節(jié)為單位的處理過程并不能生成不同的字符。在這種情況下,它將表達(dá)如下:

StrArg = "fe140"

StrArg = StrConv(StrArg, vbFromUnicode)    ' ANSI fe165fe160fe166

RetArg = MidB(StrArg,1,1) + MidB(StrArg,2,1)    ' fe143fe144fe145fe146fe147fe019fe155fe156fe157fe158

   ' fe175fe176

StrArg = StrConv(StrArg, vbUnicode)    ' fe177fe178fe235fe181fe182fe161fe150 Unicode fe165

RetArg = StrConv(RetArg, vbUnicode)    ' fe160fe166fe095fe089fe232

一般來說,如果在處理字符串之前將其轉(zhuǎn)換成了 ANSI 字符,那么處理完畢后應(yīng)將其恢復(fù)成 Unicode 字符。

字節(jié)字符串處理函數(shù)總是一個(gè)用于處理字符串的函數(shù)。若要處理二進(jìn)制數(shù)據(jù),可使用字節(jié)數(shù)組,而不要用字符串變量或字節(jié)字符串處理函數(shù)。

以字節(jié)“數(shù)組”形式存儲(chǔ)的字符串如下所示:

fe143fe144fe145

Array fe165

fe155fe156fe157fe158fe150fe184fe185fe095fe089fe186fe187fe090

   fe188fe019fe229fe230fe165fe231fe093fe095fe232

Dim Var() As Byte

Var = "fe189fe156fe019fe191fe192fe193"             ' Unicode fe163fe164fe087fe184fe185

Var = StrConv("fe189fe156fe019fe191fe192fe193", vbFromUnicode)    ' ANSI fe163fe164fe087fe184fe185

Function AnsiStrConv(StrArg, flag)

   nsiStrConv = StrConv(StrArg, flag)

End Function

' LenB fe087fe175fe176fe095fe089fe199fe165ANSI fe155fe156fe157fe158fe165fe160fe166fe231fe233

   fe175fe176fe177fe178fe150

Unicode fe165fe174fe231fe093fe095fe232

Function AnsiLenB(ByVal StrArg As String) As Long

   AnsiLenB = LenB(AnsiStrConv(StrArg, vbFromUnicode))

End Function

' MidB fe087fe175fe176fe095fe089fe199fe165fe233ANSI fe155fe156fe157fe158fe165fe160fe166fe231fe233fe233

   fe175fe176fe177fe178fe150

Unicode fe165fe174fe231fe093fe095fe232

fe201fe202fe226fe227fe205fe181fe182fe161fe150fe208fe209fe210fe112fe231fe154fe211fe081fe224fe182fe161fe150fe213fe214fe231fe093fe095fe232

Function AnsiMidB(ByVal StrArg As String, ByVal arg1 As Long, _

           Optional arg2) As String

   If IsMissing(arg2) Then

   AnsiMidB = AnsiStrConv(MidB(AnsiStrConv(StrArg, vbFromUnicode) _

           , arg1),vbUnicode)

   Else

   AnsiMidB = AnsiStrConv(MidB(AnsiStrConv(StrArg, vbFromUnicode) _

           , arg1, arg2), vbUnicode)

   End If

End Function

' LeftB fe087fe175fe176fe095fe089fe199fe165fe233

ANSI fe155fe156fe157fe158fe165fe160fe166fe231fe233fe233

   fe175fe176fe177fe178fe150

Unicode fe165fe174fe231fe093fe095fe232

Function AnsiLeftB(ByVal StrArg As String, ByVal arg1 As Long) As String

   AnsiLeftB = AnsiStrConv(LeftB(AnsiStrConv(StrArg, _

           vbFromUnicode), arg1), vbUnicode)

End Function

' RightB fe087fe175fe176fe095fe089fe199fe165fe233ANSI fe155fe156fe157fe158fe165fe160fe166fe231fe233fe233

   fe175fe176fe177fe178fe150

Unicode fe165fe174fe231fe093fe095fe232

Function AnsiRightB(ByVal StrArg As String, ByVal arg1 As Long) As String

   AnsiRightB = AnsiStrConv(RightB(AnsiStrConv(StrArg, _

           vbFromUnicode), arg1), vbUnicode)

End Function

' InStrB fe019 2 fe215fe019fe155fe156fe157fe158fe181fe182fe161fe165fe233 Ansi fe155fe156fe157fe158fe235fe233Ansi fe143fe144fe145fe147fe216fe150fe181fe182fe009fe218fe231fe093fe095fe232

Function AnsiInStrB(arg1, arg2, Optional arg3) As Integer

   If IsNumeric(arg1) Then

   pos = LenB(AnsiLeftB(arg2, arg1))

   AnsiInStrB = InStrB(arg1, AnsiStrConv(arg2, vbFromUnicode) _

           , AnsiStrConv(arg3, vbFromUnicode))

   Else

   AnsiInStrB = InStrB(AnsiStrConv(arg1, vbFromUnicode) _

           , AnsiStrConv(arg2, vbFromUnicode))

   End If

End Function

使用 Byte 數(shù)據(jù)類型

在 Microsoft Access 中,Byte 數(shù)據(jù)類型已成為一種新增的數(shù)據(jù)類型。如果在處理二進(jìn)制數(shù)據(jù)時(shí)使用了字符串變量類型,則文本將在 ANSI 和 Unicode 之間進(jìn)行轉(zhuǎn)換,并且將改變二進(jìn)制數(shù)據(jù)。因此,處理二進(jìn)制數(shù)據(jù)時(shí)應(yīng)使用 Byte 數(shù)據(jù)類型的變量。

Dim ByteData() As Byte

ByteData = "fe155fe156fe157fe158"        ' Unicode fe163fe164fe087fe184fe185fe085fe221fe093fe095fe232

ByteData = StrConv("fe155fe156fe157fe158", vbFromUnicode)     'ANSI fe163fe164fe087fe184fe185fe085fe221fe093fe095fe232

ByteData = InputB(10, #1)    'fe143fe144fe145fe222

fe191fe192fe193fe236fe184fe185fe085fe221fe093fe095fe232

Debug.Print ByteData(5)        'fe223fe224fe157fe158fe235fe231fe154fe191fe192fe193fe150fe148fe149fe226fe227fe087fe095fe232