Вызов любой ABAP программы из внешней системы посредством RFC

Задача:
Вызывать, из удаленной системы посредством 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.

  1. function z_srt_for_webshell.
  2. *"----------------------------------------------------------------------
  3. *"*"Локальный интерфейс:
  4. *" IMPORTING
  5. *" VALUE(IM_PROG) TYPE SY-CPROG
  6. *" EXPORTING
  7. *" VALUE(EX_XML) TYPE STRING
  8. *" TABLES
  9. *" T_SELOPT STRUCTURE RSPARAMS
  10. *" F_XTAB STRUCTURE ZSDOKCNTBIN
  11. *" F_XTAB_FIELDS STRUCTURE ZSDOKCNTBIN OPTIONAL
  12. *"----------------------------------------------------------------------
  13. *..data declaration
  14.  
  15. data: lr_data type ref to data.
  16. data: ls_key type wwwdata,
  17. ls_fldkey type wwwdata.
  18. field-symbols: <table> type standard table.
  19.  
  20. define get_data.
  21. *..Экспорт
  22. zcl_clst_cmd=>agent->import_tables(
  23. exporting
  24. wakey = ls_key
  25. wafldkey = &1
  26. changing
  27. tbdata_01 = lr_data ).
  28.  
  29. *..create table
  30. assign lr_data->* to <table>.
  31.  
  32. *..go <table> to xstring (xml)
  33. call transformation id
  34. source tb = <table>
  35. result xml ex_xml.
  36.  
  37. call function 'CONVERT_STRING_TO_TABLE'
  38. exporting
  39. i_string = ex_xml
  40. i_tabline_length = 255
  41. et_table = &2.
  42.  
  43.  
  44.  
  45.  
  46. data: x_callwebshell(1) value 'X'.
  47. export x_callwebshell to memory id 'Z_SRT_FOR_WEBSHELL_XCWS'.
  48.  
  49. *..Ключевые поля кластера
  50. ls_key-relid = 'OK'. " Включая RELID
  51. concatenate 'Z_' im_prog into ls_key-objid.
  52. *..Не ключевые поля
  53. ls_key-tdate = sy-datum.
  54. ls_key-ttime = sy-uzeit.
  55.  
  56. *..get data
  57. submit (im_prog) with selection-table t_selopt
  58. exporting list to memory and return .
  59.  
  60. "..clear memory after EXPORTING LIST TO MEMORY
  61. call function 'LIST_FREE_MEMORY'.
  62.  
  63. * ..Ключ для описания
  64. ls_fldkey = ls_key.
  65. concatenate 'Z_' im_prog '_F' into ls_fldkey-objid.
  66.  
  67. get_data ls_fldkey f_xtab.
  68.  
  69. ** ..Ключ для описания
  70. * ls_fldkey = ls_key.
  71. * concatenate 'Z_' im_prog '_FF' into ls_fldkey-objid.
  72. * get_data ls_fldkey f_xtab_fields.
  73.  
  74.  
  75. *..free clst table
  76. zcl_clst_cmd=>agent->delete_tables(
  77. exporting
  78. wakey = ls_key
  79. wafldkey = ls_fldkey ).
  80.  

2) Пример вызова FM в программе

  1. call function 'Z_SRT_FOR_WEBSHELL'
  2. exporting
  3. im_cprog = sy-cprog
  4. t_tab = bestand[].” Внутренняя таблица с данными которая при обычных обстоятельствах выводиться на экран.

