Friday 4 December 2020

EXCEL MACRO - Multiple excel combine as one excel

1. In Excel - Developer tool at right top - Click Visual basic :

2. Right side - Rightclick on Sheet1 - Insert-Modules. 

3. Paste this code and update the split files folder.


EXCEL MACRO - Multiple excel combine as one excel:

'Description: Combines all files in a folder to a master file.
Sub MergeFiles()
Dim path As String, ThisWB As String, lngFilecounter As Long
Dim wbDest As Workbook, shtDest As Worksheet, ws As Worksheet
Dim Filename As String, Wkb As Workbook
Dim CopyRng As Range, Dest As Range
Dim RowofCopySheet As Integer

RowofCopySheet = 2 ' Row to start on in the sheets you are copying from

ThisWB = ActiveWorkbook.Name

path = "C:\Users\\Desktop\test\newfolder\" ' Dont't forget to change this

Application.EnableEvents = False
Application.ScreenUpdating = False

Set shtDest = ActiveWorkbook.Sheets(1)
Filename = Dir(path & "\*.csv", vbNormal)
If Len(Filename) = 0 Then Exit Sub
Do Until Filename = vbNullString
If Not Filename = ThisWB Then
Set Wkb = Workbooks.Open(Filename:=path & "\" & Filename)
Set CopyRng = Wkb.Sheets(1).Range(Cells(RowofCopySheet, 1), Cells(ActiveSheet.UsedRange.Rows.Count, ActiveSheet.UsedRange.Columns.Count))
Set Dest = shtDest.Range(" A" & shtDest.UsedRange.SpecialCells(xlCellTypeLastCell).Row + 1)
CopyRng.Copy Dest
Wkb.Close False
End If

Filename = Dir()
Loop

Range("A1").Select

Application.EnableEvents = True
Application.ScreenUpdating = True


MsgBox "Done!"
End Sub
-------------------------------------------------------

Press F5 to run the macro to extract the file.





Wednesday 11 November 2020

substring in Content Modifier in SAP CPI

 substring(//DemandAssignmentRequest/DemandAssignmentRequest/TicketItem/ItemAssignment/AssignmentUUID,6,8)




Monday 2 November 2020

XPATH or Router namespace based field handling in SAP CPI/SCPI

 In Content Modifier, XPATH namespace based field handling in SAP CPI/SCPI


Input Field: <n1:LX_TKT_EXTERNALID>38683</n1:LX_TKT_EXTERNALID>


If we are using direct namespace like below will not work:

 //DemandReplicationRequest/DemandHeaderInfo/RefTicketInfo/ns1:LX_TKT_EXTERNALID


Correct XPATH: //DemandReplicationRequest/DemandHeaderInfo/RefTicketInfo/*:LX_TKT_EXTERNALID


Field node not exist condition check : (Router)

Router condition: count(//PromisedDateTime) != 0




Count expression in router to field the field/node exist

 In router, we tent to find the node / field exist in the incoming xml , based on the we will route the path.

Expression Type: XML

Condition: count(//PromisedDateTime) = 0 




Monday 19 October 2020

Property read and calculate length equals zero


Routing logic in CPI:

 ${property.AppTaskID.trim().length()} = '0'




Wednesday 23 September 2020

Get Bearer token and pull users from SAP cloud platform

When connecting with SCP to pull the users using the API management.

Get the bearer token using the client key and secret and pass that to get the user details.

First call: To get the bearer token


POST: https://api.eu2.hana.ondemand.com/oauth2/apitoken/v1?grant_type=client_credentials


While providing authorization: you have ClientID and Secret from SCP ,so construct in the format below

Basic:  ClientID:ClientSecret – Base64 format(https://www.base64encode.net/)

Authorization : Basic NzJlYjM3NDMtOTQ3OC0zMmI4LTItMDMwM2ZkNmQyNWE0OTVhOGY0LTBlMmMtM2Y0YS05ZTRmLTVkNmY5NzIzMDJjMw== 

Output:

{

"access_token": "42d6da336c437955de45829a611f5b",

"token_type": "Bearer",

"expires_in": 1500,

"scope": "hcp.readAccountMembers hcp.manageAccountMembers hcp.manageAuthorizationSettings hcp.readAuthorizationSettings"

}


Second call: Access token to be passed as Bearer in this call and get the user details from SCP:




GET: https://api.eu1.hana.ondemand.com/authorization/v1/platform/accounts/a79a6ea13/Users



"key":"Authorization","value":"Bearer 42d6da336c437955de45829a611f5b



Output Data:


{

    "Resources": [

        {

            "id": "C5200000",

            "meta": {

                "created": "2020-09-18T13:02:33.628Z",

                "lastModified": "2020-09-18T13:02:33.628Z",

                "location": "https://apissecurity.hana.ondemand.com/authorization/v1/platform/accounts/a79a6ea10/Users/C5200000"

            },

            "schemas": [

                "urn:sap:cloud:scim:schemas:extension:custom:2.0:UserExt",

                "urn:ietf:params:scim:schemas:core:2.0:User"

            ],

            "userName": "C5200000",

            "name": {

                "familyName": "C",

                "givenName": "ramu"

            },

            "emails": [

                {

                    "value": "ramu@gmail.com",

                    "primary": true

                }

            ],

            "roles": [

                {

                    "value": "AccountAdministrator",

                    "primary": false,

                    "type": "Predefined"

                }

            ],

            "urn:sap:cloud:scim:schemas:extension:custom:2.0:UserExt": {

                "userbase": "xxCOM",

                "description": "SAP API Management team"

            }

        }





Tuesday 22 September 2020

Error: Invalid parametertype used at function 'ge'

When getting an error calling the target system as below:

Error: Invalid parametertype used at function 'ge' 


Date format to be changed from 

((CHANGED_DT ge'2020-08-10T00:00:00') and (CHANGED_DT le'2020-09-22T00:00:00'))


to


((CHANGED_DT ge datetime'2020-08-10T00:00:00') and (CHANGED_DT le datetime'2020-09-22T00:00:00'))


Hope this works!!!




Friday 18 September 2020

Script: Routing logic to send to different system based on condition in sap cpi/hci

 



Routing logic to send to different system based on condition


Groovy Script:

import com.sap.gateway.ip.core.customdev.util.Message;

import java.util.HashMap;

import groovy.json.*;

import groovy.util.logging.*;

import org.codehaus.*;

import groovy.xml.*;




def Message processData(Message message) {

def body = message.getBody(java.lang.String) as String;

map = message.getProperties();




JobCategory = map.get("JobCategory");

requestid = map.get("requestid");

taskid = map.get("taskid");

message.setProperty("JobCategory1",JobCategory);

message.setProperty("requestid1",requestid);

message.setProperty("taskid1",taskid);




def route1 = "M";

def route2 = "F;

def route3 = "F;

def route4 = "M";




if(JobCategory.equals("03")) 

{

if((taskid.equals("")) && (requestid.equals("")))

{

Header = route1;

}

else

{

Header = route2;

}

}

else 

{

if((JobCategory.equals("02")) || (JobCategory.equals("01")))

{

Header = route3;

}

else

{

Header = route4;

}

}

message.setProperty("Header",Header);

return message;

}



Wednesday 16 September 2020

One line script to remove all double quotes for integer in Json data

 It is simple to remove the double quotes from the json data for the individual values. Earlier we used to pull the value in xpath and convert that value to interger to remove the double quotes.

But it makes more easier.

Groovy Script:

import com.sap.gateway.ip.core.customdev.util.Message;

def Message processData(Message message) {

def body = message.getBody(java.lang.String) as String;

// remove double quotes from all integer vaules in json data

String output = body.replaceAll("\"(\\d+)\"", "\$1");

message.setBody(output);

return message;

}



Tuesday 15 September 2020

Unmarshalling XML error in SAP CPI while converting XML to CSV convertor


Incase if you are getting this error when use XML to CSV convertor, want to add header field name in xml to csv then by standard way it's not possible. 


  1.  uncheck use field name as header in xml to csv converter.

  2. Add content modifier after your converter. In the body part add all your header field names you want like Name,Rank,subject,etc., in first line.

 3. In second line of body add ${in.body}



Thursday 10 September 2020

Groovy script to pick the count of days from today's date



import java.util.concurrent.TimeUnit;

import java.lang.*;

import java.time.*;

import com.sap.gateway.ip.core.customdev.util.Message;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.HashMap;


def Message processData(Message message)

{

def map = message.getHeaders();

String getCertExpirydate = map.get("CertExpiryDate");

Date CertExpirydate = new SimpleDateFormat("yyyy-MM-dd").parse(getCertExpirydate);

Date dateNow = new Date(System.currentTimeMillis());

long dateDiff = CertExpirydate.getTime() - dateNow.getTime();

def daysToExpire = TimeUnit.DAYS.convert(dateDiff, TimeUnit.MILLISECONDS);

message.setHeader("daysToExpire",daysToExpire);

return message;

}



Thursday 3 September 2020

Pick the xml node value and remove brackets

To pick the xml node value from the input XML which return as 

E.g: requestid => [345]

Now to remove the array brackets, also handled in script.

Now, requestid => 345 


Groovy Script:


import com.sap.gateway.ip.core.customdev.util.Message;

import java.util.HashMap;


def Message processData(Message message) {

def body = message.getBody(java.lang.String) as String;

def data = new XmlSlurper().parseText(body);

def requestid = data.'**'.findAll { node -> node.name() == 'request_id' }*.text();

def taskid = data.'**'.findAll { node -> node.name() == 'task_id' }*.text();

requestid= requestid.toString().replaceAll("\\[", "");
requestid= requestid.toString().replaceAll('\\]', "");

message.setProperty("requestid",requestid);

taskid= taskid.toString().replaceAll("\\[", "");
taskid= taskid.toString().replaceAll('\\]', "");

message.setProperty("taskid",taskid);

return message;
}



Saturday 29 August 2020

Groovy script to find the xml field and store in property

 Groovy script to find the xml field from the input payload and display the value in payload logging title in the monitoring.

Eg: 

<root>

<id>112</id>

<request_id>234</request_id>

<task_id>456</task_id>

</root>


Script:

import com.sap.gateway.ip.core.customdev.util.Message;

import java.util.HashMap;

def Message processData(Message message) {

def body = message.getBody(java.lang.String) as String;


def data = new XmlSlurper().parseText(body);


def requestid = data.'**'.findAll { node -> node.name() == 'request_id' }*.text();

def taskid = data.'**'.findAll { node -> node.name() == 'task_id' }*.text();


requestid= requestid.toString().replaceAll("\\[", "");

requestid= requestid.toString().replaceAll('\\]', "");


message.setProperty("requestid",requestid);


taskid= taskid.toString().replaceAll("\\[", "");

taskid= taskid.toString().replaceAll('\\]', "");


message.setProperty("taskid",taskid);

return message;

}

Output

generally it displays as requestid as [234] and taskid as [456]

but need to remove [ ] for our requirement, so handled that aswell in script.



Friday 28 August 2020

Error on inbound connection to C4C


Error message:


com.sap.it.rt.adapter.http.api.exception.HttpResponseException: An internal server error occured: Response was of unexpected text/html ContentType. Incoming portion of HTML stream: (none).

ErrorFaultCode = {http://cxf.apache.org/faultcode}server



When you facing similar kind of error, their could be some cases.

1. URL might mismatch

2. User credentials/certificate issue

3. One system uses Certificate based authentication and other uses user credentials.




Hope this solves!!



Friday 24 July 2020

Connect to Azure File storage using script from SAP CPI

There is no standard way to connect to Azure file storage and does not have a adapter aswell in SAP CPI. 
Advantco Azure Adapter used to connect Azure storage but that is not added in CPI.

So would need to connect externally using script from SAP CPI.


Script:

import com.sap.gateway.ip.core.customdev.util.Message
import java.io.*
import com.microsoft.azure.storage.*;
import com.microsoft.azure.storage.file.*;
import com.microsoft.azure.storage.common.*;

def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String

String accountName = "myaccountstorage"
String accountKey = "Key"
String storageConnectionString = "DefaultEndpointsProtocol=https;" + "AccountName=" + accountName+ ";" + "AccountKey=" + accountKey;


CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString)
CloudFileClient fileClient = storageAccount.createCloudFileClient();


CloudFileShare share = fileClient.getShareReference("fsmshare");


String fileName = "filename1.jpg"
String fileContent = body
byte[] fileBytes = fileContent.getBytes()


CloudFileDirectory rootDir = share.getRootDirectoryReference();

CloudFileDirectory sampleDir = rootDir.getDirectoryReference("attachments_inbound");



CloudFile cloudFile = sampleDir.getFileReference(fileName); cloudFile.uploadFromByteArray(fileBytes, 0, fileBytes.length)


cloudFile.getProperties().setContentType("image/jpeg")
cloudFile.uploadProperties()


message.setBody("OK")


return message;
}






Thursday 23 July 2020

Script error - unable to resolve class in sap cpi/scpi

If you are using eclipse then have a option to add the external jar libraries and import the class and solve this issue but if there is an error in WEB IDE which we use commonly now. Here is the solution for it.


Error:

com.sap.it.rt.adapter.http.api.exception.HttpResponseException: An internal server error occured: startup failed: script1__Script.groovy: 14: unable to resolve class CloudStorageAccount @ line 14, column 25.

Go to your integration flow and select the resource at the bottom and add -> archives, then select the jar file which is available in the local drive.




Now the issue will be resolved!!!

Hope this helps.


Monday 13 July 2020

CPI IP range whitelisting


Region         
Key      
Host                                 

           IP Ranges    
Europe (Rot)
neo-eu1
hana.ondemand.com
eu1.hana.ondemand.com
Link
155.56.128.0/17



Tuesday 30 June 2020

SFTP connection setup using Public key from SAP CPI

Configure SAP CPI with SFTP using Public key based authentication:


Step 1: Host Key retrieval from SAP CPI - Connectivity

For SSH based communication, CPI tenant needs the host key of the sftp server, which has to be added to the known hosts file and deployed on the cpi tenant. The host key can either be downloaded from sftp server or has to be provided by the administrator of the sftp server.



You can download the host key with the SSH connection test with Connectivity Test option and the Copy Host Key and add to knownhost file.


Creating Public key:

For SSH  based communication using public key authentication towards the sftp server, a private key pair with the any alias like id_rsa or id_dsa is required in CPI tenant’s keystore. Create this key pair in CPI keystore for the connection to the sftp server and use the same alias in the sftp adapter configuration at private key alias.



As provided, configure the channel with the below parameters:










Tuesday 23 June 2020

SuccessFactor Mutiple query on WHERE on SOAP

Query: SELECT person, employment_information, job_information FROM CompoundEmployee WHERE person_id_external IN ('94172064T','109996354T')



Tuesday 26 May 2020

Replace double quotes for CSV files validation issue in SAP CPI

Some tools give a validation error on single double quote like:

123,Bricks measurement 24"/60cm,Erode,TN

where the double quotes cause an issue here.

So  in message mapping, we removed the single double quoted to two double quotes can escape the character.

Groovy Script:

import com.sap.it.api.mapping.*;

def String customFunc(String arg1){

def str2 = arg1.replaceAll("\"","\"\"")

return str2

}
Output:
123,Bricks measurement 24""/60cm,Erode,TN



Thursday 16 April 2020

Delay processing of iflow on every message in SAP CPI

Processing delay of 8s for every messages sent to the end system.

1. Replace xml node
2. delay code of 8 secs

Groovy Script

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.lang.*

def Message processData(Message message) {

def body = message.getBody(java.lang.String) as String;

body = body.replaceAll("\\<\\?xml(.+?)\\?\\>", "").trim(); //Replace xml node

message.setBody(body);


sleep(8000)    // wait for 8 secs

return message;
}



Monday 6 April 2020

Remove certain string from the query/url passing to target using groovy script in SAP CPI

Read the query parameters from the source system and remove the $filter= from it as shown below:


CamelHttpQuery from source :$filter=ContactID%3d%271925053%27%2cContactOrigin%3d%27SAP_C4C_BUPA%27

URL should be as send to target system: https://myXXX-api.s4hana.ondemand.com/sap/opu/odata/sap/API_MKT_CONTACT_SRV;v=0003/ContactOriginData(ContactOrigin='SAP_XXX',ContactID='190000')

Query in the channel:

https://myXXX-api.s4hana.ondemand.com/sap/opu/odata/sap/API_MKT_CONTACT_SRV;v=0003/ContactOriginData(${header.Query})

Script:

import com.sap.gateway.ip.core.customdev.util.Message;

import java.util.HashMap;

def Message processData(Message message) {

def map = message.getHeaders();

def value = map.get("CamelHttpQuery");

value = value.drop(8);

message.setHeader("Query", value);

return message;

}



Standard Character encoding change in SAP CPI

Standard Character encoding change like UTF-8 or different ISO standard formats.

Groovy script:

import com.sap.gateway.ip.core.customdev.util.Message

import java.nio.charset.StandardCharsets

def Message processData(Message message) {

def body = message.getBody(java.lang.String)

message.setBody(body.getBytes(StandardCharsets.ISO_8859_1))

return message

}



Monday 2 March 2020

Groovy script for DateTime formatting ODATA filter





import com.sap.gateway.ip.core.customdev.util.Message;

import java.util.HashMap;

import java.util.TimeZone


def Message processData(Message message) {

//Body

def body = message.getBody();

//Properties

map = message.getProperties();

value = map.get("LastSuccessfulRun886PRD");

def curDateTime1 = "";

def tz = TimeZone.getTimeZone("Europe/Berlin")

def ts = new Date()

curDateTime1 = (ts.format("yyyy-MM-dd'T'HH:mm:ss", timezone=tz))

def datequery = "(CCSRQ_DOC_CREATED_DATE_TIME ge"+"'"+value+" CET"+"'"+" and CCSRQ_DOC_CREATED_DATE_TIME le"+"'"+curDateTime1+" CET"+"'"+")";

message.setHeader("datequery",datequery);

message.setProperty("CurrentDate",curDateTime1);

return message;

}



Thursday 13 February 2020

POSTMAN- CSRF token validation failed error - Fix

If you encounter an issue in the POSTMAN when calling the POST method even though you are passed in the valid X-CSRF token by using the GET call in the previous step. Then here is the solution for your problem.

While sending the POST method, use the extra header parameters to solve this.

"CSRF token" and  "cookie" header should be picked from the GET call.

X-CSRF-Token:pIgKS5dokT0FZTouD8-jig==
Content-Type:application/json
Connection:keep-alive
Cookie:SAP_SESSIONID_KUH_246=fgAZqA33-I3QLvTa5yuXPb-AoFlObxHqhCcAFj5r60I%3d


Hope this resolves your issue. If yes, comment below. Thanks



Wednesday 5 February 2020

Find the field from atom-xml / pick the field from unformatted xml in SAP CPI

Find the field from atom-xml / pick the field from unformatted xml in SAP CPI.

Data:

<?xml version="1.0" encoding="utf-8"?>
<feed xml:base="https://XXX.ondemand.com/sap/c4c/odata/cust/v1/servicelocation/" xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
  <id>https://XXX.ondemand.com/sap/c4c/odata/cust/v1/servicelocation/AddressSnapshotPostalAddressCollection</id>
  <title type="text">AddressSnapshotPostalAddressCollection</title>
  <updated>2020-02-04T10:00:13Z</updated>
  <author>
    <name/>
  </author>
  <link href="AddressSnapshotPostalAddressCollection" rel="self" title="AddressSnapshotPostalAddressCollection"/>
  <entry m:etag="W/&quot;datetimeoffset'2020-01-23T12%3A51%3A32.3360950Z'&quot;">
    <id>https://XXX.ondemand.com/sap/c4c/odata/cust/v1/servicelocation/AddressSnapshotPostalAddressCollection('00163E6CDD2F1EEA8FBBE27F8D76E336')</id>
    <title type="text">AddressSnapshotPostalAddressCollection('00163E6CDD2F1E7A8FBBE22F8D76E336')</title>
   <updated>2020-02-04T10:00:13Z</updated>
    <category term="cust.AddressSnapshotPostalAddress" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
    <link href="AddressSnapshotPostalAddressCollection('00163E6CDD2F1E7A8FBBE22F8D76E336')" rel="edit" title="AddressSnapshotPostalAddress"/>
    <content type="application/xml">
      <m:properties>
        <d:ObjectID>00163E6CDD2F1E7A8FBBE22F8D76E336</d:ObjectID>
        <d:ETag>2020-01-23T12:51:32.3360950Z</d:ETag>
        <d:CountryCode>BE</d:CountryCode>
        <d:CityName>Scherpenheuvel-Zichem</d:CityName>
        <d:StreetName>Bergstraat 1</d:StreetName>
        <d:StreetPostalCode>3272</d:StreetPostalCode>
        <d:CountyName/>
      </m:properties>
    </content>
  </entry>
</feed>

Groovy Script:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) {
def body = message.getBody();
def data = new XmlSlurper().parseText(body);
String[] productId= " ";

def id = data.'**'.findAll { node -> node.name() == 'ObjectID' }*.text();
def country = data.'**'.findAll { node -> node.name() == 'CountryCode' }*.text();
def city = data.'**'.findAll { node -> node.name() == 'CityName' }*.text();

assert id.size() == 1;
assert country.size() ==1;
assert city.size() ==1;
message.setProperty("objectid",id);
message.setProperty("CountryCode",country);
message.setProperty("CityName",city);

return message;

}

Thanks Shruthi for helping on this solution.



Date format groovy script from UTC timezone in SAP CPI

To convert the time into the below format, we used this method for temporary fix.

Output required as : 2020-02-05 14:10:00 UTC

Groovy script:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.util.TimeZone

def Message processData(Message message) {

//Body
def body = message.getBody();

//Properties
map = message.getProperties();

//LastSuccessfulRunTeleDev - variable value maintained in cpi system.
value = map.get("LastSuccessfulRunTeleDev");

def curDateTime1 = "";
def tz = TimeZone.getTimeZone("Europe/Berlin")
def ts = new Date()

curDateTime1 = (ts.format("yyyy-MM-dd HH:mm:ss", timezone=tz))

def datequery = "(CHANGE_DATE_TIME ge"+"'"+value+" UTC"+"'"+" and CHANGE_DATE_TIME le"+"'"+curDateTime1+" UTC"+"'"+")";

message.setHeader("datequery",datequery);
message.setProperty("CurrentDate",curDateTime1);
return message;

}