日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

常见字典用法集锦及代码详解

發布時間:2024/1/1 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常见字典用法集锦及代码详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 前言
  • 字典的簡介
  • 1. 字典對象
    • 1.1 Add 方法
    • 1.2 Exists 方法
    • 1.3 Keys 方法
    • 1.4 Items 方法
    • 1.5 Remove 方法
    • 1.6 RemoveAll 方法
  • 2. 實例
    • 2.1 實例1. 普通常見的求不重復值問題
      • 2.1.1 問題
      • 2.1.2 實例代碼
      • 2.1.3 代碼詳解
    • 2.2 實例2 求多表的不重復值問題
      • 2.2.1 問題
      • 2.2.2 代碼
      • 2.2.3 代碼詳解
    • 2.3 實例3 A列中顯示1 ~ 1000中被6除余1和余5 的數字
      • 2.3.1 問題
      • 2.3.2 代碼
      • 2.3.3 代碼詳解
    • 2.4 實例4 拆分數據不重復
      • 2.4.1 問題
      • 2.4.2 代碼
      • 2.4.3 代碼詳解
      • 2.4.4 山菊花版主的代碼
      • 2.4.5 代碼詳解
    • 2.5 實例5 前期綁定的字典實例
      • 2.5.1 問題
      • 2.5.2 代碼
      • 2.5.3 代碼詳解
    • 2.6 實例6 多條件復雜匯總
      • 2.6.1 問題
      • 2.6.2 代碼
      • 2.6.3 代碼詳解
    • 2.7 實例7 字典法排序
      • 2.7.1 問題
      • 2.7.2 代碼
      • 2.7.3 代碼詳解
    • 2.8 實例8 2級動態數據有效性問題
      • 2.8.1 問題
      • 2.8.2 代碼
      • 2.8.3 代碼詳解
    • 2.9 實例9 字典取行數,數組重新賦值
      • 2.9.1 問題
      • 2.9.2 代碼
      • 2.9.3 代碼詳解
    • 2.10 實例10 先字典求得行后顯示整行數據
      • 2.10.1 問題
      • 2.10.2 代碼
      • 2.10.3 代碼詳解
    • 2.11 實例11 關鍵字賦給兩列后用Replace方法
      • 2.11.1 問題
      • 2.11.2 代碼
      • 2.11.3 代碼詳解
    • 2.12 實例12 復雜報表匯總
      • 2.12.1 問題的提出 :
      • 2.12.2 代碼
      • 2.12.3 代碼詳解
  • 3. 后語



前言


????????凡是上過學校的人都使用過字典,從新華字典、成語詞典,到英漢字典以及各種各樣數不勝數的專業字典,字典是上學必備的、經常查閱的工具書。有了它們,我們可以很方便的通過查找某個關鍵字,進而查到這個關鍵字的種種解釋,非??旖輰嵱?。

????????凡是上過 EH 論壇的想學習VBA里面字典用法的,幾乎都看過研究過 northwolves 狼版主、oobird版主的有關字典的精華貼和經典代碼。我也是從這里接觸到和學習到字典的,在此,對他們表示深深的謝意,同時也對很多把字典用得出神入化的高手們致敬,從他們那里我們也學到了很多,也得到了提高。

????????字典對象只有 4個屬性6個方法 ,相對其它的對象要簡潔得多,而且容易理解使用方便,功能強大,運行速度非常快,效率極高。深受大家的喜愛。

????????本文希望通過對一些字典應用的典型實例的代碼的詳細解釋來給初次接觸字典和想要進一步了解字典用法的朋友提供一點備查的參考資料,希望大家能喜歡。

????????給代碼注釋估計是大家都怕做的,因為往往是出力不討好的,稍不留神或者自己確實理解得不對,還會貽誤他人。所以下面的這些注釋如果有不對或者不妥當的地方,請大家跟帖時指正批評,及時改正。

字典的簡介

????????字典Dictionary)對象是微軟Windows腳本語言中的一個很有用的對象。

????????附帶提一下,有名的 正則表達式RegExp)對象和能方便處理驅動器、文件夾和文件的(FileSystemObject )對象也是微軟Windows腳本語言中的一份子。

????????字典對象相當于一種聯合數組,它是由具有唯一性的關鍵字(Key)和它的項(Item)聯合組成。就好像一本字典書一樣,是由很多生字和對它們對應的注解所組成。比如字典的 “” 字的解釋是這樣的:

???????? “” 字就是具有唯一性的關鍵字,后面的解釋就是它的項,和“”字聯合組成一對數據。

常用關鍵字英漢對照:

關鍵字譯文
Dictionary字典
Key關鍵字
Item項,或者譯為 條目

1. 字典對象

????????字典對象的方法有6個:Add方法、Keys方法、Items方法、Exists方法、Remove方法、RemoveAll方法。

1.1 Add 方法

Dictionary 對象中添加一個關鍵字項目對。

  • 語法:

    object.Add (key, item)
  • 參數:

    數說明
    object必選項。總是一個 Dictionary 對象的名稱。
    key必選項。與被添加的 item 相關聯的 key。
    item必選項。與被添加的 key 相關聯的 item

    說明:如果 key 已經存在,那么將導致一個錯誤。

  • 常用語句

    Dim d Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo"
  • 代碼詳解:

    1)Dim d創建變量,也稱為聲明變量。變量d聲明為可變型數據類型(Variant),d后面沒有寫數據類型,默認就是可變型數據類型(Variant)。也有寫成Dim d As Object的,聲明為 對象 。

    2)Set d = CreateObject("Scripting.Dictionary"):創建字典對象,并把字典對象賦給變量d。這是最常用的一句代碼。所謂的 “后期綁定” 。用了這句代碼就不用先引用 C:\windows\system32\scrrun.dll了。

    3)d.Add "a", "Athens":添加一關鍵字"a"和對應于它的項”Athens”。

    4)d.Add "b", "Belgrade":添加一關鍵字"b"和對應于它的項"Belgrade"。

    5) d.Add "c", "Cairo":添加一關鍵字"c"和對應于它的項"Cairo"。

1.2 Exists 方法

如果 Dictionary 對象中存在所指定的關鍵字則返回 true,否則返回 false。

  • 語法:

    object.Exists(key)
  • 參數:

    參數說明
    object必選項??偸且粋€ Dictionary 對象的名稱。
    key必選項。需要在 Dictionary 對象中搜索的 key 值。
  • 常用語句:

    Dim d, msg$ Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" If d.Exists("c") Thenmsg = "指定的關鍵字已經存在。" Elsemsg = "指定的關鍵字不存在。" End If
  • 代碼詳解:

    1)Dim d, msg$ :聲明變量,d見前例;msg$ 聲明為字符串數據類型(String),一般寫法為Dim msg As String。String 的類型聲明字符為美元號 ($)。

    2)If d.Exists("c") Then:如果字典中存在關鍵字"c",那么執行下面的語句。

    3)msg = "指定的關鍵字已經存在。":把 "指定的關鍵字已經存在。" 字符串 賦給變量 msg。

    4)Else :否則執行下面的語句。

    5)msg = "指定的關鍵字不存在。" :把 "指定的關鍵字不存在。" 字符串 賦給變量msg。

    6)End If :結束If …Else…Endif判斷。

1.3 Keys 方法

返回一個數組,其中包含了一個 Dictionary 對象中的全部現有的關鍵字。

  • 語法:

    object.Keys()

    其中 object 總是一個 Dictionary 對象的名稱。

  • 常用語句:

    Dim d, k Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" k=d.Keys [B1].Resize(d.Count,1)=Application.Transpose(k)
  • 代碼詳解:

    1)Dim d, k :聲明變量,d見前例;k默認是 可變型數據類型 (Variant)。

    2)k=d.Keys:把字典中存在的所有的關鍵字賦給變量k。得到的是一個一維數組,下限為0,上限為d.Count-1。這是數組的默認形式。

    3)[B1].Resize(d.Count,1)=Application.Transpose(k) :這句代碼是很常用很經典的代碼,所以這里要多說一些:

    Resize是 Range對象 的一個屬性,用于調整指定區域的大小,它有兩個參數:

    ①、第一個是行數,本例是d.Count,指的是字典中關鍵字的數量,整本字典中有多少個關鍵字,本例d.Count=3,因為有 3 個關鍵字。呵呵,是不是說多了。

    ②、第二個是列數,本例是1。這樣:

    =左邊的意思就是:把一個單元格B1調整為以B1開始的一列單元格區域,行數等于字典中關鍵字的數量d.Count,就是把單元格B1調整為單元格區域B1:B3了。

    =右邊的k是個一維數組,是水平排列的。

    ????????我們知道 Excel 工作表函數里面有個轉置函數 Transpose,用它可以 把水平排列的置換成豎向排列。但是在 VBA 中不能直接使用該工作表函數,需要通過Application對象的WorksheetFunction屬性來使用它。所以完整的寫法是Application. WorksheetFunction.Transpose(k),中間的WorksheetFunction可省略。


    ~現在可以解釋這句代碼了:

    把字典中所有的關鍵字賦給以B1單元格開始的單元格區域中。


1.4 Items 方法

返回一個 數組,其中包含了一個 Dictionary 對象中的所有項目。

  • 語法:

    object.Items( )

    其中 object 總是一個 Dictionary 對象的名稱。

  • 常用語句:

    Dim d, t Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" t=d.Items [C1].Resize(d.Count,1)=Application.Transpose(t)
  • 代碼詳解:

    1)Dim d, t :聲明變量,d見前例;t默認是可變型數據類型(Variant)。

    2)t=d.Items :把字典中所有的關鍵字對應的項賦給變量t。得到的也是一個一維數組,下限為0,上限為d.Count-1。這是數組的默認形式。

    3)[C1].Resize(d.Count,1)=Application.Transpose(t) :有了上面Keys方法的解釋這句代碼就不用多說了,就是把字典中所有的關鍵字對應的項賦給以C1單元格開始的單元格區域中。


1.5 Remove 方法

Remove 方法從一個 Dictionary 對象中 清除 一個關鍵字項目對。

  • 語法:

    object.Remove(key )

    其中 object 總是一個 Dictionary 對象的名稱。

    key:必選項。key 與要從 Dictionary 對象中刪除的關鍵字、項目對相關聯。

    說明:如果所 指定的關鍵字,項目對不存在,那么將導致一個 錯誤 。

  • 常用語句:

    Dim d Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" ' …… d.Remove(“b”)
  • 代碼詳解:

    1)d.Remove("b"):清除字典中 "b" 關鍵字和與它對應的項。清除之后,現在字典里只有2個關鍵字了。

1.6 RemoveAll 方法

RemoveAll 方法從一個 Dictionary 對象中清除所有的 關鍵字項目對

  • 語法:

    object.RemoveAll()

    其中 object 總是一個 Dictionary 對象的名稱。

  • 常用語句:

    Dim d Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" ' …… d.RemoveAll
  • 代碼詳解:

    1)d.RemoveAll:清除字典中所有的數據。也就是清空這字典,然后可以添加新的關鍵字和項,形成一本新字典。

    字典對象的屬性有4個:Count屬性、Key屬性、Item屬性、CompareMode屬性。

    • Count 屬性

      屬性說明
      Count返回一個Dictionary 對象中的項目數。只讀屬性。

      object.Count:其中 object一個字典對象的名稱。

      常用語句:

      Dim d,n% Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" n = d.Count

      代碼詳解:

      1)Dim d, n% :聲明變量,d見前例;n被聲明為整型數據類型(Integer)。一般寫法為Dim n As Integer 。 Integer 的類型聲明字符為百分比號 (%)。
      2)n = d.Count :把字典中所有的關鍵字的數量賦給變量n。本例得到的是3。

    • Key 屬性:

      Dictionary 對象中設置一個 key。

      語法:

      object.Key(key) = newkey

      參數:

      參數說明
      object必選項??偸且粋€字典 (Dictionary) 對象的名稱。
      key被改變的 key 值。
      newkey必選項。替換所指定的 key 的新值。

      說明:如果在改變一個 key 時沒有發現該 key,那么將創建一個新的 key 并且其相關聯的 item 被設置為空。


      常用語句:

      Dim d Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" d.Key("c") = "d"

      代碼詳解:

      1)d.Key("c") = "d" :用新的關鍵字"d"來替換指定的關鍵字"c",這時,字典中就沒有關鍵字c了,只有關鍵字d了,與d對應的項是"Cairo"。

    • Item 屬性:

      在一個 Dictionary 對象中設置或者返回所指定 key 的 item。對于集合,則根據所指定的 key 返回一個 item。 /

      語法:

      object.Item(key)[ = newitem]

      參數:

      參數說明
      object必選項??偸且粋€Dictionary 對象的名稱。
      key與要被查找或添加的 item 相關聯的 key。
      newitem可選項。僅適用于 Dictionary 對象;newitem 就是與所指定的 key 相關聯的新值。

      說明:如果在改變一個 key 的時候沒有找到該 item,那么將利用所指定的 newitem 創建一個新的 key。如果在試圖返回一個已有項目的時候沒有找到 key,那么將創建一個新的 key 且其相關的項目被設置為空。


      常用語句:

      Dim d Set d = CreateObject("Scripting.Dictionary") d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" MsgBox d.Item("c")

      代碼詳解:

      1)d.Item("c") :獲取指定的關鍵字"c"對應的項。

      2)MsgBox :是一個 VBA 函數,用消息框顯示。如果要詳細了解MsgBox函數的,可參見我的另一篇文章 常用VBA函數精選合集。


    • CompareMode 屬性:

      設置或者返回在 Dictionary 對象中進行 字符串關鍵字比較 時所使用的 比較模式。

      語法:

      object.CompareMode[ = compare]

      參數:

      參數說明
      object必選項??偸且粋€Dictionary 對象的名稱。
      compare可選項。如果提供了此項,compare 就是一個代表比較模式的值。
      可以使用的值是 0 (二進制)、1 (文本)、 2 (數據庫)。

      說明:如果試圖改變一個已經包含有數據的 Dictionary 對象的比較模式,那么將導致一個錯誤。


      常用語句:

      Dim d Set d = CreateObject("Scripting.Dictionary") d.CompareMode = vbTextCompare d.Add "a", "Athens" d.Add "b", "Belgrade" d.Add "c", "Cairo" d.Add " B ", " Baltimore"

      代碼詳解:

      1)d.CompareMode = vbTextCompare :設置字典的比較模式是文本,在這種比較模式下 不區分關鍵字的大小寫 ,即關鍵字”b”和”B”是一樣的。vbTextCompare的值為1,所以上式也可寫為 d.CompareMode =1 。如果設置為vbBinaryCompare(值為0),則執行 二進制比較 ,即 區分關鍵字的大小寫,此種情況下關鍵字”b”和”B”被認為是不一樣的。

      2)d.Add " B ", " Baltimore" :添加一關鍵字”B”和對應于它的項”Baltimore”。由于前面已經設置了比較模式為文本模式,不區分關鍵字的大小寫,即關鍵字”b”和”B”是一樣的,此時發生錯誤添加失敗,因為字典中已經存在”b”了,字典中的關鍵字是唯一的,不能添加重復的關鍵字



