Задача:
Вызывать, из удаленной системы посредством RFC на выполнение любую SAP транзакцию (ABAP отчет) и возвратить данные, которые эта программа (отчет) должна была выводить на экран пользователю в SAP GUI, в удаленную систему в виде XML.
Ниже рассмотрен полный пример решения подобной задачи. Как со стороны ABAP части, так и пример вызова ABAP отчета из внешней системы.
Решение (альтернатива для SAP WEB Services):
ABAP часть:
0) Используем класс ZCL_CLST_CMD описанный здесь: http://www.sapboard.ru/forum/viewtopic.php?f=13&t=68638&view=previous
1) Функциональный модуль (RFC enabled), который будет вызывать внешняя система.
Где:
• F_XTAB в итоге содержит данные вызываемого ABAP отчета
• F_XTAB_FIELDS содержит структуру полей, из которых состоит отчет
• IM_CPROG – параметр на вход, в который передается наименование ABAP программы которую вызовет на обработку данный FM и из которой вернет данные во внешнюю систему.
• T_SELOPT – Параметры выбора с селективного экрана вызываемой транзакции.
Описание Z типов:
Структура ZSDOKCNTBIN. Компонент: LINE. Тип Char 255.
function z_srt_for_webshell. *"---------------------------------------------------------------------- *"*"Локальный интерфейс: *" IMPORTING *" VALUE(IM_PROG) TYPE SY-CPROG *" EXPORTING *" VALUE(EX_XML) TYPE STRING *" TABLES *" T_SELOPT STRUCTURE RSPARAMS *" F_XTAB STRUCTURE ZSDOKCNTBIN *" F_XTAB_FIELDS STRUCTURE ZSDOKCNTBIN OPTIONAL *"---------------------------------------------------------------------- *..data declaration ls_fldkey type wwwdata. define get_data. *..Экспорт zcl_clst_cmd=>agent->import_tables( exporting wakey = ls_key wafldkey = &1 changing tbdata_01 = lr_data ). *..create table *..go <table> to xstring (xml) call transformation id source tb = <table> result xml ex_xml. call function 'CONVERT_STRING_TO_TABLE' exporting i_string = ex_xml i_tabline_length = 255 et_table = &2. *..Ключевые поля кластера ls_key-relid = 'OK'. " Включая RELID *..Не ключевые поля ls_key-tdate = sy-datum. ls_key-ttime = sy-uzeit. *..get data exporting list to memory and return . "..clear memory after EXPORTING LIST TO MEMORY call function 'LIST_FREE_MEMORY'. * ..Ключ для описания ls_fldkey = ls_key. get_data ls_fldkey f_xtab. ** ..Ключ для описания * ls_fldkey = ls_key. * concatenate 'Z_' im_prog '_FF' into ls_fldkey-objid. * get_data ls_fldkey f_xtab_fields. *..free clst table zcl_clst_cmd=>agent->delete_tables( exporting wakey = ls_key wafldkey = ls_fldkey ).
2) Пример вызова FM в программе
call function 'Z_SRT_FOR_WEBSHELL' exporting im_cprog = sy-cprog t_tab = bestand[].” Внутренняя таблица с данными которая при обычных обстоятельствах выводиться на экран.
WEB Часть:
Для вызова RFC модуля используется php библиотека SAPRFC http://saprfc.sourceforge.net/
Ниже пример запроса данных и отображаения их в гриде jqGrid.
<?php setcookie('MATNRS_MB52', $ordernum, time()+$time, "/"); setcookie('MATNRPO_MB52', $ordernum, time()+$time, "/"); setcookie('WERKS_MB52', $ordernum, time()+$time, "/"); setcookie('WERKPO_MB52', $ordernum, time()+$time, "/"); setcookie('LGORTS_MB52', $ordernum, time()+$time, "/"); setcookie('LGORTPO_MB52', $ordernum, time()+$time, "/"); setcookie('CHARGS_MB52', $ordernum, time()+$time, "/"); setcookie('CHARGPO_MB52', $ordernum, time()+$time, "/"); setcookie('MTARTS_MB52', $ordernum, time()+$time, "/"); setcookie('MTARTPO_MB52', $ordernum, time()+$time, "/"); setcookie('MATKLS_MB52', $ordernum, time()+$time, "/"); setcookie('MATKLPO_MB52', $ordernum, time()+$time, "/"); header('Content-type: text/html; charset=cp-1251'); $MATNRS = $_POST['MATNRS_MB52']; // материал $MATNRPO = $_POST['MATNRPO_MB52']; $WERKS = $_POST['WERKS_MB52']; // завод $WERKPO = $_POST['WERKPO_MB52']; $LGORTS = $_POST['LGORTS_MB52']; // склад $LGORTPO = $_POST['LGORTPO_MB52']; $CHARGS = $_POST['CHARGS_MB52']; // партия $CHARGPO = $_POST['CHARGPO_MB52']; $MATARTS = $_POST['MTARTS_MB52'];// MATART вид материала $MATARTPO = $_POST['MTARTPO_MB52']; $MATKLAS = $_POST['MATKLS_MB52'];// MATKLA группа материалов $MATKLAPO = $_POST['MATKLPO_MB52']; ?> <html xmlns="<a href="http://www.w3.org/1999/xhtml"">http://www.w3.org/1999/xhtml"</a> xml:lang="ru" lang="ru"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Windows-1251" /> <title>Просмотр складских запасов к материалу</title> <link rel="stylesheet" type="text/css" media="screen" href="../css/flick/jquery-ui-1.7.2.custom.css" /> <link rel="stylesheet" type="text/css" media="screen" href="../css/ui.jqgrid.css" /> <style> html, body { margin: 0; padding: 0; font-size: 100%; } #table { } .alll { position: absolute; top: 10%; left: 3%; margin-top: -30px; margin-left: -30px; } .breadcrumb, .breadcrumb a { color: #006cc6; font-size: 21px; padding: 0; } </style> <script type="text/javascript" src="../js/jquery-1.4.min.js"></script> <script src="../js/i18n/grid.locale-ru.js" type="text/javascript"></script> <script src="../js/jquery.jqgrid.min.js" type="text/javascript"></script> <?php //Login to SAP R/3 if (isset($_COOKIE["password3"])) { include './../savecon.php'; // <strong>здесь подключение к SAP app. Server через php saprfc</strong> if (! $rfc ) { echo "RFC connection failed"; exit; } //Discover interface for function module Z_SRT_FOR_WEBSHELL $fce = saprfc_function_discover($rfc,"Z_SRT_FOR_WEBSHELL"); if (! $fce ) { echo "Discovering interface of function module failed"; exit; } //Set import parameters. You can use function saprfc_optional() to mark parameter as optional. saprfc_import ($fce,"IM_PROG","ZRM07MLBS_COPY"); //Fill internal tables saprfc_table_init ($fce,"F_XTAB"); saprfc_table_init ($fce,"T_SELOPT"); //saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATNR","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"130000348","HIGH"=>"")); // Фильтр if ($MATNRS != "" and $MATNRPO == "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATNR","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$MATNRS","HIGH"=>"")); } elseif ($MATNRS != "" and $MATNRPO != "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATNR","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$MATNRS","HIGH"=>"$MATNRPO")); } if ($WERKS != "" and $WERKPO == "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"WERKS","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$WERKS","HIGH"=>"")); } elseif ($WERKS != "" and $WERKPO != "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"WERKS","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$WERKS","HIGH"=>"$WERKPO")); } if ($LGORTS != "" and $LGORTPO == "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"LGORT","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$LGORTS","HIGH"=>"")); } elseif ($LGORTS != "" and $LGORTPO != "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"LGORT","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$LGORTS","HIGH"=>"$LGORTPO")); } if ($CHARGS != "" and $CHARGPO == "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"CHARG","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$CHARGS","HIGH"=>"")); } elseif ($CHARGS != "" and $CHARGPO != "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"CHARG","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$CHARGS","HIGH"=>"$CHARGPO")); } if ($MATKLAS != "" and $MATKLAPO == "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$MATKLAS","HIGH"=>"")); } elseif ($MATKLAS != "" and $MATKLAPO != "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$MATKLAS","HIGH"=>"$MATKLAPO")); } if ($MATARTS != "" and $MATARTPO == "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$MATARTS","HIGH"=>"")); } elseif ($MATARTS != "" and $MATARTPO != "") { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$MATARTS","HIGH"=>"$MATARTPO")); } // значения по умолчанию saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"PA_SOND","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"X","HIGH"=>"")); saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"XMCHB","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"X","HIGH"=>"")); saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"NOZERO","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"X","HIGH"=>"")); //Do RFC call of function Z_SRT_FOR_WEBSHELL, for handling exceptions use saprfc_exception() $rfc_rc = saprfc_call_and_receive ($fce); if ($rfc_rc != SAPRFC_OK) { if ($rfc == SAPRFC_EXCEPTION ) echo ("Exception raised: ".saprfc_exception($fce)); else echo (saprfc_error($fce)); exit; } //Retrieve export parameters $EX_XML = saprfc_export ($fce,"EX_XML"); $rows = saprfc_table_rows ($fce,"F_XTAB"); for ($i=1;$i<=$rows;$i++) $F_XTAB[] = saprfc_table_read ($fce,"F_XTAB",$i); $rows = saprfc_table_rows ($fce,"T_SELOPT"); for ($i=1;$i<=$rows;$i++) $T_SELOPT[] = saprfc_table_read ($fce,"T_SELOPT",$i); //Debug info //saprfc_function_debug_info($fce); saprfc_function_free($fce); saprfc_close($rfc); foreach ($F_XTAB as $b) { $varc = $varc+1; } } else { die('Данные для соеденения не введены <a href="index2.php">ввести данные</a>'); } $page = $_POST['page']; $sord = $_POST['sord']; // if(!$sidx) $sidx =1; //$result = mysql_query("SELECT COUNT(*) AS count FROM cities"); //$row = mysql_fetch_array($result,MYSQL_ASSOC); $count = $varc; // // if( $count > 0 && $limit > 0) { $total_pages = ceil($count/$limit); } else { $total_pages = 0; } // ?if ($page > $total_pages) $page=$total_pages; // $start = $limit*$page - $limit; // ?? $data->page = $page; $data->total = $total_pages; $data->records = $count; //// $i = 0; // function json_fix_cyr($var) { if (is_array($var)) { $new = array(); foreach ($var as $k => $v) { $new[json_fix_cyr($k)] = json_fix_cyr($v); } $var = $new; } elseif (is_object($var)) { $vars = get_object_vars($var); foreach ($vars as $m => $v) { $var->$m = json_fix_cyr($v); } } elseif (is_string($var)) { $var = iconv('cp1251', 'utf-8', $var); } return $var; } function json_safe_encode($var) { return json_encode(json_fix_cyr($var)); } foreach ($F_XTAB as $b) { $xmlstring = $xmlstring.$b[LINE]; } //echo json_fix_cyr($xmlstring); // формируем XML файл который будет прочитан нашим гридом $file = 'mb52.xml'; //$var33 = json_fix_cyr($xmlstring); $xmlstring2= ltrim ($xmlstring,'#'); $xmlstring3 = str_replace("utf-16", "utf-8", $xmlstring2); file_put_contents($file, json_fix_cyr($xmlstring3)); ?> <script type="text/javascript"> jQuery("#getselected").click(function(){ var selr = jQuery('#grid').jqGrid('getGridParam','selrow'); if(selr) alert(selr); else alert("No selected row"); return false; }); $.ajaxSetup({scriptCharset: "cp-1251" , contentType: "application/json; charset=cp-1251"}); $(function(){ var pager = $('#tablePager'); $('#table').jqGrid({ url:'mb52.xml', autosearch: true, enableClear: true, enableSearch: true, viewrecords: true, datatype: 'xml', mtype: 'GET', // <strong>колонки можно формировать на лету, используя таблицу //F_XTAB_FIELDS из FM z_srt_for_webshell, но для примера столбцы заданы явно.</strong> colNames:['Материал','Наименование материала','Завод','Склад','O','Оценка','Номер особого запаса','Скл','Партия','БЕИ','СвобИспользЗапас','Валюта','Ст-ть/своб. испол.','Транзит и перемещ.','Стоим. в пути+пер.',' На КонтрКачества','Ст-ть/контр.кач-ва','ОграничИспольз','Ст-ть/огр. испол.','Блокированный','Ст-ть/блок. запаса','Возвраты','Ст-ть/блок. возвр.'], colModel :[ // 20 {name:'MATNR', index:'MATNR', width:200}, {name:'MAKTX', index:'MAKTX', width:380}, {name:'WERKS', index:'WERKS', width:80}, {name:'LGORT', index:'LGORT', width:80}, {name:'SOBKZ', index:'SOBKZ', width:80}, {name:'KZBWS', index:'KZBWS', width:80}, {name:'SSNUM', index:'SSNUM', width:80}, {name:'LVORM', index:'LVORM', width:80}, {name:'CHARG', index:'CHARG', width:80}, {name:'MEINS', index:'MEINS', width:80}, {name:'LABST', index:'LABST', width:80}, {name:'WAERS', index:'WAERS', width:80}, {name:'WLABS', index:'WLABS', width:80}, {name:'INSME', index:'INSME', width:80}, {name:'WINSM', index:'WINSM', width:80}, {name:'SPEME', index:'SPEME', width:80}, {name:'WSPEM', index:'WSPEM', width:80}, {name:'EINME', index:'EINME', width:80}, {name:'WEINM', index:'WEINM', width:80}, {name:'RETME', index:'RETME', width:80}, {name:'WRETM', index:'WRETM', width:80}, //21 {name:'UMLME', index:'UMLME', width:80}, {name:'WUMLM', index:'WUMLM', width:80} ], pager: $('#tablePager'), rowNum:100, rowList:[100,200,300,400,500], caption: 'Просмотр складских запасов к материалу', rownumbers: true, height: 600, rownumWidth: 40, gridview: true, rownumbers: true, footerrow: true, gridComplete: function(){ var ids = $("#table").jqGrid('getDataIDs'); for(var i=1;i < ids.length;i++){ var ret2 = $("#table").jqGrid('getRowData',i); $.ajax({ async: false, type: 'GET', url: 'q.php', // отправка данных на сохранение (вызов отдельного RFC FM который выполнит сохранение данных) data: { QQQ: ret2.MEINS, }, success: function(res) { var DIMIDX = res; //alert(DIMIDX); // ClearCoc (); // тут очищаем сессию $("#table").jqGrid('setRowData',i,{MEINS:DIMIDX}); } }); } }, loadComplete: function() { sum = jQuery("#table").jqGrid('getCol', 'LABST', false, 'sum'); sum2 = jQuery("#table").jqGrid('getCol', 'WLABS', false, 'sum'); jQuery("#table").jqGrid('footerData','set', {MATNR: 'Итого:', LABST: sum, WLABS: sum2.toFixed(3)}); }, xmlReader: { root : "TB", row: "item", repeatitems: false } }) //jQuery("#table").jqGrid('filterToolbar'); }); </script> </head> <body> <div class="breadcrumb"><a href="/webi/ZMB52">Назад</a></div> <div class="alll"> <table id="table"></table> <div id="tablePager"></div> </div> </body> </html>