GUI Scripting: A how to guide

Home / Blog / GUI Scripting: A how to guide

Using SAP GUI Script

SAP GUI Script is a fantastic tool that can be used to create transactional testing data, Change existing master or transactional data, create master data in mass or even just data conversion for certain tasks that LSMW can’t handle.  GUI Script has been around for a while, but it always surprises me that so few people are familiar with it.
The basic concept around GUI script is that you can load information into an Excel worksheet, and using a macro, allows you to load data into SAP.  This document is going to walk you through creating your own GUI scripts and using them effectively.

Turning on GUI Scripting

Tranaction: RZ11
Param. Name: sapgui/user_scripting

Press Display
gui-01
If current value is not set to TRUE, press the Change Value and set the value = TRUE.
Please note, typically this a basis function, so if you don’t have access to transaction RZ11, please contact your basis team.
As an additional hint, if you want to have GUI Scripting always active, it is encouraged to activate it in RZ10 (this adds it to the startup profile).

Recording the Transaction

When you are ready to perform the recording,  be sure you know the transaction you want to execute and the data that you can use.  You should also know the screens you plan to visit and the fields that you will be filling in.  Keep in mind, you can always update the recording file, but the better your recording, the less errors you will encounter.
The important thing to remember is that GUI script can NOT perform any logic.  it only works for repeating the same steps over and over again.  This means that if you receive an error on some records, but not others, you will need to execute 2 different scripts.  One script will do the non errors, and other script will do the errors.  You can cut down a lot of time if you can segregate the data early.

gui-02

Activate the recorder.  It is encouraged to always start the main screen in SAP.  This prevents weird things that happens if an error occurs during the playback.

gui-03

Press More if you want to control where the file is saved.

gui-04

When you are ready to start, press the record button (Red Dot Button).

Then proceed to execute the transaction you wish to record.

gui-05

Be sure to use ‘/N’ in front of the transaction code.

gui-07
Enter in the document number and press Operations Button.

gui-08

Please note, when I added a new operation, I entered it on the bottom of the screen.  This allows you to avoid the risk of overriding exisitng data.

Press Enter.
Press Components Tab

gui-09

Again, add the data to the bottom of the screen.
Press Enter
Press Save
Note:  sometimes there will be errors.  If errors occur, you need to remember that maybe not Every order you change will have the error.
gui-10
I encourage you to press the green arrow back on every recording at the end.  This just helps to avoid incorrect loading of data.
gui-11
Press stop.
Now, go find the file.  Be sure to RIGHT click on it.  If you double click on it, it will attempt to execute the exact same transaction again.
You should see something similar to this:

gui-12
The parts of this file you care about are the lines that start: session.xxx
I encourage you to skip the first line that resizes your screen.  and copy all of the remaining lines in the file.
Next up, add this information to the excel file.

Gui Script

This will depend on your version of excel, but what you need to do is find the macro button:
MS 2003:

gui-13

MS 2007

gui-21
Be sure to enable macros.
gui-14
When the macro window opens, be sure to select the correct view on the left hand side of the screen.  Then move to the code section and find the area shown that says “Paste your recorded script below”.
If there is anything currently in this section, be sure to remove it, and replace it with the information from your recording (session.xxx).
gui-15

Now, I’m going to show you how to point this to your excel document.
session.findById(“wnd[0]/tbar[0]/okcd”).text = “/niw32”

session.findById(“wnd[0]”).sendVKey 0

Change:
session.findById(“wnd[0]/usr/ctxtCAUFVD-AUFNR”).text = “4000000”
To:
session.findById(“wnd[0]/usr/ctxtCAUFVD-AUFNR”).text = A

session.findById(“wnd[0]/tbar[1]/btn[17]”).press

