SAP
SAP
Prepare SAP client connection
Automation process must utilize WinappDriver on the same machine where NodeAgent is running and SAP environment is configured
SAP main window must hold all the elements without the need to stretch or maximize from standard view
Run Sap Logon and create new connection.
The setup steps will be presented for EasyRPA demo example.
Click new New Item in upper menu:
Click Next and specify Description, Application Server, Instance Number and System ID:
Finally switch to List View. This will prevent the connection entry from being hided during occasional tabs switching.
Enable scripting
It is recommended to download Tracker from https://tracker.stschnell.de/
One must be able to run Tracker against SAP Frontend and see its object tree after completing this step
Enable scripting on client side, switch off the notifications:
Enable scripting on server:
Log into created connection using your credentials
Run rz11 transaction code
Type in sapgui/user_scripting
parameter name and press Enter
Make sure current value is set to TRUE, otherwise change it using upper menu
Demo overview
SAP short example consists of the following steps:
- start SAP session with a certain transaction using sapshcut.exe
- perfrom simple actions such as clicks and text input
- logoff and terminate session
apm_run.properties file stores settings required to start application.
app.sap.path=C:/Program Files (x86)/SAP/FrontEnd/SAPgui/sapshcut # system ID from connection properties app.sap.sid=S4H # here 100 is fully activated trial client app.sap.client=100
where:
app.sap.sid -
app.sap.client - client
vault.properties stores SAP user credentials encoded as base64
sap.user={"user": "RPABOT", "password": "Password1"}
SapFrontendApplication class provides two methods for SAP window management:
open(String... args)
- initiates SAP Frontend session by starting sapshcut executable with aforementioned settings
Here transaction MB52 opens immediately on start which corresponds to list of warehouse stocks
package eu.ibagroup.easyrpa.sap; import eu.ibagroup.easyrpa.engine.rpa.Application; import eu.ibagroup.easyrpa.engine.rpa.driver.SapDriver; import eu.ibagroup.easyrpa.engine.rpa.element.SapElement; import eu.ibagroup.easyrpa.sap.page.ReportSetupPage; import lombok.extern.slf4j.Slf4j; @Slf4j public class SapFrontendApplication extends Application<SapDriver, SapElement> { public SapFrontendApplication(SapDriver driver) { super(driver); } @Override public ReportSetupPage open(String... args) { String sapPath = args[0]; String user = args[1]; String password = args[2]; String system = args[3]; String client = args[4]; String tCode = "MB52"; getDriver().get(sapPath, user, password, "EN", system, null, null, client, tCode, null); return createPage(ReportSetupPage.class); } }
Next follow two SAP page objects
ReportsSetupPage contains handles for setting up warehouse stock report prior to its execution
Here materialField
and plantField
are respectively material code and plant code placeholders
window
corresponds to entire SAP window which is handy to call hotkeys against, such as F8 (execute report)
package eu.ibagroup.easyrpa.sap.page; import eu.ibagroup.easyrpa.engine.rpa.element.SapElement; import eu.ibagroup.easyrpa.engine.rpa.page.SapPage; import lombok.extern.slf4j.Slf4j; import org.openqa.selenium.Keys; import eu.ibagroup.easyrpa.engine.rpa.po.annotation.FindBy; @Slf4j public class ReportSetupPage extends SapPage { @FindBy(id = "/app/con[0]/ses[0]/wnd[0]/usr/ctxtMATNR-LOW") private SapElement materialField; @FindBy(id = "/app/con[0]/ses[0]/wnd[0]/usr/ctxtWERKS-LOW") private SapElement plantField; @FindBy(id = "/app/con[0]/ses[0]/wnd[0]") private SapElement window; public void setupReport() { materialField.setText("TG11"); plantField.setText("1010"); } public ReportResultPage generateReport() { window.sendKeys(Keys.F8); try { Thread.sleep(3000); } catch (InterruptedException e) { log.error(e.getMessage(), e); } return this.getApplication().createPage(ReportResultPage.class); } }
ReportResultPage represents ALV (ABAP List Viewer) which is basically a table layout containing report result
We only implement close()
method since we're not going to perform any further actions on this page
package eu.ibagroup.easyrpa.sap.page; import eu.ibagroup.easyrpa.engine.rpa.page.SapPage; import lombok.SneakyThrows; public class ReportResultPage extends SapPage { @SneakyThrows public void close() { getDriver().close(); } }
Finally let's bring together application initialization, pages creation and action calls in WarehouseStock task
package eu.ibagroup.easyrpa.sap.task; import eu.ibagroup.easyrpa.engine.annotation.ApTaskEntry; import eu.ibagroup.easyrpa.engine.annotation.Configuration; import eu.ibagroup.easyrpa.engine.annotation.Driver; import eu.ibagroup.easyrpa.engine.apflow.ApTask; import eu.ibagroup.easyrpa.engine.model.SecretCredentials; import eu.ibagroup.easyrpa.engine.rpa.driver.SapDriver; import eu.ibagroup.easyrpa.sap.SapFrontendApplication; import eu.ibagroup.easyrpa.sap.page.ReportResultPage; import eu.ibagroup.easyrpa.sap.page.ReportSetupPage; @ApTaskEntry(name = "Get warehouse stocks of material") public class WarehouseStock extends ApTask { @Configuration("sap.user") private SecretCredentials credentials; @Driver private SapDriver sapDriver; @Configuration(value = "app.sap.path", defaultValue = "C:/Program Files (x86)/SAP/FrontEnd/SAPgui/sapshcut") private String sapPath; @Configuration(value = "app.sap.sid", defaultValue = "S4H") private String sapSystemID; @Configuration(value = "app.sap.client", defaultValue = "100") private String sapClient; @Override public void execute() { SapFrontendApplication sapLogonApplication = new SapFrontendApplication(sapDriver); ReportSetupPage setupPage = sapLogonApplication.open(sapPath, credentials.getUser(), credentials.getPassword(), sapSystemID, sapClient); setupPage.setupReport(); ReportResultPage resultPage = setupPage.generateReport(); resultPage.close(); sapDriver.quit(); sapLogonApplication.close(); } }