注冊 登錄
Office中國論壇/Access中國論壇 返回首頁

的個人空間 http://ctxi.cn/?0 [收藏] [復制] [分享] [RSS]

日志

編碼提示與優(yōu)化技巧

已有 630 次閱讀2007-9-2 23:20 |個人分類:我的作品

1. 使用Option Explicit

    一定要使用Option ExplicitOption Explicit 要求確定所有變量的大小,要不然VBA就會用最大、最靈活的數(shù)據(jù)類型來保存變量。通常來講,規(guī)模很大、靈活性很強的應用也是最慢的。

2.  慎重選擇變量大小
       在確定變量大小時,使用盡可能最小的變量尺寸。在整型就可以時不要使用雙精度型,可能情況下使用固定長度字符串而不要使用可變長度字符串。

3.  使用字符串變量以節(jié)省堆棧空間

     字符串變量是代碼中最常用的一種數(shù)據(jù)類型,它們可以被分解成三種類型:
     . 局部固定長度(長度不超過64個字符)——這些字符串每個字符僅用兩個字節(jié),而且不使用堆空間。
     . 局部固定長度(長度超過65個字符)——這些字符串每個字符仍然使用兩個字節(jié),但是在堆內(nèi)存中。同時,它們還要求堆棧中的四個字節(jié)來指向堆中的變量。
     .局部可變量長度(長度一限)——堆空間的數(shù)量依存字符串長度而定。四字節(jié)的堆棧內(nèi)存被用指向堆中變量的指針。
   在處理字符串時,目標就應該是減少正在使用的堆棧內(nèi)存。嘗試著把字符串轉換成局部可變長度或靜態(tài)固定長度字符串。下面的代碼段舉說明為了節(jié)省堆棧內(nèi)存而把內(nèi)存而把可變長度字符串重新聲明為靜態(tài)固定長度字符串。

     Dim strstring as string


     Static strstring as string*30


     提示:用表的字段大小來決定固定寬度文本字符串的長度

4.特寫的對象類型聲明

    在聲明對象變量時要精確。如果代碼將要運行經(jīng)過窗體的文本框控件,聲明對象變量為文本框,而不要僅僅聲明為控件。這樣,VBA不必確定到底說的是哪種控件。例如:可以用

         Sub CycleControls (cntl as TextBox)


      代替

         Sub CycleControls (cntl as control)


      來節(jié)省運行時間。

5.切換True False

    在把一個標志位從True 翻轉到 False 時,沒有必要用一個IF…Then…Else結構來完成檢查值標志的任務?梢杂NOT操作符把值翻轉,從而節(jié)省時間和代碼。通過設定一個布爾變量為該變量的非,就可以翻轉它。

       可以用

           bFlag=Not bFlag


       代替

           If bFlag=False then


              bFlag=True


           Else


              bFlag=False


           End IF


       運行一行代碼比運行幾行計算要節(jié)省許多時間。

6.用Len()的函數(shù)代替空字符串

    為了測試一個字符串變量中是否含有字符,應該使用Len函數(shù)而不是把字符串變量和空字符串(”” “”)進行比較。用Len計算比將變量和空字符串進行比較更快。

       Sub CheckString (strString as string)


            If Len(strString) then


               MsgBox “Here is the string : “ & strString


           End if


      End Sub


7
.用True False 代替Zero


    因為True False是二進進制的,它們比數(shù)字Zero更容易求值?梢韵裣旅孢@樣使用TrueFalse

       Function ShowNumber(dblNumber as Double) as string


           If dblNumber then


             ShowNumber=”The number is “ & dblNumber


         End if


      End Function


8.快速對象引用

      使用變量而不是重復的對象引用。引用一個在窗體、控件、報表或查詢中存在的變量比再回頭引用這個對象更快。代替再次引用窗體

      Forms![frmMyForm].Height=500

      Forms![frmMyForm].Width=500

      可以嘗試聲明一個變量并按下面這樣的引用它:

      Dim Frm as Form


      Set Frm =Forms![frmMyForm]

      Frm.Height=500
      Frm.Width=500

    在處理一個對象的多個屬性時,用With…End With來減少對象的引用。這在路徑和引用很長時特別有用,而且也容易錄入

      With Forms![frmMainForm]![txtCustomerName]


         .left=200

         .top=300
         .height=200
         .width=100


       End with


    其中ME代表活動窗體,所以它直接指向當前窗體,省略了確定變量大小和聲明對象變量。因為它只在CBF中有效,所以不能把它用在一般的標模塊中,例如:

      With ME


        .Height=500


        .Width=500


      End With


