返回列表 上一主題 發帖

[發問] 怎麼在USERFORM中加入可篩選複選之樹狀圖

回復 2# chaoyiho

===Module===
  1. Public vD

  2. Option Explicit
  3. ...
複製代碼
  1. Private Sub Workbook_Open()
  2.     Set vD = CreateObject("Scripting.Dictionary")
  3.     EXCEL表單處理介面.Show vbModeless
  4. End Sub
複製代碼
  1. Private Sub CommandButton1_Click()
  2.     If Application.FindFile = False Then
  3.         MsgBox "您沒有開啟母檔"
  4.     End If

  5.     Dim lRow&
  6.    
  7.     lRow = 3
  8.     vD.RemoveAll
  9.     While Cells(lRow, 1) <> ""
  10.       If Not vD.Exists(CStr(Cells(lRow, 1))) Then
  11.         EXCEL表單處理介面.ListBox1.AddItem CStr(Cells(lRow, 1))
  12.         vD(CStr(Cells(lRow, 1))) = lRow
  13.       End If
  14.       lRow = lRow + 1
  15.     Wend
  16. End Sub
複製代碼
因為時間上來不及, 這裡只做加到 ListBox 的方法,
你可以參照改成動態新增為你要的 CheckBox 元件.

表單處理系統3.2(PLS)-a.zip (614.78 KB)

TOP

本帖最後由 luhpro 於 2016-4-22 23:35 編輯

回復 9# chaoyiho
抱歉,現在才有時間回文.

我之所以會把 vD 的定義放在 Module 上,
原先的構想是資料檔案就那一個,
那麼開始時就讀取一次,
字典建好後面只要拿來用就好了,
不用每按一次按鈕就又要重新讀取檔案及建立對應資料.

習慣性的點兩下 "開啟舊檔" 按鈕開啟 CommandButton1_Click 實做自己的構想,
因為回文後才發現處理 "您沒有開啟母檔" 的 Sub 有好幾個,  O.O"
怕會與之前結果重疊才會加那一行消除前手.

至於你發生的問題,
我在這兩個檔案間操作並不會發生,
因為 RemoveAll 只清除 Key 與 資料 間的對應關係,
並不會刪除 vD 字典物件.
研判可能是操作中程式先後順序問題,
導致你沒有執行到  Set vD = CreateObject("Scripting.Dictionary").

而關於問題的處理:
在 10# 的是一種簡單明瞭的處理方法.
不過依個人之前的經驗,
也有可能是個人功力太差,
我發現 Excel 上並不能用一個 Is Nothing 就包辦所有這類物件錯誤的判斷,
因為這一行指令也可能會出現錯誤(因為連 vD 這個物件都不能出現在判斷式中)

另有一個很多人使用的處理方法,
就是一開始就加個 On Error Resume Next,
這樣遇到錯誤就當做沒問題發生繼續跑下去,
運氣好就沒事...
但要是運氣不好的話...

比較正統且不易出現非預期結果的做法是針對錯誤做專門的處理. (請搜尋 On Error 陳述式 的說明)

Sub ChkFile()
...
    On Error GoTo ErrorHandler    ' 開啟錯誤處理程式。
    vD.RemoveAll ' 發生錯誤需做處理的程式
    On Error Goto 0    ' 關閉錯誤處理程式。
...   
Exit Sub        ' 離開程式,以避免進入錯誤處理程式。

ErrorHandler:    ' 錯誤處理程式。
    Select Case Err.Number    ' 檢查錯誤代碼。
        Case 424    ' 發生「此處需要物件」之錯誤。
            Set vD = CreateObject("Scripting.Dictionary") ' 建立物件。(針對錯誤發生原因做補救或處理)

        Case Else ' 用 Err.number 取得錯誤代碼, 用 Err.Description 取得錯誤說明文字. Err.Clear 清除錯誤旗標
            MsgBox Prompt:=Err.Description, Buttons:=vbOK, Title:="發生錯誤"
            Err.Clear
            Exit Sub
    End Select
    Resume    ' 將程式執行步驟回到原發生錯誤的陳述式中。
End Sub


另外, 針對重複且可替代的程序建議另建立副程式以供呼叫, 如:
Image22_Click
Image3_Click
Image32_Click()
CommandButton1_Click()
CommandButton10_Click()
CommandButton14_Click()
CommandButton6_Click()
的內容全部都是 :

    If Application.FindFile = False Then
        MsgBox "您沒有開啟母檔"
    End If

