cancel
Showing results for 
Search instead for 
Did you mean: 

Using substring function with error

Former Member
0 Kudos

Hi Guys,

I have a source field with 1200 characters which need to map to multiple target segments for 132 count of this source field.

This is not a mandatory field so it sometimes come without any value.

I am using substring function to breakout the string for every 132 characters and mapped to the target segments.

There are two problems, first it seems that if source is blank, there will be error.

Second, if source field come with only eg. 300 characters, error will also occurs.

I have searched thru SDN and try some of the UDF but to no avail.

Appreciate your guidance on this problem.

Regards

FNG

Accepted Solutions (0)

Answers (5)

Answers (5)

Former Member
0 Kudos

Hi

I apologise for not able to get back to you as early as possible on this testing due

to some critical issue happened on some other interfaces.

I promise to revert back asap with test result.

Thank you for your active inputs.

Sincere regards,

FNG

Former Member
0 Kudos

Hi Freddy,

Earlier i faced same issue, I just used the simple UDF function to rectify the problem

For ex: If your Source filed= 1200 chacters, you want only 132 chacters, and some times Source filed having no data . Use this below UDF:

java.*;

public String Substring_UDF(String a,String b,Container container){

//write your code here

int i = Integer.parseInt(a);

int str_length= b.length();

if (str_length > i && b != null)

{

String c = b.substring(0,i);

return c;

}

else

{

return b;

}

In the above UDF, 'a' and 'b' are input values

'a' is the how much chacters you excepted in target field in your case value of 'a' is = 132

'b' is the your source field.

Add to these two inputs to UDF and map to your target field

Hope you will get the excepted result.

Thank you,

Sateesh

Edited by: sateesh kumar .N on Dec 3, 2010 6:18 AM

Edited by: sateesh kumar .N on Dec 3, 2010 6:19 AM

Former Member
0 Kudos

Hi Guys,

Thank you for your pointers.

I will get back to you once I implement your suggestion.

Former Member
0 Kudos

Hi Freddy

Has this worked ...i have tried using the stringtokens UDF and my output matches my input ie it doesn't break it up into 132 characters. Unless I am doing something wrong.

Thanks

Former Member
0 Kudos

Hi,

Ya I wrote i instead of j in a place...

Try the updated UDF.

for(int i =0;i<inputString.length;i++)
{
   String stringTokens[] = inputString<i>.split("(?<=\\G.{132})");
	for(int j=0;j< stringTokens.length ;j++)
	{
//It should be j instead of i
	result.addValue(stringTokens[j]);
	}
}

Regards

Arpil

Former Member
0 Kudos

Hi Arpil,

I tried your logic, but it calculate the first 132 characters of the source, populate to the multiple target segments with

the same 132 characters.

Former Member
0 Kudos

Hi Freddy,

Are you referring to my 2nd post ??

In 1st post there was a typo ( i instead of j ) .. which I corrected in 2nd post.

It worked for me... shud work for you as well.

Regards

Former Member
0 Kudos

I am using the 2nd codes with the changes in "j"

But the target segment is still getting the repeated first 132 characters of the from the source though I tested with 500 characters.

Former Member
0 Kudos

Hi Freddy,

I had a similar problem. I used the following UDF:

public void SplitString(String[] Input, String Output, ResultList result, Container container) throws StreamTransformationException{

String zspeich = Input[0];       
       int maxSize = 80;
       int textLen = zspeich.length();

		
       if (textLen > maxSize) {
           int si = 0;
           int ei = maxSize;

           while (si < textLen) {
                   if (ei > textLen) ei = textLen;

//Text in Feld schreiben
                   Output= zspeich.substring(si, ei);
                   result.addValue(Output);
                   result.addContextChange();
                   si = ei;
                   ei = ei + maxSize;
           }
}
}

Instead of 80 you have to set your 132 characters as MaxSize. I hope this helps.

Best Regards

Martin

Former Member
0 Kudos

Hi Stampflmar ,

I have tried your codes but the target segment is still repeating the same first 132 characters of the source field.

Fyi, the target segment is as follows

TDLINE is a child of EPITXT1.

I have created duplicate subtree of EPITXT. So in total I created 10 TDLINE.

Source -> UDF -> TDLINE

TDLINE

TDLINE......

For the execution type, should I use All Values of a Context or All Values of a Queuee ?

If I used All Values of a Queue, I face the message in queue in SXMB_MONI.

Former Member
0 Kudos

Hi,

I am assuming your requirement is something like this eg:

Source field :: 1350 characters i.e. 132*10 + 30 characters.

Target fields ::

Target1

.

.

.

Target10 (132 characters)

Target11 (remaining 30 characters).

You can use such a UDF

//Queue type UDF

for(int i =0;i<inputString.length;i++)
{
   String stringTokens[] = inputString<i>.split("(?<=\\G.{132})");
	for(int j=0;j<	stringTokens.length ;j++)
	{
	result.addValue(stringTokens<i>);
	}
}

former_member207622
Contributor
0 Kudos

Let me know if I am wrong , you mean to say in total 1200 characters you have to map every set of 132 characters to target

meaningly first set -


target1

second set --- target 2

As 1200 is not divisible by 132 there will be some characters left so what do you want to do in that case

similarly in case if only 300 characters are there

please clarify to let experts help you

regards

Ninad

Former Member
0 Kudos

The source field is defined as 1200 characters and a variable as it can come in less or equal to 1200.

as it is not divisible by 132, the last substring function has been defined as the no. of count to reach 1200.

Overall, I think this graphical function using substring has flawed.

I believe I will need a UDF to first check if this field is blank , if not then do the mapping based on the 132 counts to each target segment..

I hope this is clear for your understanding.

Thanks.

stefan_grube
Active Contributor
0 Kudos

You can use this UDF for substring:

int len = value.length();
if (len > characterCount)
  return value.substring(0,characterCount);
else
  return value;

For shorter strings you can do:

value - concat (constant( x spaces) ) - substring (x)

But for your request you should use the UDF.

RKothari
Contributor
0 Kudos

Hi,

Please try the below mentioned logic:

int i,j,k;
int StartIndex = 0;
int EndIndex = 0;


j = input.length();

k = j % 132;


for(i=0;i<k;i++)
{
if(j > 0)
{
	if (i == 0)
	{ // for intial record or length is less than 132
		if( j > 132)
		{
			EndIndex = 132;
		}
		else
		{
			EndIndex = j;
		}
		
		result.addValue(input.subString(0,EndIndex));
		StartIndex = EndIndex+1;
	}
	else
	{
		if ( ((i+1) == k) && ((j - EndIndex) < 132))
		{ // for some last remaining records 
			EndIndex = j - EndIndex;
			result.addValue(input.subString(StartIndex,EndIndex));
			break;
		}
		else
		{ 
			EndIndex = EndIndex + 132;
			result.addValue(input.subString(StartIndex,EndIndex));
			StartIndex = EndIndex+1;		
		}
	} 
}


}

-Rahul

Former Member
0 Kudos

H Rahul,

I have tried your quote but face some syntax error as follows

Function calculate, Line 6:

cannot find symbol symbol : method length() location: class java.lang.String[] j = input.length();

Function calculate, Line 26:

cannot find symbol symbol : method subString(int,int) location: class java.lang.String[]

result.addValue(input.subString(0,EndIndex)); ^

Function calculate, Line 34:

cannot find symbol symbol : method subString(int,int) location: class java.lang.String[] result.addValue(input.subString(StartIndex,EndIndex)); ^

Function calculate, Line 40:

cannot find symbol symbol : method subString(int,int) location: class java.lang.String[] result.addValue(input.subString(StartIndex,EndIndex)); ^ Note: /usr/sap/D03/DVEBMGS00/j2ee/cluster/server0/./temp/classpath_resolver/Mapd66a3a60002911e09ba9e41f132d6b68/source/com/sap/xi/tf/_MM_MT_COMS_TO_ZME_CRE_CHG_CONTRACT_.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. Note: /usr/sap/D03/DVEBMGS00/j2ee/cluster/server0/./temp/classpath_resolver/Mapd66a3a60002911e09ba9e41f132d6b68/source/com/sap/xi/tf/_MM_MT_COMS_TO_ZME_CRE_CHG_CONTRACT_.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 4 errors

RKothari
Contributor
0 Kudos

Hello,

Please try the below code:

int i,j,k;
int StartIndex = 0;
int EndIndex = 0;

String s = "";
s = input[0];
j = input[0].length();

if(j > 0)
{
if( (j % 132) == 0)
{
	k = (j / 132) ;
}
else
{
	 k = (j / 132) + 1 ; 
}

for(i=0;i<k;i++)
{

	if (i == 0)
	{ // for intial record or length is less than 132
		if( j > 132)
		{
			EndIndex = 132;
		result.addValue(s.substring(0,EndIndex));
		StartIndex = EndIndex;
		}
		else
		{
			result.addValue(s);
			break;
		}

	}
	else
	{
		if ( (i) == (k - 1) && ( (j - EndIndex) <= 132) )
		{// for some last remaining records 
				EndIndex = j;
			result.addValue(s.substring(StartIndex,EndIndex));
			break;
	}
		else
		{
			EndIndex = EndIndex + 132;
			result.addValue(s.substring(StartIndex,EndIndex));
			StartIndex = EndIndex;		
		}
	} 
}
}

-Rahul

Former Member
0 Kudos

Hi Rahul,

I tried your codes.

But similar problem as previous. The target segment is repeating the first 132 characters of the source 's string.

source field -> UDF -> TDLINE (E1lTXT [0])

--> TDLINE (E1lTXT [1])

--> TDLINE (E1lTXT [2])

---> ...........................

DId I miss out anything, as it seems like all logic I tried have the same problem ?

markangelo_dihiansan
Active Contributor
0 Kudos

Hi Freddy,

UDF type is of context

Argument var1

code is


for(int a=0;a<var1.length;a++){
	StringBuffer sb = new StringBuffer(var1[a]);
	for(int b=0;b<var1[a].length();b+=132){
			if(sb.length()<132){
				result.addValue(sb.toString());
			}
		else{
			if(b+132<var1[a].length()){
					result.addValue(sb.substring(b,b+132));
				}
				else
					result.addValue(sb.substring(b,sb.length()));
		}
	}
}

Here is the mapping logic:

SourceField --> mapWithDefault --> UDF --> Target (0..unbounded or 1..unbounded)

The mapWithDefault is used to eliminate null values (the UDF will fail if this is not included). There is no need to use duplicate subtree.

Hope this helps,

Mark

Edited by: Mark Dihiansan on Dec 8, 2010 6:41 AM

RKothari
Contributor
0 Kudos

Hi Freddy,

Try to use the below logic on the node EPITXT1:

Source>UDF>EPITXT1

Souce>UDF>SplitByValue(each)-->TDLine

Don't duplicate the TDLIne node.

-Rahul