9.快速數(shù)組使用

      要使用數(shù)組。在一般情況下,數(shù)組駐留在內(nèi)存中,對其防問和操作都很快。數(shù)組的擴大所需的時間無窮小,并且它們對內(nèi)存使作效率極高。假如在開發(fā)過程中數(shù)組的大小沒有確定,那么可使用動態(tài)數(shù)組。動態(tài)數(shù)組在運行時可以根據(jù)需要重新定義維數(shù)。千萬不要聲明一個浪費內(nèi)存的大型靜態(tài)數(shù)組。
    用Erase 關鍵字可以清空數(shù)組而不破壞它的結構。Erase清空數(shù)組的內(nèi)容,但不完全刪除它。

       Erase myArray

    相反地,需要擴大一個數(shù)組但不破壞它的內(nèi)容時可以用Redim Preserve

       ReDim Preserve myArray (Ubound(myArray+1))


    數(shù)組存儲的數(shù)據(jù)可以來自已記錄集、控件組,也可以讀自文件、用戶輸入以及任何一致的數(shù)據(jù)。例如,與其保持DAO記錄集打開而招致相關的開銷,不如打開數(shù)組后用GetRow()方法來產(chǎn)生一個合適的專用數(shù)組,然后釋放記錄集,這樣可以節(jié)省內(nèi)存并緩解多用戶情況下的沖突。GetRow()帶有一個參數(shù):需要裝載到數(shù)組中的記錄行數(shù)。

        Dim db as Database

        Dim RowArray as Variant
        Dim rs as Recordset

        Set db=CurrentDb()

        Set rs=db.opentrecordset(“Quarterly Orders”)
        RowArray=rs.GetRows(rs.Recordcount)
        Rs.close
         …
       在數(shù)組裝載以后就可以對其中的數(shù)據(jù)根據(jù)情形進行操作或者把記錄裝載到一個非綁定的窗體中。

10.盡可能使用常數(shù)

    為了讓VBA取回一個變量的當前值,該變量必須是沒有被引用的,這個過程每次都需要幾個CPU指令;如果該變量沒有在處理器的寄存器或緩存中,需要的指令更多。相反,常數(shù)只需很少的幾條指令,而且還有益于增加代碼的可讀性。例如,可以創(chuàng)建一個符號常量,代替在代碼中從頭到尾使用42,比方說

       TheAnswerToLifeTheUniverseAndEverything
并把它設定為42。VBA讀取常量比變量更快。況且,其它的開發(fā)者使用常量也比42這個鬼數(shù)更容易。

11.書簽的合理使用

      書簽是可以在用戶界面里許多記錄中瀏覽移動時使用的簡便方法,但它們也是有害卻引人上癮的。說它們簡便是因為它們速度快,對代碼微不足道。說它們有害是因為它們只代表一個記錄在一系列行中的臨時位置。
    要記住有兩種書簽:一種用于窗體,一種用于記錄集。窗體書簽是一個動態(tài)分配給底層記錄集副本的變體數(shù)組。DAO書簽是在字節(jié)數(shù)組中指向記錄集中每一個記錄的條目。但無論哪種書簽都是隨著記錄集及其副本而不停地創(chuàng)建、破壞、重建。它們并不代表記錄,與主鍵也沒有任何關系。數(shù)據(jù)操作應該使用那些與關系數(shù)據(jù)庫理論和設計相關一致的技術,而不是那些記錄集中的記錄的偶然位置。

12.關閉與銷毀

    快速的代碼是整齊嚴謹?shù)拇a。在完成任務時要關閉記錄集,在對象不再使用時要把它們設定為Nothing。不用的窗體要關閉,不用的數(shù)據(jù)庫連接也要關閉。保存變量的局域化,這樣在控制轉換到另一個函數(shù)時它們會因超出有效范圍而自動消失。寧可使用動態(tài)數(shù)組也不用靜態(tài)數(shù)組。總之,要盡一切努力來消化Access應用可能消耗的資源。

       Rs.close

       Set db=Nothing