Change:
session.findById(“wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1107/tabsTS_1100/tabpVGUE/ssubSUB_AUFTRAG:SAPLCOVG:3010/tblSAPLCOVGTCTRL_3010/txtAFVGD-LTXA1[7,8]”).text = “my test op”
To:
session.findById(“wnd[0]/usr/subSUB_ALL:SAPLCOIH:3001/ssubSUB_LEVEL:SAPLCOIH:1107/tabsTS_1100/tabpVGUE/ssubSUB_AUFTRAG:SAPLCOVG:3010/tblSAPLCOVGTCTRL_3010/txtAFVGD-LTXA1[7,8]”).text = B

Since this can get long, I’ll jsut show you the first 2 changes.  You’ll notice that I found the first two lines where I entered in data.  I changed it to a single letter (no quotes).  This is the excel column where you enter in the data.  It’s that simple.  If anything is a constant, just leave it as it is.
When you’re done, press save and you’re ready to execute.

Executing the Script

Now, the first step before executing the script is gathering all the data.  Typically, this is done using SE16, SE16N, or certain reports (IW73, VA05, COOIS, etc).  As always, be careful with the data you enter.  It’s your user id that will be assigned to the change :).

Once you have the data you wish to execute, simply go the excel worksheet and execute the macro
*** NOTE:  Remember, when the script is running you can’t do anything with Excel.  You can continue working in SAP, but Excel will be locked for the duration of the script.

gui-16
**** NOTE ***
This is a VERY important one.  Be sure that the first SAP window open on your screen is the client you wish to change.  If you are doubt, be sure to logout of any client/system you do not want to change.  For example, if you are logged into production and QA.  You want to make the change to QA, I encourage you to log out of production.

gui-17
Press Run
Note:  if you have multiple excel windows open, be sure the correct macro name is highlighted.  If you aren’t sure, close the other excel documents.

gui-18

Gui Script will always give you a chance to check the results of the FIRST record.

gui-19

I encourage you to always check and make sure it saved properly before pressing ok.  If it did not, press cancel.  Otherwise the script will go all the way to the end.

Once you are done, it will return control back to excel.

gui-20

As long as you see OK in the row, the record processed.  if you don’t see ok, you’ll need to check that record and possibly reprocess it.

 

As always, thanks for reading and don't forget to check out our SAP Service Management Products at my other company JaveLLin Solutions,
Mike

