Compile function NDW_GAN_RETAIN_MANAGER_SEARCH_EDIT_EVENTS(CtrlEntId, Event, @PARAMS) /*********************************************************************************************************************** Name : NDW_GAN_RETAIN_MANAGER_SEARCH_EDIT_EVENTS Description : Commuter module for the NDW_GAN_RETAIN_MANAGER_SEARCH_EDIT form. Notes : Application errors should be logged using the Error Services module. There are a few methodological assumptions built into way errors are managed which are important to understand in order to properly work with Error Services: - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger this will appear backwards since the originating procedure always appears at the bottom of the list and the current routine appears at the top of the list. We are using this orientation because it is common to refer to the process of calling other procedures as 'drilling down'. - The reason for defining the orientation of the call stack is because Error_Services allows for multiple error conditions to be appended to an original error. In most cases this will happen when a procedure at the bottom of the stack generates an error condition and then returns to its calling procedure. This higher level procedure can optionally add more information relevant to itself. This continues as the call stack 'bubbles' its way back to the top to where the originating procedure is waiting. - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus) preserve their error state until explicitly cleared. This can hinder the normal execution of code since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists. Our philosophy is that error conditions should automatically be cleared before a new procedure is executed to avoid this problem. However, the nature of Basic+ does not make this easy to automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our philosophy then it should include a call into the 'Clear' service request at the top of the program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.) - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any error conditions that were set before. Parameters : Service [in] -- Name of the service being requested Param1-10 [in/out] -- Additional request parameter holders Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure Metadata : History : (Date, Initials, Notes) 03/27/20 cn Original programmer. 06/23/20 cn Deployed filtering logic to production ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler #window NDW_GAN_RETAIN_MANAGER_SEARCH_EDIT $Insert LOGICAL $Insert APPCOLORS $Insert RETAINED_WAFERS_EQUATES $Insert MSG_EQUATES // Control Name equates Equ SearchTable$ To @Window : '.OLE_EDT_SEARCH' Equ BreadcrumbBar$ To @Window : '.OLE_BREADCRUMBBAR' Equ StatusBar$ To @Window : '.OLE_STATUSBAR' // OLE Edit Table Columns Equ RUN_ID$ To 1 Equ RECIPE$ To 2 Equ POCKET$ To 3 Equ SCRIBE$ To 4 Equ GRADE$ To 5 Equ PART$ To 6 Equ WO_NO$ To 7 Equ RETAIN_BOX$ To 8 Equ RETAIN_SLOT$ To 9 Equ RETAIN_LOC$ To 10 Equ STATUS$ To 11 Equ COMMENT$ To 12 Equ OPERATOR$ To 13 Equ RETAIN_DATE$ To 14 Equ DESTROY_SIG$ To 15 Equ DESTROY_DATE$ To 16 Equ WAFER_ID$ To 17 // Reduce modes (for Select statement) Equ NEW_EXIST$ To 0 Equ NEXT_CUR$ To 1 Equ ADD_EXIST$ To 2 // Carriage Return and Line Feed for CSV report EQU CRLF$ TO \0D0A\ Declare Function Form_Services, Get_Property, Utility, Database_Services, Error_Services, Send_Message Declare Function Memory_Services, Create_Dialog, Dialog_Box, SRP_FastArray, SRP_Array, Msg Declare Function Retain_Manager_Services, SRP_Trim, SRP_BreadcrumbBar, Gan_Services, DateTime, SRP_Run_Command Declare Subroutine SRP_Show_Window, Set_Property, Send_Message, Post_Event, Reduce, FSMsg, Btree.Extract Declare Subroutine SRP_Stopwatch, SRP_Edittable_Manager, Error_Services, Memory_Services, Utility, SRP_FastArray Declare Subroutine SRP_BreadcrumbBar, SRP_Set_MinMaxInfo, OConv, Form_Services SubclassInfo = Form_Services('FindSubclassControl') Subclass = SubclassInfo<1> If Assigned(Param8) else Param8 = '' If Event EQ 'OLE' then Transfer Event to OIEvent Transfer Param1 to Event Transfer Param2 to Param1 Transfer Param3 to Param2 Transfer Param4 to Param3 Transfer Param5 to Param4 Transfer Param6 to Param5 Transfer Param7 to Param6 Transfer Param8 to Param7 end Type = Get_Property(CtrlEntId, 'TYPE') If Type EQ 'RADIOBUTTON' then Convert ' ' to '_' in CtrlEntID end GoToEvent Event for CtrlEntId else // Event not implemented end Return EventFlow or 1 //----------------------------------------------------------------------------- // EVENT HANDLERS //----------------------------------------------------------------------------- Event WINDOW.CREATE(CreateParam) GoSub SetupOLEControls Set_Property(@Window, 'TIMER', 30000 : @FM : 30000) SRP_Set_MinMaxInfo(@Window, 'DEF', 'DEF', 'DEF') SRP_Show_Window(@Window, '', 'C', 'C', 1, '', False$, False$, '', 1) End Event Event WINDOW.TIMER() GoSub UpdateServiceLastRunTime end event Event WINDOW.CLOSE(CancelFlag) Memory_Services('RemoveKey', 'SelectedFilterItems') Memory_Services('RemoveKey', 'Cell_Size') Memory_Services('RemoveKey', 'AllowFilter') SRP_BreadcrumbBar(BreadcrumbBar$, 'Close') end event Event PUB_UPDATE.CLICK() GoSub UpdateWaferDetails GoSub UpdateCachedDataValues end event Event RAG_WAFER_TYPE.150_MM_6_IN.CLICK() Event RAG_WAFER_TYPE.200_MM_8_IN.CLICK() Event CHB_SHOW_DESTROYED.CLICK() Form_Services('DisplayWaitScreen', '', 'Refreshing Data') Set_Property(SearchTable$, 'OLE.Redraw', False$) Gosub ClearData GoSub LoadSearchData GoSub ResetFocusToBottomRow Set_Property(SearchTable$, 'OLE.Redraw', True$) Form_Services('CloseWaitScreen') end event Event PUB_EXPORT.CLICK() GoSub ExportWaferReport end event Event PUB_CLIPBOARD.CLICK() ReportHeaderArrray = '' ReportRowArrray = '' HeaderCounter = '' HeaderArray = Get_Property(SearchTable$, 'OLE.TitleList') CurrentWaferArray = Get_Property(SearchTable$, 'OLE.ARRAY') For Each Header In HeaderArray using @VM HeaderCounter += 1 HeaderVisibility = Get_Property(SearchTable$, 'OLE.DataColumn[' : HeaderCounter : ']')<2> If HeaderVisibility EQ True$ then ReportHeaderArrray := Header : @VM ReportRowArrray := CurrentWaferArray : @FM end Next Header ReportHeaderArrray[-1, 1] = '' ReportRowArrray[-1, 1] = '' ReportRowArrray = SRP_Array('Rotate', ReportRowArrray, @FM, @VM) FullReport = ReportHeaderArrray : @FM : ReportRowArrray Swap @VM with CHAR(9) in FullReport Swap @FM with CRLF$ in FullReport Set_Property('CLIPBOARD', 'TEXT', FullReport) Message = '' Message = 'Search data has been copied to clipboard.' Message = 'BO' Status = Msg(@Window, Message) end event Event OLE_EDT_SEARCH.OnHeaderClick(Cell, Point, Button, Shift, Ctrl) Set_Property(SearchTable$, 'OLE.Redraw', False$) FilterOptions = '' CellxPos = Cell[1, ';'] CellyPos = Cell[Col2() + 1, ';'] // Remove 1 cell position due to the hidden header column CellSize = Send_Message(SearchTable$, "OLE.GetCellRect", (CellxPos - 1) : ';' CellyPos) Memory_Services('SetValue', 'Cell_Size', CellSize) Begin Case Case Button EQ 'Left' Header = Get_Property(SearchTable$, 'HeaderText[' : Cell : ']') ColumnPos = CellxPos - 1 AllowedFilters = Get_Property(@Window, '@ALLOWEDFILTERS') // Check to see if the current active segment is equal to the header. If not, set a flag so we don't // allow the user to save new filters against an existing header. Only the current active segment can // receive new filter items. Locate Header in AllowedFilters using @VM setting pos then SegmentKey = SRP_BreadcrumbBar(BreadcrumbBar$, 'GetActiveSegment') Convert '-' to @FM in SegmentKey // Create a segment key to keep track of existing filters and results. Locate Header in SegmentKey using @FM setting dummypos then TotalSegments = Count(SegmentKey, @FM) + 1 LastSegment = SegmentKey If Header EQ LastSegment then Memory_Services('SetValue', 'AllowFilter', True$) end else Memory_Services('SetValue', 'AllowFilter', Fasle$) end end else SegmentKey = SegmentKey : @FM : Header Memory_Services('SetValue', 'AllowFilter', True$) end Convert @FM to '-' in SegmentKey SegmentExists = SRP_Breadcrumbbar(BreadcrumbBar$, 'SegmentExists', SegmentKey) If SegmentExists EQ False$ then // Build Filter Options FilterArray = Get_Property(SearchTable$, 'OLE.ColumnData[' : ColumnPos : ']') Swap @VM with @FM in FilterArray FilterArray = SRP_Array('SortSimpleList', FilterArray, 'AscendingText', @FM) FilterArray = SRP_Array('Clean', FilterArray, 'TrimAndMakeUnique') FormattedFilterArray = '' // Build filter list in SRP Tree Control format For Each Filter in FilterArray using @FM FormattedFilterArray := 1 : @VM : SRP_Trim(Filter, 'FA', '0') : @VM : Filter : @VM : @VM : @VM : @VM : @VM : @VM : @VM : @VM : 'Left' : @VM : @FM Next FilterArray // Place all filter options into memory using SegmentKey for reference Set_Property(@Window, '@' : SegmentKey : '*FORMATTEDFILTERARRAY', FormattedFilterArray) DataList = Get_Property(SearchTable$, 'OLE.ARRAY') Set_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST', DataList) // Set PreviousSelectedFilters to null as this is a new segment PreviousSelectedFilters = '' end else UnfilteredDataList = Get_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST') FilteredDataList = Get_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST') FormattedFilterArray = Get_Property(@Window, '@' : SegmentKey : '*FORMATTEDFILTERARRAY') PreviousSelectedFilters = Get_Property(@Window, '@' : SegmentKey : '*PREVIOUSSELECTEDFILTERS') end // Set SelectedFilterItems in memory services to NDW_Tree_Filter can display them Memory_Services('SetValue', 'SelectedFilterItems', PreviousSelectedFilters) // Call the Tree_Filter Window and place it under the column header. Pass in Tree Control formatted list SelectedFilterItems = Dialog_Box('NDW_TREE_FILTER', @Window, FormattedFilterArray) CurrentActiveSegment = SRP_BreadcrumbBar(BreadcrumbBar$, 'GetActiveSegment') If SelectedFilterItems NE 'Cancel' then Set_Property(@Window, '@' : SegmentKey : '*PREVIOUSSELECTEDFILTERS', SelectedFilterItems) Begin Case Case SegmentExists EQ True$ AND SelectedFilterItems EQ '' SRP_Breadcrumbbar(BreadcrumbBar$, 'RemoveSegment', SegmentKey, True$) // Load parent's cached data into FilteredDataList CurrentActiveSegment = SRP_BreadcrumbBar(BreadcrumbBar$, 'GetActiveSegment') CachedDataHandle = SRP_Breadcrumbbar(BreadcrumbBar$, 'GetSegmentMisc', CurrentActiveSegment) DataList = Get_Property(@Window, CachedDataHandle) Case SegmentExists EQ True$ SRP_BreadcrumbBar(BreadcrumbBar$, 'SetActiveSegment', Header) DataList = Get_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST') Case SelectedFilterItems NE '' SRP_BreadcrumbBar(BreadcrumbBar$, 'AddSegment', SegmentKey : @VM : Header : @VM : '@' : SegmentKey : '*FILTEREDDATALIST', CurrentActiveSegment, True$) Case Otherwise$ End Case DataList = SRP_Array('Rotate', DataList, @FM, @VM) DataListHandle = SRP_FastArray('Create', DataList) FilteredDataList = Retain_Manager_Services('UpdateRetainList', DataListHandle, SelectedFilterItems) Set_Property(SearchTable$, 'OLE.ARRAY', FilteredDataList) Set_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST', FilteredDataList) GoSub ResetFocusToBottomRow end end else Error_Services('Set' , 'Filtering not allowed on this column.') Error_Services('DisplayError', 'C') end End Case SRP_FastArray("Release", DataListHandle) Set_Property(SearchTable$, 'OLE.Redraw', True$) end event Event OLE_BREADCRUMBBAR.OnSegmentClick(CurrentCell) Set_Property(SearchTable$, 'OLE.Redraw', False$) PrevActiveSegment = SRP_Breadcrumbbar(BreadcrumbBar$, 'GetPrevActiveSegment') If CurrentCell NE PrevActiveSegment then FieldCount = DCount(PrevActiveSegment, '-') SegmentKey = Field(PrevActiveSegment, '-', 1, FieldCount) Loop Set_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST', '') Set_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST', '') Set_Property(@Window, '@' : SegmentKey : '*FORMATTEDFILTERARRAY', '') Set_Property(@Window, '@' : SegmentKey : '*PREVIOUSSELECTEDFILTERS', '') Fieldcount = FieldCount-1 SegmentKey = Field(PrevActiveSegment, '-', 1, FieldCount) Until SegmentKey EQ CurrentCell Repeat SRP_Breadcrumbbar(BreadcrumbBar$, 'RemoveAllChildrenSegments', CurrentCell, True$) // Display Cached Data CachedDataHandle = SRP_Breadcrumbbar(BreadcrumbBar$, 'GetSegmentMisc', SegmentKey) CachedHeaderData = Get_Property(@Window, CachedDataHandle) Set_Property(SearchTable$, 'OLE.ARRAY', CachedHeaderData) GoSub ResetFocusToBottomRow end Set_Property(SearchTable$, 'OLE.Redraw', True$) end event Event OLE_EDT_SEARCH.OnClick(Cell, Point, Button, Shift, Ctrl) If Button EQ 'Right' then Menu = '' ColPos = Cell[1, ';'] RowPos = Cell[Col2() + 1, ';'] RetainBox = Get_Property(SearchTable$, 'OLE.CellText[' : RETAIN_BOX$ : ';' : RowPos : ']') Menu<-1> = 'Warehouse' : @VM : 'Set location to Warehouse for all wafers in box ' : RetainBox : @VM : 1 Menu<-1> = 'Cleanroom' : @VM : 'Set location to Cleanroom for all wafers in box ' : RetainBox : @VM : 1 Send_Message(SearchTable$, 'OLE.ShowContextMenu', Point, Menu, RetainBox) end end event Event OLE_EDT_SEARCH.OnContextMenuClick(Item, UserData) Form_Services('DisplayWaitScreen', '', 'Relocating Wafers') Set_Property(SearchTable$, 'OLE.Redraw', False$) Location = Item RetainedBox = UserData CurrentViewWaferArray = Get_Property(SearchTable$, 'OLE.ARRAY') MasterRetainWaferList = Get_Property(@Window, '@MASTERRETAINWAFERLIST') // Update data in MasterRetainWaferList cache For Each Wafer in MasterRetainWaferList using @VM setting WaferPos then If RetainedBox EQ MasterRetainWaferList then WaferID = MasterRetainWaferList Status = MasterRetainWaferList Comment = MasterRetainWaferList Response = Gan_Services('UpdateRetainedWaferDetails', WaferID, Location, Status, Comment) MasterRetainWaferList = Location Set_Property(@Window, '@MASTERRETAINWAFERLIST', MasterRetainWaferList) end Next Wafer // Update current display in SearchTable$ For Each Wafer in CurrentViewWaferArray using @VM setting WaferPos then If RetainedBox EQ CurrentViewWaferArray then Set_Property(SearchTable$, 'OLE.CellText[' : RETAIN_LOC$ :';' : WaferPos : ']', Location) end Next Wafer // Update data in filter caches PrevActiveSegment = SRP_Breadcrumbbar(BreadcrumbBar$, 'GetActiveSegment') FieldCount = DCount(PrevActiveSegment, '-') SegmentKey = Field(PrevActiveSegment, '-', 1, FieldCount) Loop UnFilteredDataList = Get_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST') For Each Wafer in UnFilteredDataList using @VM setting WaferPos then If RetainedBox EQ UnFilteredDataList then UnFilteredDataList = Location Set_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST', UnFilteredDataList) end Next Wafer FilteredDataList = Get_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST') For Each Wafer in FilteredDataList using @VM setting WaferPos then If RetainedBox EQ FilteredDataList then FilteredDataList = Location Set_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST', FilteredDataList) end Next Wafer Fieldcount = FieldCount-1 SegmentKey = Field(PrevActiveSegment, '-', 1, FieldCount) Until SegmentKey EQ 'RootKey' Repeat GoSub LoadWaferDetails Set_Property(SearchTable$, 'OLE.Redraw', True$) Form_Services('CloseWaitScreen') end event Event OLE_EDT_SEARCH.PosChanged(Cell, PrevCell, Button, RepeatCount) PrevColPos = PrevCell[1, ';'] PrevRowPos = PrevCell[Col2() + 1, ';'] ColPos = Cell[1, ';'] RowPos = Cell[Col2() + 1, ';'] If PrevRowPos NE RowPos then GoSub LoadWaferDetails end end event Event COB_STATUS.CHANGED(NewData) OldStatus = Get_Property(@Window, '@WAFERSTATUS') NewStatus = NewData Location = Get_Property(@Window : '.COB_LOCATION', 'TEXT') If Location EQ 'Wafer Destroyed' AND NewStatus EQ 'Do Not Destroy' then Message = '' Message = 'Cannot set Status to "Do Not Destroy" when Location is "Wafer Destroyed".' Message = 'BO' Status = Msg(@Window, Message) Set_Property(@Window : '.COB_STATUS', 'TEXT', OldStatus) end end event Event COB_LOCATION.CHANGED(NewData) OldLocation = Get_Property(@Window, '@WAFERLOCATION') NewLocation = NewData Status = Get_Property(@Window : '.COB_STATUS', 'TEXT') If Status EQ 'Do Not Destroy' AND NewLocation EQ 'Wafer Destroyed' then Message = '' Message = 'Cannot set Location to "Wafer Destroyed" when Status is "Do Not Destroy".' Message = 'BO' Status = Msg(@Window, Message) Set_Property(@Window : '.COB_LOCATION', 'TEXT', OldLocation) end end event //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SetupOLEControls: Set_Property(@Window : '.STA_DESTROYED_SIGN', 'VISIBLE', False$) Set_Property(@Window : '.EDL_DESTROYED_SIGN', 'VISIBLE', False$) Set_Property(@Window : '.STA_DESTROYED_DATE', 'VISIBLE', False$) Set_Property(@Window : '.EDL_DESTROYED_DATE', 'VISIBLE', False$) // Recreating EditTable format using SRP_EditTable_Manager for better control ArrayDimension = 17 : @FM : 50 TitleList = 'Run ID' : @VM : 'Recipe' : @VM : 'Pocket' : @VM : 'Scribe' : @VM : 'Grade' : @VM : 'Part' : @VM ColumnWidths = '80' : @FM : '160' : @FM : '55' : @FM : '70' : @FM : '50' : @FM : '120' : @FM ColumnAlignments = 'L' : @FM : 'L' : @FM : 'C' : @FM : 'C' : @FM : 'C' : @FM : 'L' : @FM TitleList := 'WO' : @VM : 'Retain Box' : @VM : 'Slot' : @VM : 'Location' : @VM : 'Status' : @VM : 'Comment' : @VM ColumnWidths := '45' : @FM : '75' : @FM : '40' : @FM : '100' : @FM : '105' : @FM : 'A' : @FM ColumnAlignments := 'C' : @FM : 'C' : @FM : 'C' : @FM : 'L' : @FM : 'L' : @FM : 'L' : @FM TitleList := 'Retained Sign' : @VM : 'Retain Date' : @VM : 'Destroy Sign' : @VM : 'Destroy Date' : @VM : 'Wafer ID' ColumnWidths := '90' : @FM : '80' : @FM : '85' : @FM : '85' : @FM : '' ColumnAlignments := 'C' : @FM : 'C' : @FM : 'C' : @FM : 'C' : @FM : 'C' VirtualPos = '' RowsAsColumns = '' CellsAsFields = '' ClearFill = '' OIEditTable = '' SRP_EditTable_Manager('Setup1', SearchTable$, ArrayDimension, TitleList, ColumnWidths, ColumnAlignments, VirtualPos, RowsAsColumns, CellsAsFields, ClearFill, OIEditTable) Set_Property(SearchTable$, 'OLE.SelectionStyle', 'Black' : @VM : OI_HOT_BLUE$ : ' L=70' : @FM : 'Black' : @VM : OI_HOT_BLUE$) ; // Automatically highlight the current row with one color and highlight the current row with another color. Set_Property(SearchTable$, 'OLE.HeaderFont[All; All]', 'Segoe UI' : @SVM : 8) Set_Property(SearchTable$, 'OLE.CellFont[All; All]', 'Segoe UI' : @SVM : 8) Set_Property(SearchTable$, 'OLE.HeaderColumn[1]', '' : @FM : False$ : @FM : False$ : @FM) Set_Property(SearchTable$, 'OLE.CellProtection[ALL; All]', 'SEL') Set_Property(SearchTable$, 'OLE.NewRowCount', 0) Set_Property(SearchTable$, 'OLE.HeaderRow[ALL]', '' : @FM : '' : @FM : False$ : @FM) Set_Property(SearchTable$, 'OLE.DataColumn[ALL]', '' : @FM : '' : @FM : False$ : @FM) Set_Property(SearchTable$, 'OLE.DataRow[ALL]', '' : @FM : '' : @FM : False$ : @FM) Set_Property(SearchTable$, 'OLE.HeaderColors[All; All]', 'Auto' : @FM : 'None' : @FM : 'None' : @FM : OI_HOT_BLUE$ : @FM : False$) Set_Property(SearchTable$, 'OLE.ResetSelPos', False$) // Add drop down arrows to columns Set_Property(SearchTable$, 'OLE.HeaderArrow[All; 1]', 'Down') // Remove columns that do not allow filtering. // Note: Add one column value due to HeaderArrow property picking up the hidden first column. Set_Property(SearchTable$, 'OLE.HeaderArrow[' : RETAIN_SLOT$ + 1 : '; 1]', '') Set_Property(SearchTable$, 'OLE.HeaderArrow[' : STATUS$ + 1 : '; 1]', '') Set_Property(SearchTable$, 'OLE.HeaderArrow[' : COMMENT$ + 1 : '; 1]', '') Set_Property(SearchTable$, 'OLE.AllowDeletions', False$) Set_Property(SearchTable$, 'OLE.AllowInserts', False$) // Begin with hidden destroyed sig and date Set_Property(SearchTable$, 'OLE.DataColumn[' : DESTROY_SIG$ : ']', '' : @FM : False$) Set_Property(SearchTable$, 'OLE.DataColumn[' : DESTROY_DATE$ : ']', '' : @FM : False$) Set_Property(SearchTable$, 'OLE.DataColumn[' : WAFER_ID$ : ']', '' : @FM : False$) Set_Property(SearchTable$, 'OLE.SelectionStyle', '' : @FM : '' : @FM : '' : @FM : '' : @FM : '' : @FM : '' : @FM : '' : @FM : True$ : @FM) // Qualify OLE events that we want to intercept Qualifier = '' Qualifier<1> = 1 Qualifier<4> = 0 ; * process synchronously (i.e. immediately) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.AfterUpdate', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnButtonClick', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.PosChanged', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnComboClicked', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnHeaderClick', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnCheckChanged', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.AfterUpdate', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnContextMenuClick', Qualifier) Send_Message(SearchTable$, 'QUALIFY_EVENT', 'OLE.OnDblClick', Qualifier) // Configure columns that have filtering requirements AllowedFilters = 'Run ID' : @VM : 'Recipe' : @VM : 'Pocket' : @VM : 'Scribe' : @VM : 'Grade' : @VM : 'Part' : @VM AllowedFilters := 'WO' : @VM : 'Retain Box' : @VM : 'Retained Sign' : @VM : 'Retain Date' : @VM : 'Location' Set_Property(@Window, '@ALLOWEDFILTERS', AllowedFilters) SRP_BreadcrumbBar(BreadcrumbBar$, 'Init', SystemFont$) GoSub UpdateWaferStatistics Set_Property(StatusBar$, 'OLE.PaneCount', 1) Set_Property(StatusBar$, 'OLE.Resizable', False$) Set_Property(StatusBar$, 'OLE.PaneType[1]', 'NOR') GoSub UpdateServiceLastRunTime Set_Property(SearchTable$, 'OLE.Redraw', False$) GoSub LoadSearchData Set_Property(SearchTable$, 'OLE.Redraw', True$) return LoadSearchData: WaferSize = Get_Property(@Window : '.RAG_WAFER_TYPE', 'VALUE') ShowDestroyed = Get_Property(@Window : '.CHB_SHOW_DESTROYED', 'CHECK') WaferList = Retain_Manager_Services('GetWaferDataWithFilter', WaferSize, ShowDestroyed) WaferList<14> = OConv(WaferList<14>, 'D2/') WaferList<16> = OConv(WaferList<16>, 'D2/') WaferList = SRP_Array('SortRows', WaferList, 'AN8' : @FM : 'DN9') Set_Property(SearchTable$, 'OLE.ARRAY', WaferList) GoSub ResetFocusToBottomRow // Save the whole retain list to global variable for later reference by primary filter Set_Property(@Window, '@MASTERRETAINWAFERLIST', WaferList) SRP_BreadcrumbBar(BreadcrumbBar$, 'AddSegment', 'RootKey' : @VM : 'All Data' : @VM : '@MASTERRETAINWAFERLIST', '', True$) // Set Destroy Signature and Destroy Date columns based off of Show Destroyed checkbox Set_Property(SearchTable$, 'OLE.DataColumn[' : DESTROY_SIG$ : ']', '' : @FM : ShowDestroyed) Set_Property(SearchTable$, 'OLE.DataColumn[' : DESTROY_DATE$ : ']', '' : @FM : ShowDestroyed) Set_Property(@Window : '.STA_DESTROYED_SIGN', 'VISIBLE', ShowDestroyed) Set_Property(@Window : '.EDL_DESTROYED_SIGN', 'VISIBLE', ShowDestroyed) Set_Property(@Window : '.STA_DESTROYED_DATE', 'VISIBLE', ShowDestroyed) Set_Property(@Window : '.EDL_DESTROYED_DATE', 'VISIBLE', ShowDestroyed) return UpdateWaferDetails: Set_Property(SearchTable$, 'OLE.Redraw', False$) WaferID = Get_Property(@Window :'.EDL_WAFER_ID', 'TEXT') Location = Get_Property(@Window :'.COB_LOCATION', 'TEXT') Status = Get_Property(@Window :'.COB_STATUS', 'TEXT') Comment = Get_Property(@Window :'.EDB_COMMENTS', 'TEXT') Response = Gan_Services('UpdateRetainedWaferDetails', WaferID, Location, Status, Comment) CurrentCellyPos = Get_Property(SearchTable$, 'OLE.SelPos')<2> Set_Property(SearchTable$, 'OLE.CellText[' : RETAIN_LOC$ :';' : CurrentCellyPos : ']', Location) Set_Property(SearchTable$, 'OLE.CellText[' : STATUS$ :';' : CurrentCellyPos : ']', Status) Set_Property(SearchTable$, 'OLE.CellText[' : COMMENT$ :';' : CurrentCellyPos : ']', Comment) If Location EQ 'Wafer Destroyed' then Set_Property(SearchTable$, 'OLE.CellText[' : DESTROY_SIG$ :';' : CurrentCellyPos : ']', @User4) Set_Property(SearchTable$, 'OLE.CellText[' : DESTROY_DATE$ :';' : CurrentCellyPos : ']', OConv(Date(), 'D2/')) end Set_Property(SearchTable$, 'OLE.Redraw', True$) return LoadWaferDetails: CellPos = Get_Property(SearchTable$, 'OLE.SelPos') ColPos = CellPos<1> RowPos = CellPos<2> // Load RunID data to wafer details area RunID = Get_Property(SearchTable$, 'OLE.CellText[' : RUN_ID$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_RUN_ID', 'TEXT', RunID) // Load Recipe data to wafer details area Recipe = Get_Property(SearchTable$, 'OLE.CellText[' : RECIPE$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_RECIPE', 'TEXT', Recipe) // Load Pocket data to wafer details area Pocket = Get_Property(SearchTable$, 'OLE.CellText[' : POCKET$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_POCKET', 'TEXT', Pocket) // Load Scribe data to wafer details area Scribe = Get_Property(SearchTable$, 'OLE.CellText[' : SCRIBE$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_SCRIBE', 'TEXT', Scribe) // Load Grade data to wafer details area Grade = Get_Property(SearchTable$, 'OLE.CellText[' : GRADE$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_GRADE', 'TEXT', Grade) // Load Part data to wafer details area Part = Get_Property(SearchTable$, 'OLE.CellText[' : PART$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_PART', 'TEXT', Part) // Load WO data to wafer details area WO = Get_Property(SearchTable$, 'OLE.CellText[' : WO_NO$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_WO', 'TEXT', WO) // Load RetainBox data to wafer details area RetainBox = Get_Property(SearchTable$, 'OLE.CellText[' : RETAIN_BOX$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_RETAIN_BOX', 'TEXT', RetainBox) // Load Slot data to wafer details area Slot = Get_Property(SearchTable$, 'OLE.CellText[' : RETAIN_SLOT$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_SLOT', 'TEXT', Slot) // Load Retained Sign data to wafer details area RetainedSign = Get_Property(SearchTable$, 'OLE.CellText[' : OPERATOR$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_RETAINED_SIGN', 'TEXT', RetainedSign) // Load Retain Date data to wafer details area RetainedDate = Get_Property(SearchTable$, 'OLE.CellText[' : RETAIN_DATE$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_RETAINED_DATE', 'TEXT', RetainedDate) // Load Destroy Sign data to wafer details area DestroyedSign = Get_Property(SearchTable$, 'OLE.CellText[' : DESTROY_SIG$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_DESTROYED_SIGN', 'TEXT', DestroyedSign) // Load Destroy Date data to wafer details area DestroyedDate = Get_Property(SearchTable$, 'OLE.CellText[' : DESTROY_DATE$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_DESTROYED_DATE', 'TEXT', DestroyedDate) // Load Location data to wafer details area Location = Get_Property(SearchTable$, 'OLE.CellText[' : RETAIN_LOC$ :';' : RowPos : ']') Set_Property(@Window :'.COB_LOCATION', 'TEXT', Location) // Store Location for comparison when updating wafer details Set_Property(@Window, '@WAFERLOCATION', Location) // Load Status data to wafer details area Status = Get_Property(SearchTable$, 'OLE.CellText[' : STATUS$ :';' : RowPos : ']') Set_Property(@Window :'.COB_STATUS', 'TEXT', Status) // Store Status for comparison when updating wafer details Set_Property(@Window, '@WAFERSTATUS', Status) // Load Comment data to wafer details area Comment = Get_Property(SearchTable$, 'OLE.CellText[' : COMMENT$ :';' : RowPos : ']') Set_Property(@Window :'.EDB_COMMENTS', 'TEXT', Comment) // Load Comment data to wafer details area WaferID = Get_Property(SearchTable$, 'OLE.CellText[' : WAFER_ID$ :';' : RowPos : ']') Set_Property(@Window :'.EDL_WAFER_ID', 'TEXT', WaferID) return UpdateWaferStatistics: // Cleanroom Location WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_6IN') ListHandle = SRP_FastArray('Create', WaferList) Filter = 'Cleanroom' CleanroomRetained6in = Retain_Manager_Services('GetWaferCount', ListHandle, Filter) Set_Property(@Window : '.EDL_RETAINED_CLEANROOM_6IN', 'TEXT', CleanroomRetained6in) WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_8IN') ListHandle = SRP_FastArray('Create', WaferList) Filter = 'Cleanroom' CleanroomRetained8in = Retain_Manager_Services('GetWaferCount', ListHandle, Filter) Set_Property(@Window : '.EDL_RETAINED_CLEANROOM_8IN', 'TEXT', CleanroomRetained8in) TotalCleanroom = CleanroomRetained6in + CleanroomRetained8in Set_Property(@Window : '.EDL_CLEANROOM_TOTAL', 'TEXT', TotalCleanroom) // Warehouse Location WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_6IN') ListHandle = SRP_FastArray('Create', WaferList) Filter = 'Warehouse' WarehouseRetained6in = Retain_Manager_Services('GetWaferCount', ListHandle, Filter) Set_Property(@Window : '.EDL_RETAINED_WAREHOUSE_6IN', 'TEXT', WarehouseRetained6in) WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_8IN') ListHandle = SRP_FastArray('Create', WaferList) Filter = 'Warehouse' WarehouseRetained8in = Retain_Manager_Services('GetWaferCount', ListHandle, Filter) Set_Property(@Window : '.EDL_RETAINED_WAREHOUSE_8IN', 'TEXT', WarehouseRetained8in) TotalWarehouse = WarehouseRetained6in + WarehouseRetained8in Set_Property(@Window : '.EDL_WAREHOUSE_TOTAL', 'TEXT', TotalWarehouse) // Wafer Destroyed Total WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_6IN') ListHandle = SRP_FastArray('Create', WaferList) Filter = 'Wafer Destroyed' Destroyed6in = Retain_Manager_Services('GetWaferCount', ListHandle, Filter) Set_Property(@Window : '.EDL_DESTROYED_6IN', 'TEXT', Destroyed6in) WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_8IN') ListHandle = SRP_FastArray('Create', WaferList) Filter = 'Wafer Destroyed' Destroyed8in = Retain_Manager_Services('GetWaferCount', ListHandle, Filter) Set_Property(@Window : '.EDL_DESTROYED_8IN', 'TEXT', Destroyed8in) TotalDestroyed = Destroyed6in + Destroyed8in Set_Property(@Window : '.EDL_DESTROYED_TOTAL', 'TEXT', TotalDestroyed) // Retained Wafers WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_6IN') ListHandle = SRP_FastArray('Create', WaferList) Retained6in = Retain_Manager_Services('GetWaferCount', ListHandle) TotalRetained6in = Retained6in - Destroyed6in Set_Property(@Window : '.EDL_RETAINED_6IN', 'TEXT', TotalRetained6in) WaferList = Database_Services('ReadDataRow', 'APP_INFO', 'RETAINED_WAFERS_8IN') ListHandle = SRP_FastArray('Create', WaferList) Retained8in = Retain_Manager_Services('GetWaferCount', ListHandle) TotalRetained8in = Retained8in - Destroyed8in Set_Property(@Window : '.EDL_RETAINED_8IN', 'TEXT', TotalRetained8in) TotalRetained = TotalRetained6in + TotalRetained8in Set_Property(@Window : '.EDL_RETAINED_TOTAL', 'TEXT', TotalRetained) // To Be Retained Total ToBeRetained6inWaferCount = Retain_Manager_Services('GetToBeRetainedCount', '150 mm 6 in') Set_Property(@Window : '.EDL_TO_BE_RETAINED_6IN', 'TEXT', ToBeRetained6inWaferCount) ToBeRetained8inWaferCount = Retain_Manager_Services('GetToBeRetainedCount', '200 mm 8 in') Set_Property(@Window : '.EDL_TO_BE_RETAINED_8IN', 'TEXT', ToBeRetained8inWaferCount) TotalToBeRetainedWaferCount = ToBeRetained6inWaferCount + ToBeRetained8inWaferCount Set_Property(@Window : '.EDL_TO_BE_RETAINED_TOTAL', 'TEXT', TotalToBeRetainedWaferCount) // To Be Destroyed Total ToBeDestroyed6inWaferCount = Retain_Manager_Services('GetToBeDestroyedCount', '150 mm 6 in') Set_Property(@Window : '.EDL_TO_BE_DESTROYED_6IN', 'TEXT', ToBeDestroyed6inWaferCount) ToBeDestroyed8inWaferCount = Retain_Manager_Services('GetToBeDestroyedCount', '200 mm 8 in') Set_Property(@Window : '.EDL_TO_BE_DESTROYED_8IN', 'TEXT', ToBeDestroyed8inWaferCount) TotalToBeDestroyedWaferCount = ToBeDestroyed6inWaferCount + ToBeDestroyed8inWaferCount Set_Property(@Window : '.EDL_TO_BE_DESTROYED_TOTAL', 'TEXT', TotalToBeDestroyedWaferCount) return UpdateServiceLastRunTime: LastRunDTM = Retain_Manager_Services('GetRetainServiceLastRunTime') Set_Property(StatusBar$, 'OLE.PaneCaption[1]', 'Retain Wafer Service last ran at: ' : LastRunDTM) return ExportWaferReport: ReportHeaderArrray = '' ReportRowArrray = '' HeaderCounter = '' HeaderArray = Get_Property(SearchTable$, 'OLE.TitleList') CurrentWaferArray = Get_Property(SearchTable$, 'OLE.ARRAY') For Each Header In HeaderArray using @VM HeaderCounter += 1 HeaderVisibility = Get_Property(SearchTable$, 'OLE.DataColumn[' : HeaderCounter : ']')<2> If HeaderVisibility EQ True$ then ReportHeaderArrray := Header : @VM ReportRowArrray := CurrentWaferArray : @FM end Next Header ReportHeaderArrray[-1, 1] = '' ReportRowArrray[-1, 1] = '' ReportRowArrray = SRP_Array('Rotate', ReportRowArrray, @FM, @VM) FullReport = ReportHeaderArrray : @FM : ReportRowArrray Swap @VM with ',' in FullReport Swap @FM with CRLF$ in FullReport DialogParams = True$ : @FM : '' : @FM : '' : @FM : 'Retained Wafer Export.csv' SaveLocation = Utility('CHOOSEFILE', @Window, DialogParams) If SaveLocation NE '' then OSWrite FullReport To SaveLocation // Add quotes for the CMD command RunCommand = 'explorer.exe /select,"' : SaveLocation : '"' Output = SRP_Run_Command(RunCommand, 'DOS') end return ResetFocusToBottomRow: // Set focus to bottom row for both SearchTable$ and Wafer Detail DataList = Get_Property(SearchTable$, 'OLE.ARRAY') DataList = SRP_Array('Rotate', DataList, @FM, @VM) // Reset position to 1,1 so empty space does not reappear when setting to bottom row Set_Property(SearchTable$, 'OLE.SelPos', 1 : @FM : 1) // Get total amount of records and set position to bottom record RecordCount = Count(DataList, @FM) + 1 Set_Property(SearchTable$, 'OLE.SelPos', 1 : @FM : RecordCount) Send_Message(SearchTable$, 'OLE.FireEvent', 'PosChanged', 1 : ';' : RecordCount) return UpdateCachedDataValues: CellPos = Get_Property(SearchTable$, 'OLE.SelPos') ColPos = CellPos<1> RowPos = CellPos<2> RowData = Get_Property(SearchTable$, 'OLE.RecordData[' : RowPos : ']') WaferID = RowData<1, WAFER_ID$> Comment = RowData<1, COMMENT$> Status = RowData<1, STATUS$> Location = RowData<1, RETAIN_LOC$> MasterRetainWaferList = Get_Property(@Window, '@MASTERRETAINWAFERLIST') Locate WaferID In MasterRetainWaferList using @VM setting WaferPos then MasterRetainWaferList = Comment MasterRetainWaferList = Status MasterRetainWaferList = Location Set_Property(@Window, '@MASTERRETAINWAFERLIST', MasterRetainWaferList) end PrevActiveSegment = SRP_Breadcrumbbar(BreadcrumbBar$, 'GetActiveSegment') FieldCount = DCount(PrevActiveSegment, '-') SegmentKey = Field(PrevActiveSegment, '-', 1, FieldCount) Loop UnFilteredDataList = Get_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST') Locate WaferID In UnFilteredDataList using @VM setting WaferPos then UnFilteredDataList = Comment UnFilteredDataList = Status UnFilteredDataList = Location Set_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST', UnFilteredDataList) end FilteredDataList = Get_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST') Locate WaferID In FilteredDataList using @VM setting WaferPos then FilteredDataList = Comment FilteredDataList = Status FilteredDataList = Location Set_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST', FilteredDataList) end Fieldcount = FieldCount-1 SegmentKey = Field(PrevActiveSegment, '-', 1, FieldCount) Until SegmentKey EQ 'RootKey' Repeat return ClearData: ActiveSegment = SRP_Breadcrumbbar(BreadcrumbBar$, 'GetActiveSegment') FieldCount = DCount(ActiveSegment, '-') SegmentKey = Field(ActiveSegment, '-', 1, FieldCount) Loop Set_Property(@Window, '@' : SegmentKey : '*UNFILTEREDDATALIST', '') Set_Property(@Window, '@' : SegmentKey : '*FILTEREDDATALIST', '') Set_Property(@Window, '@' : SegmentKey : '*FORMATTEDFILTERARRAY', '') Set_Property(@Window, '@' : SegmentKey : '*PREVIOUSSELECTEDFILTERS', '') Fieldcount = FieldCount-1 SegmentKey = Field(ActiveSegment, '-', 1, FieldCount) Until SegmentKey EQ 'RootKey' Repeat SRP_Breadcrumbbar(BreadcrumbBar$, 'RemoveAllSegments', True$) return