13.用SQL代替DAO

   只有在別無選擇時才在整個記錄集中循環(huán)操作。優(yōu)化Jet數(shù)據(jù)庫以使用SQL來操作數(shù)據(jù)和數(shù)據(jù)結構。只要可能,就使用查詢而不是DAO,很少有DAO比精心創(chuàng)建的查詢速度快的情況。查詢有執(zhí)行規(guī)劃而且可以利用索引,但DAO卻不能。
    如果必須用一個對象模型來選定數(shù)據(jù),應該用ADO而不是DAOADO是通過對象模塊來完成選定數(shù)據(jù)操作或數(shù)據(jù)定義的首選標準。DAO是凝固不變的,而且沒有進一步的擴展和提高。

14.使用集合的索引數(shù)

      在使用對象集合時,盡可能使用它們的索引數(shù)。索引數(shù)是集合的內(nèi)部識別標記,它們比集合對象的其他屬性(如名稱)用起來更快。例如,下面的兩個語句顯示了引用當前數(shù)據(jù)庫的兩種不同方法。對Currentdb()的引用會自動刷新數(shù)據(jù)庫的集合從而消耗時間,但第一個引用則不會。

        Set db=DBEngine(0)(0)


      比

        Set db=Currentdb()


      更快。類似地,語句

        Set cntl=Forms!frmMyForm(0)


      比

        Set contl=Forms![frmMyForm]![myControl]

      更快。

      使用集合成員的索引數(shù)在循環(huán)中尤其有用,這將在下面討論。

15.加快循環(huán)速度

    當循環(huán)經(jīng)過一個集合時,使用For…Each 而不是For…Next。多考慮一下窗體的控件,是這些控件組成了集合。使用下面的語法來使循環(huán)通過每一個控件:

      For Each cntl on frm


           ….


      Next


    要比使用一個簡單的For…Next循環(huán)運行快。For…Next循環(huán)需要重復對象引用,但是For…Each 循環(huán)不需要。
如果需要使用循環(huán)通過對象集合,開發(fā)者肯定希望避免對集合的不必要刷新。即使在一個小的數(shù)據(jù)庫中,刷新集合也會破壞應用的性能。在使用For …Next循環(huán)時不必在下一行重復變量,所以可以節(jié)省時間。

      For i=1 to 100


          …….do what you want


      Next


    這樣做的好處在嵌套循環(huán)中特別顯著。另外,也不要重復計算For 所在行的上下限。上限應該在進入循環(huán)之前就建立好。下面的第一個代碼段計算循環(huán)退出標準reccount一次。第二個代碼段則在每一步循環(huán)中都計算一次。顯然,第一個代碼段是更快的代碼。

       Reccount=rs.recordcount/2


        For i=1 to recount

          …
        Next

       For i=1 to rs.recordcount/2

          …..


       Next


16.杜絕在代碼中使用IIF()

      不要在代碼中使用IIF() 函數(shù)。這個函數(shù)在產(chǎn)生結果之前必須計算包含其中的所有表達式。標準的IF…Then..Else結構速度更快。

17.合理安排Select Case

    在使用Select Case結構時,結構安排上要把經(jīng)常遇到的情況放在頂端,因為在通過情況選項時要依次對每一種情況進行嘗試,安排它們時把最常發(fā)生的放在前面可以使執(zhí)行盡早退出這個選擇結構。

18.使用.Excute,棄用RunSQL

      任何時候都要避免基于Docmd的代碼,DocmdVBA最高級別的代碼,是從Access沒有采用VBA而只是簡單的宏來完成自動操作的版本中繼承來的。如果還有其他的選擇,請接受吧。

        Docmd.RunSql “….”


     比

        Querydef.Excute


     運行速度慢。

發(fā)表評論 評論 (2 個評論)

回復 zbjit 2007-9-12 13:30
受益匪淺,謝謝。
回復 rcylbx 2009-2-10 15:13
這篇文章應該經(jīng)?纯

facelist doodle 涂鴉板

您需要登錄后才可以評論 登錄 | 注冊

QQ|站長郵箱|小黑屋|手機版|Office中國/Access中國 ( 粵ICP備10043721號-1 )  

GMT+8, 2024-10-23 08:23 , Processed in 0.100061 second(s), 15 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

返回頂部