· Apr 12

Transform HL7 message to multi-line output flat file

I have a project where I will need to take an HL7 messages and transforms it into a multi-line flat file. I tried creating a complex record map but those require leading data to identify the record type I'm dealing with but based on the destination vendors spec they do not want any leading data prior to the actual data being sent. Also the lines in the output file require different pieces of data pull from different HL7 fields in the messages and in the third field in the flat file I need to generate a unique line number.

Any assistance would be greatly appreciated.

Sample HL7 message:

RQD|1|41|45452^SECOND ONE|5500^^SID|2|EA|10000||ISC|20200305

Sample flat file output:


Product version: Ensemble 2018.1
$ZV: Cache for UNIX (IBM AIX for System Power System-64) 2018.1.4 (Build 505_1U) Thu May 28 2020 10:11:51 EDT [HealthShare Modules:Core:15.032.9035 + Linkage Engine:15.032.9035]
Discussion (9)3
Log in or sign up to continue

I would recommend approaching this in three parts:

  1. Create a custom message class for your target system.
  2. Use a DTL to transform your HL7 into your custom message class
  3. Use a custom File Operation to write the file output based on your custom message class

For #1, this could be as basic as:

Class Demo.Messages.SystemX.CustomBody Extends Ens.Request

Property Param1 As %String;

Property Param2 As %String;

Property Param3 As %String;

Property Etc As %String;


For #2, your transform would then be something like:

And then for #3, your file operation would be something along the lines of:

Class Demo.Operations.SystemX.FileWriter Extends Ens.BusinessOperation

Parameter ADAPTER = "EnsLib.File.OutboundAdapter";

Property Adapter As EnsLib.File.OutboundAdapter;

Parameter INVOCATION = "Queue";

Method OnMessage(pRequest As Demo.Messages.SystemX.CustomBody, Output pResponse As Ens.Response) As %Status

	Set Line1 = pRequest.Param1_"|"pRequest.Param2
	Set Line2 = pRequest.Param3_"|"pRequest.Param4
	Set Line3 = pRequest.Param5_"|"pRequest.Param6
	Set outString = Line1_$C(13)_$C(10)_Line2_$C(13)_$C(10)_Line3_$C(13)_$C(10)
	Set fileName = "Filename"
	Set sc = ..Adapter.PutString(fileName_".dat",outString)
	Quit sc


Please note that the above is a super rough draft - there's no error handling, and you'd need to consider how you'd make the filename unique per message, but I'm hoping this gets you on the right path.

I went ahead and created a DTL that appears to do what you requested and does not require a custom File Operation to work; It assumes you're using EnsLib.File.PassthroughOperation as the outbound operation class.

The filename is created using the value set for target.OriginalFilename in Ens.StreamContainer in the DTL, so you could base it on something from the HL7 message itself or just set it to a static value (as I've done). You can use date/time tokens in the outbound operation's File Name field to aggregate multiple messages per file, or just let it create uniquely named files for each message with the default pattern.

Here's the DTL Configuration:

And the rules:

To test, I created a HL7 file with repeating ORC groups based on the sample provided in your post, but the DTL will work whether it's repeating or not:

The Filename pattern I used in the outbound operation:

This file was created:

And contained this output:

Hope this helps.

Hi Jeff

Thank you for your help, it’s always good to hear from you and your help is always appreciated.

Unfortunately, when I provided a copy of the output to the vendor they indicated that the spec I was provided was out of date and the new spec calls for a fixed length file. However, some of the fields need to be zero filed and other filed with spaces.

Example the second field in each line the file is location, that field length is five characters but left justified, in another example the quantity field is a total of 13 characters the first 9 are the whole number and the last 4 are decimal

10000ISC  00002020040120200305
10000ISC  000145452                    0000000020000EA

Hi Doug,

Looks like only two lines need to be changed in what I posted previously; they're numbered 20 and 26 in the screen shot. You'd use a combination of string concatenation and $EXTRACT(), along with $JUSTIFY() to line things up according to the specification. Alternately you can set the variables to the justified/aligned/padded version of the values extracted from the HL7 message and then just concatenate them without the pipe characters in lines 20 and 26.

If I have time over the weekend I'll take a stab at it, but if you figure it out beforehand, please post your solution here.

So I forgot that there's a Pad() method in the DTL function list that would likely work better for your purposes than $EXTRACT() and $JUSTIFY(). You can use it to zero or space fill the fields to the required width. The first argument is the value to pad, the 2nd the width (positive numbers for pad right, negative for left), and the 3rd is the pad character to fill with.

Your update to the requirements is incomplete; it doesn't specify what, if anything, goes in the 2nd (and subsequent) row(s) of the output after the ItemCodeExternal.Identifier value, whether the fractional value is in the Quantity field is right or left justified zero-filled, or whether the UnitofMeasure and DateNeeded values are padded to make line length consistent across all records.

Here's an example of what it might look like and will need to be adjusted to accommodate your vendor's spec:

The code rules that write the records to the stream would need to be adjusted to eliminate the "|" delimiters and insert the renamed/added variables:

This should get you to where you need to be.