Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Srdjan
Product and Topic Expert
Product and Topic Expert


Reading the Raymond Ni blog on generating UI forms from JSON script, I combined this "cool hack with potential" with Python scripting, to read ABAP metadata from the backend system and generate UI5 or HTML5 form, like this one here, automatically.

This can save the prototyping time because the developer does not have to start from scratch but from automatically generated form HTML fragment.

The source code can be downloaded from bsrdjan/formgen · GitHub

Form Metadata


Let take one complex form as example and assume that selection screen of Timesheets approval transaction CAPS, for some reason shall be implemented in UI5 or HTML5:



Using F1 HELP in ABAP Workbench you may find out technical types of input field of this selection screen and copy your findings in one JSON or YAML file, like below. For the purpose of this blog I used YAML, just to put few comments in, but you can remove them and save-as JSON.

form.yaml

{

    #

    # CAPS Selection

    #

    "form": [

        { "FIELD": ["PERNR", "PERNR"], "SHLP": "PREM" }, # Personnel Number

        { "FIELD": ["PERNR", "STAT2"]},   # Employment status

        { "FIELD": ["PERNR", "PERSG"]},   # Employment group

        { "FIELD": ["PERNR", "PERSK"]},   # Employee subgroup

        { "FIELD": ["PERNR", "VDSK1"]},   # Organization ke

        { "FIELD": ["PERNR", "ABKRS"]},   # Payroll area

        { "FIELD": ["PERNR", "KOKRS"]},   # Controlling area

        { "FIELD": ["PERNR", "KOSTL"]},   # Cost center

        { "FIELD": ["PERNR", "ORGEH"]},   # Organizational unit

        { "FIELD": ["PERNR", "MSTBR"]},   # Supervisor area

        { "FIELD": ["PERNR", "SBMOD"]},   # Administrator group

        { "FIELD": ["PERNR", "SACHZ"]},   # Time recording administrator

        { "FIELD": ["PERNR", "SASBZ"]}    # Administrator group: time

    ]

}

 

To process this form you can write a simple nodejs or Python script, like this one.

UI5 Form


ui5form.py

#!/usr/bin/python

# connect to abap

from pyrfc import *

def get_connection (conn):

   """ get Connection"""

   print 'connecting %s ...' % conn['ashost']

   return Connection(**conn)

I64 = {

  'user': 'demo',

  'passwd': 'welcome',

  'ashost': '10.11.12.12',

  'sysnr': '00',

  'client': '800',

  'saprouter': ''

}

c = get_connection(I64)

# read form fields

import yaml

from pprint import pprint

with open('form.yaml', 'r') as data_file:

    form_fields = yaml.load(data_file)["form"]

# make ui5 form

# header

print '''

var oLayout1 = new sap.ui.layout.form.GridLayout();

var oLayout2 = new sap.ui.layout.form.ResponsiveLayout();

var oLayout3 = new sap.ui.layout.form.ResponsiveGridLayout();

var oForm1 = new sap.ui.layout.form.Form("F1",{

    title: new sap.ui.core.Title({text: "Time Approval", tooltip: "Time Approval tooltip"}),

    layout: oLayout1,

    formContainers: [

        new sap.ui.layout.form.FormContainer("F1C1",{

            title: "Time Approval",

            formElements: [

'''

for _line in form_fields:

    field = _line['FIELD']

    r = c.call('DDIF_FIELDINFO_GET',

                TABNAME=field[0], FIELDNAME=field[1],

                ALL_TYPES='X',    GROUP_NAMES='X' )

    dfies=r['DFIES_TAB'][0]

    print '''

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"%s",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "%s", maxLength: "%d",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),'''  % (dfies['SCRTEXT_L'], '', int(dfies['LENG']))

    print

    print

# footer

print '''

        ]

    });

oForm1.placeAt("sample1");

'''

Both Python and nodejs can directly call ABAP RFCs (see PyRFC and nodeRFC) and you can use the language you like more.

After running this script and redirecting the output to ui5form.html, the following fragment is generated

ui5form.html

connecting 10.117.24.158 ...

var oLayout1 = new sap.ui.layout.form.GridLayout();

var oLayout2 = new sap.ui.layout.form.ResponsiveLayout();

var oLayout3 = new sap.ui.layout.form.ResponsiveGridLayout();

