Compile function WO_MAT_GAN_EVENTS(CtrlEntId, Event, @PARAMS) /*********************************************************************************************************************** Name : WO_Mat_Gan_Events Description : Commuter module for the WO_MAT_GAN 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) 08/05/19 djs Coverted old commuter module, WO_MAT_GAN, to WO_MAT_GAN_EVENTS. Updated the form to allow users to reorder wafers in the cassette via arrow buttons. ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler #window WO_MAT_GAN DECLARE SUBROUTINE Set_Property, Set_Status,obj_WO_Wfr, obj_React_Run, Print_GaN_Out_Labels, obj_WO_Mat DECLARE SUBROUTINE ErrMsg, Send_Message, Set_Property, Send_Event, obj_AppWindow, Security_Err_Msg, Forward_Event DECLARE SUBROUTINE End_Window,obj_React_Reads, obj_WO_Mat_Log, obj_WO_Mat, obj_Appwindow,obj_Run_Stage DECLARE SUBROUTINE Database_Services, Gan_Services, Error_Services, Dialog_Box, Btree.Extract, Print_Manifest DECLARE SUBROUTINE Material_Services, Print_Gan_Scribe_Labels DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, Utility, Popup, Collect.Ixvals, obj_Appwindow, Database_Services DECLARE FUNCTION Send_Message, Msg, Security_Check, obj_WO_Log, Set_Property, Create_Dialog, obj_wo_Mat_GaN, SRP_Array DECLARE FUNCTION Error_Services, GaN_Services, Datetime, RGB, Form_Services $INSERT REACT_RUN_EQUATES $INSERT RUN_STAGE_EQUATES $INSERT WO_MAT_EQUATES $INSERT WO_MAT_WFR_EQUATES $INSERT WO_WFR_EQUATES $INSERT LSL_USERS_EQUATES $INSERT POPUP_EQUATES $INSERT TOOL_CLASS_EQUATES $INSERT RTI_STYLE_EQUATES $INSERT MSG_EQUATES $INSERT APPCOLORS $INSERT SECURITY_RIGHTS_EQU $INSERT RUN_STAGE_WFR_EQUATES $INSERT WO_LOG_EQUATES EQU COL$OUT_SLOT TO 1 EQU COL$OUT_WFR_ID TO 2 EQU COL$OUT_CARR_SLOT_ID TO 3 EQU COL$OUT_GAN_WFR_ID TO 4 EQU COL$OUT_SCRIBE TO 5 EQU COL$OUT_GRADE TO 6 EQU COL$POP_WFR_ID TO 1 EQU COL$POP_CARR_SLOT_ID TO 2 Equ COL$LOG_FILE to 1 Equ COL$LOG_DTM to 2 Equ COL$ACTION to 3 Equ COL$WH_CD to 4 Equ COL$LOC_CD to 5 Equ COL$WO_NOS to 6 Equ COL$CASS_NOS to 7 Equ COL$USER_ID to 8 Equ COL$TAGS to 9 Equ COL$TOOL_ID to 10 // In Cass OLE Edit Table EQU COL$CASS_SLOT TO 1 EQU COL$CASS_WFR_ID TO 2 EQU COL$CASS_CARR_SLOT_ID TO 3 EQU COL$CASS_GAN_WFR_ID TO 4 EQU COL$CASS_SCRIBE TO 5 EQU COL$CASS_GRADE TO 6 EQU COL$CASS_WMO_NCR TO 7 // NCR OLE Edit Table EQU COL$NCR_NO TO 1 EQU COL$NCR_STATUS TO 2 EQU COL$NCR_REJ_QTY TO 3 EQU COL$NCR_RESP TO 4 EQU COL$NCR_STAGE TO 5 EQU COL$NCR_LOSS_DESC TO 6 EQU COL$NCR_LOSS_COMM TO 7 EQU COL$NCR_FIN_SIG TO 8 EQU COL$NCR_FIN_SIG_DTM TO 9 EQU CRLF$ TO \0D0A\ EQU TAB$ TO \09\ EQU TOP$ROW TO 1 EQU BOTTOM$ROW TO 25 SubclassInfo = Form_Services('FindSubclassControl') Subclass = SubclassInfo<1> If Assigned(Param8) else Param8 = '' // Update the arguments so that the OpenInsight OLE event will treate the ActiveX event as a native event handler. 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 GoToEvent Event for CtrlEntId else // Event not implemented end Return EventFlow or 1 //----------------------------------------------------------------------------- // EVENT HANDLERS //----------------------------------------------------------------------------- Event WINDOW.CREATE(CreateParam) obj_Appwindow('Create',@WINDOW) End Event Event WINDOW.READ() Set_Property(@Window, 'REDRAW', False$) Set_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.Redraw', False$) Set_Property(@Window:'.OLE_EDT_NCR', 'OLE.Redraw', False$) WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') IF RowExists('WO_MAT',WONo:'*':CassNo) THEN IF NOT(Security_Check('RDS',READ$)) THEN Send_Event(@WINDOW,'CLEAR') Security_Err_Msg('Work Order Mat',READ$) RETURN END IF NOT(Security_Check('RDS',EDIT$)) THEN obj_Appwindow('ReadOnly',@WINDOW) ;*Set to Read Only END END ELSE ErrMsg('Work Order Mat entries are only created by the program.') Send_Event(@WINDOW,'CLEAR') RETURN END GoSub SetupOLEControls GoSub FillForm GoSub EnableArrowButtons GoSub EnableAddButton GoSub EnableRemoveButton GoSub EnableSignButton GoSub StyleSymbolics CassList = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.LIST') Set_Property(@Window, '@ORIGCASSLIST', CassList) Set_Property(@Window, 'REDRAW', True$) Set_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.Redraw', True$) Set_Property(@Window:'.OLE_EDT_NCR', 'OLE.Redraw', True$) end event Event WINDOW.CLOSE(CancelFlag) obj_Appwindow('DetailReturn') end event Event WINDOW.CLEAR(bSaveKey, bSuppressWarning, bMaintainFocus, CtrlIDFocus) GoSub StyleSymbolics end event Event WINDOW.WRITE() IOOptions = Get_Property(@Window, 'IOOPTIONS') IOOptions<6> = True$ Set_Property(@Window, 'IOOPTIONS', IOOptions) CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS' CassList = Get_Property(CassEDTCtrl, 'OLE.ARRAY') OutSlots = CassList<1> InWfrIDs = CassList<2> CarrSlotIDs = CassList<3> WONo = Get_Property(@Window:'.WO_NO', 'TEXT') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') // Update WO_MAT_WFR record WOMatWfrKey = WONo:'*':CassNo WOMatWfrRec = Database_Services('ReadDataRow', 'WO_MAT_WFR', WOMatWfrKey) WOMatWfrRec = InWfrIDs Database_Services('WriteDataRow', 'WO_MAT_WFR', WOMatWfrKey, WOMatWfrRec, True$, False$, True$) // Update REACT_RUN and WO_WFR records For each InWfrID in InWfrIDs using @VM setting wPos OutSlotID = WONo:'*':CassNo:'*':OutSlots<0, wPos> RDSNo = Xlate('WO_WFR', InWfrID, 'RDS_NO', 'X') // Update REACT_RUN record ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo) RRInWfrIDs = ReactRunRec RROutSlotIDs = ReactRunRec Locate InWfrID in RRInWfrIDs using @VM setting vPos then RROutSlotIDs<0, vPos> = OutSlotID end ReactRunRec = RROutSlotIDs Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$) // Update WO_WFR record WOWfrRec = Database_Services('ReadDataRow', 'WO_WFR', InWfrID) EventDTMs = WOWfrRec NumEvents = DCount(EventDTMs, @VM) SlotIDs = WOWfrRec SlotIDs<0, NumEvents> = OutSlotID WOWfrRec = SlotIDs Database_Services('WriteDataRow', 'WO_WFR', InWfrID, WOWfrRec, True$, False$, True$) Next InWfrID Forward_Event() Send_Event(@Window, 'READ') end event Event PUB_ADD_WAFERS.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') CurrLoad = Get_Property(@WINDOW:'.OLE_EDT_IN_CASS', 'OLE.ARRAY') CurrSlotNos = CurrLoad CurrWfrIDs = CurrLoad OutCassID = WONo:'*':CassNo WfrData = obj_WO_Mat_GaN('GetManifestWfrs', WONo) IF Not( Get_Status(errCode) ) THEN IF WfrData NE '' THEN CONVERT @VM:@FM TO @SVM:@VM IN WfrData TypeOver = '' TypeOver = WfrData SelWfrs = Popup(@WINDOW, TypeOver, 'WO_WFRS') swCnt = DCount(SelWfrs, @FM) WfrArray = SRP_Array('Rotate', SelWfrs, @FM, @VM) WaferIDs = WfrArray<1> Error_Services('Clear') Gan_Services('AddWfrsToOutCass', OutCassID, WaferIDs) If Error_Services('NoError') then Send_Event(@Window, 'READ') GoSub EnableAddButton GoSub EnableRemoveButton end else ErrorMessage = Error_Services('GetMessage') ErrMsg(ErrorMessage) end end else Msg(@WINDOW,'','NO_SHIPPABLE') end end else ErrMsg(errCode) end end event Event PUB_REM_WAFERS.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') SlotSelection = Get_Property(@WINDOW:'.OLE_EDT_IN_CASS', 'OLE.SelPos') SelectedRows = SlotSelection<2> WfrIDs = '' WfrArray = Get_Property(@WINDOW:'.OLE_EDT_IN_CASS', 'OLE.ARRAY') InWfrIDs = WfrArray<2> For each SelRow in SelectedRows using @VM setting vPos WfrIDs<0, -1> = InWfrIDs<0, SelRow> Next SelRow OutCassID = WONo:'*':CassNo Error_Services('Clear') Gan_Services('RemoveWfrsFromOutCass', OutCassID, WfrIDs) If Error_Services('NoError') then Send_Event(@Window, 'READ') GoSub EnableAddButton GoSub EnableRemoveButton end else ErrorMessage = Error_Services('GetMessage') ErrMsg(ErrorMessage) end end event Event PUB_SIGN_FQA.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) ) IF NOT(Valid) THEN RETURN 0 END SigDTM = OCONV( Date(), 'D4/' ):' ':OCONV( Time(), 'MTS' ) Set_Property(@WINDOW:'.CASS_FINAL_SIG','DEFPROP',@USER4) Set_Property(@WINDOW:'.CASS_FINAL_SIG_DTM','DEFPROP',SigDTM) Send_Event(@WINDOW,'WRITE') ScanUser = @USER4 ScanDTM = SigDTM WOStep = '1' ;* GaN is a single step process StatusStage = 'G_FQA' WhCd = 'CR' LocCd = 'QA' Tags = '' ToolID = '' owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:StatusStage:@RM:ScanUser:@RM:ScanDTM:@RM:ToolID:@RM:WHCd:@RM:LocCD:@RM:Tags If Get_Status(errCode) then ErrMsg(errCode) end else EventParms = '' EventParms = 'WO_MAT' EventParms = SigDTM EventParms = WOStep:'QA' EventParms = 'CR' EventParms = 'QA' EventParms = WONo EventParms = CassNo EventParms = @USER4 EventParms = '' EventParms = '' CONVERT @FM TO @RM IN EventParms obj_WO_Mat_Log('Create',EventParms) If Get_Status(errCode) Then ErrMsg(errCode) End // Move wafers out of G_PACK location queue CurrDTM = Datetime() EDTList = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.LIST') * WOLogRec = Database_Services('ReadDataRow', 'WO_LOG', WONo) * AvailSlotList = WOLogRec For each Row in EDTList using @FM setting RowIndex WfrID = Row<0, COL$OUT_WFR_ID> RDSNo = Field(Row<0, COL$OUT_CARR_SLOT_ID>, '.', 1) CurrStage = GaN_Services('GetCurrStage', WfrID) CurrQ = GaN_Services('GetWfrQueue', WfrID) Gan_Services('RemoveWfrFromWIP', WfrID) // Mark current stage complete Convert '*' to '.' in WfrID RunStageWfrKey = RDSNo:'*':CurrStage:'*':WfrID RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey) StageStatus = RunStageWfrRec If StageStatus _EQC 'INIT' then // Mark DISP stage as complete RunStageWfrRec = @USER4 RunStageWfrRec = CurrDTM RunStageWfrRec = 'COMP' Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$) end // Ensure all slots are marked as unavailable in the WO_LOG record Convert '.' to '*' in WfrID SlotNo = RowIndex SlotKey = CassNo:'*':SlotNo * Locate SlotKey in AvailSlotList using @VM setting vPos then * AvailSlotList<0, vPos> = 0 * end Next Row * WOLogRec = AvailSlotList * Database_Services('WriteDataRow', 'WO_LOG', WONo, WOLogRec, True$, False$, True$) end obj_AppWindow('LoadFormKeys',@WINDOW:@RM:WONo:'*':CassNo) end event Event PUB_PRINT_CASS_LABEL.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') Print_Gan_Out_Labels(WONo,CassNo) end event Event PUB_PRINT_MANIFEST.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') Print_Manifest(WONo, CassNo) end event Event PUB_UPDATE_DB.CLICK() Response = Msg(@Window, '', 'YESNO', '', 'Verification':@FM:'Have you verified the wafer List accuracy?') If Response EQ Yes$ then WONo = Get_Property(@Window:'.WO_NO', 'TEXT') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') WMOKey = WONo:'*1*':CassNo Material_Services('UpdateWaferLocation', WMOKey) Msg(@Window, '', 'OK', '', 'Success':@FM:'Data updated successfully!') end end event Event PUB_TOP_ARROW.CLICK() CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS' CassList = Get_Property(CassEDTCtrl, 'OLE.LIST') SelList = Get_Property(CassEDTCtrl, 'OLE.SelPos') SelRowIndex = SelList<2, 1> SelRow = CassList CassList = Delete(CassList, SelRowIndex, 0 ,0) CassList = Insert(CassList, TOP$ROW, 0, 0, SelRow) Set_Property(CassEDTCtrl, 'LIST', CassList) GoSub UpdateSlotNos GoSub SetSavewarn Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:TOP$ROW) GoSub EnableArrowButtons end event Event PUB_UP_ARROW.CLICK() CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS' CassList = Get_Property(CassEDTCtrl, 'OLE.LIST') SelList = Get_Property(CassEDTCtrl, 'OLE.SelPos') SelRowIndex = SelList<2, 1> SelRow = CassList CassList = Delete(CassList, SelRowIndex, 0 ,0) NewRowIndex = SelRowIndex - 1 CassList = Insert(CassList, NewRowIndex, 0, 0, SelRow) Set_Property(CassEDTCtrl, 'LIST', CassList) GoSub UpdateSlotNos GoSub SetSavewarn Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:NewRowIndex) GoSub EnableArrowButtons end event Event PUB_DOWN_ARROW.CLICK() CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS' CassList = Get_Property(CassEDTCtrl, 'OLE.LIST') SelList = Get_Property(CassEDTCtrl, 'OLE.SelPos') SelRowIndex = SelList<2, 1> SelRow = CassList CassList = Delete(CassList, SelRowIndex, 0 ,0) NewRowIndex = SelRowIndex + 1 CassList = Insert(CassList, NewRowIndex, 0, 0, SelRow) Set_Property(CassEDTCtrl, 'LIST', CassList) GoSub UpdateSlotNos GoSub SetSavewarn Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:NewRowIndex) GoSub EnableArrowButtons end event Event PUB_BOTTOM_ARROW.CLICK() CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS' CassList = Get_Property(CassEDTCtrl, 'OLE.LIST') SelList = Get_Property(CassEDTCtrl, 'OLE.SelPos') SelRowIndex = SelList<2, 1> SelRow = CassList CassList = Delete(CassList, SelRowIndex, 0 ,0) CassList = Insert(CassList, BOTTOM$ROW, 0, 0, SelRow) Set_Property(CassEDTCtrl, 'LIST', CassList) GoSub UpdateSlotNos GoSub SetSavewarn // Return focus to the new row index. Set_Property(CassEDTCtrl, 'SELPOS', 0:@FM:BOTTOM$ROW) GoSub EnableArrowButtons end event Event PUB_CREATE_NCR.CLICK() ! To do end event Event OLE_EDT_IN_CASS.OnClick(Cell, Point, Button, Shift, Ctrl) GoSub EnableArrowButtons GoSub EnableRemoveButton end event Event OLE_EDT_IN_CASS.OnCheckChanged(Cell, OldValue, NewValue) Col = Field(Cell, ';', 1, 1) Row = Field(Cell, ';', 2, 1) NCRButton = '' Begin Case Case Col EQ COL$CASS_WMO_NCR // The checkbox is only used for creating NCRs. We don't need to save anything at this time. // Check (no pun intended) if any of the checkboxes in this column are True$. If so, then enable // the "Create NCR" button, otherwise disable it. GoSub EnableNCRButton End Case end event Event OLE_EDT_NCR.OnDblClick(Cell, Point, Button, Shift, Ctrl) Row = Field(Cell, ';', 2, 1) NCRNo = Get_Property(CtrlEntID, "OLE.CellText[":COL$NCR_NO:";":Row:"]") If RowExists('NCR', NCRNo) then PreNCRRec = Database_Services('ReadDataRow', 'NCR', NCRNo) Dialog_Box('NCR', @Window, NCRNo) PostNCRRec = Database_Services('ReadDataRow', 'NCR', NCRNo) If PreNCRRec NE PostNCRRec then GoSub FillNCREditTable end end event Event PUB_PRINT_SCRIBE.CLICK() WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP') CassNo = Get_Property(@WINDOW:'.CASS_NO','DEFPROP') If ( (WONo NE '') and (CassNo NE '') ) then Response = Dialog_Box('NDW_REC_SEND', @Window) If Response then Recipient = Response<1> Sender = Response<2> If ( (Sender NE '') and (Recipient NE '') ) then Print_Gan_Scribe_Labels(WONo, CassNo, Recipient, Sender) end end end end event //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// StyleSymbolics: * Turn edit table symbolic column backgrounds to green ETSymbolics = Get_Property('WO_MAT_WFR','@ET_SYMBOLICS') ;* Loaded during 'Create' in obj_Appwindow ETCtrls = ETSymbolics<1> ETCols = ETSymbolics<2> FOR I = 1 TO COUNT(ETCtrls,@VM) + (ETCtrls NE '') ETCtrl = ETCtrls<1,I> IF ETCtrl NE 'WO_MAT_WFR.SLOT_NO' THEN ETList = Get_Property(ETCtrl,'LIST') FOR Line = 1 TO COUNT(ETList,@FM) + (ETList NE '') IF ETList NE '' THEN FOR N = 1 TO COUNT(ETCols<1,I>,@SVM) + (ETCols<1,I> NE '') stat = Send_Message(ETCtrl,'COLOR_BY_POS',ETCols<1,I,N>,Line,GREEN$) NEXT N END NEXT Line END NEXT I return EnableArrowButtons: WONo = Get_Property(@Window:'.WO_NO', 'TEXT') PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') TechType = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X') CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS' TopArrow = @Window:'.PUB_TOP_ARROW' UpArrow = @Window:'.PUB_UP_ARROW' DownArrow = @Window:'.PUB_DOWN_ARROW' BottomArrow = @Window:'.PUB_BOTTOM_ARROW' CassList = Get_Property(CassEDTCtrl, 'OLE.ARRAY') SelRow = '' SelWfrID = '' WfrList = CassList<2> NumWfrs = 0 For each Row in WfrList using @VM setting fPos If Row NE '' then NumWfrs += 1 Next Row SelList = Get_Property(CassEDTCtrl, 'OLE.SelPos') SelRows = SelList<2> NumSelRows = DCount(SelRows, @VM) If NumSelRows EQ 1 then SelRow = SelRows<0, 1> SelWfrID = WfrList<0, SelRow> end CassList = Delete(CassList, 1, 0, 0) Convert @FM to '' in CassList Convert @VM to '' in CassList Convert @FM to '' in SelList Convert @VM to '' in SelList Begin Case Case TechType EQ 'P' Set_Property(TopArrow, 'ENABLED', False$) Set_Property(UpArrow , 'ENABLED', False$) Set_Property(DownArrow, 'ENABLED', False$) Set_Property(BottomArrow, 'ENABLED', False$) Case (CassList NE '') and (SelList NE '') and (NumSelRows EQ 1) and (SelWfrID NE '') Begin Case Case SelRow EQ TOP$ROW Set_Property(TopArrow, 'ENABLED', False$) Set_Property(UpArrow , 'ENABLED', False$) Set_Property(DownArrow, 'ENABLED', True$) Set_Property(BottomArrow, 'ENABLED', True$) Case (SelRow EQ BOTTOM$ROW) Set_Property(TopArrow, 'ENABLED', True$) Set_Property(UpArrow , 'ENABLED', True$) Set_Property(DownArrow, 'ENABLED', False$) Set_Property(BottomArrow, 'ENABLED', False$) Case Otherwise$ Set_Property(TopArrow, 'ENABLED', True$) Set_Property(UpArrow , 'ENABLED', True$) Set_Property(DownArrow, 'ENABLED', True$) Set_Property(BottomArrow, 'ENABLED', True$) End Case Case Otherwise$ Set_Property(TopArrow, 'ENABLED', False$) Set_Property(UpArrow , 'ENABLED', False$) Set_Property(DownArrow, 'ENABLED', False$) Set_Property(BottomArrow, 'ENABLED', False$) End Case return UpdateSlotNos: CassEDTCtrl = @Window:'.OLE_EDT_IN_CASS' CassList = Get_Property(CassEDTCtrl, 'OLE.ARRAY') SlotList = '' SlotNo = '' For SlotNo = 1 to 25 SlotList<0, -1> = SlotNo Next SlotNo CassList<1> = SlotList Set_Property(CassEDTCtrl, 'OLE.ARRAY', CassList) return SetSavewarn: CurrCassList = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.LIST') OrigCassList = Get_Property(@Window, '@ORIGCASSLIST') If CurrCassList NE OrigCassList then Set_Property(@Window, 'SAVEWARN', True$) end else Set_Property(@Window, 'SAVEWARN', False$) end return EnableRemoveButton: WONo = Get_Property(@Window:'.WO_NO', 'TEXT') PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') TechType = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X') CassArray = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.ARRAY') SlotSelection = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.SelPos') WfrSelected = False$ WfrCol = CassArray<2> SelectedRows = SlotSelection<2> SelCnt = DCount(SelectedRows, @VM) If SelCnt GT 0 then For each RowIndex in SelectedRows using @VM setting vPos // Does at least one row selected have a wafer ID in it? WfrID = WfrCol<0, RowIndex> If WfrID NE '' then WfrSelected = True$ Until WfrSelected EQ True$ Next RowIndex end Begin Case Case TechType EQ 'P' Set_Property(@Window:'.PUB_REM_WAFERS', 'ENABLED', False$) Case ( (SelCnt GT 0) and (WfrSelected EQ True$) ) Set_Property(@Window:'.PUB_REM_WAFERS', 'ENABLED', True$) Case Otherwise$ Set_Property(@Window:'.PUB_REM_WAFERS', 'ENABLED', False$) End Case return EnableAddButton: WONo = Get_Property(@Window:'.WO_NO', 'TEXT') PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') CurrPartNo = Xlate('PROD_SPEC', PSNo, 'CURR_PART_NO', 'X') TechType = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X') CassArray = Get_Property(@Window:'.OLE_EDT_IN_CASS', 'OLE.ARRAY') WfrCol = CassArray<2> SlotAvailable = False$ For each WfrID in WfrCol using @VM setting WfrIndex // Is at least one row empty? If WfrID EQ '' then SlotAvailable = True$ Until SlotAvailable EQ True$ Next WfrID Begin Case Case TechType EQ 'P' ; // and CurrPartNo NE 'U314' Set_Property(@Window:'.PUB_ADD_WAFERS', 'ENABLED', False$) Case SlotAvailable EQ True$ Set_Property(@Window:'.PUB_ADD_WAFERS', 'ENABLED', True$) Case Otherwise$ Set_Property(@Window:'.PUB_ADD_WAFERS', 'ENABLED', False$) End Case return SetupOLEControls: GoSub SetupCassEditTable GoSub SetupNCREditTable return SetupCassEditTable: NumCassCols = 7 NumCassRows = 25 CassCtrl = @Window:'.OLE_EDT_IN_CASS' HeaderFontArray = 'Segoe UI':@SVM:8:@SVM:700 CassDimArray = NumCassCols :@FM: NumCassRows Set_Property(CassCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(CassCtrl, "OLE.Dimension", CassDimArray) Set_Property(CassCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(CassCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) CassHeaderTitles = 'Slot':@VM:'Inbound':@VM:'Carrier':@VM:'GaN Wfr ID':@VM:'Scribe':@VM:'Grade':@VM:'WMO NCR' Set_Property(CassCtrl, "OLE.TitleList", CassHeaderTitles) Set_Property(CassCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(CassCtrl, "OLE.CellAlignment[1; All]", 'C':@FM:'C':@FM:'L') Set_Property(CassCtrl, "OLE.CellAlignment[2-":NumCassCols-1:"; All]", 'C':@FM:'L':@FM:'L') Set_Property(CassCtrl, "OLE.CellAlignment[":COL$CASS_WMO_NCR:"; All]", 'C':@FM:'C':@FM:'L') Set_Property(CassCtrl, "OLE.AllowDeletions", False$) Set_Property(CassCtrl, "OLE.AllowInserts", False$) HeaderColArray = '' HeaderColArray<2> = False$ Set_Property(CassCtrl, "OLE.HeaderColumn[1]", HeaderColArray) // Set default header colors HeaderColorArray = '' HeaderColorArray<1> = 'Auto' HeaderColorArray<2> = 'None' HeaderColorArray<3> = 'None' HeaderColorArray<4> = OI_HOT_BLUE$ HeaderColorARray<5> = False$ Set_Property(CassCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) // Qualify OLE events that we want to intercept Qualifier = '' Qualifier<1> = 1 Qualifier<4> = 0 ; * process synchronously (i.e. immediately) Send_Message(CassCtrl, 'QUALIFY_EVENT', 'OLE.OnCheckChanged', Qualifier) Send_Message(CassCtrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualifier) // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(CassCtrl, "OLE.HeaderRow[1]") HeaderRowArray<3> = False$ Set_Property(CassCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form ColSize = Get_Property(CassCtrl, "OLE.DataColumn[1]") ColSize<3> = False$ Set_Property(CassCtrl, "OLE.DataColumn[All]", ColSize) // Manually set column widths ColSize<1> = 45 Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_SLOT:"]", ColSize) ColSize<1> = 80 Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_WFR_ID:"]", ColSize) ColSize<1> = 76 Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_CARR_SLOT_ID:"]", ColSize) ColSize<1> = 100 Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_GAN_WFR_ID:"]", ColSize) ColSize<1> = 76 Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_SCRIBE:"]", ColSize) ColSize<1> = 50 Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_GRADE:"]", ColSize) ColSize<1> = 70 Set_Property(CassCtrl, "OLE.DataColumn[":COL$CASS_WMO_NCR:"]", ColSize) // Disable scroll bars Set_Property(CassCtrl, "OLE.ScrollBarsVisible", 'N':@FM:'N') // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(CassCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(CassCtrl, "OLE.DataRow[All]", RowSizeProps) Set_Property(CassCtrl, "OLE.CellProtection[All; All]", 'SEL') // Color headers HeaderColorArray = '' HeaderColorArray<2> = "{200, 200, 200}" HeaderColorArray<4> = "{200, 200, 200}" Set_Property(CassCtrl, "OLE.HeaderColors[All; 1]", HeaderColorArray) // Color cells Set_Property(CassCtrl, "OLE.CellColors[All; All]", 'None':@FM:RGB(192,220,192)) // Cell selection style setup Set_Property(CassCtrl, "OLE.ResetSelPos", False$) ;// Prevent cell selection reset upon lost focus event CassSelStyleArray = Get_Property(CassCtrl, "OLE.SelectionStyle") CassSelStyleArray<2,2> = OI_HOT_BLUE$ CassSelStyleArray<3,2> = 'None' CassSelStyleArray<4> = 'None' CassSelStyleArray<6> = 'None' CassSelStyleArray<7> = 'None' CassSelStyleArray<8> = True$ ;// Keep cell highlighted when table loses focus Set_Property(CassCtrl, 'OLE.SelectionStyle', CassSelStyleArray) return SetupNCREditTable: NumNCRCols = 9 NumNCRRows = 5 NCRCtrl = @Window:'.OLE_EDT_NCR' HeaderFontArray = 'Segoe UI':@SVM:8:@SVM:700 NCRDimArray = NumNCRCols :@FM: NumNCRRows Set_Property(NCRCtrl, "OLE.CellFont[All; All]", 'Segoe UI':@SVM:8) Set_Property(NCRCtrl, "OLE.Dimension", NCRDimArray) Set_Property(NCRCtrl, "OLE.HeaderFont[All; 1]", HeaderFontArray) Set_Property(NCRCtrl, "OLE.HeaderFont[1; All]", HeaderFontArray) NCRHeaderTitles = 'NCR':@VM:'Status':@VM:'Qty':@VM:'Responsible':@VM:'Stage':@VM:'Loss Desc':@VM NCRHeaderTitles := 'Loss Comments':@VM:'Signature':@VM:'Date & Time' Set_Property(NCRCtrl, "OLE.TitleList", NCRHeaderTitles) Set_Property(NCRCtrl, "OLE.HeaderAlignment[All; 1]", 'C':@FM:'C':@FM:'L') Set_Property(NCRCtrl, "OLE.CellAlignment[All; All]", 'C':@FM:'C':@FM:'L') Set_Property(NCRCtrl, "OLE.AllowDeletions", False$) Set_Property(NCRCtrl, "OLE.AllowInserts", False$) HeaderColArray = '' HeaderColArray<2> = False$ Set_Property(NCRCtrl, "OLE.HeaderColumn[1]", HeaderColArray) // Set default header colors HeaderColorArray = '' HeaderColorArray<1> = 'Auto' HeaderColorArray<2> = 'None' HeaderColorArray<3> = 'None' HeaderColorArray<4> = OI_HOT_BLUE$ HeaderColorARray<5> = False$ Set_Property(NCRCtrl, "OLE.HeaderColors[All; All]", HeaderColorArray) // Qualify OLE events that we want to intercept Qualifier = '' Qualifier<1> = 1 Qualifier<4> = 0 ; * process synchronously (i.e. immediately) Send_Message(NCRCtrl, 'QUALIFY_EVENT', 'OLE.OnDblClick', Qualifier) // Disable resizing of the header row and header column // Resize header column to fit contents HeaderRowArray = Get_Property(NCRCtrl, "OLE.HeaderRow[1]") HeaderRowArray<3> = False$ Set_Property(NCRCtrl, "OLE.HeaderRow[1]", HeaderRowArray) // Disable resizing of columns as there is no need for this on this form ColSize = Get_Property(NCRCtrl, "OLE.DataColumn[1]") ColSize<3> = False$ ColSize<1> = 56 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_NO:"]", ColSize) ColSize<1> = 45 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_STATUS:"]", ColSize) ColSize<1> = 35 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_REJ_QTY:"]", ColSize) ColSize<1> = 90 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_RESP:"]", ColSize) ColSize<1> = 58 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_STAGE:"]", ColSize) ColSize<1> = 100 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_DESC:"]", ColSize) ColSize<1> = 100 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]", ColSize) ColSize<1> = 100 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_FIN_SIG:"]", ColSize) ColSize<1> = 100 Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_FIN_SIG_DTM:"]", ColSize) // Disable resizing of rows as there is no need for this on this form RowSizeProps = Get_Property(NCRCtrl, "OLE.DataRow[1]") RowSizeProps<3> = False$ Set_Property(NCRCtrl, "OLE.DataRow[All]", RowSizeProps) Set_Property(NCRCtrl, "OLE.CellProtection[":COL$NCR_NO:"-":COL$NCR_FIN_SIG_DTM:"; All]", 'SEL') // Color headers Set_Property(NCRCtrl, "OLE.HeaderColors[All; 1]", @FM:"{200, 200, 200}") // Color cells Set_Property(NCRCtrl, "OLE.CellColors[All; All]", 'None':@FM:RGB(192,220,192)) // Set Loss Comments column to autosized so that the table resizes when scrollbars are necessary ColArray = Get_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]") ColArray<4> = True$ Set_Property(NCRCtrl, "OLE.DataColumn[":COL$NCR_LOSS_COMM:"]", ColArray) return FillForm: WONo = Get_Property(@Window:'.WO_NO', 'TEXT') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') If ( (WONo NE '') and (CassNo NE '') ) then GoSub FillCassEditTable GoSub FillNCREditTable end return FillCassEditTable: CassCtrl = @Window:'.OLE_EDT_IN_CASS' WONo = Get_Property(@Window:'.WO_NO', 'TEXT') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') If ( (WONo NE '') and (CassNo NE '') ) then // Suppress redraw until all properties are set Set_Property(CassCtrl, "OLE.Redraw", False$) WOMatKey = WONo:'*':CassNo Database_Services('ActivateRecord', 'WO_MAT', WOMatKey) CassCtrlArray = '' CassCtrlArray = {OUT_SLOT_NO} CassCtrlArray = {OUT_WFR_ID} CassCtrlArray = {OUT_CARR_SLOT_ID} CassCtrlArray = {OUT_GAN_WFR_ID} CassCtrlArray = {OUT_SCRIBE} CassCtrlArray = {OUT_GRADE} CassCtrlArray = {OUT_NCR} For RowIndex = 1 to 25 NCRNo = CassCtrlArray WfrID = CassCtrlArray If ( (NCRNo EQ '') and (WfrID NE '') ) then // This inbound wafer is eligible to be NCR'd // Convert NCR cell for this row into a check box Set_Property(CassCtrl, "OLE.CellText[":COL$CASS_WMO_NCR:";":RowIndex:"]", '') CheckBoxArray = 'Check Box' CheckBoxArray<2,1> = True$ Set_Property(CassCtrl, "OLE.CellType[":COL$CASS_WMO_NCR:";":RowIndex:"]", CheckBoxArray) Set_Property(CassCtrl, "OLE.CellCheckEnabled[":COL$CASS_WMO_NCR:";":RowIndex:"]", True$) end else Set_Property(CassCtrl, "OLE.CellType[":COL$CASS_WMO_NCR:";":RowIndex:"]", 'Text') end Next RowIndex Set_Property(CassCtrl, 'OLE.ARRAY', CassCtrlArray) // Re-enable redraw now that all properties are set Set_Property(CassCtrl, "OLE.Redraw", True$) end return FillNCREditTable: WONo = Get_Property(@Window:'.WO_NO', 'TEXT') CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT') CassCtrl = @Window:".OLE_EDT_IN_CASS" NCRCtrl = @Window:'.OLE_EDT_NCR' SearchTable = 'NCR' SearchString = 'WO_NO' : @VM : WONo : @FM SearchString := 'OUT_CASS_NO' : @VM : CassNo : @FM hDictSearchTable = Database_Services('GetTableHandle', 'DICT.' : SearchTable) NCRNos = '' If Error_Services('NoError') then rv = Set_Status(0) MakeupBoxes = '' Flag = '' StatusCode = '' Btree.Extract(SearchString, SearchTable, hDictSearchTable, NCRNos, '', Flag) end NCRCtrlArray = '' Set_Property(NCRCtrl, "OLE.Redraw", False$) If ( (NCRNos NE 0) and (NCRNos NE '') ) then NCRCtrl = @Window:'.OLE_EDT_NCR' For each NCRNo in NCRNos using @VM setting nPos If ( (RowExists('NCR', NCRNo)) and (NCRNo NE 0) ) then Database_Services('ActivateRecord', 'NCR', NCRNo) NCRCtrlArray = NCRNo NCRCtrlArray = {STATUS} NCRCtrlArray = {REJ_CNT} NCRCtrlArray = {LOSS_BY} NCRCtrlArray = {LOSS_STAGE} NCRCtrlArray = {LOSS_DESC} NCRCtrlArray = {LOSS_COMMENTS} NCRCtrlArray = OConv({AUTH_SHIP_SIG}, '[XLATE_CONV,LSL_USERS*FIRST_LAST]') NCRCtrlArray = OConv({AUTH_SHIP_SIG_DTM}, 'DT') end Next NCR end else // No NCRs associated with this inbound cassette, so clear the NCR table. For nPos = 1 to 5 NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' NCRCtrlArray = '' Next nPos end Set_Property(NCRCtrl, "OLE.ARRAY", NCRCtrlArray) Set_Property(NCRCtrl, "OLE.Redraw", True$) return EnableNCRButton: CassCtrl = @Window:'.OLE_EDT_IN_CASS' Checkmarks = Get_Property(CassCtrl, "OLE.CellCheck[":COL$CASS_WMO_NCR:"; All]") Checksum = Sum(Checkmarks) ButtonEnabled = False$ If ( Checksum GT 0 ) then ButtonEnabled = True$ * Set_Property(@Window:'.PUB_CREATE_NCR', 'ENABLED', ButtonEnabled) return EnableSignButton: FQASig = Get_Property(@Window:'.CASS_FINAL_SIG', 'TEXT') CassCtrl = @Window:'.OLE_EDT_IN_CASS' WfrIDs = Get_Property(CassCtrl, "OLE.ColumnData[":COL$OUT_WFR_ID:"]") WfrIDs = SRP_Array('Clean', WfrIDs, 'Trim', @VM) If ( (WfrIDs NE '') and (FQASig EQ '') ) then ButtonEnabled = True$ end else ButtonEnabled = False$ end Set_Property(@Window:'.PUB_SIGN_FQA', 'ENABLED', ButtonEnabled) return