那就可以把這段歸到 Module 內, 設為 Public, 再個別放入呼叫指令即可.
好處是程式碼容易修改與管理, 縮短程式碼, 辨識度也較好.
  1. Public Sub ChkFile()
  2.     If Application.FindFile = False Then
  3.         MsgBox "您沒有開啟母檔"
  4.     End If

  5.     Dim lRow&
  6.    
  7.     lRow = 3
  8.    
  9.     On Error GoTo ErrorHandler    ' 開啟錯誤處理程式。
  10.     vD.RemoveAll
  11.     EXCEL表單處理介面.ListBox1.Clear ' 清除 ListBox 的選單
  12.     On Error GoTo 0    ' 關閉錯誤處理程式。
  13.    
  14.     While Cells(lRow, 1) <> ""
  15.       If Not vD.Exists(CStr(Cells(lRow, 1))) Then
  16.         EXCEL表單處理介面.ListBox1.AddItem CStr(Cells(lRow, 1))
  17.         vD(CStr(Cells(lRow, 1))) = lRow
  18.       End If
  19.       lRow = lRow + 1
  20.     Wend
  21. Exit Sub        ' 離開程式,以避免進入錯誤處理程式。

  22. ErrorHandler:    ' 錯誤處理程式。
  23.     Select Case Err.Number    ' 檢查錯誤代碼。
  24.    
  25.         Case 424    ' 發生「此處需要物件」之錯誤。
  26.             Set vD = CreateObject("Scripting.Dictionary") ' 建立物件。
  27.             
  28.         Case Else   ' 可用 Err.number 取得錯誤代碼, 用 Err.Description 取得錯誤說明文字. Err.Clear 清除錯誤旗標
  29.             MsgBox prompt:="錯誤代碼 : " & Err.Number & Chr(10) & "錯誤原因:" & Err.Description, Buttons:=vbOK, Title:="發生錯誤"
  30.             Err.Clear
  31.             Exit Sub
  32.     End Select
  33.     Resume    ' 將程式執行步驟回到原發生錯誤的陳述式中。
  34.    
  35. End Sub
複製代碼
  1. Private Sub CommandButton1_Click()
  2.   ChkFile
  3. End Sub
複製代碼
餘類推.

表單處理系統3.2(PLS)-a2.zip (631.5 KB)

TOP

回復 14# jackyq
嗯...
因為我大都是看小幫手與本站自學,
有時忙沒看到的討論串就只能錯失學習了,

在小幫手裡的說明:
Dictionary 物件
  描述
物件,用於儲存資料關鍵字和項目對。
語法
Scripting.Dictionary
請注意
Dictionary 物件與 PERL 相關陣列全等。可以是任何型式的資料的項目被儲存在陣列中。每個項目都與一個唯一的關鍵字相關。該關鍵字用來取出單個項目,通常是整數或字串,可以是除陣列外的任何型態。
下面的程式碼舉例說明了如何建立一個 Dictionary 物件:

Dim d                   '建立一個變數
Set d = CreateObject(Scripting.Dictionary)
d.Add "a", "Athens"     '加入一些關鍵字和項目
d.Add "b", "Belgrade"d.Add "c", "Cairo"
...


所以,我一直學到的都是 Dictionary 物件要用 Variant 資料型態 來宣告,
早先為了解決類似的錯誤, Is Nothing, Is Null, = Null, .... 試了一堆方法耗時挫折,
後來乖乖的用 錯誤處理程式 處理才順利,
謝謝分享指正.

TOP

本帖最後由 luhpro 於 2016-4-25 22:56 編輯
回復  luhpro
...
加上我因為權限的關係無法下載附檔
...
chaoyiho 發表於 2016-4-25 19:19

咦?
剛剛查了本網站的說明 小學生有 "下載/查看附件" 的權限耶,
你不能嗎?



提供另一個下載點 :
http://www.FunP.Net/695648

我的問題主要有兩個
1.嘗試前輩上面的程式碼 可能因為不知道該放哪邊而造成錯誤進而無法執行

如附網址的檔案,
試試看若有問題再提出.

2.關於重複動作的程式碼縮減

主要是把重複的程式碼獨立出來放在 Module 內,
以 Public Sub 被呼叫程序名()   做開頭(如此整個檔案都能呼叫此程序),
在確保每個呼叫點都不會因改成此呼叫而走樣的情形下,
以呼叫此程序的程式碼取代原重複的程式碼.

好處是易於維護與偵錯,
之後修改程式只需變動此程序內容,
中斷點也只要設在此程序內即可.
不用一個一個去尋找及修改程式碼或設中斷點.

TOP

        靜思自在 : 道德是提昇自我的明燈,不該是呵斥別人的鞭子。
返回列表 上一主題