Written by

Question Gary Lusso · Apr 10, 2025

HL7 control characters showing up - resolved

Business Process is adding control characters.

Input HL7 shows no control characters in Notepad ++

Output

Code:

Method FromCerner(pRequest As EnsLib.HL7.Message) As %Status
{
    #dim tStatus As %Status = $$$OK
    #dim eException As %Exception.AbstractException
    #dim tOBXText As %String
    #dim tItemNumberCount As %Integer = 0
    #dim tItemNumberProcessed As %Integer = 0
    #dim tTotalCostSegment As %Integer = 0
    #dim tOrderType As %String
    #dim As %Interger = 0
    #dim tOBXKey As %Integer = 0
    #dim tOBXTextChanged As %String
       ////
       Set pOutput = pRequest.%ConstructClone(1) // moved here because %ConstructClone() need only be done at the message object level.
       //$$$LOGINFO(pOutput_" ---- pOutput to see if clone is created****")
    // Set the message
    Set tMessageType = pOutput.GetValueAt("MSH:9.1")
    //$$$LOGINFO(tMessageType_" --- tMessageType check that pOutput works") ORM found
    //
    Try {
          // Message Subtype
          Set tMessageSubType = pOutput.GetValueAt("ORCgrp(1).ORC:1")
          //$$$LOGINFO(tMessageSubType_"----- tMessageSubType - = NW -- ") works
          // Check if OBR:19 contains "Implant Usage (PSAS)" OR "Issued in Clinic (PSAS)"
          Set tOrderType = pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBRunion.OBR:19(1).1")
          //$$$LOGINFO(tOrderType_" -- pOutput ???? -- tOrderType Ordder Type = Implant Usage (PSAS) for first interation")
       If ((tOrderType["Implant Usage (PSAS)") || (tOrderType["Issued in Clinic (PSAS)")) {
          // First loop: Count occurrences of "Item Number:"
          Set = 1
          Set tItemNumberCount = 0
          //
       While (pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX")'="") {
            // Find the number of segments that are Item Number
            Set tOBXText = pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5", .tStatus)
            //$$$LOGINFO(tOBXText_"**** "_i_" ---- tOBXText OBX 5 text and i value") // working
            //
                If (tOBXText [ "Item Number:") {
                Set tItemNumberCount = tItemNumberCount + 1
                     //$$$LOGINFO(tItemNumberCount_" ----- tItemNumberCount")
                                                                    }
            Set = + 1
        }    //end While loop
        //
        // Second loop: Modify OBX segments to remove "REASON FOR REQUEST"
        //$$$LOGINFO("SECOND LOOP for remove")
        //$$$LOGINFO(tItemNumberCount_" ----- tItemNumberCount")
        Set = 1
        Set tItemNumberProcessed = 0
           While (pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX")'="") {
               Set tOBXText = pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5", .tStatus) // using pOutput instead of pRequest
               //$$$LOGINFO(tOBXText_" ---- tOBXText get OBX 5 text")
            If (tOBXText [ "Item Number:") {
               Set tItemNumberProcessed = tItemNumberProcessed + 1
                                           }
            If (tItemNumberCount >= 1) && (tOBXText [ "REASON FOR REQUEST:") {
                Set tOBXText=$p(tOBXText,":",2,5) /// OBX 5 text parsed to replace in OBX 5 later
                // Start replacement process
                Do pOutput.SetValueAt(tOBXText,"ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5","set") /// Required
                //$$$LOGINFO(tOBXText_" ---- OBX 5 parsed to be saved in new OBX 5")
                //Set tOBXTextChanged = pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5") // NOT required
                //$$$LOGINFO(i_" **** "_tOBXTextChanged_" --- i --- tOBXTextChanged, Is OBX 5 changed???")
                Set = i
                
             //OBX|1|TX|2000.02^REASON FOR REQUEST^AS4|19||
             //Do pOutput.SetValueAt(tOBXText_"~~","ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5","set") //
                set segcnt = 0
             //
            If ((tOBXText[ "Total Cost:")) {
                Set tSegmentOBX = ##class(EnsLib.HL7.Segment).%New()
                Set tSegmentOBX.SegType = "2.3:OBX"
                Set tSC = tSegmentOBX.SetValueAt("OBX", 0, "set")
                Set tSC = tSegmentOBX.SetValueAt("1|TX|2000.02^REASON FOR REQUEST^AS4", 1, "set")
             //|1|TX|2000.02^REASON FOR REQUEST^AS4
                set count = 0
                set = +5
            If ('= (segcnt -4)) {
                Set tSC = pOutput.InsertSegmentAt(tSegmentOBX, z)
                                 }
                set segcnt = pOutput.SegCount
                set count = segcnt - 2
             //$$$LOGINFO(tOBXText_" *** "_z_" "_count_"***"_segcnt_" z ----count --- segcnt")
                Set tRemoveText = pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5", .tStatus)
             //$$$LOGINFO(i_" **** "_tRemoveText_"***"_z_"***"_count_"***"_segcnt_" --- i --- tRemoveText_ --- z ---- count --- segcount")
            If (segcnt - = 3) {
             //$$$LOGINFO(i_" **** "_tRemoveText_"***"_z_"***"_count_"***"_segcnt_" **** segcnt - 3 *** --- i --- tRemoveText_ --- z ---- count --- segcount")
                set tSC = pOutput.RemoveSegmentAt(z)
                                }
             //
             elseif (tItemNumberCount = 1) && (tOBXText [ "REASON FOR REQUEST:")
                {
                Set tOBXText=$p(tOBXText,":",2,5) /// OBX 5 text parsed to replace in OBX 5 later
                // Start replacement process
                Do pOutput.SetValueAt(tOBXText,"ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5","set") /// Required
                //$$$LOGINFO(tOBXText_" ---- OBX 5 parsed to be saved in new OBX 5")
                //Set tOBXTextChanged = pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5") // NOT required
                //$$$LOGINFO(i_" **** "_tOBXTextChanged_" --- i --- tOBXTextChanged, Is OBX 5 changed???")
                }
             }
            }
            Set = + 1
        }
    }
            //
        // Process ORM messages with subtype RE
        If tMessageSubType = "RE" {
            Set tResultType = pRequest.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp(1).OBX:11")
            If tResultType = "D" {
                $$$ThrowOnError(..ProcessPurgeDocumentToVista(pRequest))
            Else {
                $$$ThrowOnError(..ProcessNewDocumentToVista(pRequest))
            }
        }
        ElseIf (tMessageType="ORM") {
            //$$$ThrowOnError(..SendRequestAsync(..VistaTarget, pRequest, 1, "OutputCernerToVistaORM"))
            $$$ThrowOnError(..SendRequestAsync(..VistaTarget, pOutput, 1, "OutputCernerToVistaORM")) // Must use the object for the clone
        }
        ElseIf (tMessageType="ORR") || (tMessageType="ACK") {
            $$$ThrowOnError(..SendRequestAsync(..VistaTarget, pRequest, 1, "OutputCernerToVistaORR"))
        }
        Else {
            $$$ThrowOnError($$$ERROR($$$GeneralError, "Error: unable to process message from Cerner. Message type " _ tMessageType _ " received."))
        }
    }
    Catch eException {
        Set tStatus = eException.AsStatus()
        Set tStatus = $$$ADDSC(tStatus, ..CreateAndSendAlert(eException.DisplayString(), pRequest))
    }
    Quit tStatus
}/// /////////////////////////////////////////
/// ////////////////////////////////////////

Product version: IRIS 2023.1
$ZV: 2031

Comments

Gary M Lusso · May 15, 2025

Resolved

I was setting .tStatus as second paramter in: Set tOBXText pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5", .tStatus), which passed a one to anything that used the value. But I don't know why it created control characters because of it

0
Jeffrey Drumm  May 16, 2025 to Gary M Lusso

The 2nd argument to the GetValueAt() method is for delimiters, not status. The status is returned in the 3rd argument. The correct syntax for what you were trying to do is:

Set tOBXText pOutput.GetValueAt("ORCgrp(1).OBRuniongrp.OBXgrp("_i_").OBX:5", ,.tStatus)

Note the additional comma before .tStatus.

0