2. 實例


2.1 實例1. 普通常見的求不重復值問題

2.1.1 問題

表格中人員有很多是重復的,要求編寫一段代碼,把重復的人員姓名以及重復的次數求出來,復制到另一個表格中。

如圖實例1-1所示。

圖 實例1-1

2.1.2 實例代碼

Sub cfz()Dim i&, Myr&, ArrDim d, k, tSet d = CreateObject("Scripting.Dictionary")Myr = Sheet1.[a65536].End(xlUp).RowArr = Sheet1.Range("a1:g" & Myr)For i = 2 To UBound(Arr)d(Arr(i, 3)) = d(Arr(i, 3)) + 1Nextk = d.keyst = d.itemsSheet2.Activate[a2].Resize(d.Count, 1) = Application.Transpose(k)[b2].Resize(d.Count, 1) = Application.Transpose(t)[a1].Resize(1, 2) = Array("姓名", "重復個數")Set d = Nothing End Sub

2.1.3 代碼詳解

  • Dim i&, Myr&, Arr :變量i和Myr聲明為長整型變量。 也可以寫為 Dim Myr As Long 。Long的類型聲明字符為(&)。Arr后面沒有寫明數據類型,默認就是可變型數據類型(Variant)。

  • Set d = CreateObject("Scripting.Dictionary"):創建字典對象,并把字典對象賦給變量d。這是最常用的一句代碼。所謂的“后期綁定”。用了這句代碼就不用先引用c:\windows\system32\scrrun.dll了。

  • Myr = Sheet1.[a65536].End(xlUp).Row :把表1的A列最后一行不為空白的行數賦給變量Myr。這里用了Range對象的 End 屬性,它有4個方向參數,此處的xlUp表示向上,它的值為3,所以也可寫成End(3)。xlDown表示向下,它的值為4;xlToLeft表示向左,它的值為1;xlToRight表示向右,它的值為2。

  • Arr = Sheet1.Range("a1:g" & Myr):把表1的A1到G列最后一行不為空白的 單元格區域的值賦給變量Arr。這樣Arr就是個 二維數組 了,用數組替代單元格引用可對執行代碼的速度提高很多很多。

  • For i = 2 To UBound(Arr) :For…Next 循環結構,從2開始到數組的最大上界值之間循環。因為數組的第一行是表頭。Ubound是VBA函數,返回數組的指定維數的最大可用上界。

  • d(Arr(i, 3)) = d(Arr(i, 3)) + 1 :Arr(i,3)在本例是姓名列,也就是關鍵字列,舉個例子,假如Arr(i,3)=”張三”,這句代碼的意思就是把關鍵字”張三”加入字典,d(key)等于關鍵字key對應的項,每出現一次這個關鍵字,它的項的值就增加1。起到了按關鍵字累加的作用,也正因為有這個作用,所以可使用字典來進行各種匯總統計。后面要講的實例會充分的展現這個作用。

  • k=d.keys :把字典d中存在的所有的關鍵字賦給變量k。得到的是一個一維數組,下限為0,上限為d.Count-1。Keys是字典的方法,前面已經講過了。

  • t=d.items :把字典d中存在的所有的關鍵字對應的項賦給變量t。得到的也是一個一維數組,下限為0,上限為d.Count-1。Items也是字典的方法,前面也已經講過了。

  • Sheet2.Activate :激活表2;

  • [a2].Resize(d.Count, 1) = Application.Transpose(k) :把字典d中所有的關鍵字賦給以a2單元格開始的單元格區域中。詳細的解釋請見前面的keys方法一節。

  • [b2].Resize(d.Count, 1) = Application.Transpose(t) :把字典d中所有的關鍵字對應的項賦給以b2單元格開始的單元格區域中。

  • [a1].Resize(1, 2) = Array("姓名", "重復個數") :Array是一個VBA函數,返回一個下界為0的一維數組。一維數組可以看作是水平排列的,所以賦值給水平的單元格區域不需要用轉置函數了。這里作為表頭一次性輸入。

  • Set d = Nothing :釋放字典內存。

  • 代碼執行后如圖實例1-2所示。

    圖 實例1-2

    實例1文件:點擊下載????????提取碼:t34n



    2.2 實例2 求多表的不重復值問題


    2.2.1 問題

    一工作簿里面有3張工作表上,每張表格的A列都是姓名列,所有這些姓名中有些是重復的,要求編寫一段代碼,在另一個工作表上顯示不重復的姓名。

    如圖實例2-1所示

    圖 實例2-1

    這個問題也很適合用字典來解決。代碼如下:

    2.2.2 代碼

    Sub bcfz()Dim i&, Myr&, ArrDim d, k, t, Sht As WorksheetSet d = CreateObject("Scripting.Dictionary")For Each Sht In SheetsIf Sht.Name <> "Sheet4" ThenMyr = Sht.[a65536].End(xlUp).RowArr = Sht.Range("a2:a" & Myr)For i = 1 To UBound(Arr)d(Arr(i, 1)) = ""NextEnd IfNextk = d.keysSheet4.[a3].Resize(d.Count, 1) = Application.Transpose(k)Set d = Nothing End Sub

    2.2.3 代碼詳解

  • For Each Sht In Sheets :For Each…Next 循環結構,這種形式是VBA特有的,用于對對象的循環非常適用。意思是在所有的工作表中依次循環。
  • If Sht.Name <> "Sheet4" Then :如果這個工作表的名字不等于 “ Sheet4 ” 時,執行下面的代碼。
  • Myr = Sht.[a65536].End(xlUp).Row :求得這個工作表A列有數據的最后一行的行數,把它賦給變量Myr。這里用了長整型數據類型(Long),數據范圍最大可到2,147,483,647,是為了避免數據很多的時候會超出整型數據類型(Integer)而出錯,因為整型數據類型數據范圍最大只到32,767。
  • Arr = Sht.Range("a2:a" & Myr) :把A列數據賦給數組Arr。
  • For i = 1 To UBound(Arr) :For…Next 循環結構,從1開始到數組的最大上限值之間循環。Ubound是VBA函數,返回數組的指定維數的最大值。
  • d(Arr(i, 1)) = "" :這句代碼的意思就是把關鍵字Arr(i,1)加入字典,關鍵字對應的項為空,相當于字典中的這個關鍵字沒有解釋。和d.Add Arr(i,1), ""的效果相同,只是代碼更簡潔一些。
  • k=d.keys :把字典d中存在的所有的關鍵字賦給變量k。得到的是一個 一維數組,下限為0,上限為d.Count-1。Keys是字典的方法,前面已經講過了。
  • Sheet4.[a3] .Resize(d.Count, 1) = Application.Transpose(k) :把字典d中所有的關鍵字賦給表4以a3單元格開始的單元格區域中。
  • 代碼執行后如圖實例2-2所示:

    圖 實例2-2

    實例2文件:點擊下載????????提取碼:snfv



    2.3 實例3 A列中顯示1 ~ 1000中被6除余1和余5 的數字


    2.3.1 問題

    有1、2、3…1000一千個數字,要求編寫一段代碼,在工作表的A列顯示這些數被6除余1和余5的數字。

    2.3.2 代碼

    Sub15() ‘by:狼版主Dim dic As Object, i As Long, arrSet dic = CreateObject("Scripting.Dictionary")For i = 1 To 1000dic.Add i & IIf(Abs(i Mod 6 - 3) = 2, "@", ""), ""Nextarr = WorksheetFunction.Transpose(Filter(dic.keys, "@"))[a1].Resize(UBound(arr), 1) = arr[a:a].Replace "@", ""Set dic = Nothing End Sub

    2.3.3 代碼詳解

  • Dim dic As Object, i As Long, arr :也可把字典變量dic聲明為對象(Object),i As Long是規范的寫法,也可寫成i& 。

  • dic.Add i & IIf(Abs(i Mod 6 - 3) = 2, "@", ""), "" :這句代碼的內容比較多,用了兩個VBA函數IIf和Abs,用了一個Mod運算符。i Mod 6就是每一個數除6的余數,題目中有兩個要求:余1和余5,為了從1到1000都同時能滿足這兩個要求,所以用了Abs(i Mod 6 - 3) = 2 ,Abs是取絕對值函數。另一個VBA函數IIf是根據判斷條件返回結果,和If…Then判斷結果類似;IIf(Abs(i Mod 6 - 3) = 2, "@", "") 這段的意思是如果符合判斷條件,返回”@”否則返回空””。 i & IIf(Abs(i Mod 6 - 3) = 2, "@", "")的意思是把這個數與”@”或者""連起來作為關鍵字加入字典dic,關鍵字相對應的項為空。比如當i=1時,1是滿足上述表達式的,就把”1@” 作為關鍵字加入字典dic;當i=2時,2不滿足上述表達式,就把”2” 作為關鍵字加入字典dic,關鍵字相對應的項都為空。

  • arr = WorksheetFunction.Transpose(Filter(dic.keys, "@")) :這句代碼的內容分為3部分,第1部分是Filter(dic.keys, "@") 其中的 Filter 是一個 VBA 函數,VBA 函數就是可以直接在代碼中使用的,我們平常使用的函數叫工作表函數,如Sum、Sumif、Transpose 等等。Filter 函數要求在一維數組中篩選出符合條件的另一個一維數組,式中的dic.keys正是一個一維數組。這里的篩選條件是“@”,也就是把字典關鍵字中含有@ 的關鍵字篩選出來組成一個新的一維數組,其下標從零開始。第2部分是用工作表函數 Transpose 轉置這個新的一維數組,工作表函數的使用在前面keys方法一節已經說過了;第2部分是把轉置以后的值賦給數組變量Arr。

    ~呵呵,狼版主的代碼是短了,我的解釋卻太長了。

  • [a1].Resize(UBound(arr), 1) = arr :把數組 Arr 賦給 [a1] 單元格開始的區域中。

  • [a:a].Replace "@", "" :把A列中的所有的@都替換為空白,只剩下數字了。

  • 代碼詳解的4代碼執行后,如圖實例3-1所示:

    圖實例3-1 示例

    代碼全部執行后如圖實例3-2所示:

    圖實例3-2 示例

    實例3文件:點擊下載????????提取碼:d2c1



    2.4 實例4 拆分數據不重復


    2.4.1 問題

    有一列各種手機品牌型號的數據,要求編寫一段代碼,按照品牌劃分成沒有重復數據的三大類。

    2.4.2 代碼

    Sub caifen()Dim Myr&, Arr, x&Dim d, d1, d2, i&, j&Set d = CreateObject("Scripting.Dictionary")Set d1 = CreateObject("Scripting.Dictionary")Set d2 = CreateObject("Scripting.Dictionary")Myr = [a65536].End(xlUp).RowArr = Range("a2:a" & Myr)Range("c2:e" & Myr).ClearContentsmy = Array("MOTO", "諾基亞", "三星", "索愛")gc = Array("OPPO", "聯想", "天語", "金立", "步步高", "波導", "TCL", "酷派")For x = 1 To UBound(Arr)For i = 0 To UBound(my)If InStr(Arr(x, 1), my(i)) > 0 Thend(Arr(x, 1)) = ""GoTo 100End IfNext iFor j = 0 To UBound(gc)If InStr(Arr(x, 1), gc(j)) > 0 Thend1(Arr(x, 1)) = ""GoTo 100End IfNext jd2(Arr(x, 1)) = ""100:Next xRange("c2").Resize(UBound(d.keys) + 1, 1) = Application.Transpose(d.keys)Range("d2").Resize(UBound(d1.keys) + 1, 1) = Application.Transpose(d1.keys)Range("e2").Resize(UBound(d2.keys) + 1, 1) = Application.Transpose(d2.keys) End Sub

    2.4.3 代碼詳解

  • Set d2 = CreateObject("Scripting.Dictionary") :針對三個不同的種類,創建d、d1、d2三個字典對象。
  • Myr = [a65536].End(xlUp).Row :把A列最后一行不為空白的行數賦給變量Myr。
  • Arr = Range("a2:a" & Myr) :把A2開始的有數據的單元格區域賦給變量Arr。
  • Range("c2:e" & Myr).ClearContents :把C2到E列單元格區域清空。
  • my = Array("MOTO", "諾基亞", "三星", "索愛") :VBA函數Array返回一個一維數組,默認下界為0。把Array函數返回的數組賦給變量my(貿易兩漢字的首字母)。
  • gc = Array("OPPO", "聯想", "天語", "金立", "步步高", "波導", "TCL", "酷派") :把Array函數返回的數組賦給變量gc(國產兩漢字的首字母)。
  • For x = 1 To UBound(Arr) :在A列原始數據的數組中逐一循環。
  • For i = 0 To UBound(my) :在my數組中逐一循環。因為有4個貿易機品牌,所以用循環每一個與原始數據比較。
  • If InStr(Arr(x, 1), my(i)) > 0 Then :VBA函數Instr返回在第1個參數中查找的位置,如果返回結果=0,表示在第1個參數中沒有第2個參數存在。本句的意思是如果找到貿易機品牌的話,執行下面的代碼。
  • d1(Arr(x, 1)) = "" :接上句,如果上面判斷成立,就把Arr(x, 1)加入字典d。
  • GoTo 100 :Goto 語句用于無條件地轉移到過程中指定的行。這里采用跳出For i循環,一是為了減少循環的次數,比如"MOTO"找到的話,后面3個就不需要找了;二是為了跳過兩個小循環之后的其它品牌加入第3個字典的d2(Arr(x, 1)) = ""語句。
  • For j循環與上面相同,為了判斷得到國產機類的字典d1。
  • d2(Arr(x, 1)) = "" :如果上述兩個小循環都不滿足,那么就加入其它品牌類字典里。
  • Range("c2").Resize(UBound(d.keys) + 1, 1) = Application.Transpose(d.keys) :最后的3句分別把字典的關鍵字數組轉置后賦給相應的單元格區域。
  • 代碼執行后如圖實例4-1所示:

    圖 實例4-1 示例

    山菊花版主用了一個字典對象就解決了上述問題。讓我們來學習一下:

    2.4.4 山菊花版主的代碼

    Sub 拆分()Dim pp1$, pp2$, nRow%, ds, Brr(), s(1 To 3) As IntegerSet ds = CreateObject("scripting.dictionary")pp1 = Join(WorksheetFunction.Transpose(Range(Range("g2"), Range("g1").End(xlDown))), ",")pp2 = Join(WorksheetFunction.Transpose(Range(Range("h2"), Range("h1").End(xlDown))), ",")nRow = Range("a1").End(xlDown).RowArr = Range("a1:a" & nRow)ReDim Brr(1 To nRow, 1 To 3)For i = 2 To nRowIf Not ds.Exists(Arr(i, 1)) Thends(Arr(i, 1)) = ""If pp1 Like "*" & Left(Arr(i, 1), 2) & "*" Thens(1) = s(1) + 1Brr(s(1), 1) = Arr(i, 1)ElseIf pp2 Like "*" & Left(Arr(i, 1), 2) & "*" Thens(2) = s(2) + 1Brr(s(2), 2) = Arr(i, 1)Elses(3) = s(3) + 1Brr(s(3), 3) = Arr(i, 1)End IfEnd IfNextRange("c2:e" & nRow) = Brr End Sub

    2.4.5 代碼詳解

  • pp1 = Join(WorksheetFunction.Transpose(Range(Range("g2"), Range("g1").End(xlDown))), ",")

    這句代碼用了兩個 VBA 函數 Join 和 Transpose ,Range("g1").End(xlDown)從G1單元格往下直到最下面的單元格,遇到空白格就停止。因為本例的G14、G15單元格有另外的數據存在,如果還是用Range("g65536").End(xlUp),那么就會把不需要的數據帶進去,造成結果出錯。Transpose 轉置函數,前面已經介紹過了。Join函數是通過連接某個數組中的多個子字符串而創建的一個字符串,本句代碼執行后得到:
    ????????pp1 = “MOTO, 諾基亞, 三星, 索愛”;
    ????????pp2 一句同上句一樣,得到另一個字符串。

  • nRow = Range("a1").End(xlDown).Row :把A列最后一行不為空白的行數賦給整型變量nRow。

  • Arr = Range("a1:a" & nRow) :把A列A1開始的有數據的單元格區域賦給變量Arr。

  • ReDim Brr(1 To nRow, 1 To 3) :用于為動態數組變量Brr重新分配存儲空間。第一維的下界從1到上界nRow,第二維從1到3。

  • For i = 2 To nRow :從2到 nRow逐一循環。

  • If Not ds.Exists(Arr(i, 1)) Then :如果字典ds中不存在關鍵字Arr(i, 1)

  • ds(Arr(i, 1)) = "" :把Arr(i, 1)作為關鍵字加入字典ds。

  • If pp1 Like "*" & Left(Arr(i, 1), 2) & "*" Then :這里山版主用了比較運算符Like來比較pp1和取自Arr(i, 1)左邊兩個字符,再在前后加任意字符組成的字符串,如果滿足條件為真,那么執行下面的語句。

  • s(1) = s(1) + 1 :數組s的第一個元素+1以后賦給數組s的第一個元素。

  • Brr(s(1), 1) = Arr(i, 1) :把這個關鍵字賦給 第2維 為1的另一個數組Brr,也就是我們要求的貿易機類。pp1字符串里都是貿易機類的品牌。

  • ElseIf pp2 Like "*" & Left(Arr(i, 1), 2) & "*" Then :同樣,如果滿足國產品牌類這個條件,那么執行下面的代碼。

  • s(2) = s(2) + 1 :數組s的第二個元素+1以后賦給數組s的第二個元素。

  • Brr(s(2), 2) = Arr(i, 1) :把這個關鍵字賦給 第2維 為2的另一個數組Brr,也就是我們要求的國產品牌類。pp2字符串里都是國產品牌類的品牌。

  • s(3) = s(3) + 1 :前如果條件都不滿足時,數組s的第三個元素+1以后賦給數組s的第三個元素。

  • Brr(s(3), 3) = Arr(i, 1) :把這個關鍵字賦給 第3維 為1的另一個數組Brr,也就是我們要求的其它品牌類。

  • Range("c2:e" & nRow) = Brr :把數組Brr賦給[c2]單元格開始的區域中。


  • 實例4文件:點擊下載????????提取碼:nrhi



    2.5 實例5 前期綁定的字典實例


    2.5.1 問題

    有多列多行數據,其中有重復的行,要求編寫一段代碼,求得不重復的行數據。

    如圖實例5-1所示:

    圖 實例5-1 示例

    2.5.2 代碼

    Sub 保留原數據() 'by:ldy888'前期綁定,需先引用c:\windows\system32\scrrun.dllDim d As New Dictionary,tFor i = 2 To 5Set d(Cells(i, 1) & "") = Range(Cells(i, 1), Cells(i, 4))Nextt=d.items [A11].Resize(d.Count, 4) = Application.Transpose(Application.Transpose(t)) End Sub

    2.5.3 代碼詳解

  • Dim d As New Dictionary, t :本段代碼需要先引用微軟的腳本運行時庫 Microsoft Scripting Runtime,可在 VBE 窗口,從菜單-工具-引用,然后勾選Microsoft Scripting Runtime,或者點擊瀏覽,在添加引用對話框中選擇c:\windows\system32\scrrun.dll,并打開,確定。完成引用。在本聲明語句中把字典d聲明為New Dictionary。這就是 “ 前期綁定 ” 了。上面的實例用的是創建對象語句:

    Set d = CreateObject("Scripting.Dictionary"),稱為 “ 后期綁定 ” ,不需要先引用腳本運行時庫。

  • Set d(Cells(i, 1) & "") = Range(Cells(i, 1), Cells(i, 4)):把單元格對象加入字典,它對應的項是同一行的單元格區域。注意,這里用了Set,和前面的幾例不一樣哦。如果用 Typename(d(Cells(i,1) & "")),得到的是一個Range對象。這里的Cells(i, 1) & ""也可以用Cells(i, 1).Value來代替。

  • t=d.items :把字典d中存在的所有的關鍵字對應的項賦給變量t。得到的是一個一維數組,下限為0,上限為d.Count-1。

  • [A11].Resize(d.Count, 4) = Application.Transpose(Application.Transpose(t)) :這句用了兩次工作表轉置函數Transpose之后賦給A11單元格開始的區域中。

  • 代碼執行后如圖實例5-2所示:

    圖 實例5-2示例

    實例5文件:點擊下載????????提取碼:kr3o



    2.6 實例6 多條件復雜匯總


    2.6.1 問題

    有一個表格,需要對其中多個條件相同的數量進行合并匯總,并且要有匯總的明細數據,要求編寫一段代碼,實現這樣的合并同類項的要求。

    2.6.2 代碼

    Sub kf2() ‘by:oobirdDim d As Object, a, b, j%, w!Dim ss$, n%, xMe.UsedRange.Offset(3, 0) = ""a = Sheet1.Range(Sheet1.[a4], Sheet1.[i65536].End(xlUp))Set d = CreateObject("scripting.dictionary")ReDim b(1 To UBound(a), 1 To 8)For i = 1 To UBound(a)ss = a(i, 1) & a(i, 2) & a(i, 4) & a(i, 5) & a(i, 6) & a(i, 8) If Not d.Exists(ss) Thenn = n + 1d.Add ss, nb(n, 1) = a(i, 2): b(n, 2) = a(i, 5): b(n, 3) = a(i, 6): b(n, 4) = a(i, 4)b(n, 5) = a(i, 1): b(n, 6) = a(i, 8): b(n, 7) = a(i, 9)Elseb(d(ss), 7) = b(d(ss), 7) & "+" & a(i, 9)End IfNextFor i = 1 To d.Countx = Split(b(i, 7), "+")For j = 0 To UBound(x)w = w + x(j)Next jb(i, 8) = b(i, 5) * b(i, 6) * w / 100: w = 0Next[b4].Resize(n, 8) = b End Sub

    2.6.3 代碼詳解

  • Dim d As Object, a, b, j%, w! :Dim語句中的j% 等同于Dim j As Integer。w!等同于Dim w As Single。類似的還有ss$ 等同于Dim ss As String。還有雙精度數據類型Double的類型聲明字符為#、貨幣數據類型Currency的類型聲明字符為@
  • Me.UsedRange.Offset(3, 0) = "" :Offset是Range對象的屬性,Offset(3, 0)的第一個參數是行數;第二個參數是列數,意思是往下偏移3行,列不變。Me是活動工作表,相當于Activesheet; UsedRange為已經使用的單元格區域。本句可解釋為:清空第3行以下的單元格。
  • a = Sheet1.Range(Sheet1.[a4], Sheet1.[i65536].End(xlUp)) :把原始數據所在的表1自A4以下的I列最后的非空單元格區域的值賦給變量a。
  • Set d = CreateObject("scripting.dictionary") :創建字典對象d。
  • ReDim b(1 To UBound(a), 1 To 8) :根據數組a的大小重新聲明數組b。
  • For i = 1 To UBound(a) :在1 和數組a第一維的上界值之間逐一循環。
  • ss = a(i, 1) & a(i, 2) & a(i, 4) & a(i, 5) & a(i, 6) & a(i, 8) :把多個條件比例、位置、項目名稱、大系統編號、小系統編號和相同樓層數用連接符號&連成一個字符串,然后賦給變量ss。
  • If Not d.Exists(ss) Then :If…Then 結構利用了字典的Exists方法和Not來判斷:如果字典d里面不存在 ss 表示的關鍵字,那么執行下面的語句。
  • n = n + 1 :把變量n增加 1 以后仍然賦給 n。
  • d.Add ss, n :把 ss 的值作為關鍵字,n 的值作為對應的項一起加入字典 d 中。n 的值實際是關鍵字的位置次序,如n=1時是第一個關鍵字;n=2時是第二個關鍵字。
  • b(n, 1) = a(i, 2): b(n, 2) = a(i, 5): b(n, 3) = a(i, 6): b(n, 4) = a(i, 4) :為了使代碼看起來簡短一些,可以用冒號”:”把多個語句連成一行。4個語句分別給數組b的各個元素賦以對應的值。
  • b(n, 5) = a(i, 1): b(n, 6) = a(i, 8): b(n, 7) = a(i, 9) :與上述的11條相同。
  • 否則執行這句:b(d(ss), 7) = b(d(ss), 7) & "+" & a(i, 9) :d(ss)等于關鍵字對應的項,在本例里等于對應的n的值。本句是把圖紙長度a(i, 9)用"+"連起來賦給數組b,這樣就得到了長度明細一欄數據。
  • For i = 1 To d.Count :在字典關鍵字數目中逐一循環。
  • x = Split(b(i, 7), "+") :運用VBA函數Split把b(i, 7)(長度明細)按照"+"分割,返回一個下標從零開始的一維數組x。如果要詳細了解Split函數的,可參見我的另一篇文章 常用VBA函數精選合集。
  • For j = 0 To UBound(x) :在上面的x數組之間逐一循環。
  • w = w + x(j) :把變量 w 加x(j)數組的一個元素以后仍然賦給w。實際得到x數組的累加值。
  • b(i, 8) = b(i, 5) * b(i, 6) * w / 100: w = 0 :w求出后經過按要求計算得到的值賦給數組b的第8列元素。(數量列)另一句把變量w置0。避免在新一次的循環中誤加進去。
  • [b4].Resize(n, 8) = b :最后把數組 b 賦給 B4 開始的單元格區域。
  • 代碼執行后如圖實例6-1所示:

    圖 實例6-1示例

    實例 6 文件:點擊下載????????提取碼:ytp6




    2.7 實例7 字典法排序


    2.7.1 問題

    A列B列是按順序排列的全部股票代碼和股票名稱,C列D列和E列F列是另外按條件篩選出來的無序的數據, 要求編寫一段代碼,將它們排列到與A列相同的股票行里面。

    代碼執行前如圖實例7-1所示:

    圖 實例7-1示例

    2.7.2 代碼

    Private Sub CommandButton1_Click() ‘by:oobirdDim d As Object, rng, i%, j%, arrSet d = CreateObject("Scripting.Dictionary")rng = Range("a3:f" & [a65536].End(xlUp).Row)ReDim arr(1 To UBound(rng), 1 To 4)For i = 1 To UBound(rng) d(CStr(rng(i, 1))) = iNext iFor j = 3 To 5 Step 2For i = 1 To Cells(65536, j).End(xlUp).Row - 2If d(CStr(rng(i, j))) <> "" Thenarr(d(CStr(rng(i, j))), j - 2) = rng(i, j) arr(d(CStr(rng(i, j))), j - 1) = rng(i, j + 1)End IfNext iNext j[c3].Resize(UBound(rng), 4) = arr End Sub

    2.7.3 代碼詳解

  • Dim d As Object, rng, i%, j%, arr :聲明各個變量。
  • Set d = CreateObject(“Scripting.Dictionary”) :創建字典對象d。
  • rng = Range(“a3:f” & [a65536].End(xlUp).Row) :把A列到F列的單元格區域的值賦給變量rng。
  • ReDim arr(1 To UBound(rng), 1 To 4) :根據數組rng的大小重新聲明動態數組變量的大小,這里是按最大數量來聲明,可避免因聲明得小了而導致代碼出錯。
  • For i = 1 To UBound(rng) :在rng數組中逐一循環。
  • d(CStr(rng(i, 1))) = i :把A列的股票代碼的值用VBA轉換函數CStr轉換成字符串以后作為關鍵字,因為如果不作處理有時候遇到00開始的數據,可能會失去前面的0。股票代碼在數組中的行位置i作為關鍵字對應的項,一起加入字典d。
  • For j = 3 To 5 Step 2 :前面的循環得到了整個字典,下面這兩個循環用來與字典中的關鍵字比對而重新排位。Step 2是循環的步長,j=3執行以后,j=3+2=5,從而跳過j=4了。呵呵,這是For…Next循環結構的基礎知識,說多了。
  • For i = 1 To Cells(65536, j).End(xlUp).Row – 2 :因為C列和E列的最后一個非空單元格的位置不一樣,所以用了Cells(65536, j).End(xlUp).Row在循環中分別得到這兩列的最后一個非空單元格的行數,由于數組rng是從第3行開始的,為了與下面引用的rng數組對應,所以需要減去2。全句是在C列和E列中逐一循環。
  • If d(CStr(rng(i, j))) <> “” Then :rng(i, j)是C列或者E列的股票代碼,本句是如果這個股票代碼關鍵字對應的項不等于空的時候,執行下面的代碼。
  • arr(d(CStr(rng(i, j))), j - 2) = rng(i, j) :d(CStr(rng(i, j)))=i見上述6的解釋,表示數組arr的第1維,相當于行;j-2是隨著j=3的時候,j-2=1;j=5的時候j-2=3,相當于數組列的參數。把相應的股票代碼賦給相同股票代碼的第1列或者是第3列。
  • arr(d(CStr(rng(i, j))), j - 1) = rng(i, j + 1) :把相應的股票名稱賦給相同股票代碼的第2列或者是第4列;
  • [c3].Resize(UBound(rng), 4) = arr :把數組arr賦給C3開始的單元格區域。
  • 代碼執行后如圖實例7-2所示:

    圖 實例7-2示例

    實例 7 文件:點擊下載????????提取碼:3ijp




    2.8 實例8 2級動態數據有效性問題


    2.8.1 問題

    A列是源名稱,中間有空格,B列為各個源名稱對應的數目不同的代號,C列是目標名稱來源于源名稱,要求在C列設置不重復的、沒有空格的數據有效性供選擇;同時D列目標代號,要求隨著C列選擇的目標名稱的不同,提供對應的代號供選擇,是為第2級數據有效性。

    代碼執行前如圖實例8-1所示:

    圖 實例8-1示例

    2.8.2 代碼

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)If Target.Count > 1 Then Exit SubIf Target.Column <> 4 And Target.Column <> 3 Then Exit SubDim d, i&, Myr&, Arr, r%, Arr1(), cp$, ks&, js&, j&Set d = CreateObject("Scripting.Dictionary")Myr =[b65536].End(xlUp).RowArr = Range("a2:b" & Myr)If Target.Column = 3 ThenFor i = 1 To UBound(Arr)If Arr(i, 1) <> "" Thend(Arr(i, 1)) = ""End IfNextWith Target.Validation.Delete.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _Operator:=xlBetween, Formula1:=Join(d.keys, ",")End WithTarget.Offset(0, 1) = ""ElseIf Target.Column = 4 And Target.Offset(0, -1) <> "" ThenFor i = 1 To UBound(Arr)If Arr(i, 1) <> "" Thenr = r + 1ReDim Preserve Arr1(1 To r)Arr1(r) = iEnd IfNext iFor i = 1 To rIf Arr(Arr1(i), 1) = Target.Offset(0, -1).Text ThenIf i <> r Thenjs = Arr1(i + 1) - 1Elsejs = Myr - 1End Ifks = Arr1(i)For j = ks To jscp = cp & Arr(j, 2) & ","NextEnd IfNext icp = Left(cp, Len(cp) - 1)With Target.Validation.Delete.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _Operator:=xlBetween, Formula1:=cpEnd WithTarget = Split(cp, ",")(0)End IfSet d = Nothing End Sub

    2.8.3 代碼詳解

  • Private Sub Worksheet_SelectionChange(ByVal Target As Range):本例用的是工作表選擇變化事件,只要鼠標點擊單元格都會激活這個事件。Private 可譯為私有的,限制了這段代碼只能在指定的工作表里有效。參數Target聲明為單元格區域對象,有了關鍵字ByVal,說明可以按值傳遞參數。
  • If Target.Count > 1 Then Exit Sub :由于是鼠標點擊單元格都會激活這個事件,所以最好要作一些限制,使得你能避免點擊了不需要激活事件的地方而激活本事件產生錯誤。本句是如果目標單元格的數目大于1就退出本過程。這樣當你點選了多個單元格的時候,過程運行了這句代碼就會結束過程了。
  • If Target.Column <> 4 And Target.Column <> 3 Then Exit Sub :再加一個限制,如果目標單元格的列不是3列(C列)也不是4列(D列)的話就退出過程。
  • 接著的四句代碼分別是聲明變量、創建字典對象、B列最后一個非空單元格的行數以及把單元格區域的值賦給數組變量等等與前面的實例相同。請注意這里選擇了B列求最后一個非空單元格的行數,是因為A列各數據之間有空格,如果選擇A列,就會遺漏一些數據。
  • If Target.Column = 3 Then :現在分兩種情況判斷,如果點擊的目標單元格是C列的,那么執行下面的代碼。
  • If Arr(i, 1) <> “” Then :在數組Arr之間逐一循環,如果A列數組的值不等于空,就作為關鍵字加入字典d。這樣就排除了空值進入字典。
  • With Target.Validation :這里使用了With語句,With語句為我們提供了十分簡便的對象引用手段。使用它有3個優點:可以減少代碼的輸入量、增加代碼的可讀性。改善代碼的執行效率。在End With之前的語句都是對目標單元格的有效性對象的各個屬性進行設置。
  • Delete :先刪除該單元格的數據有效性。注意Delete前有個小圓點,在小圓點之前就省略了Target.Validation,即減少了代碼的輸入量。這個小圓點不能遺漏,否則會出錯。
  • Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=Join(d.keys, “,”) :Add是有效性對象的方法,向指定區域內添加數據有效性檢驗。參數Type是數據有效性類型,當類型等于xlValidateList時,后面的公式1參數Formula1 必須包含以逗號分隔的取值列表。參數AlertStyle是出錯警告樣式,這里是停止樣式;參數Operator是數據有效性運算符,有大于、小于、大于或等于、小于或等于、介于、不介于、等于、不等于等等,這里取介于;公式1參數Formula1的值用了VBA函數Join,把字典的關鍵字用逗號分隔后連接起來賦給公式1參數。這樣,目標單元格那的數據有效性中就沒有重復值了。
  • Target.Offset(0, 1) = “” :給目標單元格設置了數據有效性以后,把它同行D列單元格的值清除。這是為了確保D列的值只與C列的目標名稱相對應。
  • ElseIf Target.Column = 4 And Target.Offset(0, -1) <> “” Then :否則如果目標單元格是D列的,并且同行C列單元格不是空的情況下,執行這下面的代碼。Offset屬性的詳解可見前面實例6的第2條解釋。
  • For i = 1 To UBound(Arr) :在數組Arr之間逐一循環。
  • If Arr(i, 1) <> “” Then :如果A列數組的值不等于空,就執行下面的代碼。
  • r = r + 1 :變量r累加。
  • ReDim Preserve Arr1(1 To r) :重新聲明動態數組的大小,Preserve是關鍵字,當改變原有數組最末維的大小時,使用此關鍵字可以保持數組中原來的數據。這句是改變動態數組大小的最常用語句,不能忘記Preserve關鍵字。
  • Arr1? = i :把關鍵字在數組Arr中行的位置賦給新的動態數組Arr1?。這個循環可求得A列每一個源名稱所在的行的位置。
  • For i = 1 To r :上面的循環求得了一共有r個源名稱,逐一循環。
  • If Arr(Arr1(i), 1) = Target.Offset(0, -1).Text Then :如果C列的目標名稱等于源名稱時執行下面的代碼。
  • If i <> r Then :如果i不等于r時執行下面的代碼。
  • js = Arr1(i + 1) – 1 :把下一個源名稱所在的行數-1以后賦給變量js,這樣來求得每一個源名稱的開始和結束的位置。
  • js = Myr – 1 :否則就是最后一行-1的只賦給變量js(最后一個源名稱在數組中的位置)。
  • ks = Arr1(i) :把數組的值賦給變量ks:得到每一個源名稱的起始位置。
  • For j = ks To js :從每一個源名稱的起始位置到結束位置逐一循環。
  • cp = cp & Arr(j, 2) & “,” :把相應的代號與逗號連接起來組成的字符串賦給變量cp。
  • cp = Left(cp, Len(cp) - 1) :用了兩個VBA函數Left和Len把去掉末位的逗號。
  • With 語句解釋同上,為D列單元格設置了第2級數據有效性。
  • Target = Split(cp, “,”)(0) :按照問題的第3個要求,在目標名稱確定后,在目標代號相應位置自動生成目標名稱的第一個代號。因為Split得到的是一個以0為下界的一維函數,所以它的第一個元素就用(0)來表示。
  • 代碼執行后如圖實例8-2所示:

    圖 實例8-2示例

    實例 8 文件:點擊下載????????提取碼:lzh7




    2.9 實例9 字典取行數,數組重新賦值


    2.9.1 問題

    要求編寫一段代碼,求得B列不重復的名字,其相應的A列和D列分別用" "連起來,而相應的E列F列的數值分別相加匯總。
    代碼執行前如圖實例9-1所示。

    圖 實例9-1示例:



    2.9.2 代碼

    Sub yy() 'by:ZamyiDim d As New Dictionary, RDim k, i&, j&R = Sheet1.UsedRangek = 1For i = 2 To UBound(R)R(i, 2) = Replace(Replace(R(i, 2), "(", "("), "", ")")If d.Exists(R(i, 2)) ThenR(d(R(i, 2)), 1) = R(d(R(i, 2)), 1) & " " & R(i, 1)R(d(R(i, 2)), 4) = R(d(R(i, 2)), 4) & " " & R(i, 4)R(d(R(i, 2)), 5) = Val(R(d(R(i, 2)), 5)) + R(i, 5)R(d(R(i, 2)), 6) = Val(R(d(R(i, 2)), 6)) + R(i, 6)Elsek = k + 1d(R(i, 2)) = iFor j = 1 To UBound(R, 2)R(k, j) = R(i, j)NextEnd IfNextWith Sheet2.Cells.ClearContents.Cells.Borders.LineStyle = xlNone.[a1:F1].Resize(d.Count + 1) = R.[a1:F1].Resize(d.Count + 1).Borders.LineStyle = 1End WithSet d = Nothing End Sub

    2.9.3 代碼詳解

  • R = Sheet1.UsedRange :把表1的已經使用了的單元格區域的值賦給變量R。
  • k = 1 :變量k賦初值1。
  • For i = 2 To UBound? :由于第一行是表頭,所以從第2行開始循環。
  • R(i, 2) = Replace(Replace(R(i, 2), “(”, “(”), “)”, “)”):由于源數據中用了不統一的括號,所以加了這句把里面中文括號統一替換為英文括號。這句用了兩次VBA函數Replace,一次替換前半個,另一次替換后半個。Replace函數有6個參數,詳細請查閱VBA幫助文件。如果在這里解釋,篇幅太長了,也沖淡了字典的主題。
  • If d.Exists(R(i, 2)) Then :這句用字典的Exists方法進行判斷,如果字典中存在R(i, 2)這個關鍵字,那么執行下面的代碼。
  • 這里先解釋,Else如果上面的判斷不成立,即字典中不存在這個關鍵字時,要執行下面的代碼。
  • k = k + 1 :變量k+1以后再賦給k。
  • d(R(i, 2)) = i :公司名字作為關鍵字,對應的項是它所在的行,把它們加入字典d。
  • For j = 1 To UBound(R, 2) :知道了這個關鍵字所在的行,下面這個循環就是重新給數組同一行的各個元素賦值。UBound(R, 2)是用VBA函數Ubound求得數組R的第2維的最大上界。比如本例R數組第1維的最大上界是8,有8行數據;而第2維的最大上界是6,有6列數據。本循環j就是從第1列到第6列依次循環。
  • R(k, j) = R(i, j) :把i行j列的數組元素賦給k行j列的R數組元素。
  • R(d(R(i, 2)), 1) = R(d(R(i, 2)), 1) & " " & R(i, 1) :再回來說如果R(i, 2)這個關鍵字存在,則執行這條代碼。在這之前,這關鍵字已經加入字典了,它的同一行的各個數組元素也重新賦過值了,所以根據問題的要求,把A列的數據用" "連起來再賦給A列這個數組元素。
  • R(d(R(i, 2)), 4) = R(d(R(i, 2)), 4) & " " & R(i, 4) :D列數據同上。
  • R(d(R(i, 2)), 5) = Val(R(d(R(i, 2)), 5)) + R(i, 5) :E 列數據要相加,這里用了VBA函數Val,把E列數組元素轉為數值以后相加匯總。下句類同。
  • With Sheet2 :With語句,前面介紹過的。
  • .Cells.ClearContents :清空表2所有的數據。Cells是工作表對象的屬性,指工作表所有的單元格;ClearContents是它的方法,清除里面的公式、數據,但是保留格式設置。
  • .Cells.Borders.LineStyle = xlNone :清除表2所有的邊框。Borders是Cells的屬性,意思是單元格的邊框;LineStyle是邊框的屬性,為邊框的線型,它有直線、虛線、點劃線等等,這里取值xlNone是清除邊框。
  • .[a1:F1].Resize(d.Count + 1) = R :把數組R的值賦給表2A1單元格開始的區域。
  • .[a1:F1].Resize(d.Count + 1).Borders.LineStyle = 1 :給這些單元格添加邊框,線型為直線。
  • 代碼執行后如圖實例9-2所示:

    圖 實例9-2示例

    實例 9 文件:點擊下載????????提取碼:har1




    2.10 實例10 先字典求得行后顯示整行數據


    2.10.1 問題

    有3列數據,要求編寫一段代碼,如果C列名次、A列主排相同時,根據B列次排最大的只保留一行。
    解題思路:先對3列數據按主要關鍵字名次_升序,次要關鍵字主排_升序,第3關鍵字次排_降序進行排序,然后運用字典,以”名次|主排” 作為關鍵字,它所在的行作為關鍵字的項加入字典,最后根據行引用相對的單元格值。

    代碼執行前如圖實例10-1所示:

    圖 實例10-1示例

    2.10.2 代碼

    Sub pmc()Dim i&, Myr&, ArrDim d, x, rngApplication.ScreenUpdating = FalseSet d = CreateObject("Scripting.Dictionary")Sheet1.ActivateMyr = [a65536].End(xlUp).RowRange("A1:C" & Myr).Sort Key1:=Range("C2"), Order1:=xlAscending, Key2:=Range( _"A2"), Order2:=xlAscending, Key3:=Range("B2"), Order3:=xlDescending, _Header:=xlYesArr = Range("a2:c" & Myr)For i = 1 To UBound(Arr)x = Arr(i, 1) & "|" & Arr(i, 3)If Not d.exists(x) Thend.Add x, i + 1End IfNext[e:g].ClearContents[e2].Resize(d.Count, 1) = Application.Transpose(d.items)For Each rng In [e2].Resize(d.Count, 1)rng.Resize(1, 3) = Cells(rng, 1).Resize(1, 3).ValueNextSet d = NothingApplication.ScreenUpdating = True End Sub

    2.10.3 代碼詳解

  • Application.ScreenUpdating = False:關閉屏幕更新。關閉屏幕更新可加快宏的執行速度。請記住當宏結束執行時,將 ScreenUpdating 屬性設回到 True。
  • Range(“A1:C” & Myr).Sort Key1:=Range(“C2”), Order1:=xlAscending, Key2:=Range(“A2”), Order2:=xlAscending, Key3:=Range(“B2”), Order3:=xlDescending, Header:=xlYes :對ABC三列進行排序。主要關鍵字Key1名次_升序,次要關鍵字Key2主排_升序,第3關鍵字Key3次排_降序。
  • Arr = Range(“a2:c” & Myr) :把ABC列數據賦給變量Arr。
  • For i = 1 To UBound(Arr) :i從1到數組Arr的最大上界逐一循環。
  • x = Arr(i, 1) & “|” & Arr(i, 3) :把主排和”|”和名次連起來賦給變量x。
  • If Not d.exists(x) Then :如果字典中不存在x這個關鍵字,那么執行下面的代碼。
  • d.Add x, i + 1 :把x作為關鍵字和這個關鍵字的具體的行作為對應的項加入字典。因為數組Arr是從A2開始的,所以i與數據的實際行相差1,i+1就是數據的實際行。
  • [e:g].ClearContents :清空E~G列。
  • [e2].Resize(d.Count, 1) = Application.Transpose(d.items) :把字典所有的項轉置以后賦給E2單元格開始的區域。
  • For Each rng In [e2].Resize(d.Count, 1) :For- Each-Next控制結構是VBA中功能最強的循環控制結構,利用這個結構可對集合中的所有對象或者數組中的所有元素進行同一操作。它的一個優點在于你不必操心循環應該執行多少次,它循環的次數恰好就是數組中元素的個數(或者集合中對象的個數),因此對于處理多維數組特別是處理對象時最有效率。本句意思是在E2單元格開始的單元格區域中逐一循環。
  • rng.Resize(1, 3) = Cells(rng, 1).Resize(1, 3).Value :把關鍵字所在行的3個單元格的值賦給rng開始的3個單元格。在Cells(rng, 1)中作為參數的rng=rng.Valur,而rng.Resize(1, 3)處的rng是一個單元格對象。
  • 代碼執行后如圖實例10-2所示:

    圖 實例10-2示例

    實例 10 文件:點擊下載????????提取碼:92ie




    2.11 實例11 關鍵字賦給兩列后用Replace方法


    2.11.1 問題

    有如圖實例11-1所示的工資表,要求編寫一段代碼,運用VBA自動生成1季度的工資表。
    解題思路:先把性別和姓名連起來作為關鍵字求得人員的不重復值,然后通過循環查找關鍵字獲得其各月的工資,最后用Replace方法替換兩列關鍵字區域得到各自的數據。

    代碼執行前如圖實例11-1所示:

    圖 實例11-1示例

    2.11.2 代碼

    Sub yy()Dim d, k, t, i&, j&, Arr, x, r1Set d = CreateObject("Scripting.Dictionary")Arr = [a1].CurrentRegionFor i = 1 To UBound(Arr, 2) Step 3For j = 2 To UBound(Arr)If Arr(j, i) <> "" Thenx = Arr(j, i) & "|" & Arr(j, i + 1)d(x) = ""End IfNextNextk = d.keys[a12:i1000].ClearContents[a13].Resize(d.Count, 2) = Application.Transpose(k)[a12:b12] = Array("性別", "姓名")For i = 3 To UBound(Arr, 2) Step 3Cells(12, 2 + i / 3) = Cells(1, i)NextFor i = 3 To UBound(Arr, 2) Step 3For j = 2 To UBound(Arr)If Arr(j, i) <> "" Thenx = Arr(j, i - 2) & "|" & Arr(j, i - 1)Set r1 = [a13].Resize(d.Count, 1).Find(x, , , 1)Cells(r1.Row, 2 + i / 3) = Arr(j, i)End IfNextNext[a13].Resize(d.Count, 1).Replace "|*", "", xlPart[b13].Resize(d.Count, 1).Replace "*|", "", xlPart End Sub

    2.11.3 代碼詳解

  • Arr = [a1].CurrentRegion:把含有A1單元格的當前單元格區域的值賦給變量Arr。CurrentRegion是Range對象的屬性,當前區域指以任意空白行及空白列的組合為邊界的區域。如本題A11單元格有數據,但是因為第10行是空白行,所以沒有包含在A1的當前區域里面。
  • For i = 1 To UBound(Arr, 2) Step 3 :For-Next控制結構,從1 到數組第2維的最大上界每隔3進行一次循環,Step 3是循環的步長,第一次循環時i=1;第2次循環時i=1+3=4,第3次時i=4+3=7。
  • For j = 2 To UBound(Arr) :從第2行開始循環。沒有Step時默認Step為1。
  • If Arr(j, i) <> “” Then :If-Then-Else控制結構可根據測試條件的結果改變程序執行的流程。本句測試條件是Arr(j, i) <> “”,判斷性別是否為空白,如果不為空白則執行下面的語句,否則,執行Else下面的語句。
  • x = Arr(j, i) & “|” & Arr(j, i + 1) :把性別和姓名中間加“|”連起來賦給變量x。
  • d(x) = “” :把x的值作為關鍵字加入字典d。比如把”男|趙” 加入字典d。這兩個循環把每個月的所有的人員都加入了字典d,字典中的人員是沒有重復的。
  • k = d.keys :把字典d所有的關鍵字賦給變量k。
  • [a12:i1000].ClearContents :清空A12:I1000單元格區域。
  • [a13].Resize(d.Count, 2) = Application.Transpose(k) :把變量k轉置之后賦給A13開始的單元格區域。Resize是Range對象的屬性,調整指定區域的大小,其第1個參數是行的大小,d.Count表示字典關鍵字的數量,如果有10個關鍵字,那么就是10行;其第2個參數是列的大小,一般是賦給1列的,本例關鍵字由兩個數據合并而成,所以先賦給2列,后面再處理。
  • [a12:b12] = Array(“性別”, “姓名”) :Array是一個VBA函數,返回一個下界為0的一維數組。一維數組可以看作是水平排列的,這里作為表頭一次性輸入。
  • For i = 3 To UBound(Arr, 2) Step 3 :從第3列開始循環,步長為3。
  • Cells(12, 2 + i / 3) = Cells(1, i) :把“1月工資“、“2月工資“等輸入到相應表頭的位置。
  • Set r1 = [a13].Resize(d.Count, 1).Find(x, , , 1) :在A13單元格開始的區域中查找字符串變量x,Find方法是Range對象的一個方法,其中第4個參數值為1,其常量為xlWhole,表示精確查找,另一個常量為xlPart,它的值=2。Find方法返回的是Range對象,所以前面要用Set語句來引用對象。
  • Cells(r1.Row, 2 + i / 3) = Arr(j, i) :把關鍵字對應的工資賦給相應的單元格里。
  • [a13].Resize(d.Count, 1).Replace "|", “”, xlPart :Replace方法是Range對象的一個方法,其第1個參數是要查找的字符串,這里"|"是豎線及后面所有的字符串;其第2個參數是替換字符串,這里替換為空;其第3個參數是精確查找還是模糊查找,xlPart常量的值=2,可以用2代替它。本句是把姓名替換掉,只留下性別;下一句把B列中的性別替換掉,只留下姓名。
  • 代碼執行后如圖實例11-2所示:

    圖 實例11-2示例

    實例 10 文件:點擊下載????????提取碼:x4sb




    2.12 實例12 復雜報表匯總


    2.12.1 問題的提出 :

    有一日報表,里面有生產型號、生產數量、返修原因、返修數量、報廢原因、報廢數量,要求編寫一段代碼,按同型號產品匯總生產數量;得到同型號產品相同返修原因的唯一值;按同型號產品相同返修原因匯總返修數量; 得到同型號產品相同報廢原因的唯一值;同型號產品相同報廢原因匯總報廢數量,并且合并相同內容的單元格。

    代碼執行前如圖實例12-1所示:

    圖 實例12-1示例

    2.12.2 代碼

    Sub bbhz()Dim i&, Myr&, x(1 To 3), Arr, n%, aa, j&, Arr1(), r%, Arr2(), r2%, r3%, Arr3()Dim d(1 To 3) As New dictionary, k(1 To 3), t(1 To 3), js, ks, ii%, jj&, ks1, js1Application.ScreenUpdating = FalseMyr = Sheet1.[a65536].End(xlUp).RowArr = Sheet1.Range("a3:g" & Myr)For i = 1 To UBound(Arr)x(1) = Arr(i, 2)d(1)(x(1)) = d(1)(x(1)) + Arr(i, 3)x(2) = Arr(i, 2) & "|" & Arr(i, 4)d(2)(x(2)) = d(2)(x(2)) + Arr(i, 5)x(3) = Arr(i, 2) & "|" & Arr(i, 4) & "|" & Arr(i, 6)d(3)(x(3)) = d(3)(x(3)) + Arr(i, 7)NextFor i = 1 To 3k(i) = d(i).Keyst(i) = d(i).ItemsNextSheet4.Activate[a3:k1000].ClearContents[a3:k1000].UnMerge[a3:k1000].Borders.LineStyle = xlNone[i3].Resize(d(3).Count, 1) = Application.Transpose(t(3))n = 2For i = 0 To UBound(k(3))aa = Split(k(3)(i), "|")n = n + 1Cells(n, 2) = aa(0)Cells(n, 4) = aa(1)Cells(n, 8) = aa(2)NextFor i = 3 To nFor j = 0 To UBound(k(1))If Cells(i, 2) = k(1)(j) ThenCells(i, 3) = t(1)(j)Cells(i, 10) = Cells(i, 9) / Cells(i, 3)Cells(i, 11) = Cells(i, 10): Exit ForEnd IfNextFor j = 0 To UBound(k(2))If Cells(i, 2) & "|" & Cells(i, 4) = k(2)(j) ThenCells(i, 5) = t(2)(j)Cells(i, 6) = Cells(i, 5) / Cells(i, 3)Cells(i, 7) = Cells(i, 6): Exit ForEnd IfNextNextRange("a3:k" & n).Sort Key1:=Range("b3"), Order1:=xlAscending, Key2:=Range("d3") _, Order2:=xlAscending, Key3:=Range("h3"), Order3:=xlAscending, Header:= _xlGuessFor i = 3 To nIf Cells(i, 2) <> Cells(i - 1, 2) Thenr = r + 1ReDim Preserve Arr1(1 To r)Arr1(r) = iEnd IfNextApplication.DisplayAlerts = FalseFor j = 1 To rr3 = 0: r2 = 0If j <> r Thenjs = Arr1(j + 1) - 1Elsejs = nEnd Ifks = Arr1(j)If js - ks + 1 > 1 ThenCells(ks, 1).Resize(js - ks + 1, 1).MergeCells(ks, 2).Resize(js - ks + 1, 1).MergeCells(ks, 3).Resize(js - ks + 1, 1).MergeEnd IfCells(ks, 1) = jFor ii = ks To jsIf ii = ks Thenr2 = r2 + 1ReDim Preserve Arr2(1 To r2)Arr2(r2) = iiElseIf Cells(ii, 4) <> Cells(ii - 1, 4) Thenr2 = r2 + 1ReDim Preserve Arr2(1 To r2)Arr2(r2) = iiEnd IfNextFor ii = 1 To r2If ii <> r2 Thenjs1 = Arr2(ii + 1) - 1Elsejs1 = jsEnd Ifks1 = Arr2(ii)If js1 - ks1 + 1 > 1 ThenCells(ks1, 4).Resize(js1 - ks1 + 1, 1).MergeFor jj = ks1 To js1If jj <> ks1 ThenCells(ks, 7) = Cells(ks, 7) + Cells(jj, 7)End IfNextCells(ks1, 5).Resize(js1 - ks1 + 1, 1).MergeCells(ks1, 6).Resize(js1 - ks1 + 1, 1).MergeElseIf ii <> 1 ThenCells(ks, 7) = Cells(ks, 7) + Cells(ks1, 7)End IfEnd IfNextCells(ks, 7).Resize(js - ks + 1, 1).MergeFor ii = ks To jsIf ii = ks Thenr3 = r3 + 1ReDim Preserve Arr3(1 To r3)Arr3(r3) = iiElseIf Cells(ii, 8) <> Cells(ii - 1, 8) Thenr3 = r3 + 1ReDim Preserve Arr3(1 To r3)Arr3(r3) = iiEnd IfNextFor ii = 1 To r3If ii <> r3 Thenjs1 = Arr3(ii + 1) - 1Elsejs1 = jsEnd Ifks1 = Arr3(ii)If js1 - ks1 + 1 > 1 ThenCells(ks1, 8).Resize(js1 - ks1 + 1, 1).MergeFor jj = ks1 To js1If jj <> ks1 ThenCells(ks1, 9) = Cells(ks1, 9) + Cells(jj, 9)Cells(ks1, 10) = Cells(ks1, 10) + Cells(jj, 10)End IfCells(ks, 11) = Cells(ks, 11) + Cells(jj, 11)NextCells(ks1, 9).Resize(js1 - ks1 + 1, 1).MergeCells(ks1, 10).Resize(js1 - ks1 + 1, 1).MergeElseIf ii <> 1 ThenCells(ks, 11) = Cells(ks, 11) + Cells(ks1, 11)End IfEnd IfNextCells(ks, 11).Resize(js - ks + 1, 1).MergeNextRange("a3:k" & n).Borders.LineStyle = 1Application.DisplayAlerts = TrueApplication.ScreenUpdating = True End Sub

    2.12.3 代碼詳解

  • Dim d(1 To 3) As New dictionary :本例是前期綁定的,先引用了腳本運行時庫,聲明了3個元素的數組為新字典。
  • x(1) = Arr(i, 2) :把生產型號賦給變量x(1)。
  • d(1)(x(1)) = d(1)(x(1)) + Arr(i, 3) :把相同生產型號和它的生產數量加入字典d(1),達到匯總的目的。
  • x(2) = Arr(i, 2) & “|” & Arr(i, 4) :把生產型號和返修原因連起來賦給變量x(2)。
  • d(2)(x(2)) = d(2)(x(2)) + Arr(i, 5) : 把相同生產型號和相同返修原因的返修數量加入字典d(2),達到匯總的目的。
  • x(3) = Arr(i, 2) & “|” & Arr(i, 4) & “|” & Arr(i, 6) :把生產型號和返修原因和報廢原因連起來賦給變量x(3)。
  • d(3)(x(3)) = d(3)(x(3)) + Arr(i, 7) :把相同生產型號和相同返修原因和相同報廢原因的報廢數量加入字典d(3),達到匯總的目的。
  • For i = 1 To 3 :用一個循環運用字典的keys方法和items方法把3個字典的關鍵字和它們的項賦給對應的變量。
  • Sheet4.Activate :激活表4。
  • [a3:k1000].ClearContents :清空A3:K1000單元格區域。
  • [a3:k1000].UnMerge :將該區域所有的合并單元格分解為獨立的單元格。
  • [a3:k1000].Borders.LineStyle = xlNone :去除該區域所有的單元格邊框。
  • [i3].Resize(d(3).Count, 1) = Application.Transpose(t(3)) :把報廢數量匯總值的一維數組轉置后賦給I3開始的單元格區域。
  • n = 2 :把2賦給變量n。因為循環中要用到n=n+1,而匯總表的起始行是第3行,所以把n的初值定為2。
  • For i = 0 To UBound(k(3)) :在字典d(3)中逐一循環。
  • aa = Split(k(3)(i), “|”) :VBA函數Split在第6例已經講過了。把字典d(3)的關鍵字分解后賦給變量aa。
  • n = n + 1 :在循環中每循環一次行數就加1。
  • Cells(n, 2) = aa(0) :把aa數組的第1個元素aa(0),即生產型號,賦給對應的單元格;下面兩句分別把aa數組的第2個元素aa(1),即返修原因,賦給對應的單元格;把aa數組的第3個元素aa(2),即報廢原因,賦給對應的單元格。
  • For i = 3 To n :從第3行開始逐行循環。
  • For j = 0 To UBound(k(1)) :在一維數組k(1)中循環。
  • If Cells(i, 2) = k(1)(j) Then :如果生產型號等于字典d(1)的關鍵字時執行下面的語句。
  • Cells(i, 3) = t(1)(j) :把這個生產型號的生產數量賦給C列單元格。
  • Cells(i, 10) = Cells(i, 9) / Cells(i, 3) :把報廢數量除以生產數量得到的報廢率賦給J列單元格。
  • Cells(i, 11) = Cells(i, 10): Exit For :把報廢率賦給K列單元格。退出For j的循環。
  • For j = 0 To UBound(k(2)) :在一維數組k(2)中循環。
  • If Cells(i, 2) & “|” & Cells(i, 4) = k(2)(j) Then :如果把生產型號和返修原因連起來的值等于字典d(2)的一個關鍵字時,執行下面的代碼。
  • Cells(i, 5) = t(2)(j) :把相同生產型號和相同返修原因的返修數量賦給E列單元格。
  • Cells(i, 6) = Cells(i, 5) / Cells(i, 3) :把返修數量除以生產數量得到的返修率賦給F列單元格。
  • Cells(i, 7) = Cells(i, 6): Exit For :把返修率賦給G列單元格。退出For j的循環。
  • Range(“a3:k” & n).Sort Key1:=Range(“b3”), Order1:=xlAscending, Key2:=Range(“d3”), Order2:=xlAscending, Key3:=Range(“h3”), Order3:=xlAscending, Header:= xlGuess :本句開始給表格數據設置格式了。本句是對A3開始的單元格區域按B3_升序、D3_升序、H3_升序排序。
  • For i = 3 To n :從第3行開始逐行循環。
  • If Cells(i, 2) <> Cells(i - 1, 2) Then :如果B列單元格的值與上一行單元格不相等則執行下面的代碼。
  • r = r + 1 :變量r加1以后賦給r。
  • ReDim Preserve Arr1(1 To r) :重新聲明動態數組的大小。Preserve是ReDim 語句的關鍵字,當改變原有數組最末維的大小時,使用此關鍵字可以保持數組中原來的數據。
  • Arr1? = i :把單元格所在的行數賦給數組。經過這輪循環就得到了各個生產型號的第一行的行數。也得到了生產型號的總數為r個。
  • Application.DisplayAlerts = False :把顯示警告設置為關閉,因為下面要合并單元格,Excel會顯示一個警告對話框來打斷代碼的運行,所以先關閉此功能。
  • For j = 1 To r :在所有的生產型號中逐一循環。
  • r3 = 0: r2 = 0 :把兩個變量設置為零。
  • If j <> r Then :如果j不等于最后一個生產型號時,執行下面的代碼。
  • js = Arr1(j + 1) – 1 :把下一個生產型號開始行的上面一行的行數賦給js。
  • 否則把最后一行的行數n賦給js變量。
  • ks = Arr1(j) :把生產型號的開始行的行數賦給變量ks。
  • If js - ks + 1 > 1 Then :如果結束行減去開始行再加1的值大于1,就說明這個型號有多行需要合并,執行下面的代碼。
  • Cells(ks, 1).Resize(js - ks + 1, 1).Merge :A列對應的單元格合并;下面B列和C列相應的單元格也合并。
  • Cells(ks, 1) = j :A列依次填入序號。
  • For ii = ks To js :從開始行到結束行逐一循環。
  • If ii = ks Then :這個循環是為了求得D列返修原因是否有需要合并的單元格,如果ii = ks即是同一個生產型號中第一個返修原因的時候,把行數賦給動態數組,否則如果不等于上一行D列單元格的值時,把行數賦給動態數組的下一個元素。經過這輪循環就得到了這個生產型號每一個返修原因的第一行的行數。也得到了返修原因的總數為r2個。
  • For ii = 1 To r2 :在這個循環中,把D列、E 列F列相同的返修原因單元格合并,也匯總了G列的總返修率。
  • Cells(ks, 7).Resize(js - ks + 1, 1).Merge :把G列的總返修率單元格區域合并。
  • For ii = ks To js :從開始行到結束行逐一循環。這個循環是為了求得H列報廢原因是否有需要合并的單元格,經過這輪循環就得到了這個生產型號每一個報廢原因的第一行的行數。也得到了報廢原因的總數為r3個。
  • For ii = 1 To r3 :在這個循環中,把H 列、I 列J 列相同的報廢原因、報廢數量和報廢率單元格合并,也匯總了K列的總報廢率。
  • Range(“a3:k” & n).Borders.LineStyle = 1 :把A3開始的單元格區域設置邊框。
  • Application.DisplayAlerts = True :開啟程序顯示警告。
  • Application.ScreenUpdating = True :開啟屏幕更新。

  • 代碼執行后如圖實例12-2所示:

    圖 實例12-2示例

    實例 12 文件:點擊下載????????提取碼:z3ob




    3. 后語

    ????????常見字典用法實例集錦到此告一段落了。字典就象一個二維數組Arr(1 to n,1 to 2),不過它的第 2 維的最大上界為 2,相當于2列單元格,第1列存放的是關鍵字,這個關鍵字是除了數組以外的任何類型;第2列存放的是這個關鍵字對應的項,它可以是數據的任何類型。

    ????????我收集的和接觸到有關字典的實例的數量有限,一定會有更好更有代表性的實例沒有接觸到,希望有心人能提供出來,供大家學習分享。

    ????????謝謝大家!

    總結

    以上是生活随笔為你收集整理的常见字典用法集锦及代码详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    人交video另类hd | 国产成人精品一区二区三区网站观看 | 久久综合色8888 | 九九精品在线观看 | 免费无遮挡动漫网站 | 久久国产精品视频 | 一区二区精品视频 | 久久精品91视频 | www.夜夜| 狠狠狠狠狠干 | 久久中文欧美 | 九九综合在线 | 国产黄色精品在线 | 国内精品久久久久影院一蜜桃 | 日韩网站在线播放 | 久久婷婷色综合 | 91精品91 | 久草在线在线视频 | 日韩一区二区久久 | 久久免费高清 | 日本特黄一级片 | 精品日韩中文字幕 | 午夜丰满寂寞少妇精品 | 超碰av在线 | 国产特级毛片aaaaaaa高清 | 久久久久久国产精品999 | 久草在线最新 | 日韩高清免费在线 | 97精品电影院 | 97狠狠干 | 亚洲经典在线 | 久久久精品99 | 在线视频在线观看 | 久久久久久欧美二区电影网 | 国产麻豆视频免费观看 | 国产亚洲精品久久久久久大师 | 婷婷六月丁香激情 | 久久久久国产成人免费精品免费 | 一本一道久久a久久综合蜜桃 | 久久免费视频在线观看6 | 久久久精品午夜 | 成人午夜性影院 | 国产精品18毛片一区二区 | 亚洲亚洲精品在线观看 | 国产一级91 | 久久久香蕉视频 | 中文字幕精品久久 | 亚洲精品中文在线 | 国产 日韩 在线 亚洲 字幕 中文 | 成人综合婷婷国产精品久久免费 | 日本99热 | 亚洲精品美女久久久久网站 | 国产精品一区二区久久精品爱涩 | 一区二区中文字幕在线 | 成人黄大片视频在线观看 | 伊人国产女 | 久久久久免费网站 | 久久久久久国产一区二区三区 | 国产一卡二卡在线 | 国产无套一区二区三区久久 | 黄色一级在线观看 | 色悠悠久久综合 | 国色综合| 国产91在线免费视频 | 97狠狠操 | 伊香蕉大综综综合久久啪 | 99综合电影在线视频 | 白丝av在线 | 日韩中文字幕亚洲一区二区va在线 | 亚洲精品久久久久999中文字幕 | 国产精品成人久久久久久久 | 亚洲免费黄色 | 国产免费黄视频在线观看 | 国产精品高潮久久av | 国产一二区免费视频 | 综合色中色 | www.看片网站| 国际精品久久 | 日韩高清精品免费观看 | 国产在线观看黄 | 蜜桃视频在线视频 | 久久er99热精品一区二区三区 | 国产成人一区二区三区影院在线 | 香蕉网在线 | 在线国产一区二区 | 色婷婷亚洲综合 | 欧美夫妻生活视频 | 天天操天天操天天操天天操 | 国产精品a成v人在线播放 | 玖玖玖精品 | 免费在线观看一级片 | 日韩免费视频网站 | 国产 中文 日韩 欧美 | 天天干天天草天天爽 | 亚洲精品1234区 | 日韩免费小视频 | 欧美亚洲国产精品久久高清浪潮 | 欧美精品中文在线免费观看 | 97视频网址| 中文字幕在线日本 | 狠狠色狠狠色综合系列 | 久久99电影| av在观看 | 国产精品ⅴa有声小说 | 国产一区视频导航 | 国产成人精品久久久 | 国产美女免费观看 | 九月婷婷人人澡人人添人人爽 | 特级黄录像视频 | 欧美少妇xxx | 国产精品理论在线观看 | 天天弄天天干 | 成人午夜在线观看 | 激情五月***国产精品 | 在线播放 亚洲 | 日韩欧美一区二区三区黑寡妇 | 亚洲成人免费在线观看 | 亚洲片在线资源 | 国产精品久久一区二区无卡 | 国产高清在线视频 | 欧美激情片在线观看 | 欧美性极品xxxx娇小 | 黄色大全在线观看 | 菠萝菠萝在线精品视频 | 欧美嫩草影院 | 日韩久久精品一区二区 | 亚洲播播| 天天做天天爱天天综合网 | 九色91在线| 婷婷5月色| 欧美a视频 | 91精品国产91久久久久 | 天堂va欧美va亚洲va老司机 | 亚洲激情久久 | 91天堂素人约啪 | 91精品伦理| 在线电影91 | 视频一区二区免费 | 91av色| 伊人伊成久久人综合网小说 | 久久福利| 人人超在线公开视频 | 91九色在线视频观看 | 国产精品igao视频网网址 | 六月天色婷婷 | 免费情趣视频 | 日韩黄色中文字幕 | 久久久久免费观看 | 日韩av成人在线 | 福利视频网站 | 亚洲精品在线网站 | 国产美女久久 | 中文字幕专区高清在线观看 | 久久a热6| av看片网 | 天天操天天摸天天干 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 波多野结衣最新 | 亚洲精品视频在线观看免费视频 | 日韩在线观看小视频 | 夜夜操天天摸 | 国产亚洲婷婷 | 婷婷精品国产欧美精品亚洲人人爽 | 久操视频在线免费看 | 国产精品乱码久久 | 成人香蕉视频 | 免费在线观看一级片 | 日韩免费看片 | 免费观看全黄做爰大片国产 | 亚洲精品综合久久 | 97在线观看视频免费 | 日本69hd | 国产精品免费视频久久久 | 91久久国产精品 | 超碰在线天天 | 欧美经典久久 | 射九九| 日韩av有码在线 | 国产成人精品一区二区三区网站观看 | 国产精品久久久久毛片大屁完整版 | 国产视频黄 | 永久免费精品视频 | 国产1区2区3区精品美女 | av免费看电影 | 精品视频在线视频 | 国产精品久久久久永久免费观看 | 天天操天天操天天干 | 久草在线中文888 | 中文字幕在线视频一区二区 | 欧美a级片免费看 | 91视频a | 91精品免费在线 | 日韩欧美亚州 | 玖玖色在线观看 | av黄色大片| 天天操天天爱天天干 | 成人黄色在线看 | 成人久久精品 | 国产色婷婷精品综合在线手机播放 | 亚洲国产日韩一区 | 国产麻豆剧果冻传媒视频播放量 | 国产精品福利在线 | 色在线免费| 国产精品五月天 | 婷婷丁香激情综合 | av在线专区| 日韩国产精品一区 | 日日添夜夜添 | 91麻豆视频网站 | www.xxxx欧美 | 日韩视频一二三区 | 亚洲天天在线日亚洲洲精 | 国产九九精品视频 | av在线免费在线观看 | 国产精品一区二区三区免费看 | 国产精品女主播一区二区三区 | 超碰在线免费97 | 久久综合网色—综合色88 | 九色91在线视频 | 亚洲高清国产视频 | av福利免费 | 在线三级av | 97视频人人免费看 | 成人一级电影在线观看 | 国产97色 | 国产精品不卡一区 | 免费观看www视频 | 国产在线观看a | 精品久久久一区二区 | 一区二区精 | 亚洲成人资源网 | 欧美精品在线观看免费 | 午夜99| 九九热精品视频在线观看 | 亚洲免费精品一区二区 | 久久国产精品二国产精品中国洋人 | 免费看的黄网站软件 | 国产精品 美女 | 日本久久久影视 | 欧美一级片在线播放 | 国产在线更新 | 午夜精品在线看 | 久久精品视频18 | 天天添夜夜操 | 高潮毛片无遮挡高清免费 | 99日精品 | 亚洲精品网站在线 | 久久免费视频这里只有精品 | 日本中文一区二区 | 欧美成人影音 | 三级av在线免费观看 | 西西www4444大胆视频 | 99re久久精品国产 | 在线观看日韩专区 | 亚洲精品视频大全 | 日韩免费av网址 | 国语精品久久 | 欧美在线99 | 欧美成人xxx | 毛片网免费 | 精品亚洲免费视频 | 亚洲天堂网在线视频观看 | 国产又黄又猛又粗 | 国产在线观看免费观看 | 美女网站黄在线观看 | 午夜精品视频福利 | 日韩在线观 | 美女很黄免费网站 | 婷婷 综合 色| 婷婷.com| 久久婷婷精品 | 91精品国产91久久久久 | 久久在线| 精品视频在线免费观看 | 日韩视频一区二区三区 | 日韩区欠美精品av视频 | 欧美精品成人在线 | 美女视频久久久 | 国产精品永久久久久久久www | 国产精品 日韩 | 六月丁香婷| 久久99久久99精品免观看软件 | 国产精品1区2区3区 久久免费视频7 | 色橹橹欧美在线观看视频高清 | 91亚色视频在线观看 | 18久久久久 | 在线免费国产视频 | 99热精品免费观看 | 国产精品自产拍在线观看网站 | 国产精品久久久久久久7电影 | 手机av片| 亚洲一区二区三区四区精品 | 黄色电影网站在线观看 | 成人在线免费看视频 | 黄色大片免费播放 | 激情av网 | 国产精品男女 | 毛片无卡免费无播放器 | 国产无套精品久久久久久 | 91干干干 | 久久夜夜夜 | 麻豆精品视频在线 | 国产精品18久久久久久久网站 | 国产精品久久久久久久久岛 | 四虎国产 | 国内少妇自拍视频一区 | 国产成人亚洲在线观看 | 天天操天天操天天操 | 亚洲精品在线视频 | 丝袜美腿在线播放 | 日韩久久精品一区二区三区下载 | 国产精品丝袜久久久久久久不卡 | 美女视频久久久 | 国产91精品一区二区麻豆亚洲 | 中文字幕123区 | 欧美精品一区二区三区四区在线 | jizz欧美性9| 中文字幕欧美三区 | 嫩草av在线 | 91久久偷偷做嫩草影院 | 在线黄网站| 免费高清看电视网站 | 免费不卡中文字幕视频 | 久久蜜臀一区二区三区av | 久久精品一级片 | 免费又黄又爽的视频 | 色婷婷久久久 | 国产精品久久一区二区三区不卡 | 国产精品永久免费视频 | 伊人激情综合 | 欧美日韩国产精品爽爽 | www最近高清中文国语在线观看 | 婷婷在线资源 | 欧美日韩在线网站 | 日韩高清www | 国产精品久久99综合免费观看尤物 | 日韩欧美综合在线视频 | 四虎影视成人永久免费观看视频 | 国产99久久99热这里精品5 | 超碰国产在线 | 亚洲高清视频一区二区三区 | 免费在线国产视频 | 狠狠搞,com| 97福利| 免费三级影片 | 亚洲一区二区三区毛片 | 亚洲国产精品视频在线观看 | 日韩一区二区三区视频在线 | 久草网视频在线观看 | 久久天天综合网 | 成年人在线免费看片 | 97影视 | 黄色大全视频 | 五月婷婷激情 | 最新中文字幕在线观看视频 | 国产色婷婷 | 美女久久久久久久久久 | h文在线观看免费 | a级国产乱理论片在线观看 伊人宗合网 | 亚洲午夜久久久久久久久 | 色综合久久久网 | 日韩在线观看视频免费 | 亚州五月| 美女视频又黄又免费 | 国产资源免费在线观看 | www.午夜色.com | 欧美日韩在线免费视频 | 亚州日韩中文字幕 | 久久精品国产精品亚洲 | 色网影音先锋 | 国产免费高清 | 国产视频在线一区二区 | 亚洲资源| 欧美日韩中 | 国内精品亚洲 | 久草视频精品 | 久久综合影视 | 日日操操操 | 69成人在线 | 国产亚洲高清视频 | 亚洲 综合 国产 精品 | a天堂一码二码专区 | 免费人成在线观看网站 | 亚洲视频网站在线观看 | 久久r精品| 久久99视频免费 | 亚洲成人黄色在线观看 | 在线观看国产一区二区 | 伊在线视频 | 久草在线高清 | 久草在线免费播放 | 国产亚洲精品久久久久久久久久久久 | 久久综合电影 | 精品欧美在线视频 | 免费观看一级成人毛片 | av免费在线免费观看 | 久久免费国产精品 | 91丝袜美腿| 国产精品丝袜久久久久久久不卡 | 91视频 - v11av | 国内毛片毛片 | 中文字幕精品三区 | 中文字幕视频三区 | 黄色免费电影网站 | av在线免费播放网站 | 色综合中文字幕 | 国产精品综合久久 | 国产美腿白丝袜足在线av | 91中文字幕在线视频 | 亚洲综合色视频在线观看 | 久久久久久久影院 | 欧美国产视频在线 | 亚洲成人av在线电影 | 在线观看亚洲精品 | 特级a毛片| 婷婷丁香狠狠爱 | 亚洲 欧美 变态 国产 另类 | 在线观看的av网站 | 国产高清在线免费视频 | 久久免费视频这里只有精品 | 久久久.com | 天天躁日日躁狠狠躁 | 精品国模一区二区三区 | 91精品国产99久久久久久红楼 | 亚洲综合视频在线播放 | 中文字幕亚洲欧美日韩 | 日韩免费视频在线观看 | 手机av网站| 激情综合网色播五月 | 国产视频亚洲视频 | 天天干天天天天 | 欧美国产日韩一区二区三区 | 人交video另类hd | 超碰97av在线| 欧美日韩国产色综合一二三四 | 国产成人99久久亚洲综合精品 | 免费国产亚洲视频 | 国产一区二区三区免费在线 | 最新日韩在线 | 高清视频一区二区三区 | 久久精品直播 | 中文字幕精品在线 | 免费黄a大片 | 国产精品久久久久久久久久免费 | 91视频最新网址 | 亚洲国产精品一区二区久久hs | 国产日韩视频在线观看 | 免费在线观看污网站 | 香蕉久草| 精品久久久久久亚洲综合网站 | 国产精品观看在线亚洲人成网 | ww视频在线观看 | 久久精品免费 | 中文字幕无吗 | 最新色站 | 91日韩精品一区 | 99精品视频在线观看视频 | ,午夜性刺激免费看视频 | 丁香婷婷激情 | 国产四虎影院 | 成人av中文字幕 | 最新av在线播放 | 网址你懂的在线观看 | 欧美看片| 丁香婷婷深情五月亚洲 | 亚洲精品av在线 | 国产裸体视频网站 | 久草在线在线精品观看 | 亚洲精品视频网 | 久久久久女教师免费一区 | 欧美一区二区三区不卡 | 天堂网一区二区 | 国产在线毛片 | 特黄特色特刺激视频免费播放 | 毛片永久新网址首页 | 夜夜干夜夜 | 亚洲综合在线五月 | 国产成人精品在线播放 | 欧美性色黄 | 色婷婷伊人 | 中文字幕高清有码 | 久久久精品亚洲 | 国产精品一区二区av | 久久综合之合合综合久久 | 91视频麻豆视频 | 九九热精品在线 | 久免费视频 | 国产免费一区二区三区最新6 | 五月婷婷六月丁香在线观看 | 中文字幕免费中文 | 免费a视频在线 | 久久久99国产精品免费 | 日韩av一卡二卡三卡 | 亚洲电影在线看 | 中文字幕在线观看第三页 | 97精品国自产拍在线观看 | 亚洲91视频 | 国产色视频 | 91精品国产自产91精品 | 激情五月婷婷综合网 | 精品国产一区二区三区免费 | 激情丁香 | 一区中文字幕电影 | 久久久国产精品亚洲一区 | 狠狠操操操 | av不卡中文字幕 | 中文字幕一区二区三区视频 | 久久免费的精品国产v∧ | 国产精品视频区 | 欧美激情va永久在线播放 | 99久久婷婷国产综合精品 | 精品久久美女 | 亚洲精品欧美专区 | 欧美一级裸体视频 | 美女视频永久黄网站免费观看国产 | 国产精品久久久久影院 | 欧美另类交人妖 | 亚洲欧美激情精品一区二区 | 国产精品热视频 | 最近最新中文字幕 | 国产91在线免费视频 | 欧美成人精品三级在线观看播放 | 超碰免费观看 | 中文成人字幕 | 久久精品人人做人人综合老师 | 欧美日韩国产一区二区三区 | 精品女同一区二区三区在线观看 | 国产一级二级在线播放 | 在线观看视频免费播放 | 婷婷 中文字幕 | 97av影院| 久久久久中文 | 婷婷中文字幕综合 | 中文字幕91在线 | 91av在线免费看| 久久视频免费看 | 欧美在线视频不卡 | 成人免费视频在线观看 | 四虎在线观看精品视频 | 色小说av| 香蕉视频在线视频 | 欧美久久久久久久久中文字幕 | 国产中文字幕一区二区三区 | 欧美成年人在线观看 | 久久综合免费视频影院 | 国产女人18毛片水真多18精品 | 丝袜av一区| 人成免费网站 | 色婷婷激情电影 | 国产色资源 | 久久人人添人人爽添人人88v | 97超碰国产在线 | 免费一级特黄录像 | 欧美一级免费片 | av黄免费看 | 91九色蝌蚪视频在线 | 天天舔夜夜操 | 五月激情视频 | 国产一区在线免费观看 | 黄色软件大全网站 | 久久精品观看 | 九九热精品视频在线播放 | 99国产高清 | 在线观看色视频 | 玖玖国产精品视频 | 国产精品久久 | 另类老妇性bbwbbw高清 | 日韩久久久久久久久久久久 | 久久精品成人欧美大片古装 | 中文字幕在线观看1 | 久久精品美女视频网站 | 国产专区在线 | 成人免费看片网址 | 国产精品福利视频 | 精品久久久久国产免费第一页 | 国产精品地址 | 久久综合久久伊人 | 国产精品videoxxxx| 亚洲日本精品视频 | 日韩激情网| 在线黄色国产 | 国内精品久久久久久久久久久 | 国产美女在线观看 | 99精品国产兔费观看久久99 | 久久久精品一区二区三区 | 91网站在线视频 | 99久热在线精品视频 | 久久伊99综合婷婷久久伊 | 日韩大片免费在线观看 | 国产剧情av在线播放 | 欧美日韩高清一区二区 国产亚洲免费看 | 中文字幕在线观看的网站 | 午夜久久网站 | www欧美日韩 | www.99av| 一区二区电影在线观看 | 91在线日韩| 在线观看视频色 | 韩国av一区二区三区在线观看 | 激情开心网站 | 欧洲高潮三级做爰 | 97精品国产97久久久久久粉红 | 在线观看网站av | 午夜电影中文字幕 | 久久精品国产成人精品 | 国色天香在线观看 | 欧美日韩精品在线一区二区 | 欧美 日韩 国产 中文字幕 | 天天射网站 | 欧美少妇影院 | 一区二区三区四区免费视频 | 88av色| 欧美aaa大片 | 欧美天堂视频在线 | 在线观看完整版 | 天天射天天射 | 久久婷婷一区二区三区 | 在线 欧美 日韩 | 国产精品麻豆果冻传媒在线播放 | 精品久久久久一区二区国产 | 午夜日b视频 | 中文字幕在线乱 | 精品美女在线视频 | 啪啪免费观看网站 | 国产 字幕 制服 中文 在线 | 欧美在线视频一区二区 | 五月婷香蕉久色在线看 | 一二三精品视频 | 亚洲高清色综合 | 免费看一级黄色大全 | 99视频精品全部免费 在线 | 伊人狠狠色丁香婷婷综合 | 亚州日韩中文字幕 | 日日爽夜夜爽 | 国内精品毛片 | 日韩美女久久 | 天天夜夜亚洲 | 国产精品电影一区 | 一级片视频在线 | 成年人电影免费看 | 又长又大又黑又粗欧美 | 精品亚洲二区 | 亚洲在线观看av | 91福利视频久久久久 | 婷婷免费在线视频 | 久热免费在线 | 免费观看国产视频 | 99热只有精品在线观看 | 久久香蕉一区 | 99久热在线精品视频成人一区 | 日韩中文字幕在线看 | 免费国产在线视频 | 国产 视频 久久 | 九九热视频在线免费观看 | 国产欧美高清 | 国产在线综合视频 | 日韩高清国产精品 | 天天操天天干天天综合网 | 在线看污网站 | 五月天com| av黄色av| 成年人免费在线观看 | 一区二区丝袜 | 婷婷丁香在线视频 | 色综合天天色 | 91九色精品女同系列 | 黄色三级久久 | 天天操比 | 久久99亚洲网美利坚合众国 | 日本一区二区不卡高清 | 亚洲美女精品区人人人人 | 国产一区二区免费看 | 成人观看视频 | 黄色的网站免费看 | 国产精品午夜在线观看 | 国产亚洲精品久久久久久久久久 | 在线亚洲午夜片av大片 | 88av色| 69视频在线 | 亚洲国产精品久久久久 | 人人狠狠综合久久亚洲 | 久草免费福利在线观看 | 国产美女精品视频免费观看 | 91激情小视频| 韩国av一区二区三区在线观看 | 九色porny真实丨国产18 | 婷五月激情 | 天天操天天干天天摸 | 99免费观看视频 | 国内精品久久久久久 | 综合久色| 婷婷综合激情 | 亚洲精品激情 | 成人午夜在线观看 | 激情五月婷婷 | 久久精品视频4 | 五月婷婷一区二区三区 | 2024av| 国产精品久久久av久久久 | 天天干天天想 | 狠狠色香婷婷久久亚洲精品 | 久久99精品久久久久久三级 | 国产高清不卡一区二区三区 | 婷婷六月激情 | 黄色av一级| 精品视频免费观看 | 午夜久久影视 | 天干啦夜天干天干在线线 | 五月天久久 | 日日夜夜亚洲 | 国产成人精品福利 | 不卡电影一区二区三区 | 麻豆精品传媒视频 | 808电影免费观看三年 | av在线电影网站 | 国产不卡av在线 | 日韩精品中文字幕在线不卡尤物 | 丁香花在线观看视频在线 | 国产精品久久久久久爽爽爽 | 久久综合精品国产一区二区三区 | 亚洲妇女av | 69精品在线 | 久久久高清 | 国产精品 欧美 日韩 | 国产原创在线观看 | 久久久天天操 | 深爱开心激情网 | 欧美另类高潮 | 国产亚洲视频在线观看 | 亚洲国产精品成人精品 | 免费91在线观看 | 精品久久在线 | 亚洲3级| 97精品伊人 | 免费色视频网址 | 日韩成人av在线 | 伊人资源视频在线 | 香蕉视频国产在线 | 午夜视频在线网站 | 亚洲国产中文字幕在线观看 | 色多多在线观看 | 日本女人在线观看 | 6080yy精品一区二区三区 | 色丁香婷婷 | 国产精品久久久久高潮 | 91精品成人久久 | 最近日本韩国中文字幕 | 五月婷婷视频在线观看 | 久久久久观看 | 免费在线黄色av | 97超碰在线资源 | 色综久久 | 欧美黑人xxxx猛性大交 | 99精品乱码国产在线观看 | 日日干精品 | 蜜臀久久99精品久久久久久网站 | 成人av av在线 | 九色最新网址 | 日产乱码一二三区别免费 | 日韩在线小视频 | 在线a视频免费观看 | 亚洲精品乱码久久久久v最新版 | 人人藻人人澡人人爽 | 91福利社在线观看 | 久久久久久久久久久久久久电影 | 五月花激情| 久久久久欠精品国产毛片国产毛生 | 日韩 在线观看 | 欧美激情视频久久 | 一区二区三区免费在线 | 中文字幕在线观看国产 | 欧美精品亚洲精品 | 欧美污污视频 | 狠狠狠色丁香婷婷综合久久88 | 9999精品视频 | www.色com | 国产97在线视频 | 国产18精品乱码免费看 | 91av欧美 | 成年人免费电影 | 91精品蜜桃 | 日韩视频一区二区在线 | 久久99精品久久久久久秒播蜜臀 | 亚洲精品视频免费在线 | 在线视频日韩欧美 | 一区在线观看视频 | 国产精品 中文在线 | 99久久久久国产精品免费 | 激情久久影院 | adc在线观看 | 日日麻批40分钟视频免费观看 | 综合网在线视频 | 五月婷婷.com| 免费午夜视频在线观看 | 国产精品99久久久精品 | 久久99国产一区二区三区 | 国产精品成人久久 | 天天干天天干天天射 | 久久综合九色综合久久久精品综合 | 999视频在线播放 | 在线视频 日韩 | 欧美精品一区二区性色 | 亚洲精品免费在线播放 | 丁香激情视频 | 中文字幕免费高清 | 香蕉视频在线播放 | 亚洲经典视频在线观看 | 在线观看一区 | www.久久成人 | 波多野结衣在线观看一区二区三区 | 最近中文字幕大全 | 国产看片网站 | 91亚色视频在线观看 | va视频在线观看 | 日本在线视频一区二区三区 | 亚洲综合色网站 | 五月婷婷操 | 亚洲 欧美 国产 va在线影院 | 欧美日韩亚洲在线观看 | 亚洲国产成人精品电影在线观看 | 激情狠狠干 | 99久久精品免费看国产一区二区三区 | 午夜影视一区 | 久久国产精品99久久久久久丝袜 | 91漂亮少妇露脸在线播放 | 亚洲春色综合另类校园电影 | 在线观看视频国产 | 永久免费av在线播放 | 岛国av在线不卡 | 精品国产电影一区 | 一区二区三区在线看 | 国内精品久久久久久 | 国产一区在线视频 | 日本h视频在线观看 | 国产精品第二十页 | 久久精品久久久久久久 | 久久99国产综合精品免费 | 亚洲综合狠狠干 | 一区二区在线电影 | 91香蕉国产在线观看软件 | 日韩色高清 | 亚洲国产免费网站 | 在线中文字幕视频 | 日av免费| 久久免费的精品国产v∧ | 日韩精品一区二区三区免费观看视频 | 婷婷激情站 | 97色涩| 国际精品久久 | 国产精品成人一区 | 国产一区视频在线 | 999久久久免费精品国产 | 亚洲精品ww | 97av.com | 就要干b | 麻豆91在线看 | 在线观看精品 | 国产一级淫片在线观看 | 99精品国产在热久久下载 | 亚洲伊人婷婷 | 国产手机在线 | 国产成人精品免费在线观看 | 天天干天天拍天天操 | 欧美精品在线观看免费 | 日韩三级中文字幕 | 久久国产精品99久久久久久老狼 | 亚洲最大免费成人网 | 久久免费的视频 | 婷婷五综合 | 国产在线观看免费观看 | 日韩视频免费在线 | 91污视频在线观看 | 久久久国产精品免费 | 日韩在线免费视频 | 六月天综合网 | 9797在线看片亚洲精品 | 亚洲天堂网站视频 | 97网在线观看 | 久久久久五月 | 国产精品久久久久久模特 | 偷拍精偷拍精品欧洲亚洲网站 | 亚洲色图美腿丝袜 | 最近久乱中文字幕 | 国产一级视频在线观看 | 色婷婷丁香 | 国产福利一区二区在线 | 三级黄色片在线观看 | 亚洲成av人片在线观看 | 日韩欧美视频一区 | 欧美在线一二 | 激情五月婷婷综合网 | 国产精品久久久久久久久久三级 | 亚洲午夜精品福利 | 国产一区网址 | 亚洲日本一区二区在线 | 欧美精品亚洲精品日韩精品 | 97精品国产97久久久久久免费 | 在线成人欧美 | 91精品秘密在线观看 | 亚洲精品a区 | 日韩视频精品在线 | 在线观看激情av | 午夜av在线播放 | 久久精品国产第一区二区三区 | 美州a亚洲一视本频v色道 | 亚洲在线成人精品 | 色婷婷亚洲综合 | a√国产免费a | 久久久久久美女 | 激情中文在线 | 99精品视频在线观看视频 | 在线观看av麻豆 | 伊人激情网 | 久久理论电影网 | 日本最新一区二区三区 | 免费a视频在线观看 | 青青草国产成人99久久 | 久久视频99 | 国产精品a久久 | 色婷婷久久 | 一区二区中文字幕在线播放 | 精品嫩模福利一区二区蜜臀 | 亚洲精品视频在线播放 | 尤物九九久久国产精品的分类 | 日韩av成人在线 | 亚洲视频免费在线观看 | 久久九九久久 | 四虎影视成人永久免费观看亚洲欧美 | 久久久久久久免费看 | 51久久成人国产精品麻豆 | 69av在线播放 | 精品国产aⅴ麻豆 | 91激情视频在线播放 | 欧美日韩免费观看一区二区三区 | 天天色天天色天天色 | 黄色特级一级片 | 992tv在线成人免费观看 | 97理论片| 国产伦精品一区二区三区四区视频 | 亚洲一区二区视频 | 日韩三区在线观看 | 一区二区三区在线免费 | 国产精品你懂的在线观看 | 天天干,天天射,天天操,天天摸 | 国产高清在线看 | 久久超| 夜色成人av| 精品国产成人av | 国产精品av免费观看 | 欧美日韩在线网站 | 精品在线观看免费 | 日韩成人免费在线观看 | 丁香网婷婷 | 欧美日韩高清一区二区三区 | 欧美一级电影免费观看 | 久久婷婷色| 亚洲婷婷伊人 | 国内精品久久久久久久影视简单 | 日韩理论电影在线 | 天天干天天操天天操 | 国产精品毛片久久久久久久久久99999999 | 亚洲黄色免费电影 | 午夜成人影视 | 久草在线手机观看 | 在线国产日本 | 久久艹艹| 日三级在线 | 手机在线小视频 | 国产精品九九久久99视频 | 91麻豆精品国产91久久久无需广告 | 成人免费网视频 | 91成人免费在线视频 | 国产精品入口a级 | 丝袜+亚洲+另类+欧美+变态 | 色久天| 亚洲综合最新在线 | 免费不卡中文字幕视频 | 毛片网站在线观看 | 99精品国产一区二区三区麻豆 | 天天操天天操天天干 | 丁香婷婷久久 | 欧美精品久久久久久久亚洲调教 | 中文字幕在线视频网站 | 91在线九色| 亚洲涩涩网 | 成人午夜电影在线播放 | 玖玖在线视频观看 | 日日操夜 | 98精品国产自产在线观看 | 色偷偷人人澡久久超碰69 | 毛片3| 成人在线播放免费观看 | 99精品国产兔费观看久久99 | 精品影院一区二区久久久 | 97超碰在线久草超碰在线观看 | 国产精品高潮呻吟久久av无 | 日韩三级av | 美女视频黄在线观看 |