If you need to move a number of files or just move files between SAP and your desktop on a regular basis then you're probably not very happy with using CG3Z and CG3Y. I wrote a program to allow you to drag-and-drop files using just your mouse
On the selection screen you can enter starting paths for the PC and the server saving you time clicking around. You can also limit the file selection to just files you're interested in e.g. *.txt to get just text files.
The program uses a pair of CL_GUI_ALV_TREE controls sitting inside a splitter. You will need to create a screen with a huge custom control on it called MAINCONT.
*&---------------------------------------------------------------------* *& Report ZZFILE *& *&---------------------------------------------------------------------* *& File manager to move and copy files *& Mark Langenhoven *& 2019/02/14 *&---------------------------------------------------------------------* report zzfile. *--- Class deferring ------------------------------------------------ class lcl_tree_eventhandler definition deferred. *--- Constants ------------------------------------------------------ constants: gc_windows(10) value 'WINDOWS', gc_unix(4) value 'UNIX'. *--- Types ---------------------------------------------------------- types: begin of t_file, dirname type char600, name type char300, type_id type char1, type type char40, len(16) type p, owner type char8, mtime(6) type p, mode type char9, useable type char1, subrc type char4, errno type char3, errmsg type char40, mod_date type d, mod_time type char8, seen type char1, changed type char1, checked type c, end of t_file. data: begin of ls_tree, directory(10) type c, filename(10) type c, len(16) type p, date like sy-datum, time like sy-uzeit, end of ls_tree. types: begin of tree_type, parent_node type lvc_nkey, node_key type lvc_nkey, name type string, filetype type c, end of tree_type. *--- Data declarations ---------------------------------------------- data: the_handler type ref to lcl_tree_eventhandler, "application, custom type ref to cl_gui_custom_container, v_split type ref to cl_gui_splitter_container, l_tree_con type ref to cl_gui_container, r_tree_con type ref to cl_gui_container, server_tree type ref to cl_gui_alv_tree, pc_tree type ref to cl_gui_alv_tree. data: g_event(30), g_node_key type lvc_nkey. data: okcode like sy-ucomm, firsttime. data: gv_servtype(10), gv_pctype(10). data: gv_servdir type string, gv_pcdir type string, gv_serv_changed, gv_pc_changed. data: gs_file type t_file, gt_servfiles type standard table of t_file, gt_pcfiles type standard table of t_file. data: gt_tree like standard table of ls_tree, gt_fieldcat type lvc_t_fcat. data: gt_serv_tree type standard table of tree_type, gt_pc_tree type standard table of tree_type, gs_tree type tree_type. data: gv_serv_dragdrop type ref to cl_dragdrop, gv_pc_dragdrop type ref to cl_dragdrop, gv_serv_handle type i, gv_pc_handle type i. data: gv_answer type c, gv_stop_copy type c, gv_overwrite type c. *--- Class implementations ----------------------------------------- class lcl_dragdropobj definition. public section. data: node_keys type lvc_t_nkey. endclass. class lcl_tree_eventhandler definition. public section. methods: l_no_children for event expand_nc of cl_gui_alv_tree importing node_key, l_double for event node_double_click of cl_gui_alv_tree importing node_key, l_ondrag for event on_drag_multiple of cl_gui_alv_tree importing sender drag_drop_object fieldname node_key_table, l_ondrop for event on_drop of cl_gui_alv_tree importing drag_drop_object node_key, r_no_children for event expand_nc of cl_gui_alv_tree importing node_key, r_double for event node_double_click of cl_gui_alv_tree importing node_key, r_ondrag for event on_drag_multiple of cl_gui_alv_tree importing drag_drop_object fieldname node_key_table, r_ondrop for event on_drop of cl_gui_alv_tree importing sender drag_drop_object node_key. endclass. class lcl_tree_eventhandler implementation. "--- SERVER events -------------------------------------- method l_no_children. data: lv_path type string. g_node_key = node_key. "Build up the path, so that we can add additional nodes in under here clear lv_path. do. read table gt_serv_tree into gs_tree with key node_key = g_node_key. perform build_path using gs_tree-name gv_servtype abap_false changing lv_path. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. perform add_server_files using node_key lv_path. endmethod. "Refresh the current directory method l_double. data: lv_path type string. g_node_key = node_key. read table gt_serv_tree into gs_tree with key node_key = g_node_key. check gs_tree-filetype = 'd'. loop at gt_serv_tree into gs_tree where parent_node = g_node_key. call method server_tree->delete_subtree exporting i_node_key = gs_tree-node_key exceptions node_key_not_in_model = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. delete gt_serv_tree. endloop. "Build up the path, so that we can add additional nodes in under here clear lv_path. do. read table gt_serv_tree into gs_tree with key node_key = g_node_key. perform build_path using gs_tree-name gv_servtype abap_false changing lv_path. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. perform add_server_files using node_key lv_path. endmethod. method l_ondrag. data: dataobj type ref to lcl_dragdropobj. create object dataobj. refresh dataobj->node_keys. append lines of node_key_table to dataobj->node_keys. "If you don't fill this object references, the drop event "is never fired drag_drop_object->object = dataobj. endmethod. method l_ondrop. data: dataobj type ref to lcl_dragdropobj, ls_node type lvc_nkey, lv_movetype, lv_num type i, lv_perc type i. catch system-exceptions move_cast_error = 1. dataobj ?= drag_drop_object->object. if drag_drop_object->effect = cl_dragdrop=>copy. lv_movetype = 'C'. else. lv_movetype = 'M'. endif. clear gv_answer. describe table dataobj->node_keys lines lv_num. loop at dataobj->node_keys into ls_node. lv_perc = sy-tabix * 100 / lv_num. read table gt_pc_tree into gs_tree with key node_key = ls_node. call function 'SAPGUI_PROGRESS_INDICATOR' exporting percentage = lv_perc text = gs_tree-name. perform copy2serv using ls_node node_key lv_movetype. endloop. endcatch. if sy-subrc <> 0. call method drag_drop_object->abort. endif. call method pc_tree->frontend_update. call method server_tree->frontend_update. message s000(38) with lv_num 'files completed'. endmethod. "--- PC events ------------------------------------------ method r_no_children. data: lv_path type string. g_node_key = node_key. clear lv_path. do. read table gt_pc_tree into gs_tree with key node_key = g_node_key. perform build_path using gs_tree-name gv_pctype abap_false changing lv_path. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. perform add_pc_files using node_key lv_path. endmethod. "Refresh the current directory method r_double. data: lv_path type string. g_node_key = node_key. "Only operate on directories read table gt_pc_tree into gs_tree with key node_key = g_node_key. check gs_tree-filetype = 'd'. "Wipe out all the file nodes in this directory loop at gt_pc_tree into gs_tree where parent_node = g_node_key. call method pc_tree->delete_subtree exporting i_node_key = gs_tree-node_key exceptions node_key_not_in_model = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. delete gt_pc_tree. endloop. clear lv_path. do. read table gt_pc_tree into gs_tree with key node_key = g_node_key. perform build_path using gs_tree-name gv_pctype abap_false changing lv_path. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. perform add_pc_files using node_key lv_path. endmethod. method r_ondrag. data: dataobj type ref to lcl_dragdropobj. create object dataobj. refresh dataobj->node_keys. append lines of node_key_table to dataobj->node_keys. "If you don't fill this object references, the drop event "is never fired drag_drop_object->object = dataobj. endmethod. method r_ondrop. data: dataobj type ref to lcl_dragdropobj, ls_node type lvc_nkey, lv_movetype, lv_num type i, lv_perc type i. catch system-exceptions move_cast_error = 1. dataobj ?= drag_drop_object->object. if drag_drop_object->effect = cl_dragdrop=>copy. lv_movetype = 'C'. else. lv_movetype = 'M'. endif. clear gv_answer. describe table dataobj->node_keys lines lv_num. loop at dataobj->node_keys into ls_node. lv_perc = sy-tabix * 100 / lv_num. read table gt_serv_tree into gs_tree with key node_key = ls_node. call function 'SAPGUI_PROGRESS_INDICATOR' exporting percentage = lv_perc text = gs_tree-name. perform copy2pc using ls_node node_key lv_movetype. endloop. endcatch. if sy-subrc <> 0. call method drag_drop_object->abort. endif. call method pc_tree->frontend_update. call method server_tree->frontend_update. message s000(38) with lv_num 'files completed'. endmethod. endclass. *--- Selection screen ----------------------------------------------- selection-screen begin of line. selection-screen comment 1(25) ppc. parameters: p_pc type string obligatory default 'C:\Users\' lower case. selection-screen end of line. selection-screen begin of line. selection-screen comment 1(25) pserv. parameters: p_serv type string obligatory lower case. selection-screen end of line. selection-screen skip. selection-screen begin of line. selection-screen comment 1(25) pmask. parameters: p_mask type string lower case. selection-screen end of line. selection-screen skip. selection-screen begin of line. parameters: p_saplft as checkbox default 'X'. selection-screen comment 3(25) psaplft. selection-screen end of line. at selection-screen on value-request for p_pc. call method cl_gui_frontend_services=>directory_browse exporting window_title = 'Select a PC directory' initial_folder = p_pc changing selected_folder = p_pc exceptions cntl_error = 1 error_no_gui = 2 not_supported_by_gui = 3 others = 4. if sy-subrc <> 0. * Implement suitable error handling here endif. at selection-screen on value-request for p_serv. call function '/SAPDMC/LSM_F4_SERVER_FILE' exporting directory = p_serv filemask = '?' "Bad filemask so we only show directories importing serverfile = p_serv exceptions canceled_by_user = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. initialization. ppc = 'PC Directory'. pserv = 'Server Directory'. pmask = 'File mask (e.g. *.txt)'. psaplft = 'SAP files on the left'. concatenate '/tmp/' sy-sysid into p_serv. *=== Main program =================================================== start-of-selection. perform init_systems. call screen 0100 *&---------------------------------------------------------------------* *& Form CREATE_CONTAINERS *&---------------------------------------------------------------------* * Create all the containers on the screen *----------------------------------------------------------------------* form create_containers . data: events type cntl_simple_events, event type cntl_simple_event. data: dragtypes type i. data: ls_fcat type lvc_s_fcat. check firsttime = abap_true. clear firsttime. "Field catalog for the additional fields on both sides clear ls_fcat. ls_fcat-fieldname = 'DATE'. ls_fcat-outputlen = 12. ls_fcat-scrtext_s = 'Date'. ls_fcat-ref_field = 'DATUM'. ls_fcat-ref_table = 'SYST'. append ls_fcat to gt_fieldcat. clear ls_fcat. ls_fcat-fieldname = 'TIME'. ls_fcat-outputlen = 10. ls_fcat-scrtext_s = 'Time'. ls_fcat-ref_field = 'UZEIT'. ls_fcat-ref_table = 'SYST'. append ls_fcat to gt_fieldcat. clear ls_fcat. ls_fcat-fieldname = 'LEN'. ls_fcat-outputlen = 10. ls_fcat-scrtext_s = 'Size'. append ls_fcat to gt_fieldcat. create object the_handler. "Create a screen with a huge custom container and allow it "to resize as small as it wants create object custom exporting container_name = 'MAINCONT' exceptions cntl_error = 1 cntl_system_error = 2 create_error = 3 lifetime_error = 4 lifetime_dynpro_dynpro_link = 5 others = 6. if sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. endif. "Split the screen in half vertically create object v_split exporting parent = custom rows = 1 columns = 2. "Split each half in half again horizontally call method v_split->get_container exporting row = 1 column = 1 receiving container = l_tree_con. call method v_split->get_container exporting row = 1 column = 2 receiving container = r_tree_con. "Create the SERVER tree if p_saplft = abap_true. create object server_tree exporting parent = l_tree_con node_selection_mode = cl_tree_control_base=>node_sel_mode_multiple no_html_header = abap_true no_toolbar = abap_true exceptions cntl_error = 1 cntl_system_error = 2 create_error = 3 lifetime_error = 4 illegal_node_selection_mode = 5 failed = 6 illegal_column_name = 7 others = 8. if sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. endif. else. create object server_tree exporting parent = r_tree_con node_selection_mode = cl_tree_control_base=>node_sel_mode_multiple no_html_header = abap_true no_toolbar = abap_true exceptions cntl_error = 1 cntl_system_error = 2 create_error = 3 lifetime_error = 4 illegal_node_selection_mode = 5 failed = 6 illegal_column_name = 7 others = 8. if sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. endif. endif. call method server_tree->get_registered_events importing events = events exceptions cntl_error = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. "Set the event handlers for the server event-eventid = cl_gui_column_tree=>eventid_node_double_click. append event to events. event-eventid = cl_gui_column_tree=>eventid_expand_no_children. append event to events. call method server_tree->set_registered_events exporting events = events exceptions cntl_error = 1 cntl_system_error = 2 illegal_event_combination = 3 others = 4. if sy-subrc <> 0. * Implement suitable error handling here endif. set handler the_handler->l_no_children for server_tree. set handler the_handler->l_ondrag for server_tree. set handler the_handler->l_ondrop for server_tree. set handler the_handler->l_double for server_tree. create object gv_serv_dragdrop. dragtypes = cl_dragdrop=>move + cl_dragdrop=>copy. call method gv_serv_dragdrop->add exporting flavor = 'SERV2PC' dragsrc = abap_true droptarget = space effect = dragtypes exceptions already_defined = 1 obj_invalid = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. call method gv_serv_dragdrop->add exporting flavor = 'PC2SERV' dragsrc = space droptarget = abap_true effect = dragtypes exceptions already_defined = 1 obj_invalid = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. call method gv_serv_dragdrop->get_handle importing handle = gv_serv_handle exceptions obj_invalid = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_server_tree. "Create the PC tree if p_saplft = abap_true. create object pc_tree exporting parent = r_tree_con node_selection_mode = cl_tree_control_base=>node_sel_mode_multiple no_toolbar = abap_true no_html_header = abap_true exceptions cntl_error = 1 cntl_system_error = 2 create_error = 3 lifetime_error = 4 illegal_node_selection_mode = 5 failed = 6 illegal_column_name = 7 others = 8. if sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. endif. else. create object pc_tree exporting parent = l_tree_con node_selection_mode = cl_tree_control_base=>node_sel_mode_multiple no_toolbar = abap_true no_html_header = abap_true exceptions cntl_error = 1 cntl_system_error = 2 create_error = 3 lifetime_error = 4 illegal_node_selection_mode = 5 failed = 6 illegal_column_name = 7 others = 8. if sy-subrc <> 0. * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO * WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. endif. endif. refresh events. call method pc_tree->get_registered_events importing events = events exceptions cntl_error = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. "Set the event handlers for the PC event-eventid = cl_gui_column_tree=>eventid_node_double_click. append event to events. event-eventid = cl_gui_column_tree=>eventid_expand_no_children. append event to events. call method pc_tree->set_registered_events exporting events = events exceptions cntl_error = 1 cntl_system_error = 2 illegal_event_combination = 3 others = 4. if sy-subrc <> 0. * Implement suitable error handling here endif. set handler the_handler->r_no_children for pc_tree. set handler the_handler->r_ondrag for pc_tree. set handler the_handler->r_ondrop for pc_tree. set handler the_handler->r_double for pc_tree. create object gv_pc_dragdrop. dragtypes = cl_dragdrop=>move + cl_dragdrop=>copy. call method gv_pc_dragdrop->add exporting flavor = 'SERV2PC' dragsrc = space droptarget = abap_true effect = dragtypes exceptions already_defined = 1 obj_invalid = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. call method gv_pc_dragdrop->add exporting flavor = 'PC2SERV' dragsrc = abap_true droptarget = space effect = dragtypes exceptions already_defined = 1 obj_invalid = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. call method gv_pc_dragdrop->get_handle importing handle = gv_pc_handle exceptions obj_invalid = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_pc_tree. endform. *&---------------------------------------------------------------------* *& Form BUILD_SERVER_TREE *&---------------------------------------------------------------------* * Using the supplied path as the starting point, build up a tree of the * subdirectories below it *----------------------------------------------------------------------* form build_server_tree. data: ls_layout type lvc_s_layn, lv_relat_node_key type lvc_nkey, lv_main_key type lvc_nkey, ls_head type treev_hhdr, lv_value type lvc_value. ls_head-heading = 'Files on server'. ls_head-width = 50. ls_head-width_pix = ''. call method server_tree->set_table_for_first_display exporting is_hierarchy_header = ls_head changing it_outtab = gt_tree it_fieldcatalog = gt_fieldcat. ls_layout-isfolder = abap_true. ls_layout-expander = abap_true. ls_layout-dragdropid = gv_serv_handle. clear ls_tree. lv_value = p_serv. call method server_tree->add_node exporting i_relat_node_key = lv_relat_node_key i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_value importing e_new_node_key = lv_main_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. refresh gt_serv_tree. perform build_my_tree tables gt_serv_tree using lv_relat_node_key lv_main_key p_serv 'd'. perform add_server_files using lv_main_key gv_servdir. endform. *&---------------------------------------------------------------------* *& Module STATUS_0100 OUTPUT *&---------------------------------------------------------------------* module status_0100 output. data: lv_mask type string. set pf-status 'MAIN0100'. clear lv_mask. if p_mask is not initial. concatenate '- (' p_mask ')' into lv_mask. endif. set titlebar 'FIL' with lv_mask. perform create_containers. endmodule. *&---------------------------------------------------------------------* *& Module USER_COMMAND_0100 INPUT *&---------------------------------------------------------------------* module user_command_0100 input. if sy-ucomm = 'E'. leave to screen 0. endif. call method cl_gui_cfw=>dispatch. endmodule. *&---------------------------------------------------------------------* *& Form INIT_SYSTEMS *&---------------------------------------------------------------------* * Initialise the directories and operating systems *----------------------------------------------------------------------* form init_systems . data: lv_platform type i. firsttime = abap_true. "Determine the operating system of the server if sy-opsys cs 'Windows'. gv_servtype = gc_windows. else. gv_servtype = gc_unix. endif. "Determine the starting directory for the server if p_serv is initial. if gv_servtype = gc_unix. gv_servdir = '/'. else. gv_servdir = 'C:\'. endif. else. gv_servdir = p_serv. endif. "Check that this is a valid starting directory if gv_servtype = gc_unix. if gv_servdir cs '\'. message e000(38) with 'Invalid directory specified' 'Only Unix paths are accepted'. exit. endif. else. if gv_servdir cs '/'. message e000(38) with 'Invalid directory specified' 'Only Windows paths are accepted'. exit. endif. endif. "Determine the operating system of the PC call method cl_gui_frontend_services=>get_platform receiving platform = lv_platform exceptions error_no_gui = 1 cntl_error = 2 not_supported_by_gui = 3 others = 4. if sy-subrc <> 0. * Implement suitable error handling here endif. if lv_platform = cl_gui_frontend_services=>platform_windowsxp. gv_pctype = gc_windows. else. gv_pctype = gc_unix. message e000(38) with 'I do not support Unix frontends at the moment'. endif. "Determine the starting directory for the PC if p_pc is initial. if gv_pctype = gc_unix. gv_pcdir = '/'. else. gv_pcdir = 'C:\'. endif. else. gv_pcdir = p_pc. endif. "Check that this is a valid starting directory if gv_pctype = gc_unix. if gv_pcdir cs '\'. message e000(38) with 'Invalid directory specified' 'Only Unix paths are accepted'. exit. endif. else. if gv_pcdir cs '/'. message e000(38) with 'Invalid directory specified' 'Only Windows paths are accepted'. exit. endif. endif. "Mark both systems as changed initially so we can get the starting "direcotry information gv_serv_changed = abap_true. gv_pc_changed = abap_true. endform. *&---------------------------------------------------------------------* *& Form GET_SERV_FILES *&---------------------------------------------------------------------* * Find all the files and directories below the current directory *----------------------------------------------------------------------* form get_serv_files tables pt_files structure gs_file using pv_dir. constants: c_dir type char10 value 'DIR', c_file type char10 value 'FILE', c_name type char10 value 'NAME', c_owner type char10 value 'OWNER', c_len type char10 value 'LEN', c_mode type char10 value 'MODE', c_mtime type char10 value 'MTIME', c_type type char10 value 'TYPE', c_errmsg type char10 value 'ERRMSG', c_errno type char10 value 'ERRNO'. data: lv_path_name type localfile, lv_file_name type localfile. data: ls_file type t_file, ctime(10) type c, time like sy-uzeit, date like sy-datum. refresh pt_files. lv_path_name = pv_dir. * End of directory read (initialize the next call) call 'C_DIR_READ_FINISH' id c_errno field ls_file-errno id c_errmsg field ls_file-errmsg. call 'C_DIR_READ_START' id c_dir field lv_path_name id c_file field lv_file_name id c_errno field ls_file-errno id c_errmsg field ls_file-errmsg. if sy-subrc <> 0. message e000(38) with 'Error reading directory' gv_servdir ls_file-errmsg. else. do. call 'C_DIR_READ_NEXT' id c_type field ls_file-type id c_name field ls_file-name id c_len field ls_file-len id c_owner field ls_file-owner id c_mtime field ls_file-mtime id c_mode field ls_file-mode id c_errno field ls_file-errno id c_errmsg field ls_file-errmsg. ls_file-dirname = gv_servdir. ls_file-subrc = sy-subrc. translate ls_file-type to lower case. case sy-subrc. "Determine if a file is useable or not when 0. if ls_file-type(1) = 'f' or ls_file-type(1) = 'd'. "Add to the list of files to display if ls_file-mode(1) >= '5'. ls_file-useable = 'W'. "File or dir is writeable elseif ls_file-mode(1) = '4'. ls_file-useable = 'R'. "Only read permissions else. clear ls_file-useable. "No permissions endif. perform p6_to_date_time_tz(rstr0400) using ls_file-mtime ctime date. translate ctime using ': '. condense ctime no-gaps. time = ctime. ls_file-mod_date = date. ls_file-mod_time = time. append ls_file to pt_files. endif. when 1. exit. when others. endcase. enddo. endif. sort pt_files by name. endform. *&---------------------------------------------------------------------* *& Form BUILD_MY_TREE *&---------------------------------------------------------------------* * Build my internal version of the tree to keep track of sub-directories * and file locations *----------------------------------------------------------------------* form build_my_tree tables pt_tree structure gs_tree using pv_header_node pv_node pv_name value(pv_type). clear gs_tree. gs_tree-parent_node = pv_header_node. gs_tree-node_key = pv_node. gs_tree-name = pv_name. gs_tree-filetype = pv_type. append gs_tree to pt_tree. endform. *&---------------------------------------------------------------------* *& Form BUILD_PATH *&---------------------------------------------------------------------* * Build up the path based on the OS type *----------------------------------------------------------------------* form build_path using pv_dir_name pv_ostype pv_file changing pv_path. data: separator type c. if pv_ostype = gc_windows. separator = '\'. else. separator = '/'. endif. if pv_file = abap_true and pv_path is initial. clear separator. endif. concatenate pv_dir_name separator pv_path into pv_path. "If the user added a slash to the end of the starting paths "then we could end up with duplicated separators replace all occurrences of '\\' in pv_path with '\'. replace all occurrences of '//' in pv_path with '/'. endform. *&---------------------------------------------------------------------* *& Form ADD_SERVER_FILES *&---------------------------------------------------------------------* * Add files to the specified node for the supplied path *----------------------------------------------------------------------* form add_server_files using pv_node pv_path. data: lv_name type lvc_value, ls_layout type lvc_s_layn, lv_relat_node_key type lvc_nkey, lv_matched type c. perform get_serv_files tables gt_servfiles using pv_path. "First add any sub-directories loop at gt_servfiles into gs_file where type(1) = 'd'. lv_name = gs_file-name. check lv_name <> '.' and lv_name <> '..'. clear ls_layout. if gs_file-useable = 'W'. ls_layout-isfolder = abap_true. ls_layout-expander = abap_true. ls_layout-dragdropid = gv_serv_handle. endif. if gs_file-useable = 'R'. ls_layout-isfolder = abap_true. ls_layout-expander = abap_true. endif. if gs_file-useable = abap_false. ls_layout-isfolder = abap_true. ls_layout-disabled = abap_true. endif. clear ls_tree. ls_tree-date = gs_file-mod_date. ls_tree-time = gs_file-mod_time. clear ls_tree-len. call method server_tree->add_node exporting i_relat_node_key = pv_node i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_name importing e_new_node_key = lv_relat_node_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_my_tree tables gt_serv_tree using pv_node lv_relat_node_key gs_file-name gs_file-type(1). endloop. "Add the files loop at gt_servfiles into gs_file where type(1) = 'f'. "If there's a mask filter in place, then see if this file matches it perform match_mask using gs_file-name changing lv_matched. check lv_matched = abap_true. lv_name = gs_file-name. clear ls_layout. if gs_file-useable = 'W'. ls_layout-dragdropid = gv_serv_handle. else. ls_layout-disabled = abap_true. endif. clear ls_tree. ls_tree-date = gs_file-mod_date. ls_tree-time = gs_file-mod_time. ls_tree-len = gs_file-len. call method server_tree->add_node exporting i_relat_node_key = pv_node i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_name importing e_new_node_key = lv_relat_node_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_my_tree tables gt_serv_tree using pv_node lv_relat_node_key gs_file-name gs_file-type(1). endloop. call method server_tree->expand_node exporting i_node_key = pv_node exceptions failed = 1 illegal_level_count = 2 cntl_system_error = 3 node_not_found = 4 cannot_expand_leaf = 5 others = 6. if sy-subrc <> 0. * Implement suitable error handling here endif. call method server_tree->frontend_update. endform. *&---------------------------------------------------------------------* *& Form BUILD_PC_TREE *&---------------------------------------------------------------------* * Build up the tree containing the PC folders and files *----------------------------------------------------------------------* form build_pc_tree. data: ls_layout type lvc_s_layn, lv_relat_node_key type lvc_nkey, lv_main_key type lvc_nkey, ls_head type treev_hhdr, ls_fcat type lvc_s_fcat, lv_value type lvc_value. ls_head-heading = 'Files on PC'. ls_head-width = 50. ls_head-width_pix = ''. call method pc_tree->set_table_for_first_display exporting is_hierarchy_header = ls_head changing it_outtab = gt_tree it_fieldcatalog = gt_fieldcat. ls_layout-isfolder = abap_true. ls_layout-expander = abap_true. ls_layout-dragdropid = gv_pc_handle. clear ls_tree. lv_value = p_pc. call method pc_tree->add_node exporting i_relat_node_key = lv_relat_node_key i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_value importing e_new_node_key = lv_main_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. refresh gt_pc_tree. perform build_my_tree tables gt_pc_tree using lv_relat_node_key lv_main_key p_pc 'd'. perform add_pc_files using lv_main_key p_pc. endform. *&---------------------------------------------------------------------* *& Form ADD_PC_FILES *&---------------------------------------------------------------------* * Add the folders and files found on the PC *----------------------------------------------------------------------* form add_pc_files using pv_node pv_path. data: lv_path type string, ls_layout type lvc_s_layn, lt_files type standard table of file_info, ls_file type file_info, lv_relat_node_key type lvc_nkey, lv_value type lvc_value, lv_matched type c, lv_count type i. lv_path = pv_path. call method cl_gui_frontend_services=>directory_list_files exporting directory = lv_path changing file_table = lt_files count = lv_count exceptions cntl_error = 1 directory_list_files_failed = 2 wrong_parameter = 3 error_no_gui = 4 not_supported_by_gui = 5 others = 6. if sy-subrc <> 0. * Implement suitable error handling here endif. sort lt_files by filename. "First add all the sub-directories ls_layout-isfolder = abap_true. ls_layout-expander = abap_true. ls_layout-dragdropid = gv_pc_handle. loop at lt_files into ls_file where isdir = 1. "Insane moron using int for a flag check ls_file-ishidden = 0. clear ls_tree. ls_tree-date = ls_file-createdate. ls_tree-time = ls_file-createtime. lv_value = ls_file-filename. call method pc_tree->add_node exporting i_relat_node_key = pv_node i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_value importing e_new_node_key = lv_relat_node_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_my_tree tables gt_pc_tree using pv_node lv_relat_node_key ls_file-filename 'd'. endloop. "Now add all the files clear ls_layout. ls_layout-dragdropid = gv_pc_handle. loop at lt_files into ls_file where isdir = 0. check ls_file-ishidden = 0. clear ls_tree. lv_value = ls_file-filename. "If there's a mask filter in place, then see if this file matches it perform match_mask using ls_file-filename changing lv_matched. check lv_matched = abap_true. clear ls_tree. ls_tree-date = ls_file-createdate. ls_tree-time = ls_file-createtime. ls_tree-len = ls_file-filelength. call method pc_tree->add_node exporting i_relat_node_key = pv_node i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_value importing e_new_node_key = lv_relat_node_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_my_tree tables gt_pc_tree using pv_node lv_relat_node_key ls_file-filename 'f'. endloop. call method pc_tree->expand_node exporting i_node_key = pv_node exceptions failed = 1 illegal_level_count = 2 cntl_system_error = 3 node_not_found = 4 cannot_expand_leaf = 5 others = 6. if sy-subrc <> 0. * Implement suitable error handling here endif. call method pc_tree->frontend_update. endform. *&---------------------------------------------------------------------* *& Form COPY2PC *&---------------------------------------------------------------------* * Copy a file to the PC *----------------------------------------------------------------------* form copy2pc using pv_server_node pv_pc_node pv_move_type. data: lv_relat_node_key type lvc_nkey, lv_pc_node type lvc_nkey, lv_value type lvc_value, ls_layout type lvc_s_layn, lv_file_name type string. "If the PC destination is a file, then find the directory that it's in read table gt_pc_tree into gs_tree with key node_key = pv_pc_node. if gs_tree-filetype = 'f'. lv_pc_node = gs_tree-parent_node. else. lv_pc_node = pv_pc_node. endif. read table gt_serv_tree into gs_tree with key node_key = pv_server_node. check sy-subrc = 0. "If the SERVER origin is a directory, then copy all the files inside it if gs_tree-filetype = 'd'. "Loop through all the files in this directory and copy them over loop at gt_serv_tree into gs_tree where parent_node = pv_server_node. perform copy2pc using gs_tree-node_key lv_pc_node pv_move_type. endloop. exit. endif. "Copy the actual file ----------------------------------- clear gv_stop_copy. perform file2pc using pv_server_node lv_pc_node pv_move_type changing lv_file_name. check gv_stop_copy is initial. if gv_overwrite is initial. "Add the node to the PC tree ---------------------------- clear ls_tree. lv_value = lv_file_name. clear ls_layout. ls_layout-dragdropid = gv_pc_handle. call method pc_tree->add_node exporting i_relat_node_key = lv_pc_node i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_value importing e_new_node_key = lv_relat_node_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_my_tree tables gt_pc_tree using lv_pc_node lv_relat_node_key lv_file_name 'f'. endif. "See if this was a move rather than a copy check pv_move_type = 'M'. "Remove the node from the SERVER tree ------------------- call method server_tree->delete_subtree exporting i_node_key = pv_server_node exceptions node_key_not_in_model = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. delete gt_serv_tree where node_key = pv_server_node. endform. *&---------------------------------------------------------------------* *& Form COPY2SERV *&---------------------------------------------------------------------* * Copy files from the PC to the SERVER *----------------------------------------------------------------------* form copy2serv using pv_pc_node pv_server_node pv_move_type. data: lv_relat_node_key type lvc_nkey, lv_serv_node type lvc_nkey, lv_value type lvc_value, ls_layout type lvc_s_layn, lv_file_name type string. "If the SERVER destination is a file, then find the directory that it's in read table gt_serv_tree into gs_tree with key node_key = pv_server_node. if gs_tree-filetype = 'f'. lv_serv_node = gs_tree-parent_node. else. lv_serv_node = pv_server_node. endif. read table gt_pc_tree into gs_tree with key node_key = pv_pc_node. check sy-subrc = 0. "If the PC origin is a directory, then copy all the files inside it if gs_tree-filetype = 'd'. loop at gt_pc_tree into gs_tree where parent_node = pv_pc_node. perform copy2serv using gs_tree-node_key lv_serv_node pv_move_type. endloop. exit. endif. "Copy the actual file ----------------------------------- clear gv_stop_copy. perform file2server using pv_pc_node lv_serv_node pv_move_type changing lv_file_name. check gv_stop_copy is initial. if gv_overwrite is initial. "Add the node to the SERVER tree ------------------------ clear ls_tree. lv_value = lv_file_name. clear ls_layout. ls_layout-dragdropid = gv_serv_handle. call method server_tree->add_node exporting i_relat_node_key = lv_serv_node i_relationship = cl_tree_control_base=>relat_last_child is_outtab_line = ls_tree is_node_layout = ls_layout i_node_text = lv_value importing e_new_node_key = lv_relat_node_key exceptions relat_node_not_found = 1 node_not_found = 2 others = 3. if sy-subrc <> 0. * Implement suitable error handling here endif. perform build_my_tree tables gt_serv_tree using lv_serv_node lv_relat_node_key lv_file_name 'f'. endif. "See if this was a move rather than a copy check pv_move_type = 'M'. "Remove the node from the PC tree ----------------------- call method pc_tree->delete_subtree exporting i_node_key = pv_pc_node exceptions node_key_not_in_model = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. delete gt_pc_tree where node_key = pv_pc_node. endform. *&---------------------------------------------------------------------* *& Form FILE2SERVER *&---------------------------------------------------------------------* * Copy a file to the server *----------------------------------------------------------------------* form file2server using pv_pc_node pv_serv_node pv_move_type changing pv_file_name. data: lv_pc_name type string, lv_serv_name type string, lv_file_size type i, lv_len type i, lv_lines type i, lt_data type rcgrepfile occurs 0 with header line. g_node_key = pv_pc_node. clear lv_pc_name. do. read table gt_pc_tree into gs_tree with key node_key = g_node_key. if gs_tree-filetype = 'f'. pv_file_name = gs_tree-name. endif. perform build_path using gs_tree-name gv_pctype abap_true changing lv_pc_name. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. g_node_key = pv_serv_node. clear lv_serv_name. do. read table gt_serv_tree into gs_tree with key node_key = g_node_key. perform build_path using gs_tree-name gv_servtype abap_false changing lv_serv_name. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. concatenate lv_serv_name pv_file_name into lv_serv_name. clear: gv_stop_copy, gv_overwrite. "Check if the file already exists on the server if gv_answer is initial. open dataset lv_serv_name for input in binary mode. if sy-subrc = 0. call function 'POPUP_TO_CONFIRM' exporting titlebar = 'File already exists' text_question = lv_serv_name text_button_1 = 'Overwrite' text_button_2 = 'Overwrite ALL' default_button = '3' display_cancel_button = 'X' importing answer = gv_answer exceptions text_not_found = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. "Cancel the file copying if gv_answer = '3'. clear gv_answer. gv_stop_copy = abap_true. close dataset lv_serv_name. exit. endif. "Copy this file, but ask again next time if gv_answer = '1'. clear gv_answer. gv_overwrite = abap_true. close dataset lv_serv_name. endif. endif. endif. if gv_answer is not initial. gv_overwrite = abap_true. endif. check gv_stop_copy is initial. call function 'C13Z_UPLOAD' exporting filename = lv_pc_name filetype = 'BIN' importing filelength = lv_file_size tables data_tab = lt_data exceptions conversion_error = 1 file_open_error = 2 file_read_error = 3 invalid_type = 4 no_batch = 5 unknown_error = 6 invalid_table_width = 7 gui_refuse_filetransfer = 8 customer_error = 9 no_authority = 10 bad_data_format = 11 header_not_allowed = 12 separator_not_allowed = 13 header_too_long = 14 unknown_dp_error = 15 access_denied = 16 dp_out_of_memory = 17 disk_full = 18 dp_timeout = 19 not_supported_by_gui = 20 error_no_gui = 21 others = 22. if sy-subrc <> 0. message e000(38) with 'Unable to upload the file'. gv_stop_copy = abap_true. exit. endif. open dataset lv_serv_name for output in binary mode. if sy-subrc <> 0. message e000(38) with 'Cannot open file on server'. gv_stop_copy = abap_true. exit. endif. describe table lt_data lines lv_lines. lv_len = 2550. loop at lt_data. "Special handling for the last line if sy-tabix = lv_lines. lv_len = lv_file_size - ( 2550 * ( lv_lines - 1 ) ). endif. transfer lt_data to lv_serv_name length lv_len. endloop. close dataset lv_serv_name. "If we're moving the file, then delete the original check pv_move_type = 'M'. call method cl_gui_frontend_services=>file_delete exporting filename = lv_pc_name changing rc = lv_len exceptions file_delete_failed = 1 cntl_error = 2 error_no_gui = 3 file_not_found = 4 access_denied = 5 unknown_error = 6 not_supported_by_gui = 7 wrong_parameter = 8 others = 9. if sy-subrc <> 0. * Implement suitable error handling here endif. endform. *&---------------------------------------------------------------------* *& Form FILE2PC *&---------------------------------------------------------------------* * Copy a file to the PC *----------------------------------------------------------------------* form file2pc using pv_server_node pv_pc_node pv_move_type changing pv_file_name. data: lv_pc_name type string, lv_serv_name type string, lv_file_size type i, lv_len type i, lv_lines type i, lv_result type c, lt_data type rcgrepfile occurs 0 with header line. g_node_key = pv_server_node. clear lv_serv_name. do. read table gt_serv_tree into gs_tree with key node_key = g_node_key. if gs_tree-filetype = 'f'. pv_file_name = gs_tree-name. endif. perform build_path using gs_tree-name gv_servtype abap_true changing lv_serv_name. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. g_node_key = pv_pc_node. clear lv_pc_name. do. read table gt_pc_tree into gs_tree with key node_key = g_node_key. perform build_path using gs_tree-name gv_pctype abap_false changing lv_pc_name. g_node_key = gs_tree-parent_node. if g_node_key is initial. exit. endif. enddo. concatenate lv_pc_name pv_file_name into lv_pc_name. clear: gv_stop_copy, gv_overwrite. if gv_answer is initial. "Check if the file exists on the PC call method cl_gui_frontend_services=>file_exist exporting file = lv_pc_name receiving result = lv_result exceptions cntl_error = 1 error_no_gui = 2 wrong_parameter = 3 not_supported_by_gui = 4 others = 5. if sy-subrc <> 0. * Implement suitable error handling here endif. if lv_result = abap_true. call function 'POPUP_TO_CONFIRM' exporting titlebar = 'File already exists' text_question = lv_serv_name text_button_1 = 'Overwrite' text_button_2 = 'Overwrite ALL' default_button = '3' display_cancel_button = 'X' importing answer = gv_answer exceptions text_not_found = 1 others = 2. if sy-subrc <> 0. * Implement suitable error handling here endif. if gv_answer = '3'. clear gv_answer. gv_stop_copy = abap_true. exit. endif. if gv_answer = '1'. clear gv_answer. gv_overwrite = abap_true. endif. endif. endif. if gv_answer is not initial. gv_overwrite = abap_true. endif. check gv_stop_copy is initial. "Copy the file data: mtext type string. open dataset lv_serv_name for input in binary mode message mtext. if sy-subrc <> 0. message e000(38) with 'Cannot open file on server'. wait up to 3 seconds. gv_stop_copy = abap_true. exit. endif. do. clear lv_len. clear lt_data. read dataset lv_serv_name into lt_data-orblk length lv_len. if sy-subrc <> 0. if lv_len > 0. lv_file_size = lv_file_size + lv_len. append lt_data. endif. exit. endif. lv_file_size = lv_file_size + lv_len. append lt_data. enddo. close dataset lv_serv_name. call function 'C13Z_DOWNLOAD' exporting bin_filesize = lv_file_size filename = lv_pc_name filetype = 'BIN' importing filelength = lv_len tables data_tab = lt_data exceptions file_open_error = 1 file_write_error = 2 invalid_filesize = 3 invalid_type = 4 no_batch = 5 unknown_error = 6 invalid_table_width = 7 gui_refuse_filetransfer = 8 customer_error = 9 no_authority = 10 header_not_allowed = 11 separator_not_allowed = 12 header_too_long = 13 dp_error_create = 14 dp_error_send = 15 dp_error_write = 16 unknown_dp_error = 17 access_denied = 18 dp_out_of_memory = 19 disk_full = 20 dp_timeout = 21 file_not_found = 22 dataprovider_exception = 23 control_flush_error = 24 not_supported_by_gui = 25 error_no_gui = 26 others = 27. if sy-subrc <> 0. message e000(38) with 'Unable to download the file'. gv_stop_copy = abap_true. exit. endif. "If this was a MOVE, then delete the original file check pv_move_type = 'M'. delete dataset lv_serv_name. endform. *&---------------------------------------------------------------------* *& Form MATCH_MASK *&---------------------------------------------------------------------* * See if a given filename matches the selection screen mask *----------------------------------------------------------------------* form match_mask using pv_filename changing pv_matched. data: lv_mask type string, lv_reg type string, moff type i, mlen type i. pv_matched = abap_true. check p_mask is not initial. lv_mask = p_mask. clear lv_reg. while lv_mask is not initial. if lv_mask(1) = '*'. concatenate lv_reg '.{0,200}' into lv_reg. "Match anything from 0 to 200 chars else. if lv_mask(1) = '.'. "Escape the "." so that it matches exactly rather than generically concatenate lv_reg '\' lv_mask(1) into lv_reg. else. concatenate lv_reg lv_mask(1) into lv_reg. "Match this exact char endif. endif. shift lv_mask left. endwhile. find regex lv_reg in pv_filename match offset moff match length mlen. if sy-subrc <> 0. pv_matched = abap_false. else. "If we only matched a partial filename, then throw it away if mlen < strlen( pv_filename ). pv_matched = abap_false. endif. endif. endform.
No comments:
Post a Comment