HDR*PowerBuilder0600UDW Spy - http://www.zuskin.com/dwspy/dwspy.htm$FRE*NOD*$ENT*0600@T]w_spy.srwENT*0600n]iif.srfENT*0600r,4Mz]"n_dwspy_util.sruENT*0600"S]n_parm.udoENT*06008o]n_parm.sruENT*0600mM]iin.srfENT*0600v S]iin.funENT*0600S]iif.funENT*0600S]f_throw.funENT*0600B]f_throw.srfENT*0600LS]n_ex.udoENT*0600b+ C]n_ex.sruENT*0600xMz]"n_dwspy_util.udoENT*0600S]ifnull.srfENT*0600`S]ifnull.funENT*0600T]w_spy.winDAT*DW Spyforward global type w_spy from window end type type cb_boost_brain from commandbutton within w_spy end type type cb_club from commandbutton within w_spy end type type st_show_dw_attributes from statictext within w_spy end type type st_sDAT*how_dw_size_and_coordinates from statictext within w_spy end type type st_deleted_data from statictext within w_spy end type type st_show_window_size_and_coordinates from statictext within w_spy end type type st_filtered_data from statictext witDAT*hin w_spy end type type st_updated_fields from statictext within w_spy end type type st_row_status from statictext within w_spy end type type st_field_info from statictext within w_spy end type type st_show_dddw_data from statictext within w_sDAT*py end type type st_sort_expr from statictext within w_spy end type type st_filter_expr from statictext within w_spy end type type st_invisible_fields from statictext within w_spy end type type st_data_src from statictext within w_spy end typDAT*e type st_menu from statictext within w_spy end type type st_classes_hierarchy from statictext within w_spy end type type cb_copy_to_clipboard from commandbutton within w_spy end type type cb_close from commandbutton within w_spy end type typDAT*e gb_window from groupbox within w_spy end type type gb_datawindow from groupbox within w_spy end type type gb_clicked_field from groupbox within w_spy end type type gb_clicked_row from groupbox within w_spy end type type dw_display from datawDAT* indow within w_spy end type type mle_display from multilineedit within w_spy end type type gb_last from groupbox within w_spy end type end forward shared variables int si_instances_counter = 0 end variables global type w_spy from window DAT*" integer width = 5358 integer height = 3272 boolean titlebar = true string title = "DataWindow Spy" boolean controlmenu = true windowtype windowtype = response! long backcolor = 67108864 string icon = "AppIcon!" boolean center = true cb_boostDAT*$_brain cb_boost_brain cb_club cb_club st_show_dw_attributes st_show_dw_attributes st_show_dw_size_and_coordinates st_show_dw_size_and_coordinates st_deleted_data st_deleted_data st_show_window_size_and_coordinates st_show_window_size_and_coordinaDAT*&tes st_filtered_data st_filtered_data st_updated_fields st_updated_fields st_row_status st_row_status st_field_info st_field_info st_show_dddw_data st_show_dddw_data st_sort_expr st_sort_expr st_filter_expr st_filter_expr st_invisible_fields sDAT*(t_invisible_fields st_data_src st_data_src st_menu st_menu st_classes_hierarchy st_classes_hierarchy cb_copy_to_clipboard cb_copy_to_clipboard cb_close cb_close gb_window gb_window gb_datawindow gb_datawindow gb_clicked_field gb_clicked_field DAT** gb_clicked_row gb_clicked_row dw_display dw_display mle_display mle_display gb_last gb_last end type global w_spy w_spy type variables /*********************************************************************************************************DAT*,************* How To Use: To open the Spy, press Shift and click on a DataWindow in a running application. To get information about a row or a field, click just on that row/field. **************************************************************DAT*.********************************************************* More details: http://code.intfast.ca/viewtopic.php?t=3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ************************************************************************DAT*0*********************************************** Licence: No licence needed, this utility is absolutely free. *********************************************************************************************************************** Developer: MichaDAT*2el Zuskin > http://linkedin.com/in/zuskin | http://code.intfast.ca/ *********************************************************************************************************************** Like in FB! https://www.facebook.com/pages/DataWindow-Spy/10DAT*41422093306662 **********************************************************************************************************************/ public: constant string PARM_NAME__DW = "dw" constant string PARM_NAME__ROW = "row" constant string PARMDAT*6_NAME__COL = "col_name" private: long il_row long il_row_count long il_filtered_count long il_deleted_count string is_spy_win_title string is_field_name string is_field_label string is_sort_expr string is_prev_sort_expr_of_dw_diDAT*8splay string is_filter_expr string is_updated_fields string is_data_source_stored_proc string is_data_source_sql_select boolean ib_clicked_on_row boolean ib_clicked_on_field boolean ib_field_has_dddw boolean ib_dw_has_retrieval_args DAT*:boolean ib_dw_has_rows boolean ib_dw_has_invisible_fields boolean ib_window_has_menu Menu im Window iw DataWindow idw StaticText ist_prev_clicked n_dwspy_util inv_util constant long COLOR__BLACK = 0 constant long COLOR__RED =DAT*< 255 constant long COLOR__YELLOW = 65535 constant long COLOR__GREY = 11053224 constant long COLOR__BLUE = 16711680 constant long COLOR__BROWN = 328896 constant long COLOR__FOR_NEXT_INSTANCES = COLOR__BROWN end variables forward prototypeDAT*>s private function string wf_get_updatable_frag (string as_field_name) private subroutine wf_format_sql (ref string rs_sql) private function string wf_get_field_type (string as_field_name) private function string wf_get_field_type (datawindowchildDAT*@ adwc, string as_field_name) private function string wf_get_field_path () private function string wf_get_code_table_frag () private subroutine wf_show_row_status () private subroutine wf_show_in_mle_display (string as_msg) private subroutine wf_dDAT*Bisplay_dw () private function string wf_ornament_as_subheader (string as_orig_string) private subroutine wf_sort_dw_display_by_column (string as_col_name) private function boolean wf_dw_is_external () private subroutine wf_show_window_info () priDAT*Dvate subroutine wf_show_data_in_buffer (dwbuffer a_buffer) private subroutine wf_get_computed_fields (datawindow adw, ref string rs_computed_field_names[], ref integer ri_computed_fields_qty) private subroutine wf_init_next_instances () private subDAT*Froutine wf_show_size_and_coordinates (datawindow adw) private subroutine wf_show_size_and_coordinates (window aw) private subroutine wf_show_size_and_coordinates (integer ai_x, integer ai_y, integer ai_width, integer ai_height) private subroutine wDAT*Hf_disable_static_text (statictext ast_to_disable, string as_text) private subroutine wf_disable_static_text (statictext ast_to_disable) private function boolean wf_property_defined (string as_property_value) private subroutine wf_init_visual_appearDAT*Jance () throws n_ex private function string wf_get_inheritance_chain (graphicobject ago) throws n_ex private subroutine wf_show_classes_hierarchy () throws n_ex private subroutine wf_show_menu () throws n_ex private subroutine wf_static_text_clickDAT*Led (statictext ast_clicked) throws n_ex private function string wf_get_retrieval_args_frag (powerobject apo) throws n_ex private subroutine wf_show_data_src () throws n_ex private function string wf_get_data_source_of_dddw_frag (datawindowchild adwDAT*Nc, string as_dddw_dataobject) throws n_ex private function string wf_get_dddw_frag (string as_val) throws n_ex private subroutine wf_show_field_info () throws n_ex private function string wf_get_field_status_as_string (string as_field_name) throws DAT*Pn_ex private subroutine wf_show_invisible_fields () throws n_ex private function string wf_get_val_frag (string as_field_name) throws n_ex private function string wf_get_field_info (string as_field_name) throws n_ex private function string wf_get_DAT*Rinvisible_computed_fields_frag () throws n_ex private function string wf_get_updated_fields () throws n_ex private function boolean wf_invisible_fields_exist (datawindow adw) throws n_ex private subroutine wf_init_instance_vars () throws n_ex privDAT*Tate subroutine wf_show_dddw_data () throws n_ex public subroutine wf_show_dw_attributes () end prototypes private function string wf_get_updatable_frag (string as_field_name);/**********************************************************************DAT*V************************************************ Dscr: Returns the message fragment describing if the field is updatable. *********************************************************************************************************************** Arg: aDAT*Xs_field_name *********************************************************************************************************************** Ret: string *******************************************************************************************************DAT*Z***************/ string ls_update_expr ls_update_expr = idw.Describe(as_field_name + ".Update") choose case ls_update_expr case "yes" return "Updatable" case "no" return "Not Updatable" case "!" // irrelevant return "" case else // dyDAT*\namic expression return "Update Expr='" + ls_update_expr + "'" end choose end function private subroutine wf_format_sql (ref string rs_sql);/*******************************************************************************************************DAT*^*************** Dscr: Gets SQL statement and changes all its keywords to upper case and the rest of the words - to lower case. ***********************************************************************************************************************DAT*` Arg: rs_sql ref SQL statement to process **********************************************************************************************************************/ inv_util.uf_replace_all(ref rs_sql, "~"","") inv_util.uf_replace_all(ref rs_sql, "selDAT*bect", "SELECT") inv_util.uf_replace_all(ref rs_sql, "from ", "~r~nFROM ") inv_util.uf_replace_all(ref rs_sql, "from ", "~r~nFROM ") inv_util.uf_replace_all(ref rs_sql, "from~r~n", "~r~nFROM~r~n") inv_util.uf_replace_all(ref rs_sql, "where", "~r~nWDAT*dHERE") inv_util.uf_replace_all(ref rs_sql, "order by", "~r~nORDER BY") inv_util.uf_replace_all(ref rs_sql, "group by", "~r~nGROUP BY") inv_util.uf_replace_all(ref rs_sql, "union", "~r~nUNION~r~n") inv_util.uf_replace_all(ref rs_sql, " and", " AND"DAT*f) inv_util.uf_replace_all(ref rs_sql, "and ", "AND ") inv_util.uf_replace_all(ref rs_sql, "or ", "OR ") inv_util.uf_replace_all(ref rs_sql, " or", " OR") inv_util.uf_replace_all(ref rs_sql, "in ", "IN ") inv_util.uf_replace_all(ref rs_sql, " in",DAT*h " IN") inv_util.uf_replace_all(ref rs_sql, "in(", " IN(") inv_util.uf_replace_all(ref rs_sql, "not ", "NOT ") inv_util.uf_replace_all(ref rs_sql, " not", " NOT") inv_util.uf_replace_all(ref rs_sql, "is null", "IS NULL") inv_util.uf_replace_all(rDAT*jef rs_sql, "is not null", "IS NOT NULL") inv_util.uf_replace_all(ref rs_sql, "exists", "EXISTS") inv_util.uf_replace_all(ref rs_sql, "between", "BETWEEN") return end subroutine private function string wf_get_field_type (string as_field_name);DAT*l/********************************************************************************************************************** Dscr: Returns field's datatype as string. ***************************************************************************************DAT*n******************************** Arg: as_field_name *********************************************************************************************************************** Ret: string ***************************************************************DAT*p*******************************************************/ string ls_field_type ls_field_type = idw.Describe(as_field_name + ".ColType") // "char(50)" ==>> "char 50": inv_util.uf_replace_all(ref ls_field_type, "(", " ") inv_util.uf_replace_all(DAT*rref ls_field_type, ")", "") return ls_field_type end function private function string wf_get_field_type (datawindowchild adwc, string as_field_name);/**********************************************************************************************DAT*t************************ Dscr: Returns DataWindowChild field's datatype as string. *********************************************************************************************************************** Arg: adwc (DataWindowChild) as_field_name DAT*v *********************************************************************************************************************** Ret: string ********************************************************************************************************************DAT*x**/ string ls_field_type ls_field_type = adwc.Describe(as_field_name + ".ColType") // "char(50)" ==>> "char 50": inv_util.uf_replace_all(ref ls_field_type, "(", " ") inv_util.uf_replace_all(ref ls_field_type, ")", "") return ls_field_type DAT*z end function private function string wf_get_field_path ();/********************************************************************************************************************** Dscr: Returns the ckicked field's path (like w_xxx.tab_xxx.tabpage_xDAT*|xx.dw_xxx.field_name[3]) *********************************************************************************************************************** Ret: string *******************************************************************************************DAT*~***************************/ string ls_path string ls_objects[] int i int li_qty_of_objects GraphicObject lgo_curr ls_objects[1] = "object." + Lower(is_field_name) + "[" + String(il_row) + "]" // Fill ls_objects with objects nameDAT*s from DW to Window: lgo_curr = idw i = 2 do while true ls_objects[i] = lgo_curr.ClassName() lgo_curr = lgo_curr.GetParent() if not IsValid(lgo_curr) /* the window is reached */ then exit end if i++ loop // Build the pass moving frDAT*om Window to Field: li_qty_of_objects = UpperBound(ls_objects[]) for i = li_qty_of_objects to 1 step -1 ls_path += ls_objects[i] + "." next inv_util.uf_remove_chars_from_end(ref ls_path, 1) // remove the last "." return ls_path end function DAT* private function string wf_get_code_table_frag ();/********************************************************************************************************************** Dscr: Returns to wf_show_field_info the fragment with code table info ("" if DAT*no code table) *********************************************************************************************************************** Ret: string *****************************************************************************************************DAT******************/ string ls_frag ls_frag = idw.Describe(is_field_name + ".Values") if not wf_property_defined(ls_frag) then return "" // Display Code Table as pairs 'Displayed Value' - 'Stored Value': inv_util.uf_replace_all(ref ls_frag, " "DAT*, "' - '") inv_util.uf_replace_all(ref ls_frag, "/", "'~r~n'") ls_frag = "'" + ls_frag + "'" inv_util.uf_replace_all(ref ls_frag, "'' - ", "'<No Displayed Value - Stored is displayed>' - ") // no description - display code only inv_util.uf_replaceDAT*_all(ref ls_frag, " - ''", " - '<No Stored Value - Displayed is stored>'") // no code - display description only inv_util.uf_remove_chars_from_end(ref ls_frag, 4) // remove "'~r~n'" ls_frag = "~r~n~r~n########## Code Table:~r~n~r~n'Displayed ValueDAT*' - 'Stored Value'~r~n~r~n==================================~r~n" + ls_frag return ls_frag end function private subroutine wf_show_row_status ();/**************************************************************************************************DAT********************* Dscr: Displays DWItemStatus of the clicked row. **********************************************************************************************************************/ DWItemStatus l_row_status string ls_row_status l_row_DAT*status = idw.GetItemStatus(il_row, 0, Primary!) choose case l_row_status case New! ls_row_status = "New!" case NewModified! ls_row_status = "NewModified!" case NotModified! ls_row_status = "NotModified!" case DataModified! ls_row_statusDAT* = "DataModified!" end choose wf_show_in_mle_display(ls_row_status) return end subroutine private subroutine wf_show_in_mle_display (string as_msg);/*******************************************************************************************DAT**************************** Dscr: Displays message in mle_display. *********************************************************************************************************************** Arg: as_msg - to be displayed in mle_display ***************DAT********************************************************************************************************/ dw_display.Hide() mle_display.Show() cb_copy_to_clipboard.Enabled = true mle_display.Text = as_msg return end subroutine private suDAT*broutine wf_display_dw ();/********************************************************************************************************************** Decr: Displays message in dw_display. *****************************************************************DAT******************************************************/ dw_display.Show() mle_display.Hide() cb_copy_to_clipboard.Enabled = false return end subroutine private function string wf_ornament_as_subheader (string as_orig_string);return Left("##DAT*#### " + as_orig_string + ": ############################################", 50) + "~r~n~r~n" end function private subroutine wf_sort_dw_display_by_column (string as_col_name);/***********************************************************************DAT************************************************ Dscr: Sorts DW by a double-clicked column. *********************************************************************************************************************** Arg: as_col_name *******************DAT****************************************************************************************************/ string ls_db_name string ls_new_sort_expr_of_dw_display string ls_prev_sort_col if dw_display.RowCount() = 1 then return //???mzif Right(as_cDAT*ol_name, 2) = "_t" /* user double-clicked on a column's header */ then if inv_util.uf_ends_with(as_col_name, "_t") /* user double-clicked on a column's header */ then inv_util.uf_remove_chars_from_end(ref as_col_name, 2) // remove "_t" end if lDAT*s_db_name = dw_display.Describe(as_col_name + '.DBName') if not wf_property_defined(ls_db_name) /* no such column - the header in NOT named by the "<column name>_t" pattern */ then MessageBox("DW Spy - Sort by Column", "Double-click on the field itDAT*self~r~n(in one of the rows), NOT on its header.") return end if if is_prev_sort_expr_of_dw_display = as_col_name + " A" /* has been previously sorted in ASC order */ then ls_new_sort_expr_of_dw_display = as_col_name + " D" // change sort ordeDAT*r to DESC dw_display.Modify(as_col_name + ".Color=" + String(COLOR__RED)) else ls_new_sort_expr_of_dw_display = as_col_name + " A" dw_display.Modify(as_col_name + ".Color=" + String(COLOR__BLUE)) end if dw_display.SetSort(ls_new_sort_expr_oDAT*f_dw_display) dw_display.Sort() if is_prev_sort_expr_of_dw_display <> "" /* this function has already been called */ then // return black color to the column the previous sort was made by: inv_util.uf_remove_chars_from_end(ref is_prev_sort_expDAT*r_of_dw_display, 2) // remove " A" or " D" if as_col_name <> ls_prev_sort_col /* this function is called for a different column than in the previous time */ then dw_display.Modify(ls_prev_sort_col + ".Color=0") end if end if is_prev_sort_exDAT*pr_of_dw_display = ls_new_sort_expr_of_dw_display return end subroutine private function boolean wf_dw_is_external ();/********************************************************************************************************************** Dscr:DAT* Reports if the DW is external. *********************************************************************************************************************** Ret: boolean: true - external, false - has a data source (SQL SELECT or stored proc) ***********DAT************************************************************************************************************/ is_data_source_sql_select = idw.GetSQLSelect() if is_data_source_sql_select <> "" then wf_format_sql(ref is_data_source_sql_select) reDAT*turn false end if is_data_source_stored_proc = inv_util.uf_get_proc_of_dataobject(idw.DataObject) if is_data_source_stored_proc <> "" then return false end if return true end function private subroutine wf_show_window_info ();/******DAT***************************************************************************************************************** Dscr: Displays the window's size and coordinates. **************************************************************************************DAT*********************************/ string ls_window_info ls_window_info = "X = " + String(iw.X) + "~r~n" + & "Y = " + String(iw.Y) + "~r~n" + & "Width = " + String(iw.Width) + "~r~n" + & "Height = " + String(iw.Height) wf_shDAT*ow_in_mle_display(ls_window_info) return end subroutine private subroutine wf_show_data_in_buffer (dwbuffer a_buffer);wf_display_dw() dw_display.DataObject = idw.DataObject choose case a_buffer case Filter! dw_display.Object.Data.primaryDAT* = idw.Object.Data.filter case Delete! dw_display.Object.Data.primary = idw.Object.Data.delete case Primary! dw_display.Object.Data.primary = idw.Object.Data.primary end choose return end subroutine private subroutine wf_get_computed_fDAT*ields (datawindow adw, ref string rs_computed_field_names[], ref integer ri_computed_fields_qty);/********************************************************************************************************************** Dscr: Returns array of computed fDAT*ields (visible and invisible) contained in idw. *********************************************************************************************************************** Arg: rs_computed_field_names[] - BY REF ****************************************DAT******************************************************************************** Ret: the number of returned computed fields (int) **********************************************************************************************************************/DAT* int li_start_pos = 1 int li_tab_pos string ls_list_of_all_objects string ls_obj_name ls_list_of_all_objects = Describe(adw, "datawindow.objects") ri_computed_fields_qty = 0 li_tab_pos = Pos(ls_list_of_all_objects, "~t", li_start_pos) doDAT* while li_tab_pos > 0 ls_obj_name = Mid(ls_list_of_all_objects, li_start_pos, (li_tab_pos - li_start_pos)) if Describe(adw, ls_obj_name + ".type") = "compute" then ri_computed_fields_qty++ rs_computed_field_names[ri_computed_fields_qty] = lsDAT*_obj_name end if li_start_pos = li_tab_pos + 1 li_tab_pos = Pos(ls_list_of_all_objects, "~t", li_start_pos) loop return end subroutine private subroutine wf_init_next_instances ();/********************************************************DAT*************************************************************** Dscr: If this instance is open for dw_display of the previous instance of Spy (i.e. user pressed Shift and clicked on an already open instance of the Spy), this function changes visualDAT* appearance of the Spy to remind user that the explored DW doesn't belong to the application. Called from wf_init_visual_appearance. ******************************************************************************************************************DAT*****/ int i int li_frames_qty GroupBox lgb_frames[] if si_instances_counter = 1 then return // Change background color to red (and frames texts to yellow): this.BackColor = COLOR__FOR_NEXT_INSTANCES lgb_frames[] = {gb_window, gb_daDAT*tawindow, gb_clicked_field, gb_clicked_row, gb_last} li_frames_qty = UpperBound(lgb_frames[]) for i = 1 to li_frames_qty lgb_frames[i].BackColor = COLOR__FOR_NEXT_INSTANCES lgb_frames[i].TextColor = COLOR__YELLOW next // Disable some statiDAT*c texts to prevent displaying the info dw_display of the previous Spy: wf_disable_static_text(st_classes_hierarchy) wf_disable_static_text(st_show_window_size_and_coordinates) wf_disable_static_text(st_show_dw_size_and_coordinates) wf_disable_stDAT*atic_text(st_show_dw_attributes) return end subroutine private subroutine wf_show_size_and_coordinates (datawindow adw);/********************************************************************************************************************** DAT*Dscr: Displays the DW's size and coordinates. **********************************************************************************************************************/ wf_show_size_and_coordinates(adw.X, adw.Y, adw.Width, adw.Height) return end DAT*subroutine private subroutine wf_show_size_and_coordinates (window aw);/********************************************************************************************************************** Dscr: Displays the Window's size and coordinates. *****DAT******************************************************************************************************************/ wf_show_size_and_coordinates(aw.X, aw.Y, aw.Width, aw.Height) return end subroutine private subroutine wf_show_size_and_coordiDAT*nates (integer ai_x, integer ai_y, integer ai_width, integer ai_height);/********************************************************************************************************************** Dscr: Displays the object's size and coordinates. *******DAT****************************************************************************************************************/ string ls_info ls_info = "X = " + String(ai_x) + "~r~n" + & "Y = " + String(ai_y) + "~r~n" + & "Width = " + String(ai_width)DAT* + "~r~n" + & "Height = " + String(ai_height) wf_show_in_mle_display(ls_info) return end subroutine private subroutine wf_disable_static_text (statictext ast_to_disable, string as_text);/*************************************************DAT********************************************************************** Dscr: Disables st visually. *********************************************************************************************************************** Arg: ast_to_disable (StaticTexDAT*t) as_text (string) - the text to put on the disabled StaticText; pass empty string to keep the existing text. **********************************************************************************************************************/ ast_to_disablDAT*e.TextColor = COLOR__GREY ast_to_disable.Enabled = false if as_text <> '' then ast_to_disable.Text = as_text end if return end subroutine private subroutine wf_disable_static_text (statictext ast_to_disable);/****************************DAT******************************************************************************************* Dscr: Disables st visually. *********************************************************************************************************************** Arg: ast_DAT*clicked (StaticText) **********************************************************************************************************************/ wf_disable_static_text(ast_to_disable, '' /* empty string means "keep the existing text" */) return enDAT*d subroutine private function boolean wf_property_defined (string as_property_value);if as_property_value = "!" then return false if as_property_value = "?" then return false return true end function private subroutine wf_init_visual_appearDAT*ance () throws n_ex;/********************************************************************************************************************** Dscr: Enables/sets text of command buttons ******************************************************************DAT*****************************************************/ SetRedraw(false) ///////////////////////////////// // Frame "Inheritance Chains": // ///////////////////////////////// // st_menu: if not ib_window_has_menu then wf_disable_static_text(DAT*st_menu, "No menu in window") end if ///////////////////////// // Frame "DataWindow": // ///////////////////////// // st_data_src: if wf_dw_is_external() then wf_disable_static_text(st_data_src, "External DW - No Data Source") else if iDAT*b_dw_has_retrieval_args then st_data_src.Text = "Data Source and Arguments" end if end if // st_invisible_fields: if not ib_dw_has_invisible_fields then wf_disable_static_text(st_invisible_fields, "No Invisible Fields") end if // st_fiDAT*lter_expr: if not wf_property_defined(is_filter_expr) then wf_disable_static_text(st_filter_expr, "No Filter Applied") end if // st_filtered_data: if il_filtered_count > 0 then st_filtered_data.Text = "Filtered Rows (" + String(il_filtered_cDAT*ount) + ")" else wf_disable_static_text(st_filtered_data, "No Filtered Rows") end if // st_deleted_data: if il_deleted_count > 0 then st_deleted_data.Text = "Deleted Rows (" + String(il_deleted_count) + ")" else wf_disable_static_text(st_DAT*deleted_data, "No Deleted Rows") end if // st_sort_expr: if not wf_property_defined(is_sort_expr) then wf_disable_static_text(st_sort_expr, "No Sort Applied") end if //////////////////////////// // Frame "Clicked Field": // //////////////DAT*////////////// // The frame: gb_clicked_field.Enabled = ib_clicked_on_field gb_clicked_field.Text = "Field " + iif(ib_clicked_on_field, "~"" + is_field_label + "~"", "(click on a field to activate)") // st_field_info: if not ib_clicked_on_fieldDAT* then wf_disable_static_text(st_field_info) end if // st_show_dddw_data: if not ib_field_has_dddw then if ib_clicked_on_field then st_show_dddw_data.Text = "No DDDW in the Field" end if wf_disable_static_text(st_show_dddw_data) end ifDAT* ////////////////////////// // Frame "Clicked Row": // ////////////////////////// // The frame: gb_clicked_row.Enabled = ib_clicked_on_row if ib_clicked_on_row then gb_clicked_row.Text = "Row" if il_row_count > 1 then gb_clicked_row.TextDAT* += " #" + String(il_row) else gb_clicked_row.Text = "Row (click on a row to activate)" end if // st_updated_fields, st_row_status: if ib_clicked_on_row then if not inv_util.uf_row_modified(idw, il_row) then wf_disable_static_text(st_updaDAT*ted_fields, "No Updated Fields in the Row") end if else wf_disable_static_text(st_updated_fields) wf_disable_static_text(st_row_status) end if /////////////////// // Window Title: // /////////////////// is_spy_win_title = "DW Spy for: DAT*" if si_instances_counter = 1 then is_spy_win_title += idw.ClassName() + " (" + idw.DataObject + ")" else is_spy_win_title += idw.DataObject end if if ib_clicked_on_field then is_spy_win_title += " *** FIELD: ~"" + is_field_label + "~" ("DAT*  + is_field_name + ")" end if if ib_clicked_on_row then is_spy_win_title += " *** ROW #" + String(il_row) + " of " + String(il_row_count) end if this.Title = is_spy_win_title //////////// // Other: // //////////// wf_init_next_instanDAT* ces() SetRedraw(true) return end subroutine private function string wf_get_inheritance_chain (graphicobject ago) throws n_ex;/*********************************************************************************************************************DAT** Dscr: Returns inheritance chain of the passed control. The chain begins with the name of the control itself (as it appears on the containing window, tab or other user object) and ends with the PB built-in class (like DataWindow, UserObjectDAT* etc.) The rest of the inheritance is not included because it is obvious. Example: if a pointer to dw_cust is passed then the function will return something like "dw_cust -> dw_cust (cust.pbl) -> u_dw (pfemain.pbl) -> pfc_u_dw (pfcmain.pbl) -DAT*> DataWindow" *********************************************************************************************************************** Arg: ago GraphicObject *******************************************************************************************DAT***************************** Ret: string **********************************************************************************************************************/ string ls_base_pb_class // the first reached PB's built-in class (like DataWindow, TDAT*ab etc.) // it will be the last class shown in the chain, // we don't want to continue until PowerObject string ls_built_chain string ls_indents_accumulator Object lo_type_of_arg Window lw DataWindow ldw UDAT*serObject luo Tab ltab Menu lm ClassDefinition lcd // Begin building the chain with the passed class itself: ls_built_chain = ago.ClassName() ls_built_chain += inv_util.uf_get_pbl_of_class(ls_built_chain) // Obtain the ClassDefiniDAT*tion and the last class in chain (the first built-in PB class) for the passed class: lo_type_of_arg = ago.TypeOf() choose case lo_type_of_arg case Window! ls_base_pb_class = "Window" lw = ago // cast from GraphicObject to Window lcd = lw.ClasDAT*sDefinition case DataWindow! ls_base_pb_class = "DataWindow" ldw = ago // cast from GraphicObject to DataWindow lcd = ldw.ClassDefinition case UserObject! // including tabpage ls_base_pb_class = "UserObject" luo = ago // cast from GraphicODAT*bject to UserObject lcd = luo.ClassDefinition case Tab! ls_base_pb_class = "Tab" ltab = ago // cast from GraphicObject to Tab lcd = ltab.ClassDefinition case Menu! ls_base_pb_class = "Menu" lm = ago // cast from GraphicObject to Menu lDAT* cd = lm.ClassDefinition case else f_throw(PopulateError(0, "Unknown type of control " + ago.ClassName())) end choose // Loop through hierarchy of ancestor ClassDefinitions: do while true lcd = lcd.Ancestor if lcd.Name = Lower(ls_base_pb_clDAT*"ass) /* we have reached the first PB built-in class */ then exit ls_indents_accumulator += " " // accumulate one more indent to manage stairs-style indenting ls_built_chain += "~r~n" + ls_indents_accumulator + lcd.Name + inv_util.uf_get_pbl_of_DAT*$class(lcd.Name) loop if ls_built_chain = "" then return "" ls_built_chain = wf_ornament_as_subheader(Upper(ls_base_pb_class)) + ls_built_chain return ls_built_chain end function private subroutine wf_show_classes_hierarchy () throws n_exDAT*&;/********************************************************************************************************************** Dscr: Displays objects visible on the window (like Menu -> Window -> Tab -> TabPage -> DW -> DataObject -> Stored Proc) Each lDAT*(evel is presented as an inheritance chain (if the object is inherited). **********************************************************************************************************************/ int i // index var for both ls_class_names[] and lgo_oDAT**bjects[] int li_classes_qty string ls_class_info string ls_hierarchy string ls_class_names[] string ls_control_kinds[] GraphicObject lgo_objects[] GraphicObject lgo_curr SetPointer(HourGlass!) // Populate DW's stored proc (likDAT*,e "sp_XXX"): ls_class_names[1] = is_data_source_stored_proc ls_control_kinds[1] = iif(is_data_source_stored_proc = '', '', "STORED PROCEDURE (DW'S DATA SOURCE)") SetNull(lgo_objects[1]) // irrelevant // Populate DataObject (like "d_XXX"): ls_clDAT*.ass_names[2] = idw.DataObject ls_control_kinds[2] = "DATAOBJECT" SetNull(lgo_objects[2]) // irrelevant // Populate the DW userobject (like "dw_XXX"): ls_class_names[3] = idw.ClassName() ls_control_kinds[3] = "DATAWINDOW" lgo_objects[3] = idw DAT*0 // Loop getting the parent of the object until the window is reached: lgo_curr = idw i = 3 do while true lgo_curr = lgo_curr.GetParent() if not IsValid(lgo_curr) /* the window is reached */ then exit // now ls_class_names[] and lgo_objectsDAT*2[] contain all objects of hierarchy (names and pointers) end if i++ ls_class_names[i] = lgo_curr.ClassName() ls_control_kinds[i] = Upper(ls_class_names[i]) lgo_objects[i] = lgo_curr loop // Build result string: li_classes_qty = UpperBouDAT*4nd(ls_class_names[]) for i = li_classes_qty to 1 step -1 // loop back to diplay window first and proc (if no proc then DataObject) last // Obtain class info of current class: choose case i case 1 // stored proc ls_class_info = ls_class_namesDAT*6[1] // only name, no additional info case 2 // DataObject ("d_..."): ls_class_info = ls_class_names[i] + inv_util.uf_get_pbl_of_class(ls_class_names[i]) case li_classes_qty // Window - the last object in the array: ls_class_info = wf_get_inhDAT*8eritance_chain(lgo_objects[i]) case else // UserObject (visual custom or TabPage) or Tab ls_class_info = wf_get_inheritance_chain(lgo_objects[i]) end choose // Add currently processed object to result string: if ls_hierarchy <> "" then ls_hDAT*:ierarchy += "~r~n~r~n" choose case i case 1 if ls_control_kinds[1] <> "" /* the DW's data source is "Stored Procedure" */ then ls_hierarchy += wf_ornament_as_subheader(ls_control_kinds[1]) end if case 2 ls_hierarchy += wf_ornamenDAT*<t_as_subheader(ls_control_kinds[2]) case else // the kind of control has already been added by wf_get_inheritance_chain end choose ls_hierarchy += ls_class_info next SetPointer(Arrow!) wf_show_in_mle_display(ls_hierarchy) return enDAT*>d subroutine private subroutine wf_show_menu () throws n_ex;/********************************************************************************************************************** Dscr: Displays the window menu with inheritance chain and PBL of eaDAT*@ch object. **********************************************************************************************************************/ string ls_menu_info ls_menu_info = wf_get_inheritance_chain(im) wf_show_in_mle_display(ls_menu_info) return enDAT*Bd subroutine private subroutine wf_static_text_clicked (statictext ast_clicked) throws n_ex;/********************************************************************************************************************** Dscr: 1. Changes the clicked StaticDAT*DText's text appearance so user easily sees which "button" has been clicked last (and, accordingly, what information is currently shown). 2. Calls spy's functionality depending on the clicked st. ***********************************************DAT*F************************************************************************ Arg: ast_clicked (StaticText) **********************************************************************************************************************/ string ls_text string lsDAT*H_updated_fields constant int NORMAL = 400 constant int BOLD = 700 if ast_clicked = ist_prev_clicked /* one more click on a same st */ then return end if if IsValid(ist_prev_clicked) then ist_prev_clicked.BorderStyle = StyleRaised! istDAT*J_prev_clicked.Weight = NORMAL ist_prev_clicked.TextColor = COLOR__BLACK end if ist_prev_clicked = ast_clicked // remember that this StaticText was clicked ast_clicked.BorderStyle = StyleLowered! ast_clicked.Weight = BOLD ast_clicked.TextColDAT*Lor = COLOR__BROWN ls_text = ast_clicked.Text choose case ast_clicked // Window frame: case st_classes_hierarchy wf_show_classes_hierarchy() case st_menu wf_show_menu() case st_show_window_size_and_coordinates inv_util.uf_replace_all(rDAT*Nef ls_text, "&&", "&") wf_show_size_and_coordinates(iw) // DataWindow frame: case st_data_src wf_show_data_src() case st_invisible_fields wf_show_invisible_fields() case st_sort_expr wf_show_in_mle_display(is_sort_expr) case st_filter_eDAT*Pxpr wf_show_in_mle_display(is_filter_expr) case st_filtered_data wf_show_data_in_buffer(Filter!) case st_deleted_data wf_show_data_in_buffer(Delete!) case st_show_dw_attributes wf_show_dw_attributes() // Field frame: case st_field_info DAT*R wf_show_field_info() case st_show_dddw_data wf_show_dddw_data() case st_show_dw_size_and_coordinates inv_util.uf_replace_all(ref ls_text, "&&", "&") wf_show_size_and_coordinates(idw) // Row frame: case st_row_status wf_show_row_status(DAT*T) case st_updated_fields ls_updated_fields = wf_get_updated_fields() wf_show_in_mle_display(ls_updated_fields) case else f_throw(PopulateError(0, "StaticText '" + ls_text + "' has no 'case' in 'choose case'.")) end choose // Reflect clicDAT*Vked StaticText in the window's title: this.Title = is_spy_win_title + " *** " + ls_text return end subroutine private function string wf_get_retrieval_args_frag (powerobject apo) throws n_ex;/***************************************************DAT*X******************************************************************* Dscr: Returns a message fragment which lists idw's retrieval arguments and their values, in a multirow format: arg_name1 = arg_value1 (datatype1) arg_name2 = arg_value2 (dataDAT*Ztype2) ... arg_nameN = arg_valueN (datatypeN) *********************************************************************************************************************** Arg: apo (PowerObject) - pointer to DataWindow or DataWindowChild. *******DAT*\**************************************************************************************************************** Ret: string **********************************************************************************************************************/ strDAT*^ing ls_args[] string ls_arg_name string ls_arg_val string ls_arg_datatype string ls_frag // the fragment built and returned by this function string ls_frag_header string ls_args_list boolean lb_arg_val_is_null int li_args_qty int i int liDAT*`_tab_pos choose case apo.TypeOf() case DataWindow! if not ib_dw_has_retrieval_args then return "" ls_args_list = apo.dynamic Describe("DataWindow.Table.Arguments") ls_frag_header = "~r~n~r~n########## Retrieval Arguments and their Values:~r~DAT*bn~r~n" case DataWindowChild! ls_args_list = apo.dynamic Describe("DataWindow.Table.Arguments") if ls_args_list = "?" /* no ret. args */ then return "" // don't display the "DDDW's Retrieval Arguments and their Values" section at all ls_frag_heaDAT*dder = "~r~n~r~n########## DDDW's Retrieval Arguments and their Values:~r~n~r~n" case else f_throw(PopulateError(0, "Invalid type of 'apo' argument: " + apo.ClassName() + ". It must be DataWindow! or DataWindowChild!.")) end choose // ls_args_liDAT*fst contains now the list of the ret. args in the format, returned by Describe("DataWindow.Table.Arguments"), like // "arg_name1<tab>datatype1<new line>arg_name2<tab>datatype2<new line>...arg_nameN<tab>datatypeN" // Convert it to an array in format {DAT*h"arg_name1<new line>datatype1", "arg_name2<new line>datatype2", ... "arg_nameN<new line>datatypeN"}: li_args_qty = inv_util.uf_string_to_array(ls_args_list, "~n", ref ls_args[]) // Process each retrieval arg: for i = 1 to li_args_qty li_tab_posDAT*j = Pos(ls_args[i], "~t") ls_arg_name = Left(ls_args[i], li_tab_pos - 1) // Obtain argument's value: lb_arg_val_is_null = (apo.dynamic Describe("Evaluate('If(IsNull(" + ls_arg_name + "), 1, 0)', 0)") = "1") if lb_arg_val_is_null then ls_aDAT*lrg_val = "NULL" else ls_arg_val = apo.dynamic Describe("Evaluate('" + ls_arg_name + "', 0)" ) ls_arg_datatype = Right(ls_args[i], Len(ls_args[i]) - li_tab_pos) if iin(Left(ls_arg_datatype, 4), {"char", "stri", "date", "time"}) then ls_aDAT*nrg_val = "'" + ls_arg_val + "'" end if end if if ls_frag <> '' then ls_frag += "~r~n" ls_frag += ls_arg_name + " = " + ls_arg_val + " (" + ls_arg_datatype + ")" next return ls_frag_header + ls_frag end function private subroutine wDAT*pf_show_data_src () throws n_ex;/********************************************************************************************************************** Dscr: Displays the DW's Data Source (SELECT, Stored Proc or "External DW, no data source."). *****DAT*r*****************************************************************************************************************/ string ls_retrieval_args_frag ls_retrieval_args_frag = wf_get_retrieval_args_frag(idw) choose case true case is_data_source_sql_DAT*tselect <> "" wf_show_in_mle_display(is_data_source_sql_select + ls_retrieval_args_frag) case is_data_source_stored_proc <> "" wf_show_in_mle_display("########## Stored Procedure:~n~r~n~r~n~r" + is_data_source_stored_proc + ls_retrieval_args_frag)DAT*v case else wf_show_in_mle_display("DW Spy Error - Unknown data source in w_spy.wf_show_data_src :-(") end choose return end subroutine private function string wf_get_data_source_of_dddw_frag (datawindowchild adwc, string as_dddw_dataobject)DAT*x throws n_ex;/********************************************************************************************************************** Dscr: Displays the DW's Data Source (SELECT, Stored Proc or 'External DW, no data source.'). ***********************DAT*z************************************************************************************************ Arg: adwc (DataWindowChild) as_dddw_dataobject ******************************************************************************************************DAT*|****************/ string ls_sql string ls_proc string ls_retrieval_args_frag // Prepare "Retrieval Arguments" fragment of message: ls_retrieval_args_frag = wf_get_retrieval_args_frag(adwc) // If data source is SQL SELECT... ls_sql = adwc.GeDAT*~tSQLSelect() if ls_sql <> "" /* the data source is an SQL SELECT */ then wf_format_sql(ref ls_sql) return "~r~n~r~n########## DDDW's SQL Select:~r~n~r~n" + ls_sql + ls_retrieval_args_frag end if // If data source is Stored Procedure... ls_prDAT*oc = inv_util.uf_get_proc_of_dataobject(as_dddw_dataobject) if ls_proc <> "" /* the data source is a stored proc */ then return "~r~n~r~n########## DDDW's Stored Procedure:~r~n~r~n" + ls_proc + ls_retrieval_args_frag end if // If this code reacDAT*hed - external dw: return "~r~n~r~n########## DDDW's Data Source:~r~n~r~nExternal DW, no data source." + ls_retrieval_args_frag end function private function string wf_get_dddw_frag (string as_val) throws n_ex;/***********************************DAT************************************************************************************ Dscr: Returns to wf_show_field_info the fragment with DDDW info ("" if no DDDW) *************************************************************************************DAT*********************************** Arg: as_val - the displayed value *********************************************************************************************************************** Ret: string **********************************************DAT*************************************************************************/ int li_dwc_row string ls_data_source_of_dddw_frag string ls_dddw_dataobject string ls_pbl string ls_display_col string ls_data_col string ls_data_anDAT*d_display_cols_msg string ls_search_expr string ls_val_of_display_col string ls_dddw_frag DataWindowChild ldwc if not ib_field_has_dddw then return "" // Initial actions - populate local vars: ls_data_col = Upper(idw.Describe(is_fiDAT*eld_name + ".DDDW.DataColumn")) ls_display_col = Upper(idw.Describe(is_field_name + ".DDDW.DisplayColumn")) ls_dddw_dataobject = idw.Describe(is_field_name + ".DDDW.Name") ls_pbl = inv_util.uf_get_pbl_of_class(ls_dddw_dataobject) idw.GetChild(is_fDAT*ield_name, ref ldwc) ls_data_source_of_dddw_frag = wf_get_data_source_of_dddw_frag(ldwc, ls_dddw_dataobject) // Define Data and Display Column and their values: if ls_data_col = ls_display_col /* same field is used as Data Column and Display ColuDAT*mn */ then ls_data_and_display_cols_msg = & "~r~nData/Display Column = " + ls_data_col + " (Value" + as_val + & ", Type = " + wf_get_field_type(ldwc, ls_data_col) + ")" else // different fields are used as Data Column and Display ColumDAT*n ls_search_expr = "String(" + ls_data_col + ") = String(" + as_val +")" li_dwc_row = ldwc.Find(ls_search_expr, 1, ldwc.RowCount()) if li_dwc_row > 0 then ls_val_of_display_col = inv_util.uf_get_item_as_string(ldwc, li_dwc_row, ls_displayDAT*_col) ls_data_and_display_cols_msg = & "~r~nData Column = " + ls_data_col + " (Value = " + as_val + & ", Type = " + wf_get_field_type(ldwc, ls_data_col) + ")" + & "~r~nDisplay Column = " + ls_display_col + " (Value = " + ls_val_oDAT*f_display_col + & ", Type = " + wf_get_field_type(ldwc, ls_display_col) + ")" end if end if // Build the whole DDDW fragment of message: ls_dddw_frag = "~r~n~r~n########## DDDW Info:" + & "~r~n~r~nDataObject = ~"" + ls_dddw_datDAT*aobject + "~"" + ls_pbl + & ls_data_and_display_cols_msg + & ls_data_source_of_dddw_frag return ls_dddw_frag end function private subroutine wf_show_field_info () throws n_ex;/********************************************************DAT*************************************************************** Dscr: Displays the field info (names in DW and DB, status, type etc.) ********************************************************************************************************************DAT***/ boolean lb_field_is_computed int i int li_attributes_qty string ls_attributes[] string ls_attribute_val string ls_field_type string ls_field_name_in_db string ls_field_info string ls_enabled_expr string ls_protect_expr string ls_updatDAT*able_frag string ls_field_status string ls_filter string ls_val string ls_expr SetPointer(HourGlass!) // Obtain basic field info: ls_val = inv_util.uf_get_item_as_string(idw, il_row, is_field_name) ls_field_type = wf_get_field_type(is_fielDAT*d_name) ls_field_name_in_db = Upper(idw.Describe(is_field_name + ".DBName")) ls_enabled_expr = idw.Describe(is_field_name + ".Enabled") ls_protect_expr = idw.Describe(is_field_name + ".Protect") lb_field_is_computed = not wf_property_defined(ls_fiDAT*eld_name_in_db) if lb_field_is_computed then ls_expr = idw.Describe(is_field_name + ".Expression") ls_field_info += "########## Computed Field~r~n~r~nField Name = " + is_field_name + "~r~nData Type = " + ls_field_type else ls_field_status = DAT*wf_get_field_status_as_string(is_field_name) ls_field_info += "Field Name = " + is_field_name if ls_field_name_in_db <> is_field_name then ls_field_info += "~r~nDB Name = " + ls_field_name_in_db end if ls_field_info += "~r~nData Type = " + DAT*ls_field_type + "~r~n~r~nDWItemStatus = " + ls_field_status end if ls_val = wf_get_val_frag(is_field_name) ls_field_info += "~r~nValue" + ls_val ls_field_info += "~r~n~r~n" + wf_get_updatable_frag(is_field_name) if wf_property_defined(ls_enDAT*abled_expr) then ls_field_info += "~r~nEnabled = '" + ls_enabled_expr + "'" end if if ls_protect_expr <> "!" and ls_protect_expr <> "0" then inv_util.uf_replace_all(ref ls_protect_expr, "0 ", "") ls_field_info += "~r~nProtect = " + ls_proteDAT*ct_expr end if if lb_field_is_computed then ls_field_info += "~r~n~r~n########## Computed Expression:~r~n~r~n" + ls_expr end if ls_field_info += wf_get_dddw_frag(ls_val) // returns empty string if the field doesn't have a DDDW ls_field_infoDAT* += wf_get_code_table_frag() // returns empty string if the field doesn't have a code table if si_instances_counter = 1 then ls_field_info += "~r~n~r~n########## Dot Notation Path:~r~n~r~n" + wf_get_field_path() end if ls_field_info += "~r~n~DAT*r~n########## Attributes:~r~n" ls_attribute_val = idw.Describe(is_field_name + ".Attributes") li_attributes_qty = inv_util.uf_string_to_array(ls_attribute_val, " ", ref ls_attributes[]) for i = 1 to li_attributes_qty if iin(ls_attributes[i], DAT*{"attributes", "name", "dbname", "type", "update", "coltype"}) then continue // they have already been added to the displayed message earlier in this function ls_attribute_val = idw.Describe(is_field_name + "." + ls_attributes[i]) if not wf_proDAT*perty_defined(ls_attribute_val) then continue if ls_field_info <> '' then ls_field_info += "~r~n" ls_field_info += ls_attributes[i] + " = " + ls_attribute_val next SetPointer(Arrow!) wf_show_in_mle_display(ls_field_info) return end sDAT*ubroutine private function string wf_get_field_status_as_string (string as_field_name) throws n_ex;/********************************************************************************************************************** Dscr: Returns the specified DAT*field's status as a string (to be displayed to the user). *********************************************************************************************************************** Arg: as_field_name ***************************************************DAT********************************************************************* Ret: string **********************************************************************************************************************/ DWItemStatus l_field_status l_field_status =DAT* idw.GetItemStatus(il_row, as_field_name, Primary!) choose case l_field_status case NotModified! return "NotModified!" case DataModified! return "DataModified!" end choose f_throw(PopulateError(0, "Unknown DWItemStatus.")) return "" eDAT*nd function private subroutine wf_show_invisible_fields () throws n_ex;/********************************************************************************************************************** Dscr: Displays invisible fields info. *****************DAT******************************************************************************************************/ boolean lb_all_fields_have_same_status boolean lb_all_fields_have_same_updatable_frag string ls_dwitemstatus_of_all_fields = "" string ls_updateDAT*_property_of_all_fields = "" string ls_result // the text to be displayed in mle_display; finally, will consist of all the rows, stored in ls_result_rows[] string ls_result_rows[] // one row for each invisible column; row consists of field info (naDAT*me, value, type) + [optionally] field status (DWItemStatus) + [optionally] updatable fragment (Updatable / Not Updatable) string ls_field_infos[] // name, value, type string ls_field_statuses[] // DWItemStatus string ls_updatable_fragments[] // UpdDAT*atable / Not Updatable string ls_curr_field_name int li_all_fields_qty int li_all_fields_idx int li_prev_idx int li_invisible_fields_idx = 0 int li_invisible_fields_qty // Populate arrays of invisible fields information: li_all_fields_qDAT*ty = Integer(idw.Describe("DataWindow.Column.Count")) // all - visible & invisible for li_all_fields_idx = 1 to li_all_fields_qty ls_curr_field_name = Upper(idw.Describe("#"+ String(li_all_fields_idx) + ".Name")) if inv_util.uf_col_is_visible(idwDAT*, ls_curr_field_name) then continue li_invisible_fields_idx++ ls_field_infos[li_invisible_fields_idx] = wf_get_field_info(ls_curr_field_name) if ib_clicked_on_row then ls_field_statuses[li_invisible_fields_idx] = wf_get_field_status_as_strDAT*ing(ls_curr_field_name) end if ls_updatable_fragments[li_invisible_fields_idx] = wf_get_updatable_frag(ls_curr_field_name) next li_invisible_fields_qty = li_invisible_fields_idx // If the click was not on a row - display short message and exiDAT*t script: if not ib_clicked_on_row then for li_invisible_fields_idx = 1 to li_invisible_fields_qty ls_result += ls_field_infos[li_invisible_fields_idx] + "~r~n" next inv_util.uf_remove_chars_from_end(ref ls_result, 2) // remove the last "~r~DAT*n" wf_show_in_mle_display(ls_result) return end if // Define if invisible fields have same or different statuses and updatable frags: if ib_clicked_on_row then lb_all_fields_have_same_status = true lb_all_fields_have_same_updatable_frag =DAT* true for li_invisible_fields_idx = 2 to li_invisible_fields_qty li_prev_idx = li_invisible_fields_idx - 1 if ls_field_statuses[li_invisible_fields_idx] <> ls_field_statuses[li_prev_idx] then lb_all_fields_have_same_status = false end iDAT*f if ls_updatable_fragments[li_invisible_fields_idx] <> ls_updatable_fragments[li_prev_idx] then lb_all_fields_have_same_updatable_frag = false end if next end if // Build the result message: if idw.RowCount() > 0 then ls_result = "DAT*INVISIBLE FIELDS AND THEIR VALUES IN ROW #" + String(il_row) ls_result += "~r~n" + Fill("*", Len(ls_result)) + "~r~n~r~n" end if if ib_clicked_on_row and lb_all_fields_have_same_status then ls_result += "All invisible fields have DWItemStatus DAT*" + ls_field_statuses[1] + "~r~n" end if if lb_all_fields_have_same_updatable_frag then ls_result += "All invisible fields are " + ls_updatable_fragments[1] + "~r~n" end if if ls_result <> "" then ls_result += "~r~n" end if for li_inviDAT*sible_fields_idx = 1 to li_invisible_fields_qty ls_result_rows[li_invisible_fields_idx] = ls_field_infos[li_invisible_fields_idx] if ib_clicked_on_row and not lb_all_fields_have_same_status then ls_result_rows[li_invisible_fields_idx] += ", " +DAT* ls_field_statuses[li_invisible_fields_idx] end if if not lb_all_fields_have_same_updatable_frag then ls_result_rows[li_invisible_fields_idx] += ", " + ls_updatable_fragments[li_invisible_fields_idx] end if next inv_util.uf_sort_array(refDAT* ls_result_rows[]) for li_invisible_fields_idx = 1 to li_invisible_fields_qty ls_result += ls_result_rows[li_invisible_fields_idx] + "~r~n" next inv_util.uf_remove_chars_from_end(ref ls_result, 2) // remove the last "~r~n" // Process invisDAT*ible COMPUTED fields: ls_result += wf_get_invisible_computed_fields_frag() wf_show_in_mle_display(ls_result) return end subroutine private function string wf_get_val_frag (string as_field_name) throws n_ex;/*********************************DAT************************************************************************************** Dscr: Returns field's CURRENT value and (if the value has been changed) the ORIGINAL value. ***********************************************************************DAT************************************************* Arg: as_field_name *********************************************************************************************************************** Ret: string ***********************************************DAT************************************************************************/ string ls_orig_val string ls_curr_val string ls_val_frag if not ib_clicked_on_row then return '' ls_orig_val = inv_util.uf_get_item_as_string(idw, il_row, as_field_name,DAT* Primary!, true /* ab_orig_val */) ls_curr_val = inv_util.uf_get_item_as_string(idw, il_row, as_field_name, Primary!, false /* ab_orig_val */) if IsNull(ls_orig_val) then ls_orig_val = "NULL" if IsNull(ls_curr_val) then ls_curr_val = "NULL" lsDAT*_val_frag = " = " + ls_curr_val if ls_curr_val <> ls_orig_val then ls_val_frag += " (changed from original " + ls_orig_val + ")" end if return ls_val_frag end function private function string wf_get_field_info (string as_field_name) throwDAT*s n_ex;/********************************************************************************************************************** Dscr: Returns field info. Called from wf_show_invisible_fields in loop for each invisible field. *************************DAT*********************************************************************************************** Arg: as_field_name *********************************************************************************************************************** Ret: string *DAT**********************************************************************************************************************/ boolean lb_field_is_computed boolean lb_expr_is_set_dynamically boolean lb_label_exists // true = there is a text object named asDAT* the field + "_t" AND its text is not empty string string ls_field_info string ls_computed_field_expr string ls_field_db_name string ls_field_type string ls_val_frag string ls_field_label ls_field_type = " (" + wf_get_field_type(as_field_nameDAT*) + ")" ls_val_frag = wf_get_val_frag(as_field_name) ls_field_db_name = Upper(idw.Describe(as_field_name + ".dbname")) lb_field_is_computed = not wf_property_defined(ls_field_db_name) ls_field_label = idw.Describe(as_field_name + "_t.Text") lb_DAT*label_exists = (wf_property_defined(ls_field_label) and Trim(ls_field_label) <> '') ls_field_label = iif(lb_label_exists, ' ("' + ls_field_label + '")', '') if lb_field_is_computed then ls_computed_field_expr = idw.Describe(is_field_name + ".ExpDAT*ression") lb_expr_is_set_dynamically = not wf_property_defined(ls_computed_field_expr) ls_computed_field_expr = iif(lb_expr_is_set_dynamically, '', "Comp Expr = '" + ls_computed_field_expr + "'") ls_field_db_name = '' else ls_computed_field_eDAT*xpr = '' ls_field_db_name = iif(ls_field_db_name = as_field_name, '', "DB Name = " + ls_field_db_name) end if if ls_field_db_name <> '' then ls_field_db_name = ", " + ls_field_db_name if ls_computed_field_expr <> "" then ls_computed_field_expr DAT*= ", " + ls_computed_field_expr ls_field_info = as_field_name + & ls_field_label + & ls_val_frag + & ls_field_type + & ls_field_db_name + & ls_computed_field_expr return ls_field_info end function privDAT*ate function string wf_get_invisible_computed_fields_frag () throws n_ex;/********************************************************************************************************************** Dscr: Builds Invisible Computed Fields message fragment. DAT* *********************************************************************************************************************** Ret: string ********************************************************************************************************************DAT***/ int i int li_fields_qty string ls_field_names[] string ls_expr string ls_frag // the result to return wf_get_computed_fields(idw, ref ls_field_names[], ref li_fields_qty) for i = 1 to li_fields_qty if inv_util.uf_col_is_visible(idw, lDAT*s_field_names[i]) then continue ls_frag += "~r~n" + wf_get_field_info(ls_field_names[i]) ls_expr = idw.Describe(ls_field_names[i] + ".Expression") inv_util.uf_replace_all(ref ls_expr, "~~", "") ls_frag += ", expression: " + ls_expr next ifDAT* ls_frag = '' then return '' return "~r~n~r~nInvisible Computed Fields:~r~n" + ls_frag end function private function string wf_get_updated_fields () throws n_ex;/**********************************************************************************DAT************************************* Dscr: Returns fields (with the old and new values) which have been changed. The delimiter is new line. *************************************************************************************************************DAT*********** Ret: string **********************************************************************************************************************/ int i int li_col_count string ls_col_name string ls_orig_val string ls_curr_val string ls_field_laDAT* bel string ls_updated_fields if il_row = 0 then return '' end if li_col_count = Integer(idw.Describe("datawindow.column.count")) for i = 1 to li_col_count ls_col_name = idw.Describe("#"+ String(i) + ".name") ls_orig_val = inv_util.ufDAT* _get_item_as_string(idw, il_row, ls_col_name, true) ls_curr_val = inv_util.uf_get_item_as_string(idw, il_row, ls_col_name, false) if IfNull(ls_curr_val, '') = IfNull(ls_orig_val, '') then continue ls_field_label = inv_util.uf_get_field_label(DAT*idw, ls_col_name) ls_col_name += " (~"" + ls_field_label + "~")" ls_updated_fields += ls_col_name + ': old=' + IfNull(ls_orig_val, 'NULL') + ', new=' + IfNull(ls_curr_val, 'NULL') + '~r~n' next return ls_updated_fields end function privateDAT* function boolean wf_invisible_fields_exist (datawindow adw) throws n_ex;/********************************************************************************************************************** Dscr: Reports if there is at least one invisible field inDAT* the DW. *********************************************************************************************************************** Ret: boolean **********************************************************************************************************DAT*************/ string ls_field_name string ls_computed_field_names[] int li_fields_qty int i // Process invisible computed fields: wf_get_computed_fields(adw, ref ls_computed_field_names[], ref li_fields_qty) for i = 1 to li_fields_qty ls_DAT*field_name = ls_computed_field_names[i] if not inv_util.uf_col_is_visible(adw, ls_field_name) then return true next // Process regular (not computed) invisible fields: li_fields_qty = Integer(adw.Describe("DataWindow.Column.Count")) for i = 1 DAT*to li_fields_qty ls_field_name = Upper(adw.Describe("#"+ String(i) + ".Name")) if not inv_util.uf_col_is_visible(adw, ls_field_name) then return true next return false end function private subroutine wf_init_instance_vars () throws n_ex;/*DAT********************************************************************************************************************** Dscr: Initializes instance variables. *********************************************************************************************DAT**************************/ string ls_data_col string ls_field_type string ls_dddw_data_col string ls_retrieval_args ib_clicked_on_row = (il_row > 0) if ib_clicked_on_row then ls_field_type = idw.Describe(is_field_name + ".ColType") ib_clicDAT*ked_on_field = wf_property_defined(ls_field_type) else ib_clicked_on_field = false end if if ib_clicked_on_field then is_field_label = inv_util.uf_get_field_label(idw, is_field_name) ls_data_col = idw.Describe(is_field_name + ".DDDW.DataColDAT* umn") ib_field_has_dddw = wf_property_defined(ls_data_col) else ib_field_has_dddw = false end if iw = inv_util.uf_get_window(idw) im = iw.MenuID ib_window_has_menu = IsValid(im) ib_dw_has_rows = (idw.RowCount() > 0) ls_retrieval_args DAT*"= idw.Describe("DataWindow.Table.Arguments") ib_dw_has_retrieval_args = (ls_retrieval_args <> "?") ib_dw_has_invisible_fields = wf_invisible_fields_exist(idw) is_sort_expr = idw.object.datawindow.table.sort is_filter_expr = idw.object.datawiDAT*$ndow.table.filter if wf_property_defined(is_filter_expr) then inv_util.uf_replace_all(ref is_filter_expr, " AND ", "~r~nAND~r~n") inv_util.uf_replace_all(ref is_filter_expr, " and ", "~r~nAND~r~n") inv_util.uf_replace_all(ref is_filter_expr, "(DAT*& ", "(") inv_util.uf_replace_all(ref is_filter_expr, " )", ")") end if il_row_count = idw.RowCount() il_filtered_count = idw.FilteredCount() il_deleted_count = idw.DeletedCount() return end subroutine private subroutine wf_show_dddw_datDAT*(a () throws n_ex;/********************************************************************************************************************** Dscr: Shows DDDW's data in dw_display **************************************************************************DAT**********************************************/ int li_fields_qty int i long ll_filtered_count long ll_deleted_count string ls_err string ls_col_name string ls_which_rows // possible values: "filtered", "deleted", "filterDAT*,ed and deleted" string ls_which_button // possible values: "Filtered Rows", "Deleted Rows", "Filtered Rows / Deleted Rows" DataWindowChild ldwc wf_display_dw() idw.GetChild(is_field_name, ref ldwc) dw_display.DataObject = idw.Describe(is_fDAT*.ield_name + ".DDDW.Name") ldwc.RowsCopy(1, ldwc.RowCount(), Primary!, dw_display, 1, Primary!) // Process invisible fields of DDDW: if wf_invisible_fields_exist(dw_display) then MessageBox("DW Spy", "The DDDW has invisible fields.~r~nTo see tDAT*0hem, perform next steps:" + & "~r~n~r~n1. Close this message." + & "~r~n~r~n2. Press Shift." + & "~r~n~r~n3. Click the row, whose invisible fields you want to see." + & "~r~n~r~n4. In the opened red-colored Spy, cliDAT*2ck button 'Invisible Fields'.") end if // Process filtered rows of DDDW: ll_filtered_count = ldwc.FilteredCount() if ll_filtered_count > 0 then ldwc.RowsCopy(1, ll_filtered_count, Filter!, dw_display, 1, Filter!) ls_which_rows = "filtered" DAT*4 ls_which_button = "'Filtered Rows'" end if // Process deleted rows of DDDW: ll_deleted_count = ldwc.DeletedCount() if ll_deleted_count > 0 then ldwc.RowsCopy(1, ll_deleted_count, Delete!, dw_display, 1, Delete!) if ls_which_button <> "" theDAT*6n ls_which_rows += " and " ls_which_button += " / " end if ls_which_rows += "deleted" ls_which_button += "'Deleted Rows'" end if if ll_filtered_count > 0 or ll_deleted_count > 0 then MessageBox("DW Spy", "The DDDW has " + ls_which_rDAT*8ows + " rows.~r~nTo see them, perform next steps:" + & "~r~n~r~n1. Close this message." + & "~r~n~r~n2. Press Shift." + & "~r~n~r~n3. Click the DW of the Spy." + & "~r~n~r~n4. In the opened red-colored Spy, click buDAT*:tton" + iif(ll_filtered_count > 0 and ll_deleted_count > 0, "s", "") + " " + ls_which_button + ".") end if return end subroutine public subroutine wf_show_dw_attributes ();/**********************************************************************DAT*<************************************************ Dscr: Displays the DataWindow attributes **********************************************************************************************************************/ string ls_attributes_list string ls_aDAT*>ttributes[] string ls_attribute_val string ls_dw_info int li_attributes_qty int li_attribute_idx // The following attributes will not be displayed. Usually, they are long chunks of text which is not interesting in most cases (like HTMLs and XDAT*@MLs), // or can be explored using other buttons. Remove them from the array if you want to see them anyway: string ls_ignored_attributes[] = {"attributes" /* list of all 322 atributes, exisitng in DW */, "data.html", "data.htmltable", "htmltable.styDAT*Blesheet", & "data" /* is visible in the DW; click "Invisible Fields" and "Filtered Rows" to see data which is not displayed */, & "data.xhtml", "data.xml", "data.xmlweb", "data.xmldtd", "data.xslfo", "data.xmlschema", "objectDAT*Ds", & "syntax" /* can be seen in the Edit Mode; remove from this array if your app has DataObjects, created dynamically */, & "syntax.data", "table.arguments", "table.columns", "table.filter" /* click "Filter Expression" to sDAT*Fee it */, & "table.procedure", "table.select", /* << click "Data Source" to see them */ & "table.sort" /* click "Sort Expression" to see it */} SetPointer(HourGlass!) ls_attributes_list = idw.Describe("DataWindow.AttribDAT*Hutes") li_attributes_qty = inv_util.uf_string_to_array(ls_attributes_list, " ", ref ls_attributes[]) for li_attribute_idx = 1 to li_attributes_qty ls_attribute_val = idw.Describe("DataWindow." + ls_attributes[li_attribute_idx]) if iin(ls_attriDAT*Jbute_val, {"!", "?", "?!"}) then continue if iin(ls_attributes[li_attribute_idx], ls_ignored_attributes[]) then continue if ls_dw_info <> '' then ls_dw_info += "~r~n" ls_dw_info += ls_attributes[li_attribute_idx] + " = '" + ls_attribute_val +DAT*L "'" next SetPointer(Arrow!) wf_show_in_mle_display(ls_dw_info) return end subroutine on w_spy.create this.cb_boost_brain=create cb_boost_brain this.cb_club=create cb_club this.st_show_dw_attributes=create st_show_dw_attributes tDAT*Nhis.st_show_dw_size_and_coordinates=create st_show_dw_size_and_coordinates this.st_deleted_data=create st_deleted_data this.st_show_window_size_and_coordinates=create st_show_window_size_and_coordinates this.st_filtered_data=create st_filtered_dataDAT*P this.st_updated_fields=create st_updated_fields this.st_row_status=create st_row_status this.st_field_info=create st_field_info this.st_show_dddw_data=create st_show_dddw_data this.st_sort_expr=create st_sort_expr this.st_filter_expr=create st_DAT*Rfilter_expr this.st_invisible_fields=create st_invisible_fields this.st_data_src=create st_data_src this.st_menu=create st_menu this.st_classes_hierarchy=create st_classes_hierarchy this.cb_copy_to_clipboard=create cb_copy_to_clipboard this.cb_cDAT*Tlose=create cb_close this.gb_window=create gb_window this.gb_datawindow=create gb_datawindow this.gb_clicked_field=create gb_clicked_field this.gb_clicked_row=create gb_clicked_row this.dw_display=create dw_display this.mle_display=create mle_diDAT*Vsplay this.gb_last=create gb_last this.Control[]={this.cb_boost_brain,& this.cb_club,& this.st_show_dw_attributes,& this.st_show_dw_size_and_coordinates,& this.st_deleted_data,& this.st_show_window_size_and_coordinates,& this.st_filtered_data,DAT*X& this.st_updated_fields,& this.st_row_status,& this.st_field_info,& this.st_show_dddw_data,& this.st_sort_expr,& this.st_filter_expr,& this.st_invisible_fields,& this.st_data_src,& this.st_menu,& this.st_classes_hierarchy,& this.cb_copy_toDAT*Z_clipboard,& this.cb_close,& this.gb_window,& this.gb_datawindow,& this.gb_clicked_field,& this.gb_clicked_row,& this.dw_display,& this.mle_display,& this.gb_last} end on on w_spy.destroy destroy(this.cb_boost_brain) destroy(this.cb_clubDAT*\) destroy(this.st_show_dw_attributes) destroy(this.st_show_dw_size_and_coordinates) destroy(this.st_deleted_data) destroy(this.st_show_window_size_and_coordinates) destroy(this.st_filtered_data) destroy(this.st_updated_fields) destroy(this.st_rDAT*^ow_status) destroy(this.st_field_info) destroy(this.st_show_dddw_data) destroy(this.st_sort_expr) destroy(this.st_filter_expr) destroy(this.st_invisible_fields) destroy(this.st_data_src) destroy(this.st_menu) destroy(this.st_classes_hierarchy)DAT*` destroy(this.cb_copy_to_clipboard) destroy(this.cb_close) destroy(this.gb_window) destroy(this.gb_datawindow) destroy(this.gb_clicked_field) destroy(this.gb_clicked_row) destroy(this.dw_display) destroy(this.mle_display) destroy(this.gb_lastDAT*b) end on event open;/********************************************************************************************************************** Dscr: Initialization. //=============================================================================DAT*d======= // EXAMPLE OF CLICKED EVENT'S SCRIPT WHICH OPENS THE SPY AND PASSES THE PARAMETER: //==================================================================================== //------------------------ Open DW Spy ---------------------DAT*f--- BEGIN n_parm lnv_parm if KeyDown(KeyShift!) then if Handle(GetApplication()) = 0 /* running from PB, NOT as a standalone executable */ then if IsNull(row) or IsNull(dwo) then MessageBox("DW Spy", "To open DW Spy, click tDAT*hhe datawindow itself (not an object, placed on top of it).") else lnv_parm.uf_set(w_spy.PARM_NAME__DW, this) lnv_parm.uf_set(w_spy.PARM_NAME__ROW, row) lnv_parm.uf_set(w_spy.PARM_NAME__COL, dwo.name) OpenWithParm(w_spy, lnDAT*jv_parm) // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> http://code.intfast.ca/viewtopic.php?t=3 end if end if end if //------------------------ Open DW Spy ------------------------ END --------------------------------------------------------------DAT*l--------------------------------------------------------- Dev: Michael Zuskin Nov 18, 2010 Initial version **********************************************************************************************************************/ n_parm lnv_parm DAT*ntry lnv_parm = Message.PowerObjectParm si_instances_counter++ idw = lnv_parm.uf_get(PARM_NAME__DW) il_row = lnv_parm.uf_get(PARM_NAME__ROW) is_field_name = lnv_parm.uf_get(PARM_NAME__COL) // this.Height = gb_last.Y + gb_last.HeightDAT*p + 125 // this.Width = gb_last.X + gb_last.Width + 60 wf_init_instance_vars() // populate the rest of instance variables wf_init_visual_appearance() // enable/set text of command buttons and window title catch(n_ex e) e.uf_msg() end try DAT*r return end event event close;si_instances_counter -- end event type cb_boost_brain from commandbutton within w_spy integer x = 3794 integer y = 3028 integer width = 681 integer height = 88 integer textsize = -8 integer weight = 400 fonDAT*ttcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" string text = "Boost Your Brain" end type event clicked;inet l_inet GetContextService("Internet", ref l_inet) l_inet.HypeDAT*vrlinkToURL("http://intfast.ca/brain-on-ketones/") return end event type cb_club from commandbutton within w_spy integer x = 3794 integer y = 2940 integer width = 681 integer height = 88 integer textsize = -8 integer weight = 400 fontcharDAT*xset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" string text = "Elegant Programming Club" end type event clicked;inet l_inet GetContextService("Internet", ref l_inet) l_inet.HDAT*zyperlinkToURL("http://code.intfast.ca/") return end event type st_show_dw_attributes from statictext within w_spy integer x = 3794 integer y = 1388 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fonDAT*|tcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "Attributes" alignment alignment = center! boolean border = true borderstyle borderstDAT*~yle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_show_dw_size_and_coordinates from statictext within w_spy intDAT*eger x = 3794 integer y = 1516 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" lonDAT*g backcolor = 67108864 string text = "Size && Coordinates" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(thDAT*is) catch(n_ex e) e.uf_msg() end try return end event type st_deleted_data from statictext within w_spy integer x = 3794 integer y = 1260 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharsDAT*et fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrDAT*ectangle = false end type type st_show_window_size_and_coordinates from statictext within w_spy integer x = 3794 integer y = 360 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset =DAT* ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "Size && Coordinates" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraDAT*ised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_filtered_data from statictext within w_spy integer x = 3794 integer y = 1DAT*132 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 aligDAT*nment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event DAT*jtype st_updated_fields from statictext within w_spy integer x = 3794 integer y = 1896 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfaDAT*M@S]S] 7@@P@*@@H@@Ro@o@hn@n@|@|@e@e@m@m@y@y@@@@@.@@V@@n@@@@@@@@A@@w@w@4@@P@@h@@|@@@@@@@@@@@@@@t@t@H@@Z@@vc@c@ (z@l@@~[ A{@{@ @DAT*@:@@NVJ@J@d@@z@@@@_U@U@SD}@}@1z@@@lK @@( w_spywindowaccessiblerolemenuwindowtypewindowstatewindowobjecttoolbaralignmentwindowanimationstylestructuremailrecipientenvironmentmailDAT*filedescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobjectP ג commandbuttonfontcharsetfontpitchfontfamilystatictextalignmentfillpatternborderstylegroupboxdatawindowrichtexttoolDAT*baractivationdwobjectmultilineedittextcaseJ DataWindow SpyAppIcon!P ג dwrowcol_namen_dwspy_utilP J dwbuffern_exgraphicobjectArialBoost Your BrainElegant Programming ClubAttributesSizeDAT* && CoordinatesUpdated FieldsRow StatusField InfoDDDW's DataSort ExpressionFilter ExpressionInvisible FieldsData SourceWindow's MenuOn-Window Hierarchy<< Copy to ClipboardClose SpyWindowDataWindowFieldRownoneFixedsysP֒ DAT*dwitemstatusextobjectiifobjectuserobjecttabclassdefinitionf_throwpointeriinifnulldragobjectn_parmmessageinet D2F si_instances_counterw_spy(:  @ as_field_namewf_get_updataDAT*ble_fragrs_sqlwf_format_sqlwf_get_field_typeadwcwf_get_field_pathwf_get_code_table_fragwf_show_row_statusas_msgwf_show_in_mle_displaywf_display_dwas_orig_stringwf_ornament_as_subheaderas_col_namewf_sort_dw_display_by_columnwf_dw_is_exteDAT*rnalwf_show_window_infoa_bufferwf_show_data_in_bufferadw*drs_computed_field_namesri_computed_fields_qtywf_get_computed_fieldswf_init_next_instanceswf_show_size_and_coordinatesawai_xai_yai_widthai_heightast_to_disableas_textwf_disDAT*able_static_textas_property_valuewf_property_definedwf_init_visual_appearance@agowf_get_inheritance_chain@wf_show_classes_hierarchy@wf_show_menu@ast_clickedwf_static_text_clicked@apowf_get_retrieval_args_frag@wf_show_data_src@as_dddw_dataDAT*objectwf_get_data_source_of_dddw_frag@as_valwf_get_dddw_frag@wf_show_field_info@wf_get_field_status_as_string@wf_show_invisible_fields@wf_get_val_frag@wf_get_field_info@wf_get_invisible_computed_fields_frag@wf_get_updated_fields@wf_invisiblDAT*e_fields_exist@wf_init_instance_vars@wf_show_dddw_data@wf_show_dw_attributes< @@@@@@@@@@@@@@@@@@@+create+destroy+open+close+clickedxposyposrowdwo+doubleclickedFbvBd<jDAT* SSXQRSSCdatawindowchild.SSQ(QS{@Bn?QCdwbuffer.5QCdatawindow.RS[]RI5QCdaDAT*tawindow.QCwindow.QIIIIQCstatictext.SsQCstatictext.TBStASCgraphicobject.@dSCpowerobject.x5BCdatawindow.L@ J T \ 8LIIDAT*LCdwobject.t@ J T \ 8$8D,Tt$T`P x _initsrcwindoww_spyaccessiblerolemenuwindowtypewindowstatewindowobjecttoolbaralignmentDAT*windowanimationstylestructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobjectcommandbuttoncb_boost_brainfontcharsetfontpitchfontfamilycb_clubstatictextst_DAT*show_dw_attributesalignmentfillpatternborderstylest_show_dw_size_and_coordinatesst_deleted_datast_show_window_size_and_coordinatesst_filtered_datast_updated_fieldsst_row_statusst_field_infost_show_dddw_datast_sort_exprst_filter_exprst_inDAT*visible_fieldsst_data_srcst_menust_classes_hierarchycb_copy_to_clipboardcb_closegroupboxgb_windowgb_datawindowgb_clicked_fieldgb_clicked_rowdatawindowdw_displayrichtexttoolbaractivationdwobjectmultilineeditmle_displaytextcasegb_lastDAT*_sharsrcn_dwspy_utildwbuffern_exgraphicobjectdwitemstatusextobjectobjectuserobjecttabclassdefinitionpointerdragobjectn_parmmessageinet"@0<@Z@d@z@@@@DAT* @  @( @@ @h @@@@@@@@8V@n@@@@@@.nDAT*  8 T x *Tf@x@@H@Z @v!@DAT*#@$@%@&@'@.(@B*@P+@f,@n-@/@2@3@4@6@  !"#DAT*$%&'()*+,-./12346:<=.*& .d1"-"-".$$".$$DAT*).$$".$$.$$.$$.$$.$$.$$.$$.$$.$$.$$.$$".$$--0)%0DAT*)%0)%0)%5/!!9)@2,,0)%.      !"#$%&'()*+,- ! '; }(,D<;9;Ln;T3;hDAT*;n3;;3;}(;}) 4 DXjdZ as_field_namels_update_exprcase12< , J  idwa5.Updatedescribe0yesUpdatablenoNot Updatable!Update Expr=''DAT* D ! $' ;,3;03,P;! X' ;`3;n3,|;! ' ;3;3,;! ' ;3;3,;! ' ;3;3,;! ' ;3; 3,0;! 8' ;@3;R3,h;! p' ;x3;3,;! ' ;3;3,;! 'DAT* ;3;3,;! ' ;3;3,;! ' ;(3;03,8;! @' ;H3;P3,X;! `' ;h3;p3,x;! ' ;3;3,;! ' ;3;3,;! ' ;3;3,;! ' ;3;3,;! ' ;3;$3,4DAT*;! <' ;D3;\3,t;! |' ;3;3,;! ' ;3;3,;4 h  8l<p @tDxd rs_sql ` inv_utilUc>"uf_replace_all2c>selectSELECT2c>from FRDAT*Mz@Lz]Lz]*z@z@z@Jy@y@^@@z@@@@@@@@@@@@@@8@@Vw@w@n@@@@@@@@ A@@J@J@p@@ $ n_dwspy_utilnonvisualobjectstructuremailrecipientenvironmentmailfiledescriptiDAT*onmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobjectdatastorewindowdatawindowdwbuffern_exextobjectobjectiinclassdefinitionf_throwiif2  as_input_stringas_delimiterw rDAT*s_arruf_string_to_arrayrs_processed_stringas_old_fragas_new_fraguf_replace_allaa_valuf_populateduf_get_pb_versionorl_arruf_sort_arrayas_arruf_ds_from_arrayoal_arr oapo_objuf_get_windowadwas_field_nameuf_get_fieDAT*ld_labeluf_emptya_bufuf_row_countas_coluf_col_existsas_class_nameuf_get_pbl_of_classas_dataobjectuf_get_proc_of_dataobjectal_rowab_orig_valuf_get_item_as_stringadwcai_dwc_rowas_dwc_field_nameuf_col_modifieduf_row_modifiedas_DAT*col_nameuf_col_is_visibleas_stringai_num_of_chars_to_removeuf_remove_chars_from_enduf_remove_chars_from_startas_substringuf_starts_withuf_ends_with   +create+destroyLPDAT*<>| 0XLLSSRS[]QRSSSBAS\PLRL[]Cdatastore.S[]aCdatastore.L[]XLRS[] Cwindow.CpowerobjectDAT*. SCdatawindow.SytLCdatawindow.Cdwbuffer.BCdatawindow.SnSSsX tfSCdatawindow.LSCdwbuffer.BoX tSCdatawindow.LSCdwbuffer. tfDAT*SCdatawindowchild.ISCdwbuffer.BX SCdatawindow.LSX fSCdatawindow.LSB SCdatawindowchild.ISXtBCdatawindow.SLCdwbuffer.XtBCdatawindow.LCdwbuffer.DAT*XBCdatawindow.L@~QRSIo~~.BSS~.QDtL$0l(`x x _initsrcnonvisualobjectn_dwsDAT*py_utilstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobjectdatastorewindowdatawindowdwbuffern_exextobjectobjectclassdefinition"@DAT*B\@p@@@@@@ @0 @J @h @ @@@@@@@@ 2.DAT*OM 2c>from FROM 2c>from FROM 2c>where WHERE2c>order by ORDER BY2c>group by GROUP BY2c>union UNION 2c> and AND2c>and AND 2c>or OR 2c> or OR2c>in IN 2c> in INDAT*2c>in( IN(2c>not NOT 2c> not NOT2c>is nullIS NULL2c>is not nullIS NOT NULL2c>existsEXISTS2c>betweenBETWEEN2$ P X |         0 8 h p         DAT* 8 @ X ` x           4 < t |    ! '; }(,D<;! `';h3;l3,;! ';3;3,;9 4ldH as_field_namels_field_type( ,DAT* 0 idwa5.ColTypedescribe2inv_util>Lc>( uf_replace_all3pLc>)p D `    ;}(,4<;! P';X3;\3,;! ';3;3,;9 ,ddR adwcas_field_namDAT*els_field_type<  6 ( .ColTypedescribe"inv_utiln<c>( uf_replace_all`<c>)w@`4 P    4#;! <'}*;D})! X'S@S;}+;`})! l'4<?#,;,DAT*;&"24?d?@;}(}*! '4,;9 bv6`d!"d~ ls_pathls_objects' ili_qty_of_objectslgo_curr8d 8 -DDAT*Hl A8 object.is_field_name P[il_row>HK]idwda5classnametgetparent.inv_utilc>uf_remove_chars_from_end.< X l      ! '! <';D}(,h<;!9,;&l;3! ';DAT*3;3,;! ';3;3, ;;}(;})! '; 3;,3,;! ';3;3,;! '4,H;;P}(9 < l 4ld ls_frag "p idwa5is_field_nameDAT* P.ValuesdescribeTwf_property_definedpinv_utilc> ' - 'uf_replace_allc>/' ''c>'' - '<No Displayed Value - Stored is displayed>' - c> - '' - '<No Stored Value - Displayed is stored>'>c>uf_remove_charDAT*s_from_end>. ########## Code Table: 'Displayed Value' - 'Stored Value' ==================================  < h             H  ! '! 0'4=@,T;=@p;\3=@;f3DAT*=@;3=@;3!9,; > J Z l dT l_row_statusls_row_statuscase9<B* FB idwa5il_rowd Kgetitemstatus8New!NewModified!NotModified!DataMoDAT*dified!wf_show_in_mle_display 0 T  ! (',<;! \',p;! ' "<! ' "9 8 V xd as_msg @ dw_displayH6hide0mle_displayDI:showdcb_copy_to_clipboardMxDAT*B.enabledDI:text@( < \ p     `! (',<;! \',p;! ' "<^8 V ^d 0 dw_displayH6show0mle_displayDI:hidedcb_copy_to_clipboard@xB.enabled( < \ DAT*p   H;}(; })42@<;;~})FFd. as_orig_string  ###### : ############################################ ! (',D;4.! `'9;h3,;! '4,;! 'DAT*(;}(,<;!9,0;&;83;h3@;! @';H}(;N}(! T';\}(4S@S;}+,|<;;H}(! ';\}(4S@S;}+,<;! ',;! ',;! ';! '! "4,;DAT*global type iif from function_object end type forward prototypes global function powerobject iif (boolean ab_condition, powerobject apo_if_true, powerobject apo_if_false) global function datetime iif (boolean ab_condition, datetime adt_if_true, DAT*datetime adt_if_false) global function date iif (boolean ab_condition, date ad_if_true, date ad_if_false) global function time iif (boolean ab_condition, time at_if_true, time at_if_false) global function decimal iif (boolean ab_condition, decimal DAT*adc_if_true, decimal adc_if_false) global function long iif (boolean ab_condition, long al_if_true, long al_if_false) global function string iif (boolean ab_condition, string as_if_true, string as_if_false) end prototypes global function powerobDAT*ject iif (boolean ab_condition, powerobject apo_if_true, powerobject apo_if_false); if ab_condition then return apo_if_true return apo_if_false end function global function datetime iif (boolean ab_condition, datetime adt_if_true, datetime adtDAT*_if_false); if ab_condition then return adt_if_true return adt_if_false end function global function date iif (boolean ab_condition, date ad_if_true, date ad_if_false); if ab_condition then return ad_if_true return ad_if_false end functioDAT* n global function time iif (boolean ab_condition, time at_if_true, time at_if_false); if ab_condition then return at_if_true return at_if_false end function global function decimal iif (boolean ab_condition, decimal adc_if_true, decimal adcDAT* _if_false); if ab_condition then return adc_if_true return adc_if_false end function global function long iif (boolean ab_condition, long al_if_true, long al_if_false); if ab_condition then return al_if_true return al_if_false end functioDAT*n global function string iif (boolean ab_condition, string as_if_true, string as_if_false);/*********************************************************************************************************************************************** Dscr: TheDAT* function iif() has 3 arguments. The 1st one is boolean. If it's true then the 2nd argument's value is returned; otherwise, the 3rd argument's value is returned: ls_greeting = iif(lc_sex = "M", "Mr", "Ms") The function is ovDAT*erloaded for the following datatypes: string, long, decimal, date, time, datetime, PowerObject. To see the overloads, open the function in the "Edit Source" mode. More details: http://code.intfast.ca/viewtopic.php?t=4 ********************DAT***************************************************************************************************************************** Arg: boolean expression to evaluate; value to return if the 1st argument is true (string, long, decimal, date, time, dDAT*atetime or PowerObject); value to return if the 1st argument is false (same type as the 2nd argument) ***********************************************************************************************************************************************DAT*     * }(?@;4????\@;i@i;0#94?U?@;B(BV(d aDAT*s_input_stringas_delimiterrs_arr li_start_posli_delimiter_posll_elements_processedls_tempX 0 XJ-d~  0@;4 0#@#;DAT*r0U@;B  BR|d rs_processed_stringas_old_fragas_new_fragll_posll_old_frag_lenll_new_frag_lenx 8 P hv 'r< r@<;DAT*Mx@US]x@x@x@8y@y@L@@h@@@@@@@@@@@@ @@&@@Dw@w@i \ iiffunction_objectstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconDAT* nectioninfopowerobject2  ab_conditionapo_if_trueapo_if_falseiifadt_if_trueadt_if_falsead_if_truead_if_falseat_if_trueat_if_falseadc_if_trueadc_if_falseal_if_trueal_if_falseas_if_trueas_if_false8 DAT** B Cpowerobject.BCpowerobject.Cpowerobject.ld|WBWWs YBYY TBTT MBMM$:LBLLRhSBSSHx x\ functiDAT*$Mz@o]S] z@z@z@>y@y@R@@n@@@@@@@@@@@@@@,@@Jw@w@ n_parmnonvisualobjectstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnecDAT*&tioninfopowerobjectnGr7Or7Gr7d2  as_nameaa_valueuf_setuf_getapo_valuf_exists+create+destroy  QSAAS/N QSCpowerobjDAT*:ect.BSQ0D| xt _initsrcnonvisualobjectn_parmstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobject"@BDAT**! ';}(,<;! "9 .^2H "2$N%&*,-d as_col_namels_db_namels_new_sort_expr_of_dw_displayls_prev_sort_colP ( > |   dw_displayH6rowcountODAT*,0inv_utilLc>_tuf_ends_with1nLc>uf_remove_chars_from_end.H6.DBNamedescribewf_property_definedDW Spy - Sort by ColumnDouble-click on the field itself (in one of the rows), NOT on its header.is_prev_sort_expr_of_dw_displayDAT*.eS A DH6.Color=modifylH6lH6setsortH6sortSLc>S.H6.Color=0lS( D `      0 @ T |               ! D"! T',x;! ';DAT*0t!! ",;<! "! '! ' '9,X;! `';<<* F h td h` is_data_source_sql_selectWidwLa5getsqlselect2\WWwf_format_sql}is_data_source_stored_procVinv_DAT*2util c>La5uf_get_proc_of_dataobject#$VD T x         X ` ;! ' ('S@S;}*;0});6})! @' H'S@S;}+;0});P})! d' l'S@S;}+;0});t})! ' 'S@S;}+!9,; DAT*4d. ls_window_info H X = iw` Y = `Width = `Height = ` wf_show_in_mle_display@ ( @ H d l    b !,,;! L' l"! |' '9=@! ' 'DAT*6;<q;jC;! ' ';<q;jC;<q;,@<;X=@! H' P';<q;jC;! X' `';<qh;jC;p<q;,<;X=@X! ' ';<q;jC;! ' ';<q;jC;<q;,<;`FDAT*8Rb   X`d0 a_buffercase4(?"? wf_display_dwdw_display)4H6dataobjectTidwta54H6objecto@ta5@data__get_attribute@filterprimary__set_attribute 4H6@ta5DAT*:@delete 4H6@ta5@ , L l |         @ H P X ` h            b ;,H; 4;P?@;4?X???DAT*<\@;;T}(,`<;;h 00?#94?U;P?@;b`  2bv$TX`d adwrs_computed_field_names ri_computed_fields_qtyli_start_posli_tab_posls_list_of_all_objectsls_oDAT*>bj_nameH 5H-T  x datawindow.objectsDescribe6 .type6computeH ` 4?! $"4! @'! d'! '! '! '0 4DAT*@?( "4?( "4!! ',L;!! ',;!! ',;!! (',0; 2~ ,Jh dT ili_frames_qtylgb_frames H<H0-08 backcolorgb_winDAT*Bdow,D1gb_datawindowHE2gb_clicked_fieldlF3gb_clicked_rowG4gb_lastJ<st_classes_hierarchy A-wf_disable_static_textst_show_window_size_and_coordinatesT6"st_show_dw_size_and_coordinates4 st_show_dw_attributes3DAT*D$ @ d       L     ( 0 T! ' ' ' (',l;RJRd adw 5t(  wf_show_size_and_coordinates0   ( l T! ' 'DAT*F ' (',l;RJRd aw t(  wf_show_size_and_coordinates0   ( l ;S@S;}*;}); })S@S;}+;});*})S@S;}+;});<})S@S;}+!9,;DAT*H dZ ai_xai_yai_widthai_heightls_infod$6J  X = Y = Width = Height = wf_show_in_mle_displayP f "4 "<; \ $"9d  . BDAT*J\dd> ast_to_disableas_text( . , }  $ *!;3,@;( (d. ast_to_disable H wf_disable_static_text@ N; <L;@<LDAT*L<L @Ld4 as_property_value  !?d8!<,$;! T'&P!! l';t3,;!,;!! ';3,X;! '! ' ";3! $'&!! T';\3,;!! '9,;&L!! '; 3,0;! \'4DAT*N! ' ";! 'S@S;}*;})!! ';3,;! '4D! D' L";T! t'S@S;}*;})l!! |';3,;!! '9,;&!! ';3,;! H' `"! '! ' ";! ';! '}(;});3*;}*! DAT*P,'&|!! P',X;! '&! '! ' ";3!! ',;! $' ,"! X'! `'! h' p";x3! '4! ' ";! 'S@S;}*}*! ' ";3! $'8! @'! P'! X',;&4!! ';3,;t!! 'DAT*R, ;!! $ ',, ;! X ";` 34?! | "! ', ;; })! ' '});})}*4! "! ' '}(! '! "; !  '}(; })! 0 '});})}*! 8 '! @ ";H ! ` 'S@S;}*;h })! t 'S@S;}+}*! "! '9!, DAT*T;!<, ;b  (Pd"#$'L(d)*./0@1D5l6>?ALB^F|GHJRSTU:VW[\] _4`8aVhtijklo4pDstw}2~DZbd  setredrawYib_window_has_menu,^st_menu\@,No menu in windowwf_disable_static_textDAT*V@wf_dw_is_externalst_data_src?+External DW - No Data Sourceib_dw_has_retrieval_args(`[?+textData Source and Argumentsib_dw_has_invisible_fields ]st_invisible_fields,>*No Invisible Fieldsis_filter_expr Twf_pDAT*Xroperty_definedst_filter_expr<=)No Filter Appliedil_filtered_count8Mst_filtered_datad7#Filtered Rows (8M)d7#No Filtered Rowsil_deleted_countNst_deleted_data$5!Deleted Rows (N$5!No Deleted Rowsis_DAT*Zsort_expr Rst_sort_expr<(No Sort Appliedgb_clicked_field$F3enabledPib_clicked_on_fieldhY$F3Field &hY"is_field_labelQ(click on a field to activate)hYst_field_info4:&ib_field_has_dddw`ZhYst_show_ddDAT*\dw_data;'No DDDW in the Field;'gb_clicked_rowG4Pib_clicked_on_row4X4XG4Rowil_row_countLG4 #il_rowKG4Row (click on a row to activate)c4Xinv_utili,c>idwHa5Kuf_row_modified,`st_updated_DAT*^fields8$No Updated Fields in the Rowo8$st_row_status 9%is_spy_win_title4 ODW Spy for: 4 OHa5classname (Ha54 OHa5hY4 O *** FIELD: "Q" (is_field_name P4X4 O *** ROW #K of Ltitle| 4 DAT*`Owf_init_next_instances Y$ T l    X    $ T     0 \       D L t |      H `      , P X       $ , X ` h pDAT*b       $ @ P X      $ , X |           0 8 @ ` t     b$,$;! @'9,p;}*,; =J@ ;3 ,;DAT*d:=J@  ;3 ,;:=J@ V;3 ,;:=nJ@ ; 3 ,;:=:J@ ;3   ,(;:4;0,d;}*X@X;+;<  ,; ,;;}(;}( DAT*f,;}+! ' ,;,;}+}*:;(;3`!,;})9` L!f"r#$%&'()*+,,-8.R/f0x1234567;:<B=\>?@BD(FPG`d agols_base_pb_classls_built_chainls_indents_accumulatorlo_type_of_arglDAT*hwldwluoltablmlcdcase33 A : X D  5 E F  GD classnameinv_util_,c>uf_get_pbl_of_class"HtypeoflxWindowgetclassdefinitioDAT*JnDataWindowUserObjectETabMenuUnknown type of control getancestorlgetname ,c>"Hwf_ornament_as_subheader$ @ p      ( d        .=U@5@5;DAT*lmily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "Updated Fields" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type eDAT*nvent clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_row_status from statictext within w_spy integer x = 3794 integer y = 1768 integer width = 1463 integer height = 116 integeDAT*pr textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "Row Status" alignment alignment = center! DAT*boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_field_info from staDAT*tforward global type n_dwspy_util from nonvisualobject end type end forward global type n_dwspy_util from nonvisualobject autoinstantiate end type type variables /******************************************************************************DAT*v**************************************** Descr: NVO with utility methods called from w_spy - see http://code.intfast.ca/viewtopic.php?t=2 **************************************************************************************************************DAT*x********* Licence: No licence needed, this utility is absolutely free *********************************************************************************************************************** Developer: Michael Zuskin > http://linkedin.com/in/zuskinDAT*z | http://code.intfast.ca/ **********************************************************************************************************************/ end variables forward prototypes public function long uf_string_to_array (string as_input_string, DAT*|string as_delimiter, ref string rs_arr[]) public subroutine uf_replace_all (ref string rs_processed_string, string as_old_frag, string as_new_frag) public function boolean uf_populated (any aa_val) public function string uf_get_pb_version () publiDAT*~c function long uf_sort_array (ref long rl_arr[]) public function datastore uf_ds_from_array (string as_arr[]) public function datastore uf_ds_from_array (long al_arr[]) public function long uf_sort_array (ref string rs_arr[]) public function windDAT*ow uf_get_window (powerobject apo_obj) public function string uf_get_field_label (datawindow adw, string as_field_name) public function boolean uf_empty (any aa_val) public function long uf_row_count (datawindow adw, dwbuffer a_buf) public functioDAT*n boolean uf_col_exists (datawindow adw, string as_col) public function string uf_get_pbl_of_class (string as_class_name) public function string uf_get_proc_of_dataobject (string as_dataobject) public function string uf_get_item_as_string (datawindDAT*ow adw, long al_row, string as_field_name, dwbuffer a_buf, boolean ab_orig_val) throws n_ex public function string uf_get_item_as_string (datawindow adw, long al_row, string as_field_name, dwbuffer a_buf) throws n_ex public function string uf_get_itDAT*em_as_string (datawindowchild adwc, integer ai_dwc_row, string as_dwc_field_name, dwbuffer a_buf, boolean ab_orig_val) throws n_ex public function string uf_get_item_as_string (datawindow adw, long al_row, string as_field_name) throws n_ex public fuDAT*nction string uf_get_item_as_string (datawindow adw, long al_row, string as_field_name, boolean ab_orig_val) throws n_ex public function string uf_get_item_as_string (datawindowchild adwc, integer ai_dwc_row, string as_dwc_field_name) throws n_ex puDAT*blic function boolean uf_col_modified (datawindow adw, string as_col, long al_row, dwbuffer a_buf) throws n_ex public function boolean uf_row_modified (datawindow adw, long al_row, dwbuffer a_buf) throws n_ex public function boolean uf_row_modified DAT*(datawindow adw, long al_row) throws n_ex public function boolean uf_col_is_visible (datawindow adw, string as_col_name) throws n_ex public subroutine uf_remove_chars_from_end (ref string as_string, integer ai_num_of_chars_to_remove) public subroutDAT*ine uf_remove_chars_from_start (ref string as_string, integer ai_num_of_chars_to_remove) public function boolean uf_starts_with (string as_string, string as_substring) public function boolean uf_ends_with (string as_string, string as_substring) endDAT* prototypes public function long uf_string_to_array (string as_input_string, string as_delimiter, ref string rs_arr[]);/********************************************************************************************************************** Dscr: SpDAT*lits a list of values, separated by a delimiter, into an array. For the opposite operation see uf_array_to_string. *********************************************************************************************************************** Arg: as_inpDAT*ut_string as_delimiter rs_arr[] ref result array *********************************************************************************************************************** Ret: long - the number of produced array elements. ********************DAT***************************************************************************************************/ int li_start_pos = 1 int li_delimiter_pos long ll_elements_processed = 0 string ls_temp as_input_string = as_input_string + as_delimDAT*iter li_delimiter_pos = Pos(as_input_string, as_delimiter, li_start_pos) do while li_delimiter_pos > 0 ls_temp = Mid(as_input_string, li_start_pos, li_delimiter_pos - li_start_pos) ls_temp = Trim(ls_temp) ll_elements_processed++ rs_arr[ll_DAT*elements_processed] = ls_temp li_start_pos = li_delimiter_pos + 1 li_delimiter_pos = Pos(as_input_string, as_delimiter, li_start_pos) loop return ll_elements_processed end function public subroutine uf_replace_all (ref string rs_processed_DAT*string, string as_old_frag, string as_new_frag);/********************************************************************************************************************** Dscr: Replaces all appearances of a fragment in a string with another fragment. *DAT*********************************************************************************************************************** Arg: rs_processed_string (ref) - the string in which replacement should take place. as_old_frag - the fragment to be replaced. DAT* as_new_frag - the fragment to replace with. **********************************************************************************************************************/ long ll_pos long ll_old_frag_len long ll_new_frag_len ll_old_frag_len = Len(aDAT*s_old_frag) ll_new_frag_len = Len(as_new_frag) ll_pos = Pos(rs_processed_string, as_old_frag) do while ll_pos > 0 rs_processed_string = Replace(rs_processed_string, ll_pos, ll_old_frag_len, as_new_frag) ll_pos = Pos(rs_processed_string, as_olDAT*d_frag, ll_pos + ll_new_frag_len) loop return end subroutine public function boolean uf_populated (any aa_val);/********************************************************************************************************************** Dscr: DefinDAT*es if the passed variable of a primitive data type has a value. This function treats default values (empty string for string, 0 for numbers etc. as well as dates before HISTORICAL_YEAR) as "no value" (like NULL) and is convenient to validate rDAT*equired parameters. The default values of boolean and time variables, false and midnight, are legal "not empty" values, so for them this finction acts exactly as IsNull(). There is also an opposite function uf_empty (with negative worDAT*ding). *********************************************************************************************************************** Arg: aa_val (any) - the tested value ************************************************************************************DAT************************************ Ret: boolean (true = the var has a value; false = the var doesn't have any value) **********************************************************************************************************************/ string DAT*ls_val int li_val long ll_val character lc_val datetime ldt_val decimal ldc_val double ldb_val real lr_val date ld_val unsignedinteger lui_val unsignedlong lul_val if IsNull(aa_val) then return false choose DAT*case ClassName(aa_val) case "string" ls_val = aa_val if Trim(ls_val) = "" then return false case "long" ll_val = aa_val if ll_val = 0 then return false case "integer" li_val = aa_val if li_val = 0 then return false case "boolean" // DAT*no checkings in addition to checking for NULL; for boolean vars, you can use "not IsNull()" instead of "uf_populated()" case "character" lc_val = aa_val if Trim(lc_val) = "" then return false case "datetime" ldt_val = aa_val if Year(Date(ldtDAT*_val)) <= 1900 then return false case "decimal" ldc_val = aa_val if ldc_val = 0 then return false case "double" ldb_val = aa_val if ldb_val = 0 then return false case "date" ld_val = aa_val if Year(ld_val) <= 1900 then return false casDAT*e "time" // no checkings in addition to checking for NULL; 00:00 (midnight) is a valid value; you can use "not IsNull()" for time vars case "real" lr_val = aa_val if lr_val = 0 then return false case "unsignedinteger" lui_val = aa_val if lDAT*ui_val = 0 then return false case "unsignedlong" lul_val = aa_val if lul_val = 0 then return false end choose return true end function public function string uf_get_pb_version ();/**********************************************************DAT************************************************************* Dscr: returns the major version number of PowerBuilder, for example: "9" (not "9.0"!) ******************************************************************************************************DAT****************** Ret: PB version as string **********************************************************************************************************************/ int li_rc string ls_pb_version environment lenv li_rc = GetEnvironment(ref lDAT*env) if li_rc <> 1 then MessageBox(this.ClassName() + ".uf_get_pb_version", "GetEnvironment() failed.", StopSign!) return "" end if ls_pb_version = String(lenv.pbmajorrevision) return ls_pb_version //Some more fields which can be usefuDAT*l: //lenv.pbminorrevision //lenv.pbfixesrevision //lenv.pbbuildnumber end function public function long uf_sort_array (ref long rl_arr[]);/*********************************************************************************************************DAT************** Dscr: Sorts a long array in ascending order. To sort a string array, use an overload. *********************************************************************************************************************** Arg: rl_arr[] - long array tDAT*o sort *********************************************************************************************************************** Ret: the number of elements in the array ********************************************************************************DAT***************************************/ long ll_upper_bound DataStore lds_temp ll_upper_bound = UpperBound(rl_arr) if ll_upper_bound = 0 then return 0 lds_temp = uf_ds_from_array(rl_arr) lds_temp.SetSort("the_col ASC") lds_temp.Sort() rlDAT*_arr = lds_temp.object.the_col.current destroy lds_temp return ll_upper_bound end function public function datastore uf_ds_from_array (string as_arr[]);/**************************************************************************************DAT********************************* Dscr: Gets STRING array and creates a DS, the only column of which (named "the_col") contains the array's values. After the values, previously converted to a DataStore by this function, have been processed, they caDAT*n be easily converted back to an array by accessing the DataStore's property object.the_col.current: lds_temp = uf_ds_from_array(ls_arr[]) ...massage data in DataStore... ls_arr[] = lds_temp.object.the_col.current For LONG arrayDAT*, use another overload. *********************************************************************************************************************** Arg: as_arr[] - string array to convert to DataStore ***************************************************DAT********************************************************************* Ret: DataStore **********************************************************************************************************************/ string ls_source string ls_error string DAT* ls_pb_version DataStore lds ls_pb_version = uf_get_pb_version() ls_source = 'release ' + ls_pb_version + '; datawindow() table(column=(type=char(10000) name=the_col dbname="the_col") )' lds = create DataStore lds.create(ls_source, ls_error) DAT* if UpperBound(as_arr[]) > 0 then lds.object.the_col.current = as_arr[] end if return lds end function public function datastore uf_ds_from_array (long al_arr[]);/****************************************************************************DAT******************************************* Dscr: Gets LONG array and creates a DS, the only column of which (named 'the_col') contains the array's values. After the values, previously converted to a DataStore by this function, have been processed,DAT* they can be easily converted back to an array by accessing the DataStore's property object.the_col.current: lds_temp = uf_ds_from_array(ll_arr[]) ...massage data in DataStore... ll_arr[] = lds_temp.object.the_col.current For STDAT*RING array, use another overload. *********************************************************************************************************************** Arg: al_arr[] - long array to convert to DataStore *******************************************DAT***************************************************************************** Ret: DataStore **********************************************************************************************************************/ string ls_source string ls_error DAT* string ls_pb_version DataStore lds ls_pb_version = uf_get_pb_version() ls_source = 'release ' + ls_pb_version + '; datawindow() table(column=(type=decimal(0) name=the_col dbname="the_col") )' lds = create DataStore lds.create(ls_source, ls_DAT*error) if UpperBound(al_arr) > 0 then lds.object.the_col.current = al_arr end if return lds end function public function long uf_sort_array (ref string rs_arr[]);/***************************************************************************DAT******************************************** Dscr: Sorts a string array in ascending order. To sort a long array, use an overload. ***********************************************************************************************************************DAT* Arg: rs_arr[] - string array to sort *********************************************************************************************************************** Ret: the number of elements in the array ************************************************DAT***********************************************************************/ long ll_upper_bound DataStore lds_temp ll_upper_bound = UpperBound(rs_arr) if ll_upper_bound = 0 then return 0 lds_temp = uf_ds_from_array(rs_arr) lds_temp.SetSort("thDAT*e_col ASC") lds_temp.Sort() rs_arr = lds_temp.object.the_col.current destroy lds_temp return ll_upper_bound end function public function window uf_get_window (powerobject apo_obj);/********************************************************DAT*************************************************************** Dscr: Determines an object's parent window going through the parenting hierarchy until a window is found. Returns an object of the class Window. Use uf_get_window_name() to obtain the DAT*parent window's NAME. *********************************************************************************************************************** Arg: apo_obj (PowerObject) *******************************************************************************DAT***************************************** Ret: The parent window (Window) **********************************************************************************************************************/ Window lw_null PowerObject lpo_parent if not IsVDAT*alid(apo_obj) then return lw_null end if lpo_parent = apo_obj.GetParent() do while IsValid(lpo_parent) if lpo_parent.TypeOf() = Window! then return lpo_parent end if lpo_parent = lpo_parent.GetParent() loop return lw_null end funcDAT*tion public function string uf_get_field_label (datawindow adw, string as_field_name);/********************************************************************************************************************** Dscr: Gets field name and returns its labDAT*el (the text of the <field name>_t object). The label is returned without not-alphabetic symbols ("&Name:" is returned as "Name") to be ready for messages. If <field name>_t object doesn't exist (bad practice, but happens) then does its best to DAT*build a user-friendly label from the field's name ("first_name" ==>> "First Name") to prevent ugly messages. *********************************************************************************************************************** Arg: adw, as_fielDAT*d_name *********************************************************************************************************************** Ret: string *************************************************************************************************************DAT**********/ string ls_label ls_label = adw.Describe(as_field_name + "_t.Text") if iin(ls_label, {"!", "?"}) /* there is NO text object named "<field name>_t" */ then // Try to save the situation and return something which can be used as the coluDAT*mn's label (like "First Name" for "first_name"): ls_label = as_field_name uf_replace_all(ref ls_label, "_", " ") // "first_name" ==>> "first name" WordCap(ls_label) // "first name" ==>> "First Name" else // text object, named "<field name>_t", DAT*exists ls_label = Trim(ls_label) // Remove semicolon which exsist in many labels on free-form DW: if Right(ls_label, 1) = ":" then this.uf_remove_chars_from_end(ref ls_label, 1) end if // Remove ampersands which mark hot-key symbols, dispDAT*layed to user underlined: uf_replace_all(ref ls_label, "&&", adw.ClassName()) // save double-ampersand (which is displayed as one) from removing by next line uf_replace_all(ref ls_label, "&", "") uf_replace_all(ref ls_label, adw.ClassName(), "&"DAT*) // restore the saved ampersand (display it as one) // Remove other not-alphabetic symbols which can appear in the label: uf_replace_all(ref ls_label, "~n~r", " ") uf_replace_all(ref ls_label, "~r~n", " ") uf_replace_all(ref ls_label, "~n", "DAT* ") uf_replace_all(ref ls_label, "~r", " ") uf_replace_all(ref ls_label, "~"", "") end if return ls_label end function public function boolean uf_empty (any aa_val);/*************************************************************************DAT********************************************** Dscr: Defines if the passed variable of a primitive data type has a value. This function treats default values (empty string for string, 0 for numbers etc.) as "no value" (like NULL) and is convenDAT*ient to validate required parameters. Don't use this function to test a var if the data type's default value is an allowed one (lake date and boolean). There is also an opposite function uf_populated (with positive wording). ***********DAT* ************************************************************************************************************ Arg: aa_val (any) - the tested value *******************************************************************************************************DAT* **************** Ret: boolean (true = the var doesn't have any value; false = the var has a value) **********************************************************************************************************************/ return not uf_populated(aa_DAT*val) end function public function long uf_row_count (datawindow adw, dwbuffer a_buf);/********************************************************************************************************************** Dscr: Returns the number of rows in the rDAT*equested buffer. *********************************************************************************************************************** Arg: adw, a_buf ***********************************************************************************************DAT************************* Ret: long **********************************************************************************************************************/ choose case a_buf case Primary! return adw.RowCount() case Filter! return adw.FiltereDAT*dCount() case Delete! return adw.DeletedCount() end choose end function public function boolean uf_col_exists (datawindow adw, string as_col);/****************************************************************************************************DAT******************* Dscr: Checks if the column exists in the DW. Can be used in a generic script which processes different DataObjects. ******************************************************************************************************************DAT****** Arg: as_col *********************************************************************************************************************** Ret: boolean (true - exists, false - doesnt exist) **********************************************************DAT*************************************************************/ return (adw.Describe(as_col + '.Name') = as_col) end function public function string uf_get_pbl_of_class (string as_class_name);/*****************************************************DAT****************************************************************** Dscr: Returns the PBL the class is stored in. *********************************************************************************************************************** Arg: as_class_naDAT*me *********************************************************************************************************************** Ret: string *****************************************************************************************************************DAT* *****/ string ls_pbls[] string ls_classes[] string ls_classes_list string ls_obj string ls_pbls_list int li_pbls_count int li_pbl_idx int li_classes_count int li_class_idx int li_class_name_length int DAT*"li_last_slash_pos ClassDefinition lcd lcd = FindClassDefinition(as_class_name) // returns NULL if the obect is a DataObject ("d_...") if not IsNull(lcd) /* if not a DataObject ("d_...") */ then return " (" + lcd.LibraryName + ")" // If this coDAT*$de reached then it's a DataObject ("d_..."). // It doesn't have ClassDefinition, so it's more tricky to obtain its PBL... ls_pbls_list = GetLibraryList() li_pbls_count = uf_string_to_array(ls_pbls_list, ",", ls_pbls[]) // >>>>>>> SCAN the PBLsDAT*& of the application: for li_pbl_idx = 1 to li_pbls_count ls_classes_list = LibraryDirectory(ls_pbls[li_pbl_idx], DirAll!) li_classes_count = uf_string_to_array(ls_classes_list, "~n", ls_classes[]) // >>>>>>> SCAN the classes in the current PDAT*(BL: for li_class_idx = 1 to li_classes_count ls_obj = Trim(ls_classes[li_class_idx]) // Now ls_obj contains a string having not only the class name but also the last change date / time and, // possibly, a comment. The date is delimited DAT**from the class name by a tab, so lets's extract the name: li_class_name_length = Pos(ls_obj, " ") - 1 // until the first tab ls_obj = Left(ls_obj, li_class_name_length) // Let's check if it is the class whose PBL we are looking for (as_clDAT*,ass_name): if Lower(ls_obj) <> Lower(as_class_name) then continue // Found!!! return " (" + ls_pbls[li_pbl_idx] + ")" next next // If this code reached, this object is not stored in a PBL (for example, it's a DW placed on a window, DAT*.but only the window is stored in a PBL): return "" end function public function string uf_get_proc_of_dataobject (string as_dataobject);/*************************************************************************************************************DAT*0********* Dscr: Returns name of stored proc which is data source of DataObject. *********************************************************************************************************************** Arg: as_dataobject ****************************DAT*2******************************************************************************************* Ret: string (empty string if the DW's data source is not a stored proc) *************************************************************************************DAT*4*********************************/ string ls_proc DataStore lds_temp lds_temp = create DataStore lds_temp.DataObject = as_dataobject ls_proc = lds_temp.Describe("DataWindow.Table.Procedure") destroy lds_temp if Len(ls_proc) <= 1 /* "?", "!DAT*6", or "" */ or IsNull(ls_proc) then return "" end if //???mzls_proc = Right(ls_proc, (Len(ls_proc) - 10)) // remove "1 execute " from the beginning this.uf_remove_chars_from_start(ls_proc, 10) // remove "1 execute " from the beginning if len(LDAT*8eft(ls_proc, (Pos(ls_proc, ";") - 1))) = 0 then ls_proc = Left(ls_proc, (Pos(ls_proc, " ") - 1)) // remove proc's parms list else ls_proc = Left(ls_proc, (Pos(ls_proc, ";") - 1)) // remove proc's parms list end if uf_replace_all(ref ls_prDAT*:oc, "dbo.", ".") // "schema.dbo.sp_XXX" ==>> "schema..sp_XXX" if this.uf_starts_with(ls_proc, ".") /* no schema - like ".sp_XXX" */ then //???mzif Left(ls_proc, 1) = "." /* no schema - like ".sp_XXX" */ then this.uf_remove_chars_from_start(ls_prDAT*<oc, 1) end if return ls_proc end function public function string uf_get_item_as_string (datawindow adw, long al_row, string as_field_name, dwbuffer a_buf, boolean ab_orig_val) throws n_ex;/******************************************************DAT*>**************************************************************** Dscr: Returns the specified field's value as a string (to be displayed to the user). ***************************************************************************************************DAT*@******************** Arg: adw DataWindow al_row long as_field_name string DWBuffer a_buf ab_orig_val boolean true - get ORIGINAL value, false - get CURRENT value ******************************************************************DAT*B***************************************************** Ret: string **********************************************************************************************************************/ string ls_val string ls_field_type constant string EMPTY_SDAT*DTRING = "<<<W_SPYEMPTYSTRING>>>" ls_field_type = Lower(Left(adw.Describe(as_field_name + ".ColType"), 5)) choose case ls_field_type case "numbe", "long", "ulong", "real", "int", "decim" ls_val = String(adw.GetItemNumber(al_row, as_field_namDAT*Fe, a_buf, ab_orig_val)) case "char(", "char" ls_val = adw.GetItemString(al_row, as_field_name, a_buf, ab_orig_val) if not IsNull(ls_val) then if ls_val = "" then ls_val = EMPTY_STRING else ls_val = "'" + ls_val + "'" end if endDAT*H if case "datet", "times" ls_val = "'" + String(adw.GetItemDateTime(al_row, as_field_name, a_buf, ab_orig_val), "dd-mmm-yyyy hh:mm") + "'" case "date" ls_val = "'" + String(adw.GetItemDate(al_row, as_field_name, a_buf, ab_orig_val), "dd-mmm-yyyyDAT*J") + "'" case "time" ls_val = "'" + String(adw.GetItemTime(al_row, as_field_name, a_buf, ab_orig_val), "hh:mm") + "'" case else f_throw(PopulateError(0, "Unknown DW field data type " + ls_field_type + ".")) end choose choose case true case DAT*Lls_val = EMPTY_STRING ls_val = "''" case IsNull(ls_val), ls_val = "" ls_val = "NULL" end choose return ls_val end function public function string uf_get_item_as_string (datawindow adw, long al_row, string as_field_name, dwbuffer a_buf) thDAT*Nrows n_ex;/********************************************************************************************************************** Dscr: Returns the specified field's CURRENT value as a string (to be displayed to the user). **************************DAT*P********************************************************************************************* Arg: adw DataWindow al_row long as_field_name string DWBuffer a_buf ***********************************************************************DAT*R************************************************ Ret: string **********************************************************************************************************************/ return uf_get_item_as_string(adw, al_row, as_field_name, a_buf, fDAT*Talse /* ab_orig_val */) end function public function string uf_get_item_as_string (datawindowchild adwc, integer ai_dwc_row, string as_dwc_field_name, dwbuffer a_buf, boolean ab_orig_val) throws n_ex;/**********************************************DAT*V************************************************************************ Dscr: Returns the specified field's value as a string (to be displayed to the user). *******************************************************************************************DAT*X**************************** Arg: adwc DataWindowChild ai_dwc_row long as_dwc_field_name string a_buf DWBuffer ab_orig_val boolean true - get ORIGINAL value, false - get CURRENT value ****************************************DAT*Z******************************************************************************* Ret: string **********************************************************************************************************************/ DataWindow ldw_temp adwc.RowsCopyDAT*\(1, adwc.RowCount(), a_buf, ldw_temp, 1, a_buf) return uf_get_item_as_string(ldw_temp, ai_dwc_row, as_dwc_field_name, a_buf, ab_orig_val) end function public function string uf_get_item_as_string (datawindow adw, long al_row, string as_field_naDAT*^me) throws n_ex;/********************************************************************************************************************** Dscr: Returns the specified field's CURRENT value as a string (to be displayed to the user). ********************DAT*`*************************************************************************************************** Arg: adw DataWindow al_row long as_field_name string *************************************************************************************DAT*b********************************** Ret: string **********************************************************************************************************************/ return uf_get_item_as_string(adw, al_row, as_field_name, Primary!, false /* ab_DAT*dorig_val */) end function public function string uf_get_item_as_string (datawindow adw, long al_row, string as_field_name, boolean ab_orig_val) throws n_ex;// Overload for Primary! buffer return uf_get_item_as_string(adw, al_row, as_field_name,DAT*f Primary!, ab_orig_val) end function public function string uf_get_item_as_string (datawindowchild adwc, integer ai_dwc_row, string as_dwc_field_name) throws n_ex;// Overload for Primary! buffer and CURRENT value return uf_get_item_as_string(adDAT*hwc, ai_dwc_row, as_dwc_field_name, Primary!, false /* ab_orig_val */) end function public function boolean uf_col_modified (datawindow adw, string as_col, long al_row, dwbuffer a_buf) throws n_ex;/**************************************************DAT*j******************************************************************** Dscr: Checks if the column's value has been modified since the retrieval or last save. Use adw function instead of checking the columns DWItemStatus (that status remains DataModiDAT*lfied! if user changed the value and after that returned the original one). This function makes scripts shorter beacuse it exempts them from: 1. Declaration and populating of variables for the original and current values. 2. ProcessinDAT*ng of NULLs (the value is reported as not modified if both the values, the old and the new, are NULLs, and modified if only one of them is NULL). If the script deals only with the current record of the Primary! buffer (for example, in a FDAT*pORM DW, or in a multi-rows DW with no filtering and deletion) then you can use the overloaded version with 2 arguments. *********************************************************************************************************************** Arg: DDAT*ataWindow adw long al_row string as_col DWBuffer a_buf *********************************************************************************************************************** Ret: boolean (true - has been changed, false - has NOT been cDAT*t; rai@i;;<;  r\4<;*  rZ4?<;: 8;J rgi@i<;;<;^  rf8!@!;p@p;4l?<;p Nr^DAT*vP6J<; r`O8<;  rd 6p@p;4l?<; ; Lr_7H<;  r[ 5E<;  r] 5<<: N!^"#$%&'(*4+L,\-.DAT*x/012.3J4b5r6789;<=,>H?`@pABCFGd aa_valls_valli_valll_vallc_valldt_valldc_valldb_vallr_valld_vallui_vallul_valcase30 ,:HV f> v  DAT*z    stringlongintegerbooleancharacterdatetimedecimaldoubledatetimerealunsignedintegerunsignedlong]@];4?!,$;;,});R3=/@@;;3DAT*| 'S@S;9 " 6 tdB li_rcls_pb_versionlenv< 8  classname.uf_get_pb_versionGetEnvironment() failed.$   0404!0,4;;<,d;DAT*~,x;  ';<q;j;<q; 0Pj~d\ rl_arrmll_upper_boundlds_temp < -,J 0 uf_ds_from_arraythe_col ASCsetsortTsort l@the_col__get_DAT*attributecurrent4 d x    !,4;;<}(;N})m,;4 ';(<qX;j;`,;8Ff| dv as_arrr ls_sourcels_errorls_pb_versionlds d DAT*-, @ R n 0 uf_get_pb_versionrelease ; datawindow() table(column=(type=char(10000) name=the_col dbname="the_col") )datastorecreate]@the_col__get_attribute8current__set_attributepDAT*4    X  !,4;;<}(;N})m,;4 ';(<qX;j;`,;8Ff| dv al_arrpls_sourcels_errorls_pb_versionlds d -, @ DAT*R n 0 uf_get_pb_versionrelease ; datawindow() table(column=(type=decimal(0) name=the_col dbname="the_col") )datastorecreater]@the_col__get_attribute8current__set_attributep4    X   DAT*0404!0,4;;<,d;,x;  ';<q;j;<q; 0Pj~d\ rs_arrp ll_upper_boundlds_temp < -,J 0 uf_ds_from_arrayDAT*the_col ASCsetsortTsort l@the_col__get_attributecurrent4 d x     &,$;,<;=J@f,D;2 2<ZfdF apo_objlw_nulllpo_parent<DAT* 0 L getparenttypeof,$ < D ;}(,4<;9;<3;@3 ;9!;D3;H3,l;9r@r;i@i;4'@';;t2!4,;!;3,;,DAT*;!;3;3,;!,;;3,;!;3;H3,;!;3;H3,;!; 3;H3,$;!;,3;H3,0;!;83;3,<;9 ,fv2h (!V"%&dF adwas_field_naDAT*mels_label<  4 Dh _t.Textdescribe !?_ uf_replace_allL:uf_remove_chars_from_endr.x&&classnameL&oLL L L L L"L4 l         $DAT* 0 <  !r,,;&d aa_val4 uf_populated, =@:,$;=@h,H;=@,l;  6 Jdxd2 adwa_bufcase9< $DAT*t rowcountOfilteredcount,deletedcountP$ H l 8;}(,0<;6 6d& adwas_col(  8 .Namedescribe0 X 9@; &^; ,4;}*;<})VDAT*@'!9;@3,l;4D?@9==@@;!9;t3,x; 4d  @ ?@i@i; ;@;4\ ?@;<;?@}(;<})VZ;3VDAT*"^v !$D%r)*-01<2@5D6Vdx as_class_namels_pbls ls_classes ls_classes_listls_objls_pbls_listli_pbls_countli_pbl_idxli_classes_countli_class_idxli_class_name_lengthli_last_slash_poslcd<` <,DAT*-`H-l   "Lp  (getlibraryname),uf_string_to_array D D 4 l x m$ ,"9;4,|;4DAT*%~;3!4 ,;;@;4\@;42;@;4\@;t;@;4\@;!;3;3,;!9;3, ;!4,(;9  (HNl~.2t #$dN DAT*as_dataobjectls_proclds_temp< , < 08 datastoreDataWindow.Table.Proceduredescribebjuf_remove_chars_from_start/; dbo..uf_replace_alluf_starts_withi0/$, |     ( DAT*;>}(,d<;4@<;9;l;x%;%;%;%;%M;>S@S;j;;%,;&; ;3;}(;})j;;%>;DAT*,L;;T3T@T;}*;})j;x;,;;3T@T;}*;})j;";,;;3T@T;}*;})j4;}(;,})X@X;; <; ;03 ;  %;639DAT*L\ 4^l !:"R#$%&")j*v+,-01d adwal_rowas_field_namea_bufab_orig_valls_valls_field_typeempty_stringcase19case41 & BNf t DAT* @0 <<<W_SPYEMPTYSTRING>>>.ColTypedescribePnumbelongulongrealintdecimgetitemnumberchar(chargetitemstring'datettimesgetitemdatetime*dd-mmm-yyyy hh:mmdategetitemdatedd-mmm-yyyytimegetitemDAT*time+hh:mmUnknown DW field data type .''NULLd   L   2!9<,<;0 0dN adwal_rowas_field_namea_bufP & BD uf_get_item_as_string$< t4,$DAT*;4,@;!?9,t;r>rd adwcai_dwc_rowas_dwc_field_namea_bufab_orig_valldw_tempx 0 T`x | rowcountrowscopy,uf_get_item_as_striDAT*ng$H$ @ t 4!9=@<,<;2 2dB adwal_rowas_field_name< & D uf_get_item_as_string$< 4!9=@,<;22dZ adwal_rowas_field_nameab_orig_valPDAT* & BD uf_get_item_as_string$< 8!-9=@<,<;66dT adwcai_dwc_rowas_dwc_field_name< 0 D uf_get_item_as_string&< !,,DAT*;<!9,H;4;P3X@X;;4;z3X@X; ; ';>4;3X@X;!;!9,;&4; }(;>})X@X;";4&4;DS@S;}*;v})X@XDAT*;#;4;|S@S;}*;})S@S;}+;v})X@X;$;!9<,;!9<,$;$:<&$^<&$< ,N !"#$:%f&'("):-.12:3^56d DAT* adwas_colal_rowa_bufll_row_countls_col_typels_oldls_newcase29  &4@Z r  ,0 uf_row_counts uf_empty,4Arg as_col is empty.Arg al_row is nulDAT*tictext within w_spy integer x = 3794 integer y = 2152 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! strinDAT*g facename = "Arial" long backcolor = 67108864 string text = "Field Info" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_staticDAT*_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_show_dddw_data from statictext within w_spy integer x = 3794 integer y = 2280 integer width = 1463 integer height = 116 integer textsize = -16 integer weighDAT*on_objectiifstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobject@08@L@h@@@@@DAT* @  @& @D @ "   d\ ab_conditionapo_if_trueapo_if_false<* B  *8(8((d\DAT* ab_conditionadt_if_trueadt_if_false<* B  *6(6((dX ab_conditionad_if_truead_if_false<* @  *7(7((dXDAT* ab_conditionat_if_trueat_if_false<* @  "P P  d\ ab_conditionadc_if_trueadc_if_false<*> B>  "   dX DAT*ab_conditional_if_trueal_if_false<*@ *9(9((dX ab_conditionas_if_trueas_if_false<* @  2  iifDAT*2  \44 \\ \  \<\lH\xDAT*Mx@US]x@x@x@8y@y@L@@h@@@@@@@@@@@@ @@&@@Dw@w@i \ iinfunction_objectstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconDAT*t = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "DDDW~'s Data" alignment alignment = center! boolean border = true borderDAT*style borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_sort_expr from statictext within w_spy integer DAT*x = 3794 integer y = 876 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backDAT*color = 67108864 string text = "Sort Expression" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catchDAT*(n_ex e) e.uf_msg() end try return end event type st_filter_expr from statictext within w_spy integer x = 3794 integer y = 1004 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharDAT*set = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "Filter Expression" alignment alignment = center! boolean border = true borderstyle borderstyle = stylDAT*eraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_invisible_fields from statictext within w_spy integer x = 3794 integerDAT* y = 748 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 DAT* string text = "Invisible Fields" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_DAT*msg() end try return end event type st_data_src from statictext within w_spy integer x = 3794 integer y = 620 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitDAT*forward global type n_parm from nonvisualobject end type end forward global type n_parm from nonvisualobject autoinstantiate end type type variables /******************************************************************************************DAT***************************** How to use: http://code.intfast.ca/viewtopic.php?t=2 *********************************************************************************************************************** Licence: No licence needed, this utility is aDAT*bsolutely free *********************************************************************************************************************** Developer: Michael Zuskin > http://linkedin.com/in/zuskin | http://code.intfast.ca/ *****************************DAT******************************************************************************************/ public: // Fields for frequently passed parameters: string is_passed_from boolean ib_positive_response // In each application there is a set ofDAT* business attributes used frequently. For example, a Human Resources application can deal a lot with emp_id and dept_id. // They are transported between objects so many times that I would recommend to create public fields in n_parm to transport themDAT* - il_emp_id and il_dept_id. // The generic functions uf_set() and uf_get() should be used only for one-off and rarely used parameters. The advanages of using fields are obvious - type // safety, efficiency, no chance to misspell the parameter's nDAT*ame. But too many such fields will make the object less lightweight, so you have to decide where // the borderline between frequent and rare parameters is. private: any ia_values[] // parameters' values string is_names[] // parameters' namDAT*es boolean ib_is_object[] // its N-th element flags if N-th element of ia_values contains reference to object (true) or value of primitive type (false) uint iui_upper_bound = 0 // size of three the arrays; eliminates multiple using of UpperBound(DAT*) function which is not very quick end variables forward prototypes public subroutine uf_set (string as_name, any aa_value) public function any uf_get (string as_name) public subroutine uf_set (string as_name, powerobject apo_val) public functioDAT*n boolean uf_exists (string as_name) end prototypes public subroutine uf_set (string as_name, any aa_value);/********************************************************************************************************************** Dsc: Adds parameteDAT*r of a PRIMITIVE type to be transported. *********************************************************************************************************************** Arg: as_name (string)- parameter's name aa_value (any) - parameter's value ********DAT***************************************************************************************************************/ uint i if IsNull(as_name) or Trim(as_name) = '' then return end if // If this parm already exists then update it with the new (paDAT*ssed) value: for i = 1 to iui_upper_bound if is_names[i] = as_name then ia_values[i] = aa_value ib_is_object[i] = false return end if next // If this code reached then this parm doesn't exist, so add it: iui_upper_bound++ is_names[DAT*iui_upper_bound] = as_name ia_values[iui_upper_bound] = aa_value ib_is_object[iui_upper_bound] = false return end subroutine public function any uf_get (string as_name);/************************************************************************DAT*********************************************** Dsc: Returns value of transported parameter by its name. If there is a chance that the parameter will not exist (i.e. is not mandatory) then use uf_exists before calling uf_get to prevent possiDAT*ble run-time error: if lnv_parm.uf_exists("ds_details") then lds_details = lnv_parm.uf_get("ds_details") end if *********************************************************************************************************************** DAT* Arg: as_name - parameter's name *********************************************************************************************************************** Ret: (any) - parameter's value ****************************************************************DAT*******************************************************/ uint i any la_empty PowerObject lpo_empty as_name = Lower(Trim(as_name)) for i = 1 to iui_upper_bound if is_names[i] = as_name then if IsNull(ia_values[i]) and ib_is_object[i] then DAT* // App fails when "any" var with NULL of type, inherited from PowerObject, // assigned to another "any" var, so return empty PowerObject: return lpo_empty else return ia_values[i] end if end if next return la_empty end funDAT*ction public subroutine uf_set (string as_name, powerobject apo_val);/********************************************************************************************************************** Dsc: adds parameter of an OBJECT (REFERENCE) type to be trDAT*ansported *********************************************************************************************************************** Arg: as_name (string) - parameter's name apo_val (PowerObject) - parameter's value *******************************DAT****************************************************************************************/ uint i if IsNull(as_name) or Trim(as_name) = '' then return end if // If this parm already exists then update it with the new (passed) value: for i = 1DAT*  to iui_upper_bound if is_names[i] = as_name then ia_values[i] = apo_val ib_is_object[i] = true return end if next // If this code reached then this parm doesn't exist, so add it: iui_upper_bound++ is_names[iui_upper_bound] = as_namDAT* e ia_values[iui_upper_bound] = apo_val ib_is_object[iui_upper_bound] = true return end subroutine public function boolean uf_exists (string as_name);/********************************************************************************************DAT*************************** Dsc: Reports if parameter with requested name exists and is not null. If there is a chance that the parameter will not exist (i.e. is not mandatory) then use this function before calling uf_get to prevent possibleDAT* run-time error: if lnv_parm.uf_exists("ds_details") then lds_details = lnv_parm.uf_get("ds_details") end if *********************************************************************************************************************** ArDAT*ch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "Data Source" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrecDAT*nectioninfopowerobject2 0 as_vala5as_arriinapo_valn6apo_arral_valoal_arr   T , BSS[]B `T BRCpowerobject.RCpowerobject.[]pDAT*BLL[]4 x\ function_objectiinstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobject@08@L@h@DAT*8@@@@ @  @& @D @ 46r?@n<~,<~Db n r ~dZ as_valas_arr ili_uppDAT*tangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type st_menu from statictext within w_spy integer x = 3794 integer y = 232 integer width = 1463 integeDAT*r height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "Window~'s Menu" alignDAT*@ment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end type event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event tDAT* l.DW doesn't have DataObject.uf_col_exists!DW doesn't have column ''.Arg al_row is negative ().Arg al_row () is greater than the number of rows in DW (uf_get_item_as_string$$, H    $ ;,T;@;DAT*"4R;\S@S;}*;`}),l<;!9,;<H<2`d^ adwal_rowa_bufili_col_countas_colx &26P  datawindow.coDAT*&lumn.countdescribe@#.name@uf_col_modified*tT l  (!=@,0;&&d& adwal_row( 8 uf_row_modified+0  ;}(,4<;;<!9,\;;d}(;});}(;DAT*SCC*DAT*(})%;;}) '});})49X@X;&;4@;;4;@;4\;#@#;;}(;})S@S;}+;}), <;;( ,@0~dl adwas_col_namels_visible_exprls_errDAT**li_rowd  0 P ^, .visibledescribe"!uf_col_exists!@Failed to obtain .visible propertyColumn doesn't exist in DW p." Evaluate(, )"14 \    : 00?\@DAT*,;8 0 8dX as_stringai_num_of_chars_to_remove( $ : 00?\'@';8 0 8dX as_stringai_num_of_chars_to_remove( $ 2@;0 DAT*. 0d> as_stringas_substring( $  2'@';0 0d> as_stringas_substring( $  0;!;3,P;.d X createconstrDAT*0uctortriggerevent 6P 0!;3,@;H;.d X destructortriggerevent &destroy@    ! " #$%&'()*+,-./012 ( uf_string_to_arDAT*2rayuf_replace_alluf_populateduf_get_pb_versionuf_sort_arrayuf_ds_from_arrayuf_get_windowuf_get_field_labeluf_emptyuf_row_countuf_col_existsuf_get_pbl_of_classuf_get_proc_of_dataobjectuf_get_item_as_stringuf_col_modifieduf_row_modifieduDAT*4f_col_is_visibleuf_remove_chars_from_enduf_remove_chars_from_startuf_starts_withuf_ends_withiinf_throwiif+create+destroy46Tn  $ DAT*6> Z "FxDAT*2  Mf4hDt*jjDAT*zer_bound,P ,-8< |046n0?@0j<z,<zD^ j n zd^ apo_valapo_arr ili_upper_bound0P 0 - <@ DAT*<P@d@@@@@@  @$ @> @\ @ |i@i;;%8z4X! 4'! P'D@DAT*>! l'D#rY! 'D#<zN! "! '! 'D#9! '! 'D#rY! '! 'D#<z 08n Jrzd6 as_nameaa_valuei<  2 X iui_upper_bound is_namDAT*es<ia_valuesXib_is_object=t < X t 4 P l          i@i;4B! 0'! L'D@! h'D! 'D@$! 'D8r"X~DAT*Bype st_classes_hierarchy from statictext within w_spy integer x = 3794 integer y = 104 integer width = 1463 integer height = 116 integer textsize = -16 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfDAT*Damily fontfamily = swiss! string facename = "Arial" long backcolor = 67108864 string text = "On-Window Hierarchy" alignment alignment = center! boolean border = true borderstyle borderstyle = styleraised! boolean focusrectangle = false end typDAT*Fe event clicked;try parent.wf_static_text_clicked(this) catch(n_ex e) e.uf_msg() end try return end event type cb_copy_to_clipboard from commandbutton within w_spy integer x = 3794 integer y = 2852 integer width = 681 integer heighDAT*Ht = 88 integer textsize = -8 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" boolean enabled = false string text = "<< Copy to Clipboard" end type DAT*8 event clicked;Clipboard(mle_display.Text) end event type cb_close from commandbutton within w_spy integer x = 4475 integer y = 2540 integer width = 782 integer height = 576 integer textsize = -16 integer weight = 400 fontcharset fontcharsDAT*L4#! H'94#! P';X;X3;Z3,;44@4;4#! ' '94#;344@4;4#! ',;4#;34#! '! '4<R,4;&R?#,<;DAT*N?#?@?#24?4?4@94?:?@! X'?@9,;}*t!?@,;!?@,;;X;}( 4 ?:4@;X6DAT*P!4@9,;}*4 ?!4@9,;}*}(x=U@5@5;!9,P;< Lh !"#$%'()*6+N.R/h12345667H8p9t<>?@AC6DNEHIKMOPd ili_classes_qtyls_class_infols_hieDAT*Rrarchyls_class_namesw@ ls_control_kinds@ lgo_objects lgo_currcase49case622 N h---A A X is_data_source_stored_procDAT*TVVSTORED PROCEDURE (DW'S DATA SOURCE)idwka5DATAOBJECTa5classnameDATAWINDOWba5a5getparent inv_utilDc>uf_get_pbl_of_class"`wf_get_inheritance_chain wf_ornament_as_subheaderwf_show_in_mle_diDAT*Vsplay H P       4 < X      P H!! ',T;!9,;F$ > Fd* ls_menu_info  imd_wf_get_inheritance_chain wf_show_in_mle_displayA\ T DAT*X 2! 4'! <'! D' L"=@! T' \"2! d' l"4! t" |"=@ "2 "4 '9! ':!,;! 'f!,@;! '! ';3;3,;!! ',0;! P'DAT*Z!,|;! '.!,;! 'j!! 0'9,h;! '!! '9,;! '!=@,$;! L' !=@,T;! '6!,;! 'b!,;! <'!,h;! '! ';3;3,;!DAT*\! ',;! '*!,,;! X'v!,;!9,;4;}(;})X@X;-;! "! 4';<}(})0Pn "#$$6%P&b'|(+,-./*0D1f2345678 ;2<L=^>x?@ADEF&G@HXJrKvOQRd DAT*^ ast_clickedls_textls_updated_fieldsnormalboldcase32x ( 8 \jt H ist_prev_clickedbbb @bbb @st_classes_hierarchy@A-wf_show_classes_hierDAT*`archyst_menu @,wf_show_menul$st_show_window_size_and_coordinatesH6"inv_utilc>&&&uf_replace_alliw`wf_show_size_and_coordinates;st_data_src8?+wf_show_data_srcXst_invisible_fields>*wf_show_invisible_fieldsDAT*bst_sort_exprd<(is_sort_expr Rwf_show_in_mle_display 8st_filter_expr p=)is_filter_expr T8st_filtered_data7#wf_show_data_in_bufferst_deleted_data,5!st_show_dw_attributes\3wf_show_dw_attributesst_field_infoDAT*d:&wf_show_field_infost_show_dddw_data;'wf_show_dddw_dataDst_show_dw_size_and_coordinatesp4 c>idwa5st_row_status9%wf_show_row_statusst_updated_fields48$wf_get_updated_fields`8StaticText '' has no 'case' inDAT*f 'choose case'.title is_spy_win_title@O *** 4 < D L T \ d l t |       @     0 P |     0 h     $ L T     < h       , DAT*hX    4  , ;=J@ ! \'&N;d3;f3q;a;3V=J@ ;f3q,;a;4;d3;83V4;,;}*;})X@X;.; ! '9;3,; 4    DAT*j ?@;@; ?@ 4?\@;;}(;})q;;3};3;&}(;<})qH;a ?@ ?@ ?\'@';4@;;P3;Z3;d3;n3 /;;x}(;x});d;|}(DAT*l;}(});})});})}*}(*Nv !"(V+,-021p2x3456 7n;<=?@d2 apols_args ls_arg_namels_arg_valls_arg_datatypels_fragls_frag_headerls_args_listlb_arg_val_is_nullli_args_qtyili_tab_posDAT*ncase24( (-4 L b     "DH typeof!ib_dw_has_retrieval_args'([DataWindow.Table.ArgumentsDescribe ########DAT*p## Retrieval Arguments and their Values: ? ########## DDDW's Retrieval Arguments and their Values: Invalid type of 'apo' argument: classname. It must be DataWindow! or DataWindowChild!.inv_util'tc> uf_string_to_arrayo DAT*rEvaluate('If(IsNull(), 1, 0)', 0)1NULLEvaluate('', 0)charstridatetime' = () \  ,     H  !! ',X;<! ';|!! '}(,;! ';!; ! h'}(}),p;!;xDAT*t3,;$ 0 R x dL ls_retrieval_args_fragcase8( >H idwa5wf_get_retrieval_args_frags is_data_source_sql_select`W`Wwf_show_in_mle_display@is_data_source_stored_proceV##DAT*v######## Stored Procedure: jVDW Spy Error - Unknown data source in w_spy.wf_show_data_src :-( X     h p   !-,H;,l;;t!,;;}(})! '9,8;;t;@DAT*x}(});}(  :Nhd adwcas_dddw_dataobjectls_sqlls_procls_retrieval_args_fragd  @ N ^ ( wf_get_retrieval_args_fragggetsqlselectrPwf_format_sqlDAT*|}v ########## DDDW's SQL Select: inv_utilc>uf_get_proc_of_dataobject# ########## DDDW's Stored Procedure: ########## DDDW's Data Source: External DW, no data source.H l   8 ! 4'&$;<3! H'! l'DAT* |46n?@j<z,<z !"D#^%j'n(zdZ al_valal_arrili_upper_bound,P,-8< 2  iin<DAT*~;t}(,<;! '! ';}(,<;! '! ';}(,<;! 4'9,d;! l'! t' ,;! -9,;;}(;})});"})! -9,\;}+;d})N;h}(;x})});d}) 4 ,;,DAT*;4?N ! ' --9,;;}(;})});"})! -9,4;}+;d});<})});}) });"})! -9,d;}+;d}) ;l;}(});})})})}) 9$d :b t#$% &D(X)2N78d~ as_valli_dwc_rowDAT*2  :(4:L4:DAT*Mx@mS]S]x@x@x@>y@y@R@@n@@@@@@@@@@@@@@,@@Jw@w@ijb ifnullfunction_objectstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemDAT*connectioninfopowerobject2  apo_checked_valueapo_alternative_valueifnullab_checked_valueab_alternative_valueal_checked_valueal_alternative_valueadb_checked_valueadb_alternative_valueas_checked_valueas_alternativeDAT*_value(  4 Cpowerobject.Cpowerobject.Cpowerobject.nBBBLLL*DDDVxSSSx xb function_objectifnullstructuremailrecipientenvironmentmailfiledescriptionmaDAT*ilmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobject@0>@R@n@@@@@ @ @, @J @ DAT*(&&&&d` apo_checked_valueapo_alternative_value( 4  (&&&&d\ ab_checked_valueab_alternative_value(2 DAT* (&&&&d\ al_checked_valueal_alternative_value(2 (O&O&O&&d` adb_checked_valueadb_alternative_value( 4  0&DAT*9.9. !.d\ as_checked_valueas_alternative_value( 2  2  ifnulld2  `(4 `xDAT*```DAT** Ret: string (other overloads return other types, but always the same type as the 2nd and the 3rd arguments) *****************************************************************************************************************************************DAT*ls_data_source_of_dddw_fragls_dddw_dataobjectls_pblls_display_colls_data_colls_data_and_display_cols_msgls_search_exprls_val_of_display_colls_dddw_fragldwc 4 l     DAT* <dL b  ! " $$#~l0$~%~D&~'DAT*~(~@)l*+@(,X`-x./H0f1DAT*d'(DAT* . Z t  ib_field_has_dddwZidwg>a5is_field_namePP.DDDW.DataColumndescribe>a5PP.DDDW.DisplayColumn>a5PP.DDDW.Nameinv_util c>uf_get_pbl_of_class"<>a5PPgetchilde|wf_get_DAT*data_source_of_dddw_frag Data/Display Column = (Value, Type = wf_get_field_typea6)String() = String(rowcountfind c>uf_get_item_as_string) Data Column = (Value = 6 Display Column = 6 ########## DDDW InfoDAT*: DataObject = ""4 H l        4 d l t   \     4 d ,=U@5@5; ! $'! 4'! L'! p'9,;!! '9,;! '! ';}(,<;! '! $';,}(,@<;DAT* ! H'! P';X}(,l<;!9,;&! '! ';}(,<;;! ,'}(;4})})}* !! T'9,;;! '}(}*! 'l;}(}*;4}(;}) })}* !! '9,8;;@ }(}*;P!! \'9,DAT*;}*}*!9,;`;}(;})}* ; ;$! ' ;3;3,;; }(}*;}(}*! 9,;}*!,;}*4?;!,<;}*}*;D}(! '! ';}(,<;! '9;DAT*3,;4:?@9;3;3; 3;3;$3;23 0;! D'! L';T}(?@}),X<;!9,`;&,;V;h}(?@;n}(})}*0=U@5@5;!9,;dDfDAT*n !"#$4%N'l*+-/083`4589<=*?J@^CEFHIHKL N,OVPRTVWd lb_field_is_computedili_attributes_qtyls_attributes ls_attribute_valls_field_typels_field_name_in_dbls_field_infols_enabled_exprls_protect_exprls_updDAT*atable_fragls_field_statusls_filterls_valls_expr,:>b-     . N r    h inv_utilhc>idw,a5il_row<DAT*Kis_field_nameTPuf_get_item_as_string'xTPwf_get_field_type~,a5TP.DBNamedescribee,a5TP.Enabled,a5TP.Protectwf_property_definedt,a5TP.Expression########## Computed Field Field Name = pTP Data TDAT*ype = yTPwf_get_field_status_as_string\Field Name = TPTP DB Name = DWItemStatus = TPwf_get_val_frag Value TPwf_get_updatable_frag|dt Enabled = ''!0c>0 uf_replace_all Protect = ########## CDAT*omputed Expression: wf_get_dddw_fragjwf_get_code_table_frag ########## Dot Notation Path: wf_get_field_path ########## Attributes: ,a5TP.Attributesc> uf_string_to_arrayattributesnamedbnametypeupdateDAT*coltypen,a5TP.t = wf_show_in_mle_displayv$ 4 L p        $ @ H P l     , T     8 \       <      D L X `   ! DAT*'! 0'=@,T;=@j;\3=@;v34;3X@X;1;;3 8 DTfzdZ as_field_namel_field_statuscase12< ,BJB idwa5il_rowd KgetitemstatusDAT*Mx@US]  x@x@x@@y@y@T@@p@@@@@@@@@@@@@@.@@Lw@w@rjd An@@nez f_throwfunction_objectstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistvieDAT*witemtreeviewitemconnectioninfopowerobjectn_exerror2 Z ai_populate_error_rc_dummyf_throw VX" QI xz function_objectf_throwstructuremailrecipientenvironmentmailfiledescriptionDAT*mailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobjectn_exerror,@0@@T@p@@@@@ @ @. @L @d@nDAT*@ |m/ $'/ ,'9/ 4'9/ <'9/ D',d; $&t'zd^ ai_populate_error_rc_dummyln_exerror<F R@l8 n_ex uf_popDAT*!"dJ as_nameila_emptylpo_emptyP   $6 ( iui_upper_bound is_names8ia_valuesTib_is_objectpT0 L h   |i@i;;%8z4X! 4'DAT*! P'D@! l'D#Y ! 'D#<zN! "! '! 'D#9! '! 'D#Y ! '! 'D#<z 08n Jrzd4 as_nameapo_vali<  0 X iui_uppeDAT*r_boundf is_namesa<ia_valuesXib_is_objectat < X t 4 P l         i@i;4B! 0'! L'D@! h'D&8<"X~d$ DAT* as_namei(   p iui_upper_bound is_names8ia_valuesT0 L h 0;!;3,P;.d X createconstructortriggerevent 6P 0!;3,@;H;.d DAT* X destructortriggerevent &destroy@ 2 b uf_setuf_getuf_exists+create+destroyx,@P2  is_passed_fromib_positive_responseia_valueDAT*sGis_namesOib_is_objectGiui_upper_boundlx.PlXoPxoPoPG MdsssG 2(4@<02\D^|DAT*lrDAT*g: as_name - parameter's name *********************************************************************************************************************** Ret: (boolean) - parameter's existence ***********************************************************DAT************************************************************/ uint i as_name = Lower(Trim(as_name)) for i = 1 to iui_upper_bound if is_names[i] = as_name then return not IsNull(ia_values[i]) // found but is null end if next return falDAT*se // not found end function on n_parm.create call super::create TriggerEvent( this, "constructor" ) end on on n_parm.destroy TriggerEvent( this, "destructor" ) call super::destroy end on DAT*8NotModified!DataModified!Unknown DWItemStatus. 0 T `5 ! ';$,h;@; 4Z    ! p';x S@S;}*;|}),<;! '! ' 9,;  ?#! 9,;! 0'd ?#! 9,t; ?DAT*#! 9,;P ! '&^ 4   ?@;}(}*! '4,;!9,4;^! <'@<< 4  @  4?\ ?@ ?@< ?@ ?@<<! D',`;4DAT******** Developer: Michael Zuskin > http://linkedin.com/in/zuskin | http://code.intfast.ca/ ***********************************************************************************************************************************************/ if ab_condiDAT*;h! 'S@S;}*;;Q@Q;}*;})}*! '$";4@}(;})}*\;<4@}(;})}*;;}( 4  n ?# ?@9! p'&$* ?#;x ?@}(}*&j ?#;x ?@DAT*}(}*! ',; 4   ?@;}(}*! '4,;!,;}*!9,;^:h(8d !$%&' ()<*V.^/n0z12346709<=@>f?BCF"G*J\KpNOPQS*T4VjXnZ[\^ac<eVf^d DAT*lb_all_fields_have_same_statuslb_all_fields_have_same_updatable_fragls_dwitemstatus_of_all_fieldsls_update_property_of_all_fieldsls_resultls_result_rows ls_field_infos ls_field_statuses ls_updatable_fragmentsm ls_curr_fiDAT*eld_nameli_all_fields_qtyli_all_fields_idxli_prev_idxli_invisible_fields_idxli_invisible_fields_qtyLx,N L.-xX--- :^DAT*v idwa5DataWindow.Column.CountdescribeTa5#.NameTinv_utilc>a5uf_col_is_visible-wf_get_field_infoib_clicked_on_row Xwf_get_field_status_as_string8wf_get_updatable_frag|| X DAT*c>uf_remove_chars_from_end.wf_show_in_mle_display Xa5rowcountfOLINVISIBLE FIELDS AND THEIR VALUES IN ROW #il_rowK* XAll invisible fields have DWItemStatus All invisible fields are X, c>uf_sort_arrayc>.DAT*wf_get_invisible_computed_fields_frag h p      0 t     4 < D `   p       Z ! 4'&$;<3X! P'! `'! x'9=@<,;! '! '! '9=@<,;DAT*;3;3;}(H;}(;})}*9X $p HXdt as_field_namels_orig_valls_curr_valls_val_fragP , D \ H ib_clicked_on_rowXinv_util>DAT*c>idwXa5il_rowhKuf_get_item_as_string$>c>Xa5hK$NULL = (changed from original )4 P ` x      ;!9,<;}*;D})!9,h;! x';}(,<;!9,;& ! ';}(,<;DAT*! 9,; i@i;;$ ; }(;});32;"! '! 8';@}(,X<;!9,`;&;3;h}(;})3;;3t;3;3;}(4;;;}(;;}( DAT*}(})})})})9 4T&fn  !""4%t&(/0 dj as_field_namelb_field_is_computedlb_expr_is_set_dynamicallylb_label_existsls_field_infols_computed_field_exprls_field_db_namels_field_typels_val_fragls_field_DAT*label ,V    4 L ` (wf_get_field_type~)wf_get_val_fragHidwpa5.dbnamedescribeiwf_property_definedpa5_t.Text ("")pDAT*global type iin from function_object end type forward prototypes global function boolean iin (string as_val, string as_arr[]) global function boolean iin (ref powerobject apo_val, ref powerobject apo_arr[]) global function boolean iin (long al_DAT*val, long al_arr[]) end prototypes global function boolean iin (string as_val, string as_arr[]); int i int li_upper_bound li_upper_bound = UpperBound(as_arr[]) for i = 1 to li_upper_bound if as_arr[i] = as_val then return true end if DAT* next return false end function global function boolean iin (ref powerobject apo_val, ref powerobject apo_arr[]); int i int li_upper_bound li_upper_bound = UpperBound(apo_arr[]) for i = 1 to li_upper_bound if apo_arr[i] = apo_val then DAT* return true end if next return false end function global function boolean iin (long al_val, long al_arr[]);/********************************************************************************************************************** Dscr: RepDAT*orts if a value, passed as the 1st argument, appears in the array, passed as the 2ndt argument. Mimics the action of SQL's IN clause. The function is overloaded for the following datatypes: string, long, PowerObject. To see the ovDAT*a5is_field_nameP.ExpressionComp Expr = ''DB Name = , < h x       8 X `  !! ',P;4Nv! l'! t'?@9,;r;!?@9,;}*}*! '?@;}DAT*(,<;! '; 3;$3,D;;L}(}*D;$;$3;j}( .\Trvd| ili_fields_qtyls_field_names ls_exprls_fragPdP0-\ l P idwDAT*a5wf_get_computed_fields inv_utilXc>a5uf_col_is_visible-| wf_get_field_infoa5.Expressiondescribe"Xc>~uf_replace_all&, expression: Invisible Computed Fields:  P l t      D ! '4DAT**;(3! 4';<,;@;4! ';S@S;}*;}),<;! '! '! '9<,;! '! '! '9<, ;9;(35;9;(36;! ('! 0'9,`;;hDAT*}(;p})}*;v}(9;37;}+;})9;38;}+;})}*z9*d(n" d ili_col_countls_col_namels_orig_valls_curr_valls_field_labells_updated_fields. DAT*F ^ v   il_rowKidw*a5datawindow.column.countdescribel*a5#.namelinv_utilc>*a5Kuf_get_item_as_string(c>*a5K(c>*a5uf_get_field_label8 (""): old=NULL, new= DAT* 4             ( 0 `  !,@;4F?@9! \'9,;&<<;,;@;4;S@S;}*;}),<;! '9DAT* ,;&<< &Tp Xd adwls_field_namels_computed_field_names li_fields_qtyidd 5 d4-p8 wf_get_computed_fieldsinv_utilHc>uf_col_is_visiDAT* ble-dDataWindow.Column.Countdescribe#.NameHc>-d@ \      J! 4"! L'4! T'! d'! ';}(,<;! "!9,;! "<! $'n! L"! h'! p'! x'9,;! '! ';}(,DAT*<;! "!9,;! "<! 0"! 8'! @',d;! t"! |' '! "! '! "! ',;4! ';,P;! ";! "!! ',;! 8"! @' H';P<q;jC;<q;jC;<q;a! "DAT*! ' ';P<q;jC;<q;jC;<q;a!! '9, ;! ('! 0";83;D3,t;! |'! ";3;D3,;! '! ";3;3,;! '! ";3;3,;! "! ',;! @"! H',l;! "DAT*! ',;H $ 4 p Bjn. V"v$& '()*B+./02@3Hd ls_data_colls_field_typels_dddw_data_colls_retrieval_argsP ( D f P ib_clicked_on_rowXil_row<KXiDAT*dw\a5is_field_namelP.ColTypedescribeib_clicked_on_fieldYwf_property_definedYYis_field_label,Qinv_util@Tc>\a5lPuf_get_field_label\a5lP.DDDW.DataColumnib_field_has_dddwZZiw(`Tc>\a5uf_getDAT*_windowHiml_(`@ib_window_has_menu^l_ib_dw_has_rows\\a5rowcount*O\a5DataWindow.Table.Argumentstib_dw_has_retrieval_argsvX[?ib_dw_has_invisible_fields!]\a5wf_invisible_fields_existis_sort_expr R\a5DAT*@datawindow__get_attribute ftablefsort fis_filter_expr T\a5@fffilter fTTc>T AND AND uf_replace_all TTc>T and TTc>T( ( TTc>T ))Til_row_countL\a5Oil_filtered_countDAT*M\a5filteredcountPil_deleted_counttN\a5deletedcount4 L T d      $ L h p x         0 8 @ d t |        P     8 @ H    DAT*         ( 0 t |             @ H l    !,,;! <'! `',|;! ' "! '! ';}(,<;4,;=@! '4=@,<;!! D',;F;3;DAT*;}(;N});v});})@;,;44=@! '4=@,;;3;3,;44=@! '4=@,;;v;}(;&}(;.}(;>}(44%~;3;\}(;x});});N});})DAT* ; })44$;p3;39;}+;t})});x})@;BF `!p"#'()*6+J,`.v/23:~;d li_fields_qtyill_filtered_countll_deleted_countls_errls_col_namels_which_rowsls_which_buttonldwc,DAT*"0Tv     | wf_display_dwidw4a5is_field_nameDPgetchildhdw_displayH6dataobject 4a5DP.DDDW.Namedescriberowcount,H6rowscopy(H6wf_inviDAT*$sible_fields_existLDW SpyThe DDDW has invisible fields. To see them, perform next steps: 1. Close this message. 2. Press Shift. 3. Click the row, whose invisible fields you want to see. 4. In the opened red-colored Spy, click butDAT*&ton 'Invisible Fields'.filteredcount?H6(filtered'Filtered Rows'deletedcount<H6( and / deleted'Deleted Rows'The DDDW has rows. To see them, perform next steps: 3. Click the DW of the Spy. 4. In the opened red-colorDAT*(ed Spy, click buttons ., < ` |         < D        =U@5@5;! ';,D;! `'9;h3,;4! ';?@}(,<;9;3;3;3DAT** :;8?@9;;n;;}(?@;}(});})}*=U@5@5;!9,;B8n !#%' *d ls_attributes_listls_attributes ls_attribute_valls_dw_infoli_attributes_DAT*,qtyli_attribute_idxls_ignored_attributes  T  T6-`    1@ attributesdata.htmldata.htmltablehtmltable.stylesheetdatadata.xhtmldata.xmldata.xmlwebdata.xmldtddataDAT*..xslfodata.xmlschemaobjectssyntaxsyntax.datatable.argumentstable.columnstable.filtertable.proceduretable.selecttable.sortidwa5DataWindow.Attributesdescribe0inv_utilLc> uf_string_to_arrayla5DataWindow.0!??! = 'DAT*0'wf_show_in_mle_displayP @R&:X(6Nn D `      ! 0"-8! P"-X! "-! "-! "-! d"-l! "-! "-DAT*2! "-! $"-,! X"-`! "-! "-! "-! "-! 4"-<! p"-x! "-! "-! "-! "-(! T"-\! "-! "-! "-! "-! "! '! $'! ,'! 4'! <'! D'! L'! DAT*4T'! \'! d'! l'! t'! |'! '! '! '! '! '! '! '! '! '! '! '! '! ' ,BXn 4J`v&<6d x cb_boost_braini1cb_club@2@st_show_DAT*6dw_attributes`3`st_show_dw_size_and_coordinates4 st_deleted_data5!!st_show_window_size_and_coordinates6""st_filtered_datat7#t#st_updated_fields8$$st_row_status9%%st_field_info:&&st_show_dddw_data4;'4'DAT*8st_sort_exprh<(h(st_filter_expr=))st_invisible_fields>**st_data_src?++st_menu$@,$,st_classes_hierarchyDA-D-cb_copy_to_clipboardB..cb_closeC//gb_windowD11gb_datawindowE22gb_clicked_fieldZ 0F3DAT*:03gb_clicked_rowdG4d4dw_displayH66mle_displayI::gb_lastJ<<control|@1@2`34 5!6"t7#8$9%:&4;'h<(=)>*?+$@,DA-B.C/D1E20F3dG4H6I:J<0 8P X    d l DAT*<  $ ,X `    4 <p x     (T \      $ , 4 < D L T \ d l t |          DAT*>    n! 0'! H'! |'! '! '! <'! h'! '! '! '! '! ,'! T'! '! '! '! '! $'! @'! \'! '! '! '! '! '! ,'*8FT b p ~  &4BPDAT*@^ld 4 cb_boost_braini1cb_club82st_show_dw_attributesP3st_show_dw_size_and_coordinates4 st_deleted_data5!st_show_window_size_and_coordinates6"st_filtered_data@D7#st_updated_fieldsp8$st_row_status9%st_fDAT*Bield_info:&st_show_dddw_data;'st_sort_expr<(st_filter_expr4=)st_invisible_fields\>*st_data_src?+st_menu@,st_classes_hierarchyA-cb_copy_to_clipboardiB.cb_close,C/gb_windowHD1gb_datawindowdE2gb_clicked_fieldF3gb_clDAT*Dicked_rowG4dw_displayH6mle_displayI:gb_lastJ<0 H |   < h     , T     $ @ \      , j /5 '! ";(3q<;j5! T";\3qd;\! ";3qDAT*F;a!,;!,;,,;/5 4h./5 4'h/5R4h`/5 <'h "&#X$)*+,-/06dJ lnv_parmmessagee::messageP J"5@K2 @65@KD` w@idwa5dwuf_get.il_rowDAT*HDKrow.is_field_namelPcol_name.wf_init_instance_varswf_init_visual_appearanceuf_msg  < T d     , 4 < >/5&4<4/5 '< d$ ::message5@K DAT*J  *+-&,|}~      !"#$%&'()F&2  wf_get_updatable_fragwf_format_sqlwf_get_field_typewf_get_field_pathwf_get_coDAT*Lde_table_fragwf_show_row_statuswf_show_in_mle_displaywf_display_dwwf_ornament_as_subheaderwf_sort_dw_display_by_columnwf_dw_is_externalwf_show_window_infowf_show_data_in_bufferwf_get_computed_fieldswf_init_next_instanceswf_show_size_and_cooDAT*Nrdinateswf_disable_static_textwf_property_definedwf_init_visual_appearancewf_get_inheritance_chainwf_show_classes_hierarchywf_show_menuwf_static_text_clickedwf_get_retrieval_args_fragwf_show_data_srcwf_get_data_source_of_dddw_fragwf_get_dddDAT*Pw_fragwf_show_field_infowf_get_field_status_as_stringwf_show_invisible_fieldswf_get_val_fragwf_get_field_infowf_get_invisible_computed_fields_fragwf_get_updated_fieldswf_invisible_fields_existwf_init_instance_varswf_show_dddw_datawf_show_dwDAT*R_attributesiiff_throwiinifnull+create+destroy+open+close<XX|"> p    $RDAT*TDv(J !@"`#$%&0'\())DAT*V.)..00.)))1111)00*+,-2 8 widthheighttitlebartitlecontDAT*Xrolmenuwindowtypebackcoloriconcentercb_boost_braincb_clubst_show_dw_attributesst_show_dw_size_and_coordinatesst_deleted_datast_show_window_size_and_coordinatesst_filtered_datast_updated_fieldsst_row_statusst_field_infost_show_dddw_dataDAT*Zst_sort_exprst_filter_exprst_invisible_fieldsst_data_srcst_menust_classes_hierarchycb_copy_to_clipboardcb_closegb_windowgb_datawindowgb_clicked_fieldgb_clicked_rowdw_displaymle_displaygb_lastparm_name__dwparm_name__rowparm_name__coliDAT*\l_rowil_row_countil_filtered_countil_deleted_countis_spy_win_titleis_field_nameis_field_labelis_sort_expris_prev_sort_expr_of_dw_displayis_filter_expris_updated_fieldsis_data_source_stored_procis_data_source_sql_selectib_clicked_on_rowibDAT*^_clicked_on_fieldib_field_has_dddwib_dw_has_retrieval_argsib_dw_has_rowsib_dw_has_invisible_fieldsib_window_has_menuimiwidwist_prev_clickedinv_utilcolor__blackcolor__redcolor__yellowcolor__greycolor__bluecolor__browncolor__for_next_inDAT*`stancesx *<H ` v     < !\ " # $ % &" 'F (` )~ * +DAT*b , - ." /4 1H 2d 3 4 6 : <P:_PH_Pb_P_POPOPOPOPOP^OP|OPDAT*dOPOP GP.GPVGPzGPGPGPGP&OP,OP2O5P:OP\O>Tn_T_T_T_T_T_T_]     DAT*f    D1 @@@       ! " # $ % & ' ( ) * + , - . / 1 2 3 4 6 DAT*h: <____OOOOOOOOOGGGGGGGOOO5OO>,|f0$}8~\DDAT*j6d  " F  "P~8,DAT*l~`T~t&&x0$H|TDAT*nl`6\ !!D""f##$$DAT*p%%&&>''l(())<* =+ &>, ?-F!;3,H;;P3,;/5^4DAT*rl/5 '/54/5 '$Btd2 l_inet::message( L5@K Internetgetcontextservice"http://intfast.ca/brain-on-ketones/hyperlinktourl;H    ""2 " +cDAT*tlicked2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametext $X2DRj~]    DAT*v X  @. "!;3,H;;P3,;/5^4l/5 '/54/5 '$Btd2 l_inet::message(DAT*x L5@K Internetgetcontextservice"http://code.intfast.ca/hyperlinktourleH    ""2 " +clicked2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenDAT*zametext| $X2DRj~]    | X  @. "DAT*|@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd( e::message( @5@Kp wf_static_text_clickediuf_msgH@ X ` h ""2 " DAT*~ +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolortextalignmentborderborderstylefocusrectangle@l$t2DRjDAT*~    ]    lt  @    . "DAT*@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd( e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h " "2 " +DAT*clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolortextalignmentborderborderstylefocusrectangle@$t2DRjDAT*~    ]    t  @    . "2 DAT* 2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcoloralignmentborderborderstylefocusrectangle,$t2DRj~DAT*erloads, open the function in the "Edit Source" mode. Examples of use: if iin(ls_city, ls_cities[]) then... if iin(ll_cust_id, ll_customers[]) then... if iin(lcb_clicked_button, icb_buttons[]) then... The valDAT*ues list can be inserted inline using brackets - {..., ...} - to avoid the need to declare an array: if iin(ls_city, {"Toronto", "Ottawa", "Dnipro"}) then... if iin(ll_cust_id, {123, 456, 789}) then... if iin(lcb_clicked_button, {DAT*cb_close, cb_cancel}) then... More details: http://code.intfast.ca/viewtopic.php?t=6 *********************************************************************************************************************** Arg: value to be checked (can bDAT*e of types long, int, char, string, PowerObject) array to search in (must be of the same type as the first argument) *********************************************************************************************************************** Ret: DAT*boolean *********************************************************************************************************************** Developer: Michael Zuskin > http://linkedin.com/in/zuskin | http://code.intfast.ca/ ************************************DAT***********************************************************************************/ int i int li_upper_bound li_upper_bound = UpperBound(al_arr[]) for i = 1 to li_upper_bound if al_arr[i] = al_val then return true end if next return fDAT*]    t  @ @"!,@;@@,X;@/5^4DAT*l/5 `'/54/5 h'(<Btd( e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h """2 " +clicked2  xywidthheightteDAT*xtsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolortextalignmentborderborderstylefocusrectangle@h$t2DRj~ DAT*   ]    ht  @    . "@"!,@;@@,X;@/5^4l/5 `DAT*'/54/5 h'(<Btd( e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "#"2 " +clicked2  xywidthheighttextsizeDAT*weightfontcharsetfontpitchfontfamilyfacenamebackcoloralignmentborderborderstylefocusrectangle,l$t2DRj~DAT*]    lt  @ . "@"!,@;@@,X;@/5^4l/5 `'/54/5DAT* h'(<Btd( e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "$"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfonDAT*tpitchfontfamilyfacenamebackcolortextalignmentborderborderstylefocusrectangle@h$t2DRj~B    ] DAT*    ht  @B    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'DAT*(<Btd( e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "%"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchDAT*fontfamilyfacenamebackcolortextalignmentborderborderstylefocusrectangle@$t2DRj~`    ]  DAT*  t  @`    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'DAT*(<Btd( e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "&"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamDAT*ilyfacenamebackcolortextalignmentborderborderstylefocusrectangle@h$t2DRj~v    ]   DAT* ht  @v    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<DAT*Btd( e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "'"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacDAT*enamebackcolortextalignmentborderborderstylefocusrectangle@$t2DRj~    ]    DAT*t  @    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd(DAT* e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "("2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebDAT*ackcolortextalignmentborderborderstylefocusrectangle@l$t2DRj~    ]    lDAT*t  @    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd( DAT* e::message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h ")"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcoloDAT*rtextalignmentborderborderstylefocusrectangle@$t2DRj~    ]    tDAT*ulateL$ , 4 < D d 2 f_throw2  F4XDAT*M A C]S] A A A.y@y@B@@^@@v@@@@@@@@@@@@@@:w@w@RZ n_exexceptionstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemcoDAT*nnectioninfopowerobjectiif2 n_ex  ai_err_numas_err_msgas_classas_scriptai_lineuf_populateuf_msguf_write_to_log+create+destroy^ &<NbQISSSIQ xd _initsDAT*rcexceptionn_exstructuremailrecipientenvironmentmailfiledescriptionmailmessagesyncparmdatawindowchildlistviewitemtreeviewitemconnectioninfopowerobject"@6@@T@p@@@DAT*@@ @ @. @L @ |! ("!9,H;! d"9! "9! "z .F^rzdr ai_err_numas_err_msgas_classas_scriptai_DAT*lined& < N b( ii_err_numsetmessage0is_classPis_scriptlii_line( H d    ! ('4?;0! H'S@S;}*;P});`3;! '4;! '}(;})DAT*global type f_throw from function_object end type forward prototypes global subroutine f_throw (integer ai_populate_error_rc_dummy) throws n_ex end prototypes global subroutine f_throw (integer ai_populate_error_rc_dummy) throws n_ex;/*******DAT**************************************************************************************************************** Dscr: Creates an Exception object (of type n_ex), populates the exception-related data and throws. Should be called this way: DAT* f_throw(PopulateError(<error number>, "<error message>")) <error number> is an integer, used to quickly identify the exception in a script which throws many exceptions (so, pass 1 for the first, 2 for the second etc.). Simply pasDAT*s 0 if only one exception is thrown in the script, or if you don't want to mark exceptions with numbers. The error number is not used by the program and, so, has no importanse (it's an argument of PopulateError, so we need to provide a valueDAT*). After an exception, thrown by this func (f_throw), is caught, the exception-related information can be obtained and displayed to user by n_ex.uf_msg(): try uf_function_which_throws_n_ex_using_f_throw() // an exceptiDAT*on can be thrown... if ... then f_throw(PopulateError(0, "Oooops...")) // another exception can be thrown... catch(n_ex e) e.uf_msg() end try More details: http://code.intfast.ca/viewtopic.php?t=1 ********************DAT**************************************************************************************************** Arg: ai_populate_error_rc_dummy - placeholder for return code of PopulateError(). The only purpose of this argument is to allow writing DAT*PopulateError inside the argument parentheses of f_throw to fit the whole exception throw in one line of code *********************************************************************************************************************** DevelopDAT*er: Michael Zuskin > http://linkedin.com/in/zuskin | http://code.intfast.ca/ **********************************************************************************************************************/ n_ex ln_ex ln_ex = create n_ex // The variableDAT*s of the Error object have been populated by PopulateError(). // Copy them to the Exception object, so n_ex.uf_msg() will be able to read them and display to user: ln_ex.uf_populate(Error.Number, Error.Text, Error.Object, Error.ObjectEvent, Error.LiDAT*Lne) throw ln_ex end subroutine DAT*! '4;! '}(;})}*! '4?\; ! 'S@S;}*;})}*;$;&}(!,H;}*!,p;99=/@@;n\!"d8 ls_msgls_msg_title(  xP ii_erDAT*r_numEXCEPTION # THROWNEXCEPTION THROWNis_classClass:  is_scriptsScript: ii_lineLine:  getmessage0uf_write_to_logP( H       H p d  0DAT*;!;3,P;.d X createconstructortriggerevent 6P 0!;3,@;H;.d X destructortriggerevent &destroy@ 2 uf_populateuf_msgufDAT*_write_to_logiif+create+destroyx(6V^n2 \ ii_err_numii_lineis_classis_scriptP&6HM rL4ZDAT*ZZZDAT*  @    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd( e:DAT*:message( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "*"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolortextDAT*alignmentborderborderstylefocusrectangle@$t2DRj~    ]    tDAT*tion then return as_if_true return as_if_false end function DAT*,alse end function DAT*  @    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd( e::messagDAT*e( @5@Kp wf_static_text_clickeduf_msgH@ X ` h "+"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolortextalignmeDAT*ntborderborderstylefocusrectangle@l$t2DRj~     ]    lt DAT* @     . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd( e::message(DAT* @5@Kp wf_static_text_clickeduf_msgH@ X ` h ","2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolortextalignmentbordDAT*erborderstylefocusrectangle@$t2DRj~"    ]    t DAT*6 @"    . "@"!,@;@@,X;@/5^4l/5 `'/54/5 h'(<Btd( e::message( @DAT* forward global type n_ex from exception end type end forward global type n_ex from exception end type global n_ex n_ex type variables /********************************************************************************************************DAT* ************** How to use: http://code.intfast.ca/viewtopic.php?t=1 *********************************************************************************************************************** Licence: No licence needed, this utility is absolutely freeDAT* *********************************************************************************************************************** Developer: Michael Zuskin > http://linkedin.com/in/zuskin | http://code.intfast.ca/ *******************************************DAT****************************************************************************/ protected: int ii_err_num int ii_line string is_class string is_script end variables forward prototypes public subroutine uf_populate (integer ai_err_num,DAT* string as_err_msg, string as_class, string as_script, integer ai_line) public subroutine uf_msg () protected subroutine uf_write_to_log () end prototypes public subroutine uf_populate (integer ai_err_num, string as_err_msg, string as_class, strDAT*ing as_script, integer ai_line);/********************************************************************************************************************** Dscr: Writes into this object all the information related to the class and the script the exceptioDAT*n is thrown from. Called from f_throw(). Later, that information will be extracted from this object by uf_msg() and, optionally, uf_write_to_log(). ************************************************************************************************DAT************************ Arg: int ai_err_num string as_err_msg string as_class string as_script int ai_line **********************************************************************************************************************/ this.iiDAT*_err_num = ai_err_num this.SetMessage(as_err_msg) this.is_class = as_class this.is_script = as_script this.ii_line = ai_line return end subroutine public subroutine uf_msg ();/****************************************************************DAT******************************************************* Dscr: Displays a message with all the exception-related information. That information has been previously written to this object by f_throw(), which called uf_populate(). uf_msg() should beDAT* called when the exception is caught in "catch" section of a "try...end try" block: try uf_function_which_throws_n_ex_using_f_throw() // an exception can be thrown... if ... then f_throw(PopulateError(0, "Oooops...")) // another exceptiDAT* on can be thrown... catch(n_ex e) e.uf_msg() end try **********************************************************************************************************************/ string ls_msg string ls_msg_title ls_msg_title = iif(this.ii_eDAT*"rr_num > 0, "EXCEPTION #" + String(this.ii_err_num) + " THROWN", "EXCEPTION THROWN") if Len(this.is_class) > 0 then ls_msg = "Class: " + this.is_class + "~r~n" if Len(this.is_script) > 0 then ls_msg += "Script: " + this.is_script + "~r~n" if thisDAT*$.ii_line > 0 then ls_msg += "Line: " + String(ii_line) + "~r~n" if ls_msg <> "" then ls_msg += "~r~n~r~n" ls_msg += this.GetMessage() // that message has previously been written to this object by f_throw() this.uf_write_to_log() // If your aDAT*&llplication displays error messages using it's own mechanism rather than calls MessageBox() // each time an error occurs, then change the following line accordingly: MessageBox(ls_msg_title, ls_msg, StopSign!) // If you use PFC, then uncomment the DAT*(following line and comment out the previous line: //gnv_app.inv_error.of_Message(ls_msg_title, ls_msg) return end subroutine protected subroutine uf_write_to_log ();/*****************************************************************************DAT******************************************* Dscr: Registers the thrown exception (writes to a log table or a file, and/or sends an email to the support staff or a developer) in addition to the error message, displayed in uf_msg. Called from uf_msDAT*,g() just before displaying the error message. **********************************************************************************************************************/ //####### If you need to somehow register the thrown exception (to write to a logDAT*. table or a file, and/or send //####### an email to the support staff or a developer) in addition to the error message, displayed in uf_msg, //####### then uncomment the following fragment and customize it according to your needs: //string ls_msgDAT*0 // //if this.ii_err_num > 0 then // ls_msg = "#" + String(this.ii_err_num) + ": " //end if // //if Len(this.is_class) > 0 then ls_msg += "Class: " + this.is_class //if ls_msg <> "" then ls_msg += "; " // //if Len(this.is_script) > 0 then ls_DAT*2msg += "Script: " + this.is_script //if ls_msg <> "" then ls_msg += "; " // //if this.ii_line > 0 then ls_msg += "Line: " + String(this.ii_line) //if ls_msg <> "" then ls_msg += "; " // //ls_msg += this.GetMessage() // ///******* TODO: Write lDAT*4s_msg to log and/or send it by email to the support staff or a developer *******/ // //return end subroutine on n_ex.create call super::create TriggerEvent( this, "constructor" ) end on on n_ex.destroy TriggerEvent( this, "destructor" ) DAT*>call super::destroy end on DAT*D5@Kp wf_static_text_clickeduf_msgH@ X ` h "-"2 " +clicked2  xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolortextalignmentborderbordDAT*:et = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" string text = "Close Spy" boolean cancel = true end type event clicked;close(parent) end event type gb_window from groupbox within w_spy DAT*<integer x = 3744 integer y = 28 integer width = 1568 integer height = 496 integer textsize = -10 integer weight = 700 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" loDAT*>ng textcolor = 16711680 long backcolor = 67108864 string text = "Window" end type type gb_datawindow from groupbox within w_spy integer x = 3744 integer y = 548 integer width = 1568 integer height = 1132 integer textsize = -10 integer weigDAT*@ht = 700 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long textcolor = 16711680 long backcolor = 67108864 string text = "DataWindow" end type type gb_clicked_field DAT*Bfrom groupbox within w_spy integer x = 3744 integer y = 2076 integer width = 1568 integer height = 372 integer textsize = -10 integer weight = 700 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! DAT*l string facename = "Arial" long textcolor = 16711680 long backcolor = 67108864 string text = "Field" end type type gb_clicked_row from groupbox within w_spy integer x = 3744 integer y = 1692 integer width = 1568 integer height = 372 integeDAT*Ferstylefocusrectangle@h$t2DRj~>    ]    ht DAT*H @>    . "b" (' <'9@;/5J4`X/5 D'`.d$ ::message5@KL mle_displayI:text0( < D "DAT*J."2 " +clicked2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenameenabledtext$ $X2DRj~ DAT*Lf]    $ X   f. "J"@;/524H@/5 'Hd$ ::message5@K DAT*N "/"2 " +clicked2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcancel{ $@2DRj~DAT*P ]    { @  @ . "2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamiDAT*Rlyfacenametextcolorbackcolortext $2DRj~]      DAT*T @@2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolortext$ $l2DRjDAT*V~]    $ l  @@2  2 xywidthheighttextsizeweightfontcharsetfontpDAT*Xitchfontfamilyfacenametextcolorbackcolortext $t2DRj~]     t DAT*Z @@2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolortext $t2DRDAT*\j~]     t  @@f";<q<;a,;/5N4d\/5 'd2dHDAT*^ xposyposrowdwo::messaged$, 845@K name__get_attributewf_sort_dw_display_by_columnD<   "=8@@;;3!,$;;,3,4;;<3;N<qx;,DAT*`;-@;/54 /5 ' /5 4 /5 ' <^ dz xposyposrowdwolnv_parmlw_one_more_spy::message$, 84 JF f5@K0 dwuf_setDAT*browcol_namename__get_attributeX$ 4 x    $6+6$+2 @ +doubleclicked+clicked(.2 xywidthheighttitlehscrollbarvscrollbarlivescrollborderstyle $DAT*dN$4 2> T j  ]     $N4  @ @7  @    8d 0+. 0P$DAT*f2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolorhscrollbarvscrollbarborderstyle $N$4 2DRj~DAT*h]     $N4  E @ @;1@2  2 xDAT*jywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolor  $2DRj~]      DAT*  @ @DAT*nr textsize = -10 integer weight = 700 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long textcolor = 16711680 long backcolor = 67108864 string text = "Row" end type DAT*p type dw_display from datawindow within w_spy integer x = 32 integer y = 36 integer width = 3662 integer height = 3124 string title = "none" boolean hscrollbar = true boolean vscrollbar = true boolean livescroll = true borderstyle borderstyleDAT*r = stylelowered! end type event doubleclicked;parent.wf_sort_dw_display_by_column(dwo.name) end event event clicked;n_parm lnv_parm w_spy lw_one_more_spy // it will be displayed with red background to remind it's open for the Spy, not for a DAT*tDW in your application if KeyDown(KeyShift!) then lnv_parm.uf_set(PARM_NAME__DW, this) lnv_parm.uf_set(PARM_NAME__ROW, row) lnv_parm.uf_set(PARM_NAME__COL, dwo.name) OpenWithParm(lw_one_more_spy, lnv_parm) end if return end event tyDAT*vpe mle_display from multilineedit within w_spy integer x = 32 integer y = 36 integer width = 3662 integer height = 3124 integer textsize = -9 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = fixed! fontfamily fontfamDAT*xily = modern! string facename = "Fixedsys" long backcolor = 16777215 boolean hscrollbar = true boolean vscrollbar = true borderstyle borderstyle = stylelowered! end type type gb_last from groupbox within w_spy integer x = 3744 integer y = 2DAT*z460 integer width = 1568 integer height = 700 integer textsize = -10 integer weight = 700 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long textcolor = 16711680 longDAT*F backcolor = 67108864 end type DAT*~DRj~ ]    { @  @ . "2  2 xywidthhDAT*eighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolortext $2DRj~]    DAT*   @@ 2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolortext$ DAT*$l2DRj~]    $ l  @@ 2  2 DAT* xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolortext $t2DRj~]   DAT*  t  @@ 2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolortextDAT* $t2DRj~]     t  @@ f";<qDAT*global type ifnull from function_object end type forward prototypes global function powerobject ifnull (powerobject apo_checked_value, powerobject apo_alternative_value) global function boolean ifnull (boolean ab_checked_value, boolean ab_alternDAT*ative_value) global function long ifnull (long al_checked_value, long al_alternative_value) global function double ifnull (double adb_checked_value, double adb_alternative_value) global function string ifnull (string as_checked_value, string as_altDAT*ernative_value) end prototypes global function powerobject ifnull (powerobject apo_checked_value, powerobject apo_alternative_value);if not IsNull(apo_checked_value) then return apo_checked_value end if return apo_alternative_value end funcDAT*tion global function boolean ifnull (boolean ab_checked_value, boolean ab_alternative_value);if not IsNull(ab_checked_value) then return ab_checked_value end if return ab_alternative_value end function global function long ifnull (long alDAT*_checked_value, long al_alternative_value);if not IsNull(al_checked_value) then return al_checked_value end if return al_alternative_value end function global function double ifnull (double adb_checked_value, double adb_alternative_value);ifDAT* not IsNull(adb_checked_value) then return adb_checked_value end if return adb_alternative_value end function global function string ifnull (string as_checked_value, string as_alternative_value);/*********************************************DAT*************************************************************************************************** Dscr: If the 1st argument is NOT null then the function returns it; otherwise it returns the 2nd argument. Mimics the NVL() function of Oracle &DAT* IsNull() function of SQL Server. The function is overloaded for the following datatypes: string, long, double, boolean, PowerObject. Both the arguments and the returned value must have a same datatype To see the overloads, open the fDAT*unction in the "Edit Source" mode. Examples of use: ll_row_count = IfNull(uf_get_row_count(), 0) li_min_allowed_age = IfNull(uf_get_min_allowed_age(), 18) ls_full_name = ls_first_name + " " + IfNull(ls_mid_name + " ", "DAT*") + ls_last_name // ls_mid_name is optional ls_err = "Argument as_mode contains illegal value " + IfNull("'" + as_mode + "'", "NULL") + "." // prevent NULLifying of ls_err ls_err = "Argument ai_mode contains illegal value '" + IfNull(StringDAT*(ai_mode), "NULL") + "'." // both the arguments must have a same datatype! lb_value_changed = (IfNull(ls_new_value, '') <> IfNull(ls_old_value, '')) lcb_clicked_button = IfNull(acb_clicked_button, cb_cancel) More details: http://codDAT*e.intfast.ca/viewtopic.php?t=5 ************************************************************************************************************************************************ Arg: Checked value - to return if it is NOT null Alternative valueDAT* - to return if the checked value is null ************************************************************************************************************************************************ Ret: string (other overloads return other types, but always DAT*the same type as the arguments) ************************************************************************************************************************************************ Developer: Michael Zuskin > http://linkedin.com/in/zuskin | http://code.DAT*intfast.ca/ ***********************************************************************************************************************************************/ if not IsNull(as_checked_value) then return as_checked_value end if return as_alternatDAT*6ive_value end function DAT*<;a,;/5N4d\/5 'd2dH xposyposrowdwo::messaged$, 945@L name__get_attributewf_sort_dw_display_by_columnD<   "=8@@;;3DAT*!,$;;,3,4;;<3;N<qx;,;-@;/54 /5 ' /5 4 /5 ' <^ dz xposyposrowdwolnv_parmlw_one_more_spy::message$, 9DAT*4 KF f5@L0 dwuf_setrowcol_namename__get_attributeX$ 4 x    $7+7$+2 @ +doubleclicked+clicked(.2 xywidthheighttitlehscrollbarvDAT*scrollbarlivescrollborderstyle $N$4 2>Tj ]     $N4  @ @8@  DAT*9d 0+. 0P$2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenamebackcolorhscrollbarvscrollbarborderstyle $N$4 2DAT*DRj~  ]     $N4  E  @ @< 1DAT* @2  2 xywidthheighttextsizeweightfontcharsetfontpitchfontfamilyfacenametextcolorbackcolor  $2DRj~DAT*]        @ @ DAT* textcolor = 16711680 long backcolor = 67108864 string text = "DataWindow" end type type gb_clicked_field from groupbox within w_spy integer x = 3744 integer y = 2076 integer width = 1568 integer height = 372 integer textsize = -10 integerDAT* weight = 700 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long textcolor = 16711680 long backcolor = 67108864 string text = "Field" end type type gb_clicked_row frDAT*om groupbox within w_spy integer x = 3744 integer y = 1692 integer width = 1568 integer height = 372 integer textsize = -10 integer weight = 700 fontcharset fontcharset = ansi! fontpitch fontpitch = variable! fontfamily fontfamily = swiss! sDAT*tring facename = "Arial" long textcolor = 16711680 long backcolor = 67108864 string text = "Row" end type type dw_display from datawindow within w_spy integer x = 32 integer y = 36 integer width = 3662 integer height = 3124 string title = DAT*"none" boolean hscrollbar = true boolean vscrollbar = true boolean livescroll = true borderstyle borderstyle = stylelowered! end type event doubleclicked;parent.wf_sort_dw_display_by_column(dwo.name) end event event clicked;n_parm lnv_parmDAT* w_spy lw_one_more_spy // it will be displayed with red background to remind it's open for the Spy, not for a DW in your application if KeyDown(KeyShift!) then lnv_parm.uf_set(PARM_NAME__DW, this) lnv_parm.uf_set(PARM_NAME__ROW, row) lnv_paDAT*rm.uf_set(PARM_NAME__COL, dwo.name) OpenWithParm(lw_one_more_spy, lnv_parm) end if return end event type mle_display from multilineedit within w_spy integer x = 32 integer y = 36 integer width = 3662 integer height = 3124 integer textsiDAT*ze = -9 integer weight = 400 fontcharset fontcharset = ansi! fontpitch fontpitch = fixed! fontfamily fontfamily = modern! string facename = "Fixedsys" long backcolor = 16777215 boolean hscrollbar = true boolean vscrollbar = true borderstyle bDAT*orderstyle = stylelowered! end type type gb_last from groupbox within w_spy integer x = 3744 integer y = 2460 integer width = 1568 integer height = 700 integer textsize = -10 integer weight = 700 fontcharset fontcharset = ansi! fontpitch fDAT*&ontpitch = variable! fontfamily fontfamily = swiss! string facename = "Arial" long textcolor = 16711680 long backcolor = 67108864 end type DAT********************************************** Dscr: Removes the required number of characters from the beginning of the given string ********************************************************************************************************************DAT**** Arg: as_string - BY REF ai_num_of_chars_to_remove **********************************************************************************************************************/ as_string = Right(as_string, Len(as_string) - ai_num_of_chars_to_removeDAT*) return end subroutine public function boolean uf_starts_with (string as_string, string as_substring);/********************************************************************************************************************** Dscr: Checks if the DAT*1st string starts with the 2nd string *********************************************************************************************************************** Arg: as_string as_substring ***********************************************************DAT************************************************************* Ret: boolean **********************************************************************************************************************/ return Left(as_string, Len(as_substring)) = as_substDAT*ring end function public function boolean uf_ends_with (string as_string, string as_substring);/********************************************************************************************************************** Dscr: Checks if the 1st string DAT*starts with the 2nd string *********************************************************************************************************************** Arg: as_string as_substring **********************************************************************DAT************************************************** Ret: boolean **********************************************************************************************************************/ return Right(as_string, Len(as_substring)) = as_substring end DAT*function on n_dwspy_util.create call super::create TriggerEvent( this, "constructor" ) end on on n_dwspy_util.destroy TriggerEvent( this, "destructor" ) call super::destroy end on DAT*hanged) **********************************************************************************************************************/ long ll_row_count string ls_col_type string ls_old string ls_new ll_row_count = uf_row_count(adw, a_buf) // ValDAT*idate parameters: choose case true case uf_empty(as_col) f_throw(PopulateError(1, "Arg as_col is empty.")) case IsNull(al_row) f_throw(PopulateError(2, "Arg al_row is null.")) case adw.DataObject = '' f_throw(PopulateError(3, "DW doesn't havDAT*e DataObject.")) case not uf_col_exists(adw, as_col) f_throw(PopulateError(4, "DW doesn't have column '" + as_col + "'.")) case al_row < 0 f_throw(PopulateError(5, "Arg al_row is negative (" + String(al_row) + ").")) case al_row > ll_row_count DAT* f_throw(PopulateError(6, "Arg al_row (" + String(al_row) + ") is greater than the number of rows in DW (" + String(ll_row_count) + ").")) end choose // Obtain old (original) and new (current) values: ls_old = uf_get_item_as_string(adw, al_row, DAT*as_col, a_buf, true) ls_new = uf_get_item_as_string(adw, al_row, as_col, a_buf, false) // Define if the value has been changed: if IsNull(ls_old) and IsNull(ls_new) then return false if IsNull(ls_old) and not IsNull(ls_new) then return true if DAT*not IsNull(ls_old) and IsNull(ls_new) then return true return (ls_new <> ls_old) end function public function boolean uf_row_modified (datawindow adw, long al_row, dwbuffer a_buf) throws n_ex;/***************************************************DAT******************************************************************** Dscr: Reports if at least one field in the pased row has been updated. Field is treated as updated if its value has been changed since row is retrieved or inserted. If value waDAT*s changed and later the original value was restored then it's not updated. *********************************************************************************************************************** Arg: adw DataWindow al_row long DWBuffer DAT*a_buf *********************************************************************************************************************** Ret: boolean *************************************************************************************************************DAT**********/ int i int li_col_count string as_col li_col_count = Integer(adw.Describe("datawindow.column.count")) for i = 1 to li_col_count as_col = adw.Describe("#"+ String(i) + ".name") if uf_col_modified(adw, as_col, al_row, a_buf) then DAT* return true end if next return false end function public function boolean uf_row_modified (datawindow adw, long al_row) throws n_ex;// Overload for Primary! buffer return uf_row_modified(adw, al_row, Primary!) end function public fDAT*unction boolean uf_col_is_visible (datawindow adw, string as_col_name) throws n_ex;/********************************************************************************************************************** Dscr: Checks if a column (with or without an exDAT*pression) is visible or invisible. *********************************************************************************************************************** Arg: adw, as_col_name ***********************************************************************DAT************************************************* Ret: true - visible, false - invisible **********************************************************************************************************************/ string ls_visible_expr string ls_err DAT* long li_row = 1 ls_visible_expr = adw.Describe(as_col_name + ".visible") // ls_visible_expr contains now '0', '1' or an expression if ls_visible_expr = '!' then ls_err = iif(this.uf_col_exists(adw, as_col_name), "Failed to obtain " + as_col_naDAT*me + ".visible property", "Column " + as_col_name + " doesn't exist") + " in DW " + adw.DataObject + "." f_throw(PopulateError(0, ls_err)) end if if Left(ls_visible_expr, 1) = '"' then ls_visible_expr = Replace(ls_visible_expr, 2, Pos(ls_visibDAT*le_expr, "~t") - 1, "") ls_visible_expr = adw.Describe("Evaluate(" + ls_visible_expr + ", " + String(li_row) + ")") // populate ls_visible_expr with "0" or "1" end if return (ls_visible_expr = "1") end function public subroutine uf_remove_chDAT*ars_from_end (ref string as_string, integer ai_num_of_chars_to_remove);/********************************************************************************************************************** Dscr: Removes the required number of characters from the enDAT*d of the given string *********************************************************************************************************************** Arg: as_string - BY REF ai_num_of_chars_to_remove *****************************************************DAT******************************************************************/ as_string = Left(as_string, Len(as_string) - ai_num_of_chars_to_remove) return end subroutine public subroutine uf_remove_chars_from_start (ref string as_string, integer ai_numDAT* _of_chars_to_remove);/********************************************************************************************************************** Dscr: Removes the required number of characters from the beginning of the given string *********************DAT* ************************************************************************************************** Arg: as_string - BY REF ai_num_of_chars_to_remove *************************************************************************************************DAT**********************/ as_string = Right(as_string, Len(as_string) - ai_num_of_chars_to_remove) return end subroutine public function boolean uf_starts_with (string as_string, string as_substring);/*********************************************DAT************************************************************************** Dscr: Checks if the 1st string starts with the 2nd string *********************************************************************************************************************DAT*** Arg: as_string as_substring *********************************************************************************************************************** Ret: boolean ********************************************************************************DAT***************************************/ return Left(as_string, Len(as_substring)) = as_substring end function public function boolean uf_ends_with (string as_string, string as_substring);/********************************************************DAT*************************************************************** Dscr: Checks if the 1st string starts with the 2nd string *********************************************************************************************************************** Arg: asDAT*_string as_substring *********************************************************************************************************************** Ret: boolean *******************************************************************************************DAT****************************/ return Right(as_string, Len(as_substring)) = as_substring end function on n_dwspy_util.create call super::create TriggerEvent( this, "constructor" ) end on on n_dwspy_util.destroy TriggerEvent( this, "destrucDAT*Ntor" ) call super::destroy end on