70 thoughts on “GUI Scripting: A how to guide

    1. Sorry about that Janos. some of my early posts had issues with the images. I’ve corrected it now.
      thanks,
      Mike

  1. Hi Mike,

    thanks a lot for this post.

    I have one question: can you use SAP GUI Scripting to get information back from SAP? Not only to send, let’s say a request to SAP GUI, but also to get a response.

    The scenario I have in mind is Customer creation: 1) SAP GUI Scripting invoked from an external system ->2) the correspondent transaction is automatically opened in SAP GUI and the fields are prepopulated -> 3) the user cheks everythings ok and presses save (a new Customer is created) -> 4) SAP GUI Scripting sends back the new SAP Customer number.

    If this is not possible, would it be possible skipping steps 2 and 3? So that from the external systems a Customer is directly created in SAP (without further user interaction), and the resulting SAP Customer number is sent back?

    Thanks and regards

    1. Hi Juan,
      GUI Scripting is one of those great tools, but it is pretty limited. From the sounds of your requirement, I don’t think that GUI Scripting is the right choice. In general, GUI scripting is great for creating test data, but has no interactive capabilities. From what I’m hearing, you would be much better suited creating a standalone program, or maybe a web dynpro application that calls the customer create BAPI.
      Sorry I couldn’t be more help,
      Mike

  2. Did you manually create the SAP_GUI_SCRIPT module in the Excel VB editor?
    Also, are there any references needed to add in the Excel VB editor?
    Thanks!

    1. I found the VB script a long time ago. Since then, I’ve done minor enhancements, but the link in the post is the easiest way to get started. I included an excel with the VB script already embedded so you don’t have to do the hard work.
      Thanks,
      Mike

    1. I guess I’d need to understand what you’re trying to accomplish. The method I describe in this post doesn’t require SE16 or SE16N. What sort of script are you attempting to run?
      Thanks,
      Mike

  3. Hi,

    I am trying to get the data from the column assigning it as A , B as you mentioned.

    But somehow it is not working. What am I missing here ?

    1. Make sure you don’t have the column names within quotes. So if you replace “XX01”, be sure you replace it with A (if A is your column). Beyond that, I’m not sure.
      Good luck,
      Mike

  4. Hi,

    How did you come up with an excel file with macro already? Is the file similar to what you have downloaded on SAP or just a plain new excel file?

  5. How did you come up with a macro file already? Is this the downloaded file from SAP or just a plain new excel file? If it is just a plain excel file, then we have to copy paste the codes you provided?

    1. The file I included in the post was an Excel file I originally created when I first learned about GUI Scripting. I found some documentation a long time ago that explained how to do it. The Excel in the post contains all the macro code I originally found (plus I extended it to handle more columns than the original) and it includes the code to perform the example that I walk through in the post. It is fully functioning, but in order for it to be useful, you would need to replace the code I used to update a routing, and put in the code from your own recording.
      Does that answer your question?

        1. All the code you need is already in the macro that you can download directly from the post. It’s got all the code for the sample in the document. Not sure what else you might be looking for.

          1. Hi Pielhm,

            Thanks for this. I am actually recording one transaction in different SAP boxes. Can you help me advice a consolidated VBA code for this one?

          2. If the systems are all the same version of SAP, you can record the transaction one time, put the transaction “code” into the macro, and then use it in all system with no additional change (unless you want to change the data).
            If you are using different version of SAP, you will need to test. Some transactions are exactly the same, others, have minor changes that will force you to do a new recording. I hope this helps,
            Mike

  6. Mike, this is awesome. I have been looking for like this. As I am still dummy on VSB, may I ask a few extra suggestion to you?

    #1. Add Heading – So, maybe first row could be heading – script to skip.
    #2. First column – Y or N, so, if it is “Y”, process.. if “N”, skip.
    #2. 2nd Colum – Instead of using colm P for return message, it might be useful, as normally we don’t use full columns till “O”.

    Anyway, it is Awesome!!!

    Best,

  7. Hi Mike,
    Your script is great!!!
    I have one question..If i want to copy 10 SVO or Sales order from excel into the Multiple seletion in SAP, so you know what code should I write?

    Br Natasha

    1. HI Natasha,
      Well, the best I can recommend is actually just doing a recording to enter in the selection criteria for one or two rows. I believe you’re talking about the high and low selection options? If you enter data into 2 or 3 using both the low and high, you should see the pattern in the script code to be able to replicate it. I hope this helps.
      Thanks,
      Mike

    1. Hi Elena,
      If you look below the screen shot with the text file, you’ll see a hyper link for GUI Script. It’s near the end of the recording the transaction section (I had to page down 10 times in my browser to see this link). If you have trouble, feel free to email me and I can send you a copy.
      thanks,
      Mike

    1. Sorry for the delay. What sort of issue are you encountering?
      When dealing with Gui Script, there are host of issues depending on your operating system, version of Office, settings in SAP.
      If you can explain what is happening, I might be able to give you some ideas.
      Thanks,
      mike

        1. Most commonly this is a formatting issue. Often when I extract something from excel, it may set the format of the cells into something that won’t being put directly into a field. Normally, I’ll make sure all the columns are text related.
          Also, try walking through a record manually, but copy and paste directly from your spreadsheet. Sometimes you’ll find a value (usually a number with decimals) that will give you an error when you attempt to add the value.
          If it still isn’t working for you, feel free to email me your spreadsheet with some sample records and I can take a closer looks.
          Mike

          1. Hi,

            I tried and most probably its issue with my recording which is now correct But i am facing issue when I export file in .xlxs it ask me to save as export and don’t go forward. I have to save and macro finished. How i can command to save it automatically.

            session.findById(“wnd[0]/mbar/menu[0]/menu[3]/menu[1]”).select
            session.findById(“wnd[1]/usr/radRB_OTHERS”).setFocus
            session.findById(“wnd[1]/usr/radRB_OTHERS”).select
            session.findById(“wnd[1]/usr/cmbG_LISTBOX”).key = “10”
            session.findById(“wnd[1]/tbar[0]/btn[0]”).press

          2. I’m afraid, not all screens are gui script friendly. I’ve never tried exporting with gui script. The best i can suggest is to comment out lines one by one in your script to see how far it gets. Then you see exactly what button isn’t being pushed. Somethings you can force things with pushing the button twice or something silly like that.
            Best of luck,
            Mike

  8. Hi,

    I m using SAP GUI Scripting code for bulk record submission through SAP form. It picks records one by one from excel file and submits in SAP system.

    My Question:

    I want to include error handling into it. So that if any error occurs at any particular record submission, Script shouldn’t stop. It should move to the next line after putting appropriate message in Comment field.

    Can anyone throw some light how to identify whether SAP is facing some Error or Warning?

    And if Error occurs how to get out of it i.e., how to handle that and move to next record submissions.

    1. Well, to be honest, gui scripting isn’t meant for error handling. I’m afraid my vbscript skills are rather limited, so I guess anything is possible, but to me this sounds like you should really be using a program if you need error handling.
      If you find a way to solve this in gui script, of course I’d be interested in hearing about it 🙂 but I think this is a case that you need to suck it up and using a program to handle it.
      Good luck,
      Mike

    1. As this is a custom transaction, I’m sorry, I have no idea what to tell you.
      what sort of errors are you getting? have you tried walking through the transaction manually to make sure the data works? Are there any additional popups you didn’t expect (you often have to watch very quickly as it runs through the first record)?
      Thanks,
      Mike

      1. I managed to perform transaction using your code and other codes on web, but i am stuck in exporting to excel .
        Save as popup from SAP appears with name field blank , i want to automate this step.
        You will find the code i use below:

        Sub SAP_ZQ70()
        On Error Resume Next
        ‘Setting the connection with sap:
        Dim App, Connection, session As Object
        Set SapGuiAuto = GetObject(“SAPGUI”)
        Set App = SapGuiAuto.GetScriptingEngine
        Set Connection = App.Children(0)
        Set session = Connection.Children(0)

        If Not IsObject(Connection) Then
        ‘Set Connection = Application.Children(0)
        End If
        If Not IsObject(session) Then
        Set session = Connection.Children(0)
        End If
        If IsObject(WScript) Then
        WScript.ConnectObject session, “on”
        WScript.ConnectObject Application, “on”
        End If

        ‘launch the macro from current excel
        ‘———————————————
        Dim last As Long
        Dim customer As Range
        Dim Col As Range
        last = Range(“A65536”).End(xlUp).Row
        Sheets(“Start!”).Activate
        Set customer = Range(“A1”)
        Set Col = Range(“A:A”)

        ‘SAP GUI recording:
        ‘———————————————-
        myTransaction = “Zq70”
        session.findById(“wnd[0]/tbar[0]/okcd”).Text = “/n” & myTransaction
        session.findById(“wnd[0]”).sendVKey 0

        session.findById(“wnd[0]/usr/ctxtS_WERK-LOW”).Text = customer
        session.findById(“wnd[0]/usr/ctxtS_DATE-LOW”).Text = customer.Offset(2, 0)
        session.findById(“wnd[0]/usr/ctxtS_DATE-HIGH”).Text = customer.Offset(3, 0)
        session.findById(“wnd[0]/usr/ctxtS_MATNR-LOW”).Text = customer.Offset(4, 0)
        session.findById(“wnd[0]/usr/ctxtS_MATNR-LOW”).SetFocus
        session.findById(“wnd[0]/usr/ctxtS_MATNR-LOW”).caretPosition = 8
        session.findById(“wnd[0]/usr/btn%_S_MATNR_%_APP_%-VALU_PUSH”).press
        session.findById(“wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,0]”).Text = Col.Value
        ‘session.findById(“wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,1]”).Text = customer.Offset(6, 0)
        session.findById(“wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,0]”).caretPosition = 0
        session.findById(“wnd[1]/tbar[0]/btn[24]”).press
        session.findById(“wnd[1]/tbar[0]/btn[8]”).press
        session.findById(“wnd[0]/usr/chkP_SNGL”).Selected = True
        session.findById(“wnd[0]/usr/chkP_SNGL”).SetFocus
        session.findById(“wnd[0]/tbar[1]/btn[8]”).press
        session.findById(“wnd[0]/tbar[1]/btn[40]”).press
        session.findById(“wnd[1]/tbar[0]/btn[0]”).press

        On Error GoTo 0

        MsgBox ” Excel rows processed”
        End

        ‘——————————

        End Sub

  9. Hi Piehlm , i am seeking your support in finding a way to export results from SAP to excel ,
    the code attached below stops on Save as popup menu with blank name .
    i need to auto save as in specific path.

    On Error Resume Next
    ‘Setting the connection with sap:
    Dim App, Connection, session As Object
    Set SapGuiAuto = GetObject(“SAPGUI”)
    Set App = SapGuiAuto.GetScriptingEngine
    Set Connection = App.Children(0)
    Set session = Connection.Children(0)

    If Not IsObject(Connection) Then
    ‘Set Connection = Application.Children(0)
    End If
    If Not IsObject(session) Then
    Set session = Connection.Children(0)
    End If
    If IsObject(WScript) Then
    WScript.ConnectObject session, “on”
    WScript.ConnectObject Application, “on”
    End If

    ‘launch the macro from current excel
    ‘———————————————
    Dim last As Long
    Dim customer As Range
    Dim Col As Range
    last = Range(“A65536”).End(xlUp).Row
    Sheets(“Start!”).Activate
    Set customer = Range(“A1”)
    Set Col = Range(“A:A”)

    ‘SAP GUI recording:
    ‘———————————————-
    myTransaction = “Zq70”
    session.findById(“wnd[0]/tbar[0]/okcd”).Text = “/n” & myTransaction
    session.findById(“wnd[0]”).sendVKey 0

    session.findById(“wnd[0]/usr/ctxtS_WERK-LOW”).Text = customer
    session.findById(“wnd[0]/usr/ctxtS_DATE-LOW”).Text = customer.Offset(2, 0)
    session.findById(“wnd[0]/usr/ctxtS_DATE-HIGH”).Text = customer.Offset(3, 0)
    session.findById(“wnd[0]/usr/ctxtS_MATNR-LOW”).Text = customer.Offset(4, 0)
    session.findById(“wnd[0]/usr/ctxtS_MATNR-LOW”).SetFocus
    session.findById(“wnd[0]/usr/ctxtS_MATNR-LOW”).caretPosition = 8
    session.findById(“wnd[0]/usr/btn%_S_MATNR_%_APP_%-VALU_PUSH”).press
    session.findById(“wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,0]”).Text = Col.Value
    ‘session.findById(“wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,1]”).Text = customer.Offset(6, 0)
    session.findById(“wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,0]”).caretPosition = 0
    session.findById(“wnd[1]/tbar[0]/btn[24]”).press
    session.findById(“wnd[1]/tbar[0]/btn[8]”).press
    session.findById(“wnd[0]/usr/chkP_SNGL”).Selected = True
    session.findById(“wnd[0]/usr/chkP_SNGL”).SetFocus
    session.findById(“wnd[0]/tbar[1]/btn[8]”).press
    session.findById(“wnd[0]/tbar[1]/btn[40]”).press
    session.findById(“wnd[1]/tbar[0]/btn[0]”).press

    On Error GoTo 0

    1. Not having access to this transaction, I’m afraid I’m at a loss. it appears that you have enhanced the VBScript already. I don’t see any constant or reference to a column with the path and filename you want to save to. I am not a VB expert, so without seeing the data, I’m afraid I won’t be of much help. I’m guessing you are working off of an ALV grid or something similar, but I don’t know for sure.
      What I would recommend is to try recording it again. You might even want to simplify life and use the script I included on the post (if the link doesn’t work, let me know and I’ll correct it for you). Then, instead of defining variable, you just need to enter A for column A, B for column B. Or you could leave in some defaults.
      Best of luck,
      Mike

    1. Maybe I’m old school, but if it were me, I’d try doing it with a hardcoded value first to make sure it works. Just put in a direct path and file name, see what happens then. The beauty of GUI Script is that you don’t need to write a bunch of code. Just make a recording, set your columns and execute.
      If you are looking to build some more permanent, I typically don’t recommend this approach. build a real program to handle something more… but that’s just me.
      Mike

  10. Do you have access to MB51 transaction , so i can share with you recorded script and you help me on it accordingly .

  11. I need to run multiple scripts in parallel, but the option is grayed out once a script is in progress, although this was possible with SAP GUI 730 and below. Please suggest how I can get it back..

    1. I have never tried running scripts in parallel with the same user. If I have ever really needed to run scripts at the same time, I’ve used multiple users (since it would lock Excel in my machine anyway).
      Sorry I don’t have a better answer for you,
      Mike

  12. for multiple line item purpose this code are not work. ex(va01-creation of sale order for multiple line item.

    1. Well, when you use GUI scripting, you have to be a bit creative for certain applications. I have done multiple line sales orders, but you end up using a lot of columns within the excel spreadsheet (I have limited it to 3 lines on an order within a single call). It’s better to create the sales document header (you could use another script just for this), then build a script that adds one line at a time to the existing sales order.
      best of luck,
      Mike

  13. line item material qty
    10 vdap8012 10
    20 vdap8014 5
    30 vdap8019 15
    40 70101001-0 8
    … …………… ….

    *this is only one sale order, i have required that type of excel sheet script logic….,previous sheet are work very well..but i have required this type script for multiple line item. thank you sir………….

  14. Hi,

    Thanks for the nice post. In fact when I am executing this script in my system, I am getting below error. Any idea how do I overcome it?

    Cursor is highlighting below line item.
    “Private Declare Sub Sleep Lib “kernel32″ (ByVal dwMilliseconds As Long)”

    “Compile error:
    The code in this project must be updated for use on 64-bit systems. Please review and update Declare statements and then mark then with the PtrSafe attribute.”

    Sri ..

    1. change the second line in the script to this:
      Private Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)

      1. Thanks bro, it’s working for 1st record. However for second record giving an error “Invalid Procedure call or argument” for below line item. If I comment this confirmation section then the script is working fine. Any fix to overcome this error?

        if lDataRow < lLastRow Then
        "AppActivate "Microsoft Excel" — Error at this line

        Sri ..

  15. It stops there:
    AppActivate “Microsoft Excel”
    run-time error
    invalid procedure call or argument
    can you help me please???

    1. Depending on the version of office/windows you may need to change that to Excel. (Remove Microsoft)
      Thanks
      Mike

  16. What is the instruction to get SAP writing in the Excel file that the record has been processed, ‘ok’ in column Q ?
    Many thanks for your help.

    1. I haven’t actually done that before. You would need to Script and adjust the code. Sorry I can’t be more help.
      Mike

  17. What about use the macro in a 64bits system?
    Compilation error on:
    Private Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
    .
    .
    lLastRow = Sheets(“SAP_DATA”).UsedRange.Rows.Count

    I think some in decalrations must be changed… PtrSafe, LongLong, LongPtr, etc.
    Thanks in advance for your comments

    1. Yes. I have had to update a few of the variables to work in my 64bit system.
      If you go into debug, you will see the variables that need to be updated.
      thanks,
      Mike

  18. Hi,
    Is there anyway to control the scripts that can be executed. We do not want to allow users to create their own scripts for execution, but SAP only gives us auth check and system and user level, nothing at the script level. We are open to create any enhancement in the system to add additional control checks if that can be done. Any pointers would be appreciated.

  19. Hi can you suggest me for doing automating sm37 tcode task,
    I want to collect start and stop time of the jobs,
    the jobs is in excel sheet and start and stop time of jobs should be pasted on same excel sheet
    please help me

Leave a Reply

Your email address will not be published. Required fields are marked *