WEB Часть:
Для вызова RFC модуля используется php библиотека SAPRFC http://saprfc.sourceforge.net/
Ниже пример запроса данных и отображаения их в гриде jqGrid.

  1. <?php
  2. setcookie('MATNRS_MB52', $ordernum, time()+$time, "/");
  3. setcookie('MATNRPO_MB52', $ordernum, time()+$time, "/");
  4.  
  5. setcookie('WERKS_MB52', $ordernum, time()+$time, "/");
  6. setcookie('WERKPO_MB52', $ordernum, time()+$time, "/");
  7.  
  8. setcookie('LGORTS_MB52', $ordernum, time()+$time, "/");
  9. setcookie('LGORTPO_MB52', $ordernum, time()+$time, "/");
  10.  
  11. setcookie('CHARGS_MB52', $ordernum, time()+$time, "/");
  12. setcookie('CHARGPO_MB52', $ordernum, time()+$time, "/");
  13.  
  14. setcookie('MTARTS_MB52', $ordernum, time()+$time, "/");
  15. setcookie('MTARTPO_MB52', $ordernum, time()+$time, "/");
  16.  
  17. setcookie('MATKLS_MB52', $ordernum, time()+$time, "/");
  18. setcookie('MATKLPO_MB52', $ordernum, time()+$time, "/");
  19.  
  20.  
  21. header('Content-type: text/html; charset=cp-1251');
  22.  
  23. $MATNRS = $_POST['MATNRS_MB52']; // материал
  24. $MATNRPO = $_POST['MATNRPO_MB52'];
  25. $WERKS = $_POST['WERKS_MB52']; // завод
  26. $WERKPO = $_POST['WERKPO_MB52'];
  27. $LGORTS = $_POST['LGORTS_MB52']; // склад
  28. $LGORTPO = $_POST['LGORTPO_MB52'];
  29. $CHARGS = $_POST['CHARGS_MB52']; // партия
  30. $CHARGPO = $_POST['CHARGPO_MB52'];
  31. $MATARTS = $_POST['MTARTS_MB52'];// MATART вид материала
  32. $MATARTPO = $_POST['MTARTPO_MB52'];
  33. $MATKLAS = $_POST['MATKLS_MB52'];// MATKLA группа материалов
  34. $MATKLAPO = $_POST['MATKLPO_MB52'];
  35. ?>
  36.  
  37. <html xmlns="<a href="http://www.w3.org/1999/xhtml"">http://www.w3.org/1999/xhtml"</a> xml:lang="ru" lang="ru">
  38. <head>
  39. <meta http-equiv="Content-Type" content="text/html; charset=Windows-1251" />
  40. <title>Просмотр складских запасов к материалу</title>
  41.  
  42. <link rel="stylesheet" type="text/css" media="screen" href="../css/flick/jquery-ui-1.7.2.custom.css" />
  43. <link rel="stylesheet" type="text/css" media="screen" href="../css/ui.jqgrid.css" />
  44.  
  45. <style>
  46. html, body {
  47. margin: 0;
  48. padding: 0;
  49. font-size: 100%;
  50. }
  51. #table
  52. {
  53.  
  54. }
  55. .alll
  56. {
  57. position: absolute;
  58. top: 10%;
  59. left: 3%;
  60. margin-top: -30px;
  61. margin-left: -30px;
  62. }
  63.  
  64. .breadcrumb,
  65. .breadcrumb a {
  66. color: #006cc6;
  67. font-size: 21px;
  68. padding: 0;
  69. }
  70. </style>
  71.  
  72.  
  73. <script type="text/javascript" src="../js/jquery-1.4.min.js"></script>
  74.  
  75. <script src="../js/i18n/grid.locale-ru.js" type="text/javascript"></script>
  76. <script src="../js/jquery.jqgrid.min.js" type="text/javascript"></script>
  77. <?php
  78. //Login to SAP R/3
  79. if (isset($_COOKIE["password3"]))
  80. {
  81. include './../savecon.php'; // <strong>здесь подключение к SAP app. Server через php saprfc</strong>
  82. if (! $rfc ) { echo "RFC connection failed"; exit; }
  83. //Discover interface for function module Z_SRT_FOR_WEBSHELL
  84. $fce = saprfc_function_discover($rfc,"Z_SRT_FOR_WEBSHELL");
  85. if (! $fce ) { echo "Discovering interface of function module failed"; exit; }
  86. //Set import parameters. You can use function saprfc_optional() to mark parameter as optional.
  87. saprfc_import ($fce,"IM_PROG","ZRM07MLBS_COPY");
  88. //Fill internal tables
  89. saprfc_table_init ($fce,"F_XTAB");
  90. saprfc_table_init ($fce,"T_SELOPT");
  91. //saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATNR","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"130000348","HIGH"=>""));
  92. // Фильтр
  93. if ($MATNRS != "" and $MATNRPO == "")
  94. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATNR","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$MATNRS","HIGH"=>"")); }
  95. elseif ($MATNRS != "" and $MATNRPO != "")
  96. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATNR","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$MATNRS","HIGH"=>"$MATNRPO")); }
  97.  
  98. if ($WERKS != "" and $WERKPO == "")
  99. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"WERKS","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$WERKS","HIGH"=>"")); }
  100. elseif ($WERKS != "" and $WERKPO != "")
  101. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"WERKS","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$WERKS","HIGH"=>"$WERKPO")); }
  102.  
  103. if ($LGORTS != "" and $LGORTPO == "")
  104. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"LGORT","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$LGORTS","HIGH"=>"")); }
  105. elseif ($LGORTS != "" and $LGORTPO != "")
  106. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"LGORT","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$LGORTS","HIGH"=>"$LGORTPO")); }
  107.  
  108. if ($CHARGS != "" and $CHARGPO == "")
  109. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"CHARG","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$CHARGS","HIGH"=>"")); }
  110. elseif ($CHARGS != "" and $CHARGPO != "")
  111. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"CHARG","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$CHARGS","HIGH"=>"$CHARGPO")); }
  112.  
  113. if ($MATKLAS != "" and $MATKLAPO == "")
  114. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$MATKLAS","HIGH"=>"")); }
  115. elseif ($MATKLAS != "" and $MATKLAPO != "")
  116. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$MATKLAS","HIGH"=>"$MATKLAPO")); }
  117.  
  118. if ($MATARTS != "" and $MATARTPO == "")
  119. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"$MATARTS","HIGH"=>"")); }
  120. elseif ($MATARTS != "" and $MATARTPO != "")
  121. { saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"MATKLA","KIND"=>"S","SIGN"=>"I","OPTION"=>"BT","LOW"=>"$MATARTS","HIGH"=>"$MATARTPO")); }
  122. // значения по умолчанию
  123. saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"PA_SOND","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"X","HIGH"=>""));
  124. saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"XMCHB","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"X","HIGH"=>""));
  125. saprfc_table_append ($fce,"T_SELOPT", array ("SELNAME"=>"NOZERO","KIND"=>"S","SIGN"=>"I","OPTION"=>"EQ","LOW"=>"X","HIGH"=>""));
  126. //Do RFC call of function Z_SRT_FOR_WEBSHELL, for handling exceptions use saprfc_exception()
  127. $rfc_rc = saprfc_call_and_receive ($fce);
  128. if ($rfc_rc != SAPRFC_OK) { if ($rfc == SAPRFC_EXCEPTION ) echo ("Exception raised: ".saprfc_exception($fce)); else echo (saprfc_error($fce)); exit; }
  129. //Retrieve export parameters
  130. $EX_XML = saprfc_export ($fce,"EX_XML");
  131. $rows = saprfc_table_rows ($fce,"F_XTAB");
  132. for ($i=1;$i<=$rows;$i++)
  133. $F_XTAB[] = saprfc_table_read ($fce,"F_XTAB",$i);
  134. $rows = saprfc_table_rows ($fce,"T_SELOPT");
  135. for ($i=1;$i<=$rows;$i++)
  136. $T_SELOPT[] = saprfc_table_read ($fce,"T_SELOPT",$i);
  137. //Debug info
  138. //saprfc_function_debug_info($fce);
  139. saprfc_function_free($fce);
  140. saprfc_close($rfc);
  141.  
  142. foreach ($F_XTAB as $b) {
  143. $varc = $varc+1;
  144. }
  145. }
  146. else
  147. {
  148. die('Данные для соеденения не введены <a href="index2.php">ввести данные</a>');
  149. }
  150.  
  151. $page = $_POST['page'];
  152.  
  153. $sord = $_POST['sord'];
  154.  
  155. //
  156. if(!$sidx) $sidx =1;
  157.  
  158.  
  159. //$result = mysql_query("SELECT COUNT(*) AS count FROM cities");
  160. //$row = mysql_fetch_array($result,MYSQL_ASSOC);
  161. $count = $varc; //
  162.  
  163. //
  164. if( $count > 0 && $limit > 0) {
  165. $total_pages = ceil($count/$limit);
  166. } else {
  167. $total_pages = 0;
  168. }
  169. // ?if ($page > $total_pages) $page=$total_pages;
  170.  
  171. //
  172. $start = $limit*$page - $limit;
  173. // ??
  174.  
  175. $data->page = $page;
  176. $data->total = $total_pages;
  177. $data->records = $count;
  178. ////
  179.  
  180. $i = 0;
  181.  
  182. //
  183. function json_fix_cyr($var)
  184. {
  185. if (is_array($var)) {
  186. $new = array();
  187. foreach ($var as $k => $v) {
  188. $new[json_fix_cyr($k)] = json_fix_cyr($v);
  189. }
  190. $var = $new;
  191. } elseif (is_object($var)) {
  192. $vars = get_object_vars($var);
  193. foreach ($vars as $m => $v) {
  194. $var->$m = json_fix_cyr($v);
  195. }
  196. } elseif (is_string($var)) {
  197. $var = iconv('cp1251', 'utf-8', $var);
  198. }
  199. return $var;
  200. }
  201.  
  202. function json_safe_encode($var)
  203. {
  204. return json_encode(json_fix_cyr($var));
  205. }
  206.  
  207.  
  208. foreach ($F_XTAB as $b) {
  209. $xmlstring = $xmlstring.$b[LINE];
  210. }
  211.  
  212.  
  213. //echo json_fix_cyr($xmlstring);
  214.  
  215. // формируем XML файл который будет прочитан нашим гридом
  216. $file = 'mb52.xml';
  217. //$var33 = json_fix_cyr($xmlstring);
  218. $xmlstring2= ltrim ($xmlstring,'#');
  219. $xmlstring3 = str_replace("utf-16", "utf-8", $xmlstring2);
  220. file_put_contents($file, json_fix_cyr($xmlstring3));
  221. ?>
  222. <script type="text/javascript">
  223. jQuery("#getselected").click(function(){
  224. var selr = jQuery('#grid').jqGrid('getGridParam','selrow');
  225. if(selr) alert(selr);
  226. else alert("No selected row");
  227. return false;
  228. });
  229.  
  230. $.ajaxSetup({scriptCharset: "cp-1251" , contentType: "application/json; charset=cp-1251"});
  231.  
  232. $(function(){
  233.  
  234. var pager = $('#tablePager');
  235.  
  236. $('#table').jqGrid({
  237. url:'mb52.xml',
  238. autosearch: true,
  239. enableClear: true,
  240. enableSearch: true,
  241. viewrecords: true,
  242. datatype: 'xml',
  243. mtype: 'GET', // <strong>колонки можно формировать на лету, используя таблицу //F_XTAB_FIELDS из FM z_srt_for_webshell, но для примера столбцы заданы явно.</strong>
  244. colNames:['Материал','Наименование материала','Завод','Склад','O','Оценка','Номер особого запаса','Скл','Партия','БЕИ','СвобИспользЗапас','Валюта','Ст-ть/своб. испол.','Транзит и перемещ.','Стоим. в пути+пер.',' На КонтрКачества','Ст-ть/контр.кач-ва','ОграничИспольз','Ст-ть/огр. испол.','Блокированный','Ст-ть/блок. запаса','Возвраты','Ст-ть/блок. возвр.'],
  245. colModel :[ // 20
  246. {name:'MATNR', index:'MATNR', width:200},
  247. {name:'MAKTX', index:'MAKTX', width:380},
  248. {name:'WERKS', index:'WERKS', width:80},
  249. {name:'LGORT', index:'LGORT', width:80},
  250. {name:'SOBKZ', index:'SOBKZ', width:80},
  251. {name:'KZBWS', index:'KZBWS', width:80},
  252. {name:'SSNUM', index:'SSNUM', width:80},
  253. {name:'LVORM', index:'LVORM', width:80},
  254. {name:'CHARG', index:'CHARG', width:80},
  255. {name:'MEINS', index:'MEINS', width:80},
  256. {name:'LABST', index:'LABST', width:80},
  257. {name:'WAERS', index:'WAERS', width:80},
  258. {name:'WLABS', index:'WLABS', width:80},
  259. {name:'INSME', index:'INSME', width:80},
  260. {name:'WINSM', index:'WINSM', width:80},
  261. {name:'SPEME', index:'SPEME', width:80},
  262. {name:'WSPEM', index:'WSPEM', width:80},
  263. {name:'EINME', index:'EINME', width:80},
  264. {name:'WEINM', index:'WEINM', width:80},
  265. {name:'RETME', index:'RETME', width:80},
  266. {name:'WRETM', index:'WRETM', width:80}, //21
  267. {name:'UMLME', index:'UMLME', width:80},
  268. {name:'WUMLM', index:'WUMLM', width:80}
  269. ],
  270. pager: $('#tablePager'),
  271. rowNum:100,
  272. rowList:[100,200,300,400,500],
  273. caption: 'Просмотр складских запасов к материалу',
  274. rownumbers: true,
  275. height: 600,
  276. rownumWidth: 40,
  277. gridview: true,
  278. rownumbers: true,
  279. footerrow: true,
  280. gridComplete: function(){
  281. var ids = $("#table").jqGrid('getDataIDs');
  282.  
  283. for(var i=1;i < ids.length;i++){
  284.  
  285. var ret2 = $("#table").jqGrid('getRowData',i);
  286. $.ajax({
  287. async: false,
  288. type: 'GET',
  289. url: 'q.php', // отправка данных на сохранение (вызов отдельного RFC FM который выполнит сохранение данных)
  290. data: {
  291. QQQ: ret2.MEINS,
  292. },
  293. success: function(res) {
  294.  
  295. var DIMIDX = res;
  296. //alert(DIMIDX);
  297. // ClearCoc (); // тут очищаем сессию
  298. $("#table").jqGrid('setRowData',i,{MEINS:DIMIDX});
  299. }
  300.  
  301.  
  302. });
  303.  
  304.  
  305.  
  306.  
  307. }
  308.  
  309. },
  310. loadComplete: function() {
  311. sum = jQuery("#table").jqGrid('getCol', 'LABST', false, 'sum');
  312. sum2 = jQuery("#table").jqGrid('getCol', 'WLABS', false, 'sum');
  313.  
  314. jQuery("#table").jqGrid('footerData','set', {MATNR: 'Итого:', LABST: sum, WLABS: sum2.toFixed(3)});
  315. },
  316. xmlReader: {
  317. root : "TB",
  318. row: "item",
  319. repeatitems: false
  320. }
  321.  
  322. })
  323.  
  324.  
  325. //jQuery("#table").jqGrid('filterToolbar');
  326. });
  327.  
  328. </script>
  329. </head>
  330.  
  331. <body>
  332. <div class="breadcrumb"><a href="/webi/ZMB52">Назад</a></div>
  333. <div class="alll">
  334. <table id="table"></table>
  335. <div id="tablePager"></div>
  336.  
  337. </div>
  338. </body>
  339. </html>

Комментарии