<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d34883048\x26blogName\x3dYour+Friendly+ABAPer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://friendlyabaper.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://friendlyabaper.blogspot.com/\x26vt\x3d-4712760677496349421', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>

Dangers of type N

Happy Holidays, everyone! First of all, sorry for a long absence, which was due to my [very much needed] vacation. What could be nicer in December than to leave everyone in the middle of a boring QA testing and go to Florida where it’s sunny and +80 F? ;)

You would think that I’ve already had enough fun with numbers while working on my “Fun with numbers” post, but turns out there is more fun left to have. Yesterday I was presented with the issue that instead of sending number 5 in the file we are sending 5000. Fortunately this came up in testing, so I had enough time to poke around.

We have a lot of interfaces and most of them involve IDocs but, since we deal with many other companies and systems, we can not just send them a plain IDoc, so we have to create a file according to the standards set by those companies and systems. Not sure how familiar you guys are with the IDoc concept but, in a nutshell, IDoc is just a weirdly looking set of records in the database, which you can use to either post something in SAP from an external system or send some data out from SAP. All IDocs have a control record, which is sort of a header, and detail records, which are called segments. Segments, in turn, have the fields and the dangerous thing here is that the field names usually correspond with the fields in the major application tables (MARA or VBRK, for example), BUT the IDoc fields always are type CHAR. So when you see the field, let’s say, MENGE in the IDoc you might think that it’s a QUAN field or at least a numeric but, in fact, it’s not (check out the structure E1EDP01, for example).

By the way, if you’d like to find out more about the IDocs, ALE, EDI and stuff, here is a good web page to start with. It’s a bit dated but the concepts have not changed since. There is also a comprehensive book on the same subject which has the rave reviews on Amazon. In my opinion, the author did a great job exploring the different scenarios and trying to explain how stuff works (or at least supposed to work), but the book is a good reference if you know what you are looking for. If you haven’t had any experience with IDocs and ALE this book will most likely just add to the confusion. Also it goes waaaaay too deep into details – most of the time I don’t even want to know how it works and why. I don’t have time, users are freaking out, somebody please tell me what to do to make it work!!! But it’s the best book on IDocs so far.

Anyways, back to the subject. So I looked at the IDoc and, sure thing, the MENGE field contained ‘5.000’. In my program I have to convert this field into a field of type N 7 (it mist always be the whole number) for the file. And what do you know – turns out that ‘5.000’ is converted not into ‘0000005’, as I hoped, but into ‘0005000’. Honestly, those character fields and the fact that type N is actually a character type, which can only contain numbers, are driving me nuts. I think that SAP could have done a bit better than this. But, since we have to live with it, I had to find out once and for all how this works and, most importantly, how to solve this problem.

I put together a tiny test program to see how different strings would convert into the fields of type N and type I (since I is the real numeric type):
DATA: qty_num TYPE n LENGTH 10,
qty_i TYPE i.

PARAMETERS: p_char TYPE c LENGTH 10.

qty_num = p_char.
WRITE: / 'Type N = ', qty_num.

qty_i = p_char.
WRITE: / 'Type I = ', qty_i.

Here are the test results: ‘5,400.123’ converts into 5400 (type I) and ‘0005400123’ (type N). Explanation lies in the depths of SAP Library. If you go to the ABAP help, then drill down to Basic Statements -> Process Data -> Type Conversions, there will be a link to the Type Conversions topic in SAP Library (for some reason this link is missing in the online version). From there click the hyperlink ‘Conversion Rules for Elementary Data Types’, then in the first table under N it reads:
Only the digits in the source field are copied. The field is right-justified and filled with trailing zeros.

So basically SAP takes all the digits from the CHAR field and puts them into N field, then adds leading zeros and – voila! – you get 5000 instead of 5. Since conversion from CHAR to I is working fine, obvious solution would be to define a temporary variable of type I and convert it there and then convert I to type N. But I found that a primitive multiplication by 1 does the trick as well:
qty_num = p_char * 1.

While I was on it, I’ve also tested how would rounding work: for example, ‘5.4’ (CHAR) will convert into 5 (I) but ‘5.5’ will convert into 6 (I). When multiplied by 1, conversion from CHAR to N works exactly like conversion from CHAR to I.

posted by Your Friendly ABAPer @ 20:28,
Direct link to this post

1 Comments:

At 16/4/09 00:20, Blogger zz said...

Your post rocks.
Don't stop posting.
Keep on adding new things!

 

Post a Comment

Links to this post:

Create a Link

<< Home