Codync
免費、開源的 1:1 替代方案,取代 Grok Bot 與 Muse。從 iPhone、Mac 或 Linux 桌面將 Claude Code、Codex、Cursor 與 40+ 程式碼代理人作為持續機器人傳訊。群組聊天、主題串…
AI 翻譯
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Write abap2UI5 apps like classic ABAP reports - selection screens, WRITE lists, ALV grids and report events, on ABAP Cloud and NW 7.02
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Try the report converter in the browser
Write abap2UI5 apps the way you write a classic ABAP report. Selection
screen, WRITE list, ALV grid, START-OF-SELECTION, AT LINE-SELECTION,
MESSAGE - the same concepts, running as a UI5 app in the browser. On ABAP
Cloud as well as on NetWeaver down to 7.02.
Part of abap2UI5-addons - addons and apps for abap2UI5, installed with abapGit.
ABAP Cloud has no SAP GUI: no selection screens, no WRITE lists, no
CL_SALV_TABLE. A quick report that took ten minutes on premise suddenly
needs RAP, CDS and a Fiori app. And writing UI5 views by hand means learning
a new UI model first.
abap-cloud-gui closes that gap. You write a class that looks and reads like a
report - parameters, event blocks, write( ) - and get a UI5 app with a
selection screen, a result list or ALV grid, drilldown, value helps and
messages. No UI5 knowledge, no CDS, no RAP needed.
Good for:
What it is not:
PARAMETERS become attributes, WRITE
becomes write( ). The structure stays, the syntax changes -
report2UI5 does most of it.Requirements
Steps - with abapGit, in this order:
Z2UI5_CGUI_VAR / Z2UI5_CGUI_LAY; nothing else to set up. A release
(a tag vX.Y.Z, CHANGELOG.md) is what to pin: pull the
tag, or import the zip of its
GitHub release
abap-cloud-gui-X.Y.Z-702.zip is the copy downported to 7.02.
Branch main is the newest state the CI provedStart - run a sample like any abap2UI5 app, e.g.
?app_start=z2ui5_cl_cgui_sample_05 for a complete report.
Write your first report:
CLASS zcl_hello DEFINITION PUBLIC INHERITING FROM z2ui5_cl_cgui_report FINAL CREATE PUBLIC.
PUBLIC SECTION.
DATA p_name TYPE string.
DATA p_times TYPE i.
PROTECTED SECTION.
METHODS selection_screen REDEFINITION.
METHODS start_of_selection REDEFINITION.
ENDCLASS.
CLASS zcl_hello IMPLEMENTATION.
METHOD selection_screen.
screen->parameter( val = p_name text = `Your name` obligatory = abap_true
)->parameter( val = p_times text = `Lines` ).
ENDMETHOD.
METHOD start_of_selection.
write( |Hello { p_name }!| )->uline( ).
DO p_times TIMES.
write( |Line { sy-index }| )->new_line( ).
ENDDO.
ENDMETHOD.
ENDCLASS.
Start it like any abap2UI5 app (?app_start=zcl_hello): the selection screen
comes up, Execute runs the report and shows the list, Back returns to
the selection screen. For more, run the samples below — z2ui5_cl_cgui_sample_05
is a complete report.
| Class | Classic counterpart |
|---|---|
z2ui5_cl_cgui_report | the report itself — INITIALIZATION, AT SELECTION-SCREEN OUTPUT, AT SELECTION-SCREEN ON field, AT SELECTION-SCREEN, START-OF-SELECTION, AT LINE-SELECTION, AT USER-COMMAND, AT SELECTION-SCREEN ON VALUE-REQUEST, MESSAGE, POPUP_TO_CONFIRM |
z2ui5_cl_cgui_selscreen | PARAMETERS, SELECT-OPTIONS, SELECTION-SCREEN BEGIN OF BLOCK / LINE, COMMENT, PUSHBUTTON, AS CHECKBOX, RADIOBUTTON GROUP, OBLIGATORY, NO-DISPLAY, MODIF ID, USER-COMMAND, LOOP AT SCREEN / MODIFY SCREEN, F4 and the multiple selection of a select-option |
z2ui5_cl_cgui_list | WRITE, NEW-LINE, SKIP, ULINE, NEW-PAGE, FORMAT COLOR, HOTSPOT, HIDE, AS CHECKBOX, AS ICON |
z2ui5_cl_cgui_alv | CL_SALV_TABLE — columns and headers from RTTI/DDIC, sort, filter, double click |
z2ui5_cl_cgui_tree | CL_SALV_TREE — an ALV tree with lazy nodes and checkboxes |
z2ui5_cl_cgui_variant | selection variants — get, save, delete, start with a variant |
z2ui5_cl_cgui_variant_db | the server store of the selection variants — table Z2UI5_CGUI_VAR, shared and protected variants |
z2ui5_cl_cgui_layout, z2ui5_cl_cgui_layout_db | the ALV layout dialog and the store of the layouts — table Z2UI5_CGUI_LAY, shared, protected and a default per user |
z2ui5_cl_cgui_context | helpers — among them range_check( ), the IN of a select-option for internal tables |
Everything is ABAP Cloud ready, transpilable to Node and downportable to 7.02: classes, two interfaces, the two tables with their data elements - no programs, no tooling on the stack. Reports are converted with report2UI5, which runs in Node.
All views are built with z2ui5_cl_ui5_view_builder. The selection screen,
the list and the ALV can also be used on their own inside any abap2UI5 app:
each has render( ) to append itself to a view and stringify( ) to return
a complete view.
Inherit from z2ui5_cl_cgui_report, declare the selection screen fields as
PUBLIC attributes and redefine the event blocks you need.
The dozen a new report needs - everything else below is for a report that was converted, and reads like the classic statement it came from:
selection_screen( screen ) | the fields: screen->parameter( ), select_option( ), checkbox( ), radiobutton( ), block_begin( ) / block_end( ), button( ) |
initialization, at_selection_screen | the defaults, the checks |
start_of_selection | the run |
write( ) | the list: write( val )->write( )->new_line( ), uline( ), skip( ), color =, hotspot = |
alv( table ) | the grid, with set_column_text( ), set_line_selection( ) |
message( ) / _msg( ) | S a toast, I a box, E stops - field = marks the field |
at_line_selection( row hide ) | the click on a hotspot or a row |
at_user_command( ucomm ) | a button, a changed radio button or checkbox with user_command |
at_value_request( field ) | your own F4 (value_help_popup( )); the DDIC's F4 comes by itself |
popup_to_confirm( ) / _popup( ) | a question, the answer in at_user_command( ) or a method of your own |
set_title( ), set_variant( ) | the title; start with a saved variant |
The event blocks and when they run:
| Method | When it runs |
|---|---|
initialization | once, before the selection screen is shown — set defaults here |
selection_screen( screen ) | every time the selection screen is shown — the layout |
at_selection_screen_output( screen ) | right after selection_screen — hide fields, make them read-only or required |
at_selection_screen_on( field ) | after Execute, once per field shown — message( type = 'E' ) marks the field and stops |
at_selection_screen | after Execute — message( type = 'E' ) keeps the user on the selection screen |
start_of_selection | read the data, output it with write( ) or alv( ) |
top_of_page | when the list of a run gets its first line, before it — the page header |
at_line_selection( row hide ) | a hotspot of the list or a row of the ALV was clicked |
at_user_command( ucomm ) | a button of the selection screen, a checkbox or radio button group with user_command, or a confirmed popup_to_confirm( ) |
at_value_request( field ) | F4 on a field — the default is the standard F4 of its DDIC type; redefine it for your own and call super-> for the rest |
The rest of the API a converted report may use, by what it came from -
report2UI5 writes these, a report written by hand rarely needs them:
| Classic | Methods |
|---|---|
| more event blocks | end_of_selection, end_of_page, top_of_page_line_selection, at_selection_screen_on_block / _radio / _end_of / _help / _exit, at_link_click, at_data_changed, authority_check |
| the list read back | read_list( ), get_cursor( ), lisel( ), set_cursor_field( ), lsind( ), set_lsind( ), format( ), set_line_count( ), set_pf_status( ), set_selscreen_status( ), leave_to_selection_screen( ) |
| the ALV and the tree | tree( ), get_selected_rows( ), at_alv_value_request( ), at_tree_node / _checkbox / _expand_no_children( ), set_layout_store( ) |
| more popups | popup_to_decide( ), popup_to_decide_list( ), popup_get_values( ), popup_get_values_sval( ), popup_transport( ), get_transport( ), popup_answer( ), popup_values( ), message_t100( ), messages_from_bapiret( ) |
| other reports and transactions | submit( ), call_selection_screen( ), after_call_selection_screen( ), call_transaction( ), call_intent( ), set_catalog( ), set_command_field( ), okcode_execute( ) |
| dynpros | call_screen( ), set_screen( ), leave_to_screen( ), leave_screen( ), screen_left( ), after_call_screen( ), dynpro_screen / _pbo / _pai( ), call_subscreen( ), call_subscreen_pai( ), tablecontrol_begin / _row / _count / _cell( ), current_screen( ), window( ), selection_screen_dynnr( ), vrm_set_values( ) |
| SAP GUI controls | at_gui_event( ), the stand-ins |
Messages follow the classic semantics — S as a toast, I as a box, E
stops the run — and every message of a run but S is collected in the
message popover: a button at the left of the footer counts them, in red
for an error, and W and E open the popover by themselves. A message that
belongs to a field — raised in at_selection_screen_on( ), or with
message( field = 'P_QTY' ) — marks that field with its text, names it in
the popover, and a click on it puts the cursor into the field. Fields
declared obligatory are checked before at_selection_screen, each empty
one with a message of its own.
The short API, in the style of abap2UI5, says the same in fewer words, and its calls chain:
_msg( )->w( `Only the first 100 flights` )->s( `Flights read` ).
_msg( )->e( text = `Enter a carrier` field = `P_CARRID` ). " MESSAGE ... TYPE 'E'
_msg_box( )->i( `Saved` ). " a box of its own, the run goes on
_popup( )->confirm( question = `Post the document?` ucomm = `POST` ).
_popup( )->decide( question = `Which copy?` options = VALUE #( ( `Original` ) ( `Copy` ) ) ucomm = `PICK` ).
_msg( ) is message( ), _msg_box( ) a message box whatever the type -
not in the popover, an error does not stop the run - and _popup( ) has the
popups of the report: the answer comes as at_user_command( ucomm ).
Or the answer goes to a method of its own: with then instead of ucomm the
popup calls a public method of the report with IMPORTING answer TYPE string
1, 2, ... for the option, A for Cancel (Yes and No of a confirm are
1 and A). The statements after a classic CALL FUNCTION 'POPUP_TO_...'
fit there as they are:METHODS on_post IMPORTING answer TYPE string. " PUBLIC SECTION
_popup( )->confirm( question = `Post the document?` then = `ON_POST` ).
METHOD on_post.
IF answer = '1'.
post( ).
ENDIF.
ENDMETHOD.
set_log( ) gives the report an application log: every message - MESSAGE,
message( ), _msg( ) - goes into it as well. z2ui5_cl_cgui_log keeps the
messages in memory; an adapter of the installation implements
z2ui5_if_cgui_log (add, get) and writes them where the system keeps its
logs. messages_from_log( ) puts the messages of a log into the message
popover - a BAPI's return table, read with add_table( ), or a log of the
system - and log_display( ) shows a log as a popup, as SLG1 does.
" an adapter on ABAP Cloud - cl_bali_log
METHOD z2ui5_if_cgui_log~add.
mo_log->add_item( cl_bali_free_text_setter=>create( severity = type text = CONV #( text ) ) ).
ENDMETHOD.
" an adapter for the ABAP Logger
METHOD z2ui5_if_cgui_log~add.
CASE type.
WHEN 'E'. mo_logger->e( text ).
WHEN 'W'. mo_logger->w( text ).
WHEN OTHERS. mo_logger->i( text ).
ENDCASE.
ENDMETHOD.
set_command_field( ) in initialization( ) puts the command field of the
SAP GUI into the page header - a converted report has it from the start:
| Typed | What happens |
|---|---|
ZFLIGHTS | a transaction of the catalog starts, Back returns |
/nZFLIGHTS, /n | the transaction, or this report anew |
/oZFLIGHTS, /o | the same in a new browser tab |
ONLI, BACK, PRI | Execute, Back, Print |
| any other code | at_user_command( ), as a function of the screen |
The transactions come from the installation: an object of
z2ui5_if_cgui_catalog (set_catalog( )) returns code, report class, text
and the variant to start with; a report class name works without a catalog.
Ctrl+K (Cmd+K on a Mac) opens the command palette - the transactions and
the functions of the screen in a popup to search.
The code starts the same way: call_transaction( code = 'ZFLIGHTS' ) is
CALL TRANSACTION, skip_first = abap_true its AND SKIP FIRST SCREEN -
the report class of the catalog with its variant, Back returns here.
A report class is a tile of the launchpad like any abap2UI5 app - the
migration report of report2UI5 lists its target mapping (semantic object
the class, action display, parameter app_start). Inside the launchpad
the shell shows the title of the report, and the startup parameters of the
tile fill the selection screen as the URL does (P_CARRID=LH, variant).
A transaction of the catalog with an intent navigates through the shell -
its history and Back keep working - instead of starting the class;
call_intent( ) goes to any intent, the values as startup parameters:
( code = `ZFLIGHTS` report = `ZCL_FLIGHTS` text = `Flights`
semantic_object = `Flight` action = `display` ) " a line of the catalog
call_intent( semantic_object = `Airline`
values = VALUE #( ( name = `CARRID` kind = `P` low = p_carrid ) ) ).
Outside the launchpad call_intent( ) starts the transaction of the catalog
with that intent.
Every field remembers what was run with it: the last ten values - of a
parameter, or the first line of a select-option - stay in the browser's local
storage, one history per report, and the field suggests them as the user
types. set_prefill_last( ) in initialization( ) goes one step further: an
empty field starts with its latest entry. A parameter ID fills a field first,
a start variant and the URL win over the history.
MODIF ID, USER-COMMAND and LOOP AT SCREEN work as in a classic report:
a radio button group or a checkbox with user_command runs
at_user_command( ) as soon as the user changes it, and the selection screen
is built anew — at_selection_screen_output( ) included.
METHOD selection_screen.
screen->radiobutton( val = p_disp text = `Display` group = `MODE` user_command = `MODE`
)->radiobutton( val = p_create text = `Create` group = `MODE`
)->parameter( val = p_matnr text = `Material` modif_id = `DIS`
)->parameter( val = p_name text = `Description` modif_id = `CRE` ).
ENDMETHOD.
METHOD at_selection_screen_output.
DATA(lt_screen) = screen->loop_at_screen( ).
LOOP AT lt_screen INTO DATA(ls_screen).
CASE ls_screen-group1.
WHEN `DIS`. ls_screen-active = p_disp.
WHEN `CRE`. ls_screen-active = p_create.
ENDCASE.
screen->modify_screen( ls_screen ).
ENDLOOP.
ENDMETHOD.
A line of loop_at_screen( ) has name, group1, active, input,
required and invisible — as abap_bool, not '0' / '1'. active hides
the field with its label (a block with no field left disappears), input
makes it read-only, required obligatory, invisible masks the input like a
password.
Every parameter and select-option whose DDIC type has a standard F4 gets it
without code: the fixed values of the domain, or — on premise — its
value table. Fields declared with value_help = abap_true get F4 too and
are answered in at_value_request( ), with any table:
METHOD at_value_request.
CASE field.
WHEN `P_CARRID` OR `S_CARRID`.
value_help_popup( tab = lt_carrier col = `CARRID` title = `Airlines` ).
WHEN OTHERS.
super->at_value_request( field ). " the standard F4
ENDCASE.
ENDMETHOD.
The standard F4 asks, in this order: a CDS value help named at the
field, the search help of MATCHCODE OBJECT, the fixed values of the domain,
the elementary search help of the data element (on premise, its hit list
without a dialog), and the value table with the texts of its text
table (on premise). The CDS value help is what
@Consumption.valueHelpDefinition names - a CDS view entity, or any table or
view of the DDIC, read on ABAP Cloud as on premise, the element given the
value (else its first one):
screen->parameter( val = p_land
text = `Country`
value_help_entity = `I_Country`
value_help_element = `Country` ).
On a select-option F4 picks any number of values, which become lines
I EQ — the ones already selected come up checked. A button beside the
field opens the range popup, the classic multiple selection, for every
other condition.
The footer of every selection screen has Get Variant, Save as
Variant and Delete Variant: a variant keeps every field of the screen
— parameters, select-options with all their lines, hidden NO-DISPLAY
fields — under a name, and the list of variants shows what each one holds.
A report starts with a variant through the URL (&variant=Q1) or from
initialization( ):
METHOD initialization.
set_variant( `DEFAULT` ). " if the user saved one - silently skipped if not
ENDMETHOD.
The variants are kept in table Z2UI5_CGUI_VAR
(z2ui5_cl_cgui_variant_db), one namespace per report class — nothing to
set up, on ABAP Cloud as on premise: shared with all users, protected against
changes of others, one owner each. A store of your own - another table, a
RAP business object - implements z2ui5_if_cgui_variant_store (load, save,
delete, check_sharing) and is set with set_variant_store( store ) in
initialization( ). set_variant_store( ) without a store keeps the
variants in the browser's local storage instead - per browser and device,
another device starts without them:
METHOD initialization.
set_variant_store( ). " the browser's local storage, no table
ENDMETHOD.
The user parameters - SET / GET PARAMETER ID, MEMORY ID - live in the
same store: one entry per user, so every report of the user sees them, on
every device. SU3 in the command field opens them in a popup to change, add
or delete (an empty value deletes the parameter). Without a server store
they stay in the browser's local storage.
GET PARAMETER ID looks in three places, the first one that has the ID
answers: the user's own parameter, then the customizing parameter of the
installation, then its system parameter. Customizing parameters are kept
in the same store, one entry for every user (%CUSTOMIZING); SPRO in the
command field maintains them - for a user authority_check_customizing( )
lets through, which refuses everyone unless the installation redefines it
with its AUTHORITY-CHECK. System parameters are given in code, the same for
everyone and nowhere stored:
METHOD initialization.
set_system_parameters( VALUE #( ( n = `BUK` v = `1000` ) ( n = `WRK` v = `1010` ) ) ).
ENDMETHOD.
METHOD authority_check_customizing.
AUTHORITY-CHECK OBJECT 'S_TABU_DIS' ID 'ACTVT' FIELD '02' ID 'DICBERCLS' FIELD 'ZCGU'.
result = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
A selection screen that is filled in and then left - the browser closed, the
session timed out - keeps the entries as a draft with set_draft( ) in
initialization( ): every roundtrip saves them in the variant store under
the user's own name, the next start brings them back with a message and a
Discard Draft button, and a successful Execute deletes the draft. A
start variant wins over the draft; the draft is not in the list of variants.
METHOD initialization.
set_draft( ).
ENDMETHOD.
The layout button of every ALV opens the classic "Change Layout": the
columns shown and their order, sort, totals and subtotals. A layout is saved
under a name, shared with all users or protected when wanted, and one of
them is the user's default - the report starts with it. They are kept in
table Z2UI5_CGUI_LAY (z2ui5_cl_cgui_layout_db), one namespace per report
class and ALV. A store of your own implements z2ui5_if_cgui_layout_store
and is set with set_layout_store( store ) in initialization( );
set_layout_store( ) without a store keeps the layouts with the selection
variants.
Chart shows the rows of the ALV - its filter and search applied - as a
bar chart in a dialog: the user picks the column of the categories and the
number to sum, or counts the rows; the 20 largest bars, the rest as one.
OpenUI5 has no sap.viz, so z2ui5_cl_cgui_chart draws it as SVG of plain
attributes, which the page's content security policy lets in.
set_chart( abap_false ) takes the button off the toolbar.
Export writes the ALV as CSV or as an Excel file (Office Open XML, zipped
with CL_ABAP_ZIP - no CL_SALV_TABLE). Print hands the output to the
browser as a PDF - ABAP Cloud has no spool. The PDF is written in ABAP
(z2ui5_cl_cgui_pdf) in Courier, a font every PDF reader has, so nothing is
embedded; a wide list turns the page to landscape and shrinks the font.
Execute in Background shows on the selection screen once the report has
a job: set_job( ) in initialization( ) with an object of
z2ui5_if_cgui_job. The button runs the checks of Execute and hands the
report class and the values of the screen to schedule( ); how the job runs
is up to the installation - an application job on ABAP Cloud, a background
job on premise. The job creates the class and runs it without a browser:
" in the job - report and values as schedule( ) got them
DATA lo_report TYPE REF TO z2ui5_cl_cgui_report.
CREATE OBJECT lo_report TYPE (report).
lo_report->cgui_run_in_background( EXPORTING values = values
IMPORTING pdf = DATA(lv_pdf)
messages = DATA(lt_msg) ).
" lv_pdf as the attachment of a mail, or into a table of your own
| Class | Shows |
|---|---|
z2ui5_cl_cgui_sample_01 | the selection screen on its own — every field type, blocks, a line, a button |
z2ui5_cl_cgui_sample_02 | the list on its own — colors, checkbox, icon, pages, hotspots with HIDE |
z2ui5_cl_cgui_sample_03 | the ALV on its own — column texts, a hidden column, row click |
z2ui5_cl_cgui_sample_04 | the smallest report — hello world |
z2ui5_cl_cgui_sample_05 | a complete report — select-option, F4 help, radio buttons for ALV or list, drilldown, reset with a confirmation popup, starts with the variant DEFAULT |
z2ui5_cl_cgui_sample_06 | a dynamic selection screen — MODIF ID, USER-COMMAND, LOOP AT SCREEN, read-only and password fields, NO-DISPLAY, AT SELECTION-SCREEN ON field |
z2ui5_cl_cgui_sample_07 | value helps — standard F4 from domain fixed values and value table, own F4 for a parameter and a select-option |
z2ui5_cl_cgui_sample_11 | a dynpro — CALL SCREEN, PBO with status and LOOP AT SCREEN, PAI with a push button, LEAVE TO SCREEN 0 and the list after the screen |
src/03 holds report classes as report2UI5 writes them - the reports of
its test corpus (tools/report2ui5/test/corpus) converted, not touched by
hand: the test set to pull onto a system and run, ?app_start=z2ui5_cl_cgui_r2c_01
and so on. Only the reports that need nothing ABAP Cloud lacks are in it
(no SFLIGHT, SPFLI, SCARR - those convert too, see the snapshots), so the
repository installs on every target. The converter test keeps src/03 equal
to the conversion; UPDATE_SNAPSHOTS=1 npm run test:report2ui5 writes it
anew.
| Class | Report |
|---|---|
z2ui5_cl_cgui_r2c_01 | zr2c_01_hello - The smallest report |
z2ui5_cl_cgui_r2c_03 | zr2c_03_forms - An order simulation in FORMs |
z2ui5_cl_cgui_r2c_06 | zr2c_06_dynamic - A dynamic selection screen |
z2ui5_cl_cgui_r2c_08 | zr2c_08_listformat - The list statements |
z2ui5_cl_cgui_r2c_09 | zr2c_09_localclass - A report with local classes |
z2ui5_cl_cgui_r2c_11 | zr2c_11_legacy - Older statements |
z2ui5_cl_cgui_r2c_12 | zr2c_12_pages - Pages of a list - LINE-COUNT, TOP-OF-PAGE with the page number |
z2ui5_cl_cgui_r2c_13 | zr2c_13_includes - A report in three pieces, as a grown one is |
z2ui5_cl_cgui_r2c_22 | zr2c_22_files - The files of the user |
z2ui5_cl_cgui_r2c_23 | zr2c_23_dynpro - A dynpro of fields |
z2ui5_cl_cgui_r2c_25 | zr2c_25_textedit - Notes of an airline on a dynpro with two SAP GUI controls |
z2ui5_cl_cgui_r2c_26 | zr2c_26_events - The events of SAP GUI controls, handled by a local class |
z2ui5_cl_cgui_r2c_28 | zr2c_28_browser - A price list as an HTML page |
z2ui5_cl_cgui_r2c_29 | zr2c_29_demooutput - A small inventory written with cl_demo_output |
z2ui5_cl_cgui_r2c_30 | zr2c_30_salvcolumns - Exam results in a CL_SALV_TABLE grid, every column header its name and its text |
z2ui5_cl_cgui_r2c_31 | zr2c_31_toolbar - A toolbar and an HTML viewer on the screen itself |
z2ui5_cl_cgui_r2c_32 | zr2c_32_xmlpopup - An order as XML in a window of its own |
A report that exists already does not have to be rewritten by hand.
tools/report2ui5 converts a classic
report into a report class of this addon - PARAMETERS and
SELECT-OPTIONS into attributes and selection_screen( ), the event blocks
into the methods of the same name, WRITE / FORMAT / HIDE into the list,
CL_SALV_TABLE and REUSE_ALV_GRID_DISPLAY into alv( ), MESSAGE into
message( ), FORMs into methods:
npm ci
npm run report2ui5 -- zflights.prog.abap --out src/02
The includes of a report are read from beside it, as abapGit writes them,
and macros are expanded at their calls. It is deterministic and refuses
rather than guesses: a part of the user interface that has no counterpart
in a browser app (CALL SCREEN without its screen, dynpro modules, reading
the list back by index) is reported with file, line and column. It converts
the user interface only: the logic of the report - its tables, function
modules, native SQL, batch input - is copied as it is, and whether it runs
on the target system is the user's to check. npm run report2ui5:coverage -- <dir> converts a whole
folder of reports in memory and says how many convert and what stops the
rest - the measurement the roadmap below is ordered by. Next to the class it writes a
migration report - what was mapped, the TODOs and what was not carried
over.
report2UI5 is the generator of this repository: there is no converter or painter on the stack any more, the conversion runs in Node, on the reports of an abapGit export.
Known limitations:
IN only knows I EQ, E EQ and
I CP — use z2ui5_cl_cgui_context=>range_check( ) for internal tables if
the report must also run there. On an SAP system IN and
SELECT ... WHERE ... IN work as usual.WRITE ... CURRENCY takes the decimals of the currency from ISO 4217,
UNIT formats the number as it is — TCURX and T006 are not released on
ABAP Cloud. Print is a PDF in the browser, not a spool request.alv( ) binds a PUBLIC attribute directly; any other table is copied into
a data reference, which the draft has to rebuild with RTTI on every
roundtrip (abap2UI5#2963).set_paging( 500 ) on the ALV brings the payload down
to a page; the serialization stays
(abap2UI5#2962).Done
z2ui5_cl_cgui prefix, packages 01 core / 02
samples, CI for v750, ABAP Cloud and 7.02, abap2UI5-linter, unit testsOBLIGATORY, F4 through at_value_request; fields are
found by reference, select_option( ) needs no nameWRITE list (colors, icons, checkboxes, pages, hotspots, HIDE)POPUP_TO_CONFIRMAT SELECTION-SCREEN OUTPUT with
LOOP AT SCREEN / MODIFY SCREEN (hide, read-only, required,
invisible), MODIF ID, USER-COMMAND at checkboxes and radio button
groups, NO-DISPLAY, AT SELECTION-SCREEN ON field and messages with
the value state on their field; unit tests for the selection screenset_variant( ), kept in the browser's local
storageNext
The order is the measurement's: report2ui5:coverage over a corpus of
real reports says which construct stops the most of them, and that construct
is next. Every stage is a release of its own.
Stage 0 - release, and the number to move
migrate_report: v1.0.0,
with the abapGit zip and the 7.02 zipreport2ui5:web), the share that converts without a refusal
and the refusals ranked in the job summary - the number every stage
below is measured byreport2ui5:web --start checks, builds and starts the converted
reports weekly, the funnel and where they stopped in the job summary
(first run: 74 of 596 converted reports start, 82 with the upload
dialog of GUI_UPLOAD and cl_demo_output; most of the others read
a class or table of their repository the sparse clone lacks)npm run site)report2ui5:coverage - the measurement over a folder of reportsStage 1 - the converter: the constructs that stop the most reports
OCCURS, WITH HEADER LINE) rewritten
into a table and a work area - mechanical, and in every report older
than 7.0SUBMIT ... AND RETURN and CALL SELECTION-SCREEN: the called report
converted with the caller and started with submit( ), its WITH
values handed over; a screen of the report's own as a dialog, the
statements after the call continued in after_call_selection_screen( )
- reports call reportsCALL TRANSACTION (without batch input) as call_transaction( ) -
the report class the catalog names for the codePOPUP_TO_CONFIRM, POPUP_TO_CONFIRM_STEP,
POPUP_TO_DECIDE, POPUP_GET_VALUES): the event block cut at the
call, the rest continued in a callback on_popup_n( answer ) - the one
transformation that changes a block's shape, and the one in every
report that posts somethingSET PF-STATUS, SET TITLEBAR, AT PFnn as set_pf_status( ),
toolbar functions and the keyboard shortcuts of the runtime - the
status read from the <CUA> of the .prog.xmlsy-lsind) and WRITE AT positions, in a column
mode of the list (every item of a line with a position in a box of
its width in characters) - the evaluations that live by the columnREAD LINE / MODIFY LINE ... FIELD VALUE as read_list( )->read_field( ) / modify_field( ) - the checkboxes of a list read back by the
names of their WRITEscl_gui_alv_grid in a container with its simple handlers (hotspot,
double click, toolbar, user command) as alv( ), the screen's PBO and
PAI modules resolved - the ALV every report since 2005 is written withAT SELECTION-SCREEN ON HELP-REQUEST, SELECTION-SCREEN FUNCTION KEY,
and ( and )
on the runtime's own counterpartsStage 2 - the runtime: what a report's user sees
Selection screen
at_value_request( )
of the select-option, the values picked become lines of the popupvalue_help_entity - what
@Consumption.valueHelpDefinition names, on ABAP Cloud too), text
tables beside value tables, search helps (MATCHCODE OBJECT and the
data element's)AT SELECTION-SCREEN ON BLOCK, ON RADIOBUTTON GROUP, AS LISTBOXMEMORY IDZ2UI5_CGUI_VAR): shared
and protected variants, a pluggable store beside the browser's local
storage, dynamic date valuesOutput
Z2UI5_CGUI_LAY, shared, protected, a default per user)WRITE AT positions and UNDER, columns that line up
(every item of a positioned line in a box of its width), secondary
lists (sy-lsind, set_lsind( ))set_job( )), which gets the list and its PDFMessages and logging
_msg( )->e( ), _msg_box( )->e( ),
_popup( )->decide( ) / confirm( ) / get_values( )set_log( ),
messages_from_log( ), log_display( ) over z2ui5_if_cgui_logDialogs and screens
popup_transport( ) /
_popup( )->transport( ), z2ui5_cl_cgui_transport, beside
POPUP_TO_DECIDE and POPUP_GET_VALUES; no popup of another addon is
needed any moreCALL SCREEN of a screen in another class - the dynpro of a
function group or another program: call_screen( dynnr = '0100' owner = lo_screens ) shows the dynpro of the report class lo_screens with
its PBO and PAI as an app of its own; when its last dynpro is left
(SET SCREEN 0) the caller goes on in after_call_screen( ) and
reads the attributes of lo_screens as the dynpro left themsubmit( using_selection_screen = '1100' ) (SUBMIT ... USING
SELECTION-SCREEN, converted by report2UI5) and submit( as_window = abap_true ) - the called report's screen as a dialog box over the
caller, Execute shows its output, Cancel returnsNavigation and transactions
call_intent( )/n, /o
(set_command_field( ), set_catalog( ))Cmd+K / Ctrl+K) to search and start reportsAT PFnn and the function
keys of a GUI status (set_pf_status( shortcuts = ))set_prefill_last( ))set_draft( ))SET / GET PARAMETER ID with user parameters on the server, SU3 in
the command field to maintain themGET PARAMETER ID reads the user's, then the customizing
ones (SPRO in the command field, authority_check_customizing( )),
then the system ones (set_system_parameters( ))Stage 3 - at the scale of a code base
tools/report2ui5/package.mjs):
the classes and one summary, the refusals ranked across the packageThe converter was narrowed to the user interface after 1.0.0 and renamed
from report2cloud to report2UI5: the release check of tables and APIs, the
released successors (--successors), the function module wrappers
(--wrappers), the ATC findings (--atc), the call graph and migration
order of a package and the AI assistant are gone - the logic of a report is
the user's.
Stage 4 - in the browser, and with an agent
migrate_report in the MCP server with the class deployed into the
sandbox and its first screen answeredStage 5 - research
dynpro_screen( ), the modules
methods called by dynpro_pbo( ) / dynpro_pai( ), CALL SCREEN,
SET SCREEN, LEAVE TO SCREEN and the statements after the call in
after_call_screen( )z2ui5_cl_cgui_gui*), in a local class toofunction_selected, dropdown_clicked),
the SAPEVENT links and forms of the HTML viewer, the close of a dialog box -
SET HANDLER as set_handler( ) of the stand-inz2ui5_cl_cgui_gui_alv_grid,
the ALV of the report in its container, with its toolbar, user
command, double click and hotspotcl_gui_container=>default_screen):
toolbar, text editor and HTML viewer above the list of the run, no
dynpro needed; cl_abap_browser as the stand-in
z2ui5_cl_cgui_abap_browser; the loop over the columns of a SALV
grid; static event handlers of a local classcl_demo_output (in 72 reports of the web corpus): the stand-in
z2ui5_cl_cgui_demo_output writes into the list - values, structures
and tables as columns, sections as headingscl_gui_picture and cl_gui_simple_tree: the stand-ins
z2ui5_cl_cgui_gui_picture and z2ui5_cl_cgui_gui_simple_tree - the
nodes of MTREESNODE, lazy children on the first expand, the click as
node_double_click and selection_changedStage 6 - the review of 1.0.0: does it run, and is it fun
A review on 2026-10-30, measured: 634 of 780 open-source reports convert (81 %), the converted classes read like hand-written ones, the test-corpus reports carry at most five TODOs. What the numbers do not say: how many of the converted reports run on a real system, and the two cores grew into monoliths - the report class has 8,700 lines, 244 methods and 124 state attributes, the converter 8,700 lines in one file. The stage takes that on, in this order.
The last meter for the user
Simpler to read, simpler to change - the API stays
z2ui5_cl_cgui_report split behind its API, the PUBLIC and
PROTECTED sections byte-identical: z2ui5_cl_cgui_memory (variants,
parameters, draft, history), z2ui5_cl_cgui_command (URL, command
field, shortcuts), z2ui5_cl_cgui_gui_view (the stand-ins rendered),
the grid's table work in z2ui5_cl_cgui_alv, and the long methods of
the report split into steps - on_event 221 to 30 lines,
view_display 227 to 58, gui_render 233 to a walk; the report
8,730 to 7,809 lines, one method still over 80 (write, its 25
IS SUPPLIED checks). Each collaborator is stateless, takes the
state as a structure of references the report builds per call, and
never names the report as a type - no cycle, no friendconvert.mjs split by statement family - convert-screen, -decl,
-list, -alv, -calls, -functions, -dynpro, -gui, -locals,
-rewrites as methods mixed into the one Converter, the tables and
helpers in convert-shared - the snapshots unchanged, the largest
file 2,100 lines instead of 8,700What abap2UI5 could take over
alv( )
copies and rebuilds every other table with RTTI on each roundtrip:
proposed as abap2UI5#2963set_paging( 500 )
60 KB on Execute and 4 KB after, but still 2 s - the app with its
rows is serialized into the draft and back on every request. The
payload the addon solves, the serialization it cannot: proposed as
abap2UI5#2962Quality, through every stage
ltcl_client of the report, the ALV's own), beside the selection
screen'stest/runtime/semantic.test.mjs) - six list reports of the
corpusLater
RS_TREE_CONSTRUCT / RS_TREE_LIST_DISPLAY as the ALV tree
of the reportCL_SALV_TREE as a stand-in, as CL_SALV_TABLE is: the nodes, their
relationships, the columns, the tree settings, double_click and
checkbox_change to the handlersnpm ci
npm run lint # abaplint, v750 syntax + downport rule
npm run check:cloud # abaplint, ABAP Cloud
npm run check:702 # downport a scratch copy to 7.02 and check it
npm run check:abap2ui5 # abap2UI5-linter over apps and views
npm run check:regex # no regular expressions in src/
npm run unit # ABAP Unit in the transpiled backend (needs ../mcp-server)
npm run test:report2ui5 # the report converter: snapshots and abaplint over its output
npm run site # the GitHub Pages site with the converter playground into build/site (-- --serve: on :8080)
The ABAP Unit tests run in CI in the transpiled abap2UI5 backend
(.github/workflows/unit.yaml, scripts/unit.mjs with
abap2UI5/mcp-server as a library),
the tables of the two stores in SQLite.
Issues and pull requests are welcome. Read AGENTS.md first - it holds the layout, the release targets and the rules of this repository.
MIT - see LICENSE.
z2ui5_cl_cgui_gui*| memory and parameters | set_parameter_id( ), get_parameter_id( ), set_system_parameters( ), authority_check_customizing( ), set_prefill_last( ), set_draft( ), set_variant_store( ), set_fresh_start( ), at_roundtrip_start( ), cgui_statics_keep / _restore( ) |
| the log, the job, the link | set_log( ), messages_from_log( ), log_display( ), set_job( ), get_link( ) |
z2ui5_cl_cgui_r2c_33 |
zr2c_33_strings - A name split into its parts and rebuilt |
z2ui5_cl_cgui_r2c_34 | zr2c_34_controllevels - Sales per region and month with the classic control levels |
z2ui5_cl_cgui_r2c_35 | zr2c_35_dates - Dates of a project |
z2ui5_cl_cgui_r2c_36 | zr2c_36_ranges - A product list filtered with select-options on local data |
z2ui5_cl_cgui_r2c_37 | zr2c_37_expressions - The constructor expressions of a team roster |
z2ui5_cl_cgui_r2c_38 | zr2c_38_confirm - Cleaning up a to-do list |
z2ui5_cl_cgui_r2c_39 | zr2c_39_textedit - A note editor on the screen itself |
z2ui5_cl_cgui_r2c_40 | zr2c_40_sapevent - A menu as an HTML page on the screen |
TABBED BLOCKBEGIN OF SCREENAS WINDOWAS SUBSCREENcl_gui_column_treez2ui5_cl_cgui_gui_column_treeMTREEITMitem_double_clicklink_clickcheckbox_changecl_gui_list_tree: the stand-in z2ui5_cl_cgui_gui_list_tree - the
items of a node on its line, the first its textactivetab, CALL SUBSCREEN in PBO and PAI with the number
of the subscreen in a variable (the paging in the program)cl_gui_* the stand-ins, under their own namesLOOP WITH CONTROL a line at a time in
PBO and PAI, the columns ready for input inputs of a tablef1
and f4 once set_registered_events( ) names them, the cursor of
the text area as get_selection_pos( ) - the help of an SQL or code
editor on the word under the cursor