- 在做 WAT 量測後的資料處理時,IDAS 老舊的 VBA macro 執行時間實在過於久,且佔用大量的記憶體,於是就下了一個命題,想減少產生報表的時間。
- 通常量測多片 wafer 的狀況下,不同 wafer 的排列順序是一致的,如果可以加入 Java 中
HashMap
的資料結構來處理 VBA 中 Lookup()
,便可大幅減少 summary table 時,對 rawdata 做搜尋的時間。 - 令時間複雜度從\(O(n)\)進步到\(O(1)\)。
產生 Dictionary 物件#
- 由於 VBA 預設並沒有 Dictionary 的物,所以需要用
CreateObject("Scritping.Dictionary")
的程式碼,引入 Dictionary。 - 其 Dictionary 物件的 method 可參考 Microsoft 的文件:點此
- 在此先預先定義一個 function
setDict()
可以對初始化 Dictionary。 - 接著宣告兩個 Dictionary 物件來存取 spec 和 data 工作頁的列數(row)。
Dim SpecDict As Object ' Claim a dict to store spec rows in worksheet SPEC.
Dim DataDict As Object ' Claim a dict to store rawdata rows in worksheet Data.
Set SpecDict = CreateObject("Scripting.Dictionary")
Set DataDict = CreateObject("Scripting.Dictionary")
Call setDict("SPEC", 3, SpecDict, Worksheets("SPEC").UsedRange, True)
Call setDict("Data", 2, DataDict, Range(Worksheets("Data").Names(1)), True)
實作 setDict() 函數#
- 利用 HashTable 的概念對不同的 parameter 列數先做一次記錄,因為只需一次迴圈,故時間複雜度是 \(O(n)\),其中 n = SPEC 的列數 或是 量測的 parameter 數。
- 在此設計了五個 arguments,方便在未來如果還有使用到 Dictionary 的需求時,可以方便使用。
sheetName
字串,需要作儲存的工作頁(worksheet)。Target
要儲存的列數(row)或欄數(column)。Dict
要存放的 Dictionary 物件。mRange
要做儲存的資料範圍,若表頭並是在第一列或第一欄時可指定。- 若表頭是第一列或第一欄時,可直接代入
Worksheets("工作頁名稱").UsedRange
byRows
看要儲存的對象是列(row)或是欄(column),預設是以列來搜尋。
Public Function setDict(ByVal sheetName As String, ByVal Target As Integer, ByRef Dict As Object, ByVal mRange As Range, Optional ByVal byRows As Boolean = True)
Dim nowSheet As Worksheet
If Not IsExistSheet(sheetName) Then Exit Function
Set nowSheet = Worksheets(sheetName)
Dim i As Long
Dim n As Long
On Error Resume Next
If byRows = True Then
For i = 1 To mRange.Rows.Count
If Not Trim(mRange.Cells(i, Target).Value) = "" Then
Dict.Add mRange.Cells(i, Target).Value, i
End If
Next i
Else
For i = 1 To mRange.Columns.Count
If Not Trim(mRange.Cells(Target, i).Value) = "" Then
Dict.Add mRange.Cells(Target, i).Value, i
End If
Next i
End If
End Function
對 getSPECByPara() 做重製#
- 將 parameter or SPEC 做 hashing 的處理後,可以用 Dictionary 物件來查值,時間複雜度為 \(O(1)\)。
- 在此不對原本的設計做更動,只做單純的 implement。
nowPara
要搜尋的 parameter 字串。n
要搜尋的欄數(column),specColumn是原作者預設的 enum,存放工作頁 SPEC 的每一欄的表頭。sheetName
要搜尋的工作頁,預設為 SPECTEMP,是按完 initial,從 SPEC 工作頁複製出來的隱藏工作頁。
Public Function getSPECByPara(ByVal nowPara As String, ByVal n As specColumn, Optional sheetName As String = "SPECTEMP")
Dim reValue
Dim nowRange As Range
Dim TargetSheet As Worksheet
If Left(nowPara, 1) = "'" Then nowPara = Mid(nowPara, 2)
Set TargetSheet = Worksheets(sheetName)
Set nowRange = TargetSheet.UsedRange
On Error Resume Next
reValue = TargetSheet.Cells(SpecDict(nowPara), n)
If Not IsEmpty(reValue) Then
If Trim(reValue) = "" Then Set reValue = Nothing
End If
getSPECByPara = reValue
End Function
對 getRangeByPara() 做重製#
- 將 parameter or SPEC 做 hashing 的處理後,可以用 Dictionary 物件來查值,時間複雜度為 \(O(1)\)。
Public Function getRangeByPara(nowWafer As String, nowPara As String, Optional dieNum As Integer = 0)
Dim nowRow As Long
Dim nowRange As Range
Set nowRange = Worksheets("Data").Range("wafer_" & nowWafer)
Set getRangeByPara = Nothing
If DataDict.Exists(nowPara) Then
nowRow = DataDict(nowPara)
Set getRangeByPara = nowRange.Range(N2L(4) & CStr(nowRow) & ":" & N2L(dieNum + 3) & CStr(nowRow))
End If
End Function
- 優點:較快的執行速度。經測試可以將 2~3 分鐘的執行時間縮短到 30 秒內。
- 缺點:若修改 rawdata,會發生錯誤。但若針對每一片 wafer 都做 setDict()的話,會浪費太多 memory。