var oForm1 = new sap.ui.layout.form.Form("F1",{

    title: new sap.ui.core.Title({text: "Time Approval", tooltip: "Time Approval tooltip"}),

    layout: oLayout1,

    formContainers: [

        new sap.ui.layout.form.FormContainer("F1C1",{

            title: "Time Approval",

            formElements: [

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Personnel Number",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "8",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Employment status",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "1",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Employee group",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "1",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Employee subgroup",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "2",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Organizational key",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "14",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Payroll area",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "2",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Controlling Area",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "4",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Cost Center",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "10",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Organizational unit",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "8",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Supervisor area",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "8",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Administrator group",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "4",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Time administrator",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "3",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        new sap.ui.layout.form.FormElement({

                label: new sap.ui.commons.Label({text:"Admin.modif, time admin.",

                        layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 1}),

                                                     new sap.ui.layout.form.GridElementData({hCells: "1"}),

                                                     new sap.ui.layout.GridData({span: "L1 M1 S12"})]

                                })

                        }),

                fields: [new sap.ui.commons.TextField({value: "", maxLength: "7",

                            layoutData: new sap.ui.core.VariantLayoutData({

                                multipleLayoutData: [new sap.ui.layout.ResponsiveFlowLayoutData({weight: 4}),

                                                         new sap.ui.layout.GridData({span: "L5 M5 S12"})]

                            })

                         })

                        ],

                layoutData: new sap.ui.layout.ResponsiveFlowLayoutData({linebreak: true, margin: false})

        }),

        ]

    });

oForm1.placeAt("sample1");

The similarity with UI5 form example is obvious, this template was used in this script example. From ABAP metadata I extracted the label text, input field type and max length, but perhaps more is possible. Some manual work still needed but not like starting from the blank sheet of paper.

HTML5 Form


With slightly modified logic, the HTML5 form can be generated. The section "make ui5 form" shall be replaced with the code below.

html5form.py

# make html5 form

# header

print '<form name="Time Approval" novalidate role="form">'

for _line in form_fields:

    field = _line['FIELD']

    r = c.call('DDIF_FIELDINFO_GET',

                    TABNAME=field[0], FIELDNAME=field[1],

                    ALL_TYPES='X',    GROUP_NAMES='X' )

    dfies=r['DFIES_TAB'][0]

    fname = 'name_' + field[1]

    if dfies['DATATYPE'] == 'NUMC':

        ftype = 'number'

    else:

        ftype = 'text'

    print '''

    <div class="form-group">

      <label for="%s">%s</label>

      <input type="%s" name="%s" class="form-control" required maxLength=%d />

    </div>''' % (fname, dfies['SCRTEXT_L'], ftype, fname, int(dfies['LENG']))

    print

# footer

print '</form>'

html5form.html

<form name="Time Approval" novalidate role="form">

    <div class="form-group">

      <label for="name_PERNR">Personnel Number</label>

      <input type="number" name="name_PERNR" class="form-control" required maxLength=8 />

    </div>

    <div class="form-group">

      <label for="name_STAT2">Employment status</label>

      <input type="text" name="name_STAT2" class="form-control" required maxLength=1 />

    </div>

    <div class="form-group">

      <label for="name_PERSG">Employee group</label>

      <input type="text" name="name_PERSG" class="form-control" required maxLength=1 />

    </div>

    <div class="form-group">

      <label for="name_PERSK">Employee subgroup</label>

      <input type="text" name="name_PERSK" class="form-control" required maxLength=2 />

    </div>

    <div class="form-group">

      <label for="name_VDSK1">Organizational key</label>

      <input type="text" name="name_VDSK1" class="form-control" required maxLength=14 />

    </div>

    <div class="form-group">

      <label for="name_ABKRS">Payroll area</label>

      <input type="text" name="name_ABKRS" class="form-control" required maxLength=2 />

    </div>

    <div class="form-group">

      <label for="name_KOKRS">Controlling Area</label>

      <input type="text" name="name_KOKRS" class="form-control" required maxLength=4 />

    </div>

    <div class="form-group">

      <label for="name_KOSTL">Cost Center</label>

      <input type="text" name="name_KOSTL" class="form-control" required maxLength=10 />

    </div>

    <div class="form-group">

      <label for="name_ORGEH">Organizational unit</label>

      <input type="number" name="name_ORGEH" class="form-control" required maxLength=8 />

    </div>

    <div class="form-group">

      <label for="name_MSTBR">Supervisor area</label>

      <input type="text" name="name_MSTBR" class="form-control" required maxLength=8 />

    </div>

    <div class="form-group">

      <label for="name_SBMOD">Administrator group</label>

      <input type="text" name="name_SBMOD" class="form-control" required maxLength=4 />

    </div>

    <div class="form-group">

      <label for="name_SACHZ">Time administrator</label>

      <input type="text" name="name_SACHZ" class="form-control" required maxLength=3 />

    </div>

    <div class="form-group">

      <label for="name_SASBZ">Admin.modif, time admin.</label>

      <input type="text" name="name_SASBZ" class="form-control" required maxLength=7 />

    </div>

</form>

And here the generated form, incorporated into HTML document:



Hope this adds potential to the hack and helps saving cloud/web prototyping time, also find out if more info can be extracted from ABAP metadata and mapped to HTML5 and UI5 input attributes :smile: