cancel
Showing results for 
Search instead for 
Did you mean: 

When using DateTrans the order in the queue causes error

Former Member
0 Kudos

Hello,

I have a map that is mapping an IDOC into an XML document. The idoc contains a reference segment called Z1EDP1C. The segment contains 2 fields IDDAT (identifier) and BEZ40 (which stores any kind of data).

My mapping uses equalsS to compare IDDAT to a constant value of 026. When it finds that value it uses DateTrans to modify the date format and place it in the corresponding field on the XML document.

My problem occurrs when there are multiple Z1EDP1C segments. As long as 026 is the last Z1EDP1C segment there are no problems. But when another Z1EDP1C segment follows it will try to use DateTrans on the field. So when that field contains a string "-" then it causes a Parse Error because it cannot format "-" into a date. It will surpress this field properly but only if it can pass the DateTrans successfully.

How can I work around this error?

Thanks,

Matt

Accepted Solutions (1)

Accepted Solutions (1)

former_member200962
Active Contributor
0 Kudos
So when that field contains a string "-" then it causes a Parse Error because it cannot format "-" into a date.

When we use DateTrans function we specify some source and target date formats (along with separators), now if in runtime this format is not followed and the date is passed with other format then the above error appears.

So you need to ensure that before the source value goes to DateTrans you should remove any unwanted string (like -) from the source data and then only pass it to the DateTrans function.

Or (if possible) ask the source system to send the date in one specific format.

Regards,

Abhishek.

Former Member
0 Kudos

Hi,

Maybe your mmapping needs some tweaks to make sure the right field will be processed, but I'd also suggest writing your own UDF to parse the date, so you can embbed internal checks (make sure input field has expected format with a regex for instance, trap DateFormatExceptions so you can do what needs to be done in this case etc)

This will make date handling more secure and flexible

Rgds

Chris

Answers (8)

Answers (8)

Former Member
0 Kudos

Sarvesh - I set a single space as the default in MapWithDefault. I am using the following mapping:

BEZ40 (context PO Item) -


| then

IDDAT (context PO Item)--


| equalsS -
| IfWithoutElse -
| dattrans-|target field

Constant(026)----


|

As you suggested I tried the following:

BEZ40 (context Z1EDP1C) -


| MapWithDefualt ( ) |----


| then

IDDAT (context Z1EDP1C)--


| equalsS -
| IfWithoutElse -
| dattrans-|target field

Constant(026)----


|

The resulting queue is as I described in my previous post. With no ShipDate entered for the PO Item.

Thanks,

Matt

Former Member
0 Kudos

Sarvesh - My understanding of contexts is not expert but it seems to me that the context needs to be at the PO Item level. Because the ShipDate is derived at the PO Item level.

When I used MapWithDefault using the PO Item level context on BEZ40 and IDDAT, I had the same error. MapWithDefault can not recognize the lack of a corresponding BEZ40.

When I used MapWithDefault and I set the context to Z1EDP1C. I did not get an error but I also did not have a date in the ShipDate field. The mapping queue result was:

<null> *grey color

Suppress *grey color

01202010 *White color

01202010 *grey color

Suppress *Dark grey color

But no date was placed in the ShipDate field.

Thanks for the suggestion but it does not seem to work for this scenario.

Matt

Former Member
0 Kudos

> When I used MapWithDefault and I set the context to Z1EDP1C. I did not get an error but I also did not have a date in the ShipDate field.

Have you double clicked the MapWithDefault function and put some default value in it? Because I cannot see your default value in below result.

When you set a default value then Suppress (grey color) will be replaced with that one.

> <null> *grey color

> Suppress *grey color

> 01202010 *White color

> 01202010 *grey color

> Suppress *Dark grey color

Former Member
0 Kudos

In the end I had to fix the issue with the IDOC. I would rather have been able to match up the fields in the contexts themselves but I could not find a way to make this work. I believe the best answer to this question was the suggestion to create my own UDF.

I am not convinced that is the only answer but I could not find another way.

Example:

PO

PO ITEM (1)

Z1EDP1C

IDDAT = 008

Z1EDP1C

IDDAT = 026

BEZ40 = 01102010

Z1EDP1C

IDDAT = 001

BEZ40 = -

PO ITEM (2)

Z1EDP1C

IDDAT = 001

BEZ40 = -

I have a mapping that looks for 008 and copies the BEZ40 to a field. Another one looks for 001 and copies the BEZ40 to another field. And finally I have a mapping that looks for 026 and then does a DateTrans before copying the results to another field (ShipDate).

With the above sample data the queue for the mapping Henrique suggested looks like this in the IfWithoutElse :

In: In: Out:

008 01102010 Suppress

026 - -

001 Suppress

Then of course the mapping tries to DateTrans the - and fails.

I will close this thread with the solution being a custom UDF but I would be interested to hear of any other potential solutions.

Thanks,

Matt

Former Member
0 Kudos

> In the end I had to fix the issue with the IDOC. I would rather have been able to match up the fields in the contexts themselves but I could not find a way to make this work.

It was very much possible with MapWithDefault funciton. )

I guess when you passed your source field to MapWithDefault it was either set to the hieghest context or you may have used RemoveContext before that.

Former Member
0 Kudos

Henrique - Thanks for the help.

In this case the document I am mapping to is a PO. The field I am mapping to is a custom "Z" field that was added to the Item level of the .xml file (ZShipDate).

PO

ITEM

Material

Quantity

Price

ZShipDate

ZRevisionNumber

mapped from

IDOC

E1EDP01 (item)

Z1EDP1C

In this case the segment z1edp1c is used in several places within the PO (and item). So I have the context set to the Item level E1EDP01 for this mapping. I want to pull the 026 to fill the shipdate and the 001 to fill the "ZRevisionNumber".

Is there a way to handle that situation? For this problem I plan to correct the null BEZ40 on the IDOC but I'd be interested to know if there is a work around to keep the IDDAT and BEZ40 using the same context within the IfWithoutElse statement.

Maybe I'd have to create my own function for this?

Thanks,

Matt

Former Member
0 Kudos

Sarvesh - Thank you for the suggestion, but it did not work. The problem is not that the field is empty but that BEZ40 does not exist in the 008 segment.

I am looking at ways to correct the idoc so we do not have this situation but I thought this problem must have happened to others. Is there no way to align IDDAT with its corresponding BEZ40 and if there is no corresponding BEZ40 to skip the mapping or force a constant value in place of the null value?

I have tried using the exists function but have been unable to make it work. Surely somebody has run into this type of problem in the past?

Thanks,

Matt

Edited by: Matthew Herbert on Jan 8, 2010 4:47 PM

Former Member
0 Kudos

As per my experience MapWithDefault works even though the field exist or not. There may some other mapping issue. May be some context retaled issue.

Try MapWithDefault with some other field (just for testing) and then delete the source field in test tab and see if you get the default value or not.

Former Member
0 Kudos

Suraj - The new mapping you suggested also di d not work.

I have found some additional details through trial and error. The first segment is the key to my problem. The data did not have a BEZ40 field. So the true data looked more like this:

In this case I have 3 z1edp1c segments as follows:

seg 1

iddat = 008

seg 2

iddat = 026

bez40 = 01012010

seg 3

iddat = 001

bez40 = -

When I add a BEZ40 to Seg 1 it works. Somehow in the IfWithoutElse function it is accepting the results as follows:

IfWithoutElse:in0 ifWithoutElse: in1 ifWithoutElse:out

False 01012020 -

True - suppress

False

So with that I can see that the "in1" is not reading a null value when BEZ40 is missing. So it shifts the values up to the previous segment.

How can I force PI to ignore an IDDAT that does not have a BEZ40?

Thanks,

Matt

Former Member
0 Kudos

> How can I force PI to ignore an IDDAT that does not have a BEZ40?

You can force PI to maintain the positions in queue just by using the MapWithDefault function, so that whenever bez40 is missing then it will be mapped with the default value (you can write any default value e.g. No_Data).

So if you use MapWithDefault then your entries will look like this..

IfWithoutElse:in0                ifWithoutElse: in1               ifWithoutElse:out 
False                           No_Data                           01012020     
True                            01012020                          suppress 
False                           -

Use MapWithDefault just after BEZ40 and use the rest of the simple mapping steps.

I am sure this will solve your problem.

Regards,

Sarvesh

henrique_pinto
Active Contributor
0 Kudos

Do you have a single field in the target message?

If yes, did you simply try to set the Context of both the iddat and bez40 fields to the root tag (parent of z1edp1c), instead of the default (which is probably the multiple z1edp1c tag)?

Just right click on both of them and go to the Context option.

It would be like this:

iddat[context=root idoc] --- equalsS --- IfWithoutElse --- DateTrans --- target field
                            /           /
               Constant[026]           /
            bez40 [context = root idoc]

If you have multiple occurrences on the target message, you may have to play with the context queues.

Something like this:

multiple tag:

iddat[context=root idoc] --- createIf --- target tag
                            /
               Constant[026]

inner target field:

iddat[context=z1edp1c] --- equalsS --- IfWithoutElse --- DateTrans --- target field
                          /           /
             Constant[026]           /
            bez40 [context = z1edp1c]

Best,

Henrique.

Former Member
0 Kudos

In this case I have 3 z1edp1c segments as follows:

seg 1

iddat = 008

bez40 = PC

seg 2

iddat = 026

bez40 = 01012010

seg 3

iddat = 001

bez40 = -

When I run this mapping:

BEZ40----


| then

IDDAT----


| equals | if -


| dattrans-|target field

Constant(026)----


|

I get the parse error. When I modify the segments and put Seg 2 after Seg 1 and Seg 3 I get no errors. If I place Seg 1 after Seg 2 I will get a parse error on "PC" because it will try to format that into a date.

So my problem is telling PI only to transform the data if the IDDAT field qualifies with the equalsS statement. For some reason it still tries the transform date function even when the data will be surpressed.

I can create my own custom function to skip the datetrans function when the field is not a date but I thought there must be a more standard approach to this problem.

Also, I tried using SplitByValue but that did not change the outcome.

Any ideas?

Thanks,

Matt

Edited by: Matthew Herbert on Jan 6, 2010 5:00 PM

former_member187339
Active Contributor
0 Kudos

Hi Matthew

Try to map like this


BEZ40-------------------------------| then
IDDAT--------------------| equals --| if ----|removecontext----| dattrans--|splitbyValue---|target field
Constant(026)----------|

Regards

Suraj

former_member187339
Active Contributor
0 Kudos

Hi Matthew,

Problem is with the mapping logic which you have maintained, try doing like this


BEZ40-------------------------------| then 
IDDAT--------------------| equals --| if -------| dattrans---|splitbyvalue--|target field
Constant(026)----------|

Regards

Suraj