› Clovertech Forums › Read Only Archives › Cloverleaf › Cloverleaf › Newbie question
From ODS|D||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~~~
To ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~~~
Basically they want to change the second segment from a D to a S but only if the fourth segment has the code 83282. My question is would this best be handled via a tcl script or a xlate? At the moment I have no xlate built for this.
If it matters we are running version 5.7 of the engine.
Thanks for any help you can offer
Simple enough to do in an Xlate. Can be done either way though.
So his depends on your shop’s philosophy regarding whether you use Xlate or Tcl primarily for message transformation.
email: jim.kosloskey@jim-kosloskey.com 29+ years Cloverleaf, 59 years IT - old fart.
Well I tried my hand at creating a proc, I pilfered some of the code from other procs we have. The issue seems to be that the proc is not looping through each message type. Below is my code, ignore the puts commands those where for trouble shooting. I hope it is ok to post code in this forum
######################################################################
# Name: chg_ods_1_to_S_basedon_ods3
# Author: Chris Plummer
# Purpose: Translate ODS segment 2 from D to S based on segment 3
# Date: July 13, 2016
proc chg_ods_1_to_S_basedon_ods3 { args } {
keylget args MODE mode ;# Fetch mode
set dispList {} ;# Nothing to return
switch -exact — $mode {
start {
# Perform special init functions
# N.B.: there may or may not be a MSGID key in args
}
run {
# ‘run’ mode always has a MSGID; fetch and process it
keylget args MSGID mh
set msg [msgget $mh]
set outbuf “”
set field_sep [csubstr $msg 3 1] ;# HL7 field separator
set sub_sep [csubstr $msg 4 1] ;# HL7 subfield separator
set rep_sep [csubstr $msg 5 1]
set segmentList [split $msg r] ;# Get segments
puts “This is before the for each loop”
foreach segment $segmentList {
puts “This is in the first loop $segmentList”
if [cequal $segment “”] { continue }
puts “This is after the first if $segment”
set fieldsList [split $segment $field_sep] ;# Just in case
set segtype [csubstr $segment 0 3] ;# Get segment name
puts “This is the field sep $field_sep”
puts “this is the segtype $segtype”
if [cequal $segtype “ODS”] {
puts “This is after the second if segtype $segtype”
set fieldsList [split $segment $field_sep]
set ods_3 [split [lindex $fieldsList 3] $sub_sep]
set ods_1 [split [lindex $fieldsList 1] $sub_sep]
puts “The Patient Account is: $sub_sep”
if {[cequal $ods_3 “83282”]} {
set new_ods_1 “S”
# might not need this
set new_ods_1 [join $new_ods_1 $sub_sep]
set fieldsList [lreplace $fieldsList 1 1 $new_ods_1]
set segment [join $fieldsList $field_sep]
}
}
puts “This is the end of msg compare before the append”
append outbuf ${segment}r
} ;# end of ‘foreach’
# Put modified message ($newmsg) in message handle
msgset $mh $outbuf
lappend dispList “CONTINUE $mh”
}
time {
# Timer-based processing
# N.B.: there may or may not be a MSGID key in args
}
shutdown {
# Doing some clean-up work
}
}
# end switch mode
puts “end of switch mode”
return $dispList
}
That should be handled in an XLATE in most cases. It would be a simple IF statement with a nested COPY statement.
-- Max Drown (Infor)
I finally figured out my problem it seems my system does not like [cequal $segtype “ODS”] I used {$segtype == “ODS”} instead and it worked better. I had one or two other similar changes to make.
I assume handling it in a xlate would be more efficient though so I’ll work on that next.
To compare strings, consider using eq and ne instead of == and !=.
Also, note that the c-commands have been deprecated in favor of the string commands.
-- Max Drown (Infor)
Thanks for the info
Listen to what Max is telling you.
Also, for future reference, do not loop through all of the segments to get the segments you want. The lsearch command is much more ergonomic.
Also as stated the ‘C” commands are deprecated. Use string equal, string range, string index. etc.
As Max stated the eq or ne is preferred. When you use == or != on a string, that string must first be converted to a number.
Max or I either one could probably let you have some examples of code from the Cloverleaf classes if you think it would help.
I would recommend the Infor Tcl class. If you have ever written code in any language Tcl should be a breeze. All you need to do is become familiar with the Cloverleaf API’s
Thanks for the information Charlie. Do you happen to have a script using the lsearch that searches for a particular message segment? I would just like to see how it works. I’ll google the lsearch command to gather more information.
Here’s the reference page: https://www.tcl.tk/man/tcl8.5/TclCmd/lsearch.htm
An example:
set msg [split $msg r] ;# Convert the message to a list
set obx_segs [lsearch -all -inline -regexp $msg {^OBX} ;# Create a list of all of the OBX segments found in the message
foreach obx $obx_segs {
[code]set msg [split $msg r] ;# Convert the message to a list
set obx_segs [lsearch -all -inline -regexp $msg {^OBX} ;# Create a list of all of the OBX segments found in the message
foreach obx $obx_segs {
-- Max Drown (Infor)
Hi,
See attached tcl file with example of lsearch.
It is made to run stand-alone without the need of any example message.
You can run it inside the tcl interpreter (hcitcl ) using source example_lsearch.tcl
kind regards Marc
Marc Pleijers
Senior Integration Consultant
Enovation BV
The Netherlands
Here are a couple of examples from my old level 3 class. One using lsearch when you just want to look at the data and one where you want to change data.
The things to remember are:
If you use the -inline option lsearch returns the data else it returns the location
If you use -all it returns *ALL* locations or data as a *LIST* else it returns the location or data at the first match.
Be sure to treat a list properly!
Thank you both for these examples, will dissect them.
Thanks to your help I went from what I had to this new code which looks a lot better and works doing what was originally asked but alas they want more. If it is a supplement identified by the code 83282 (as before) they want me to copy the duration and frequency from the ORC segment section 7. I have them labeled orc_7_1 and orc_7_2. They would like these added to the end of the supplement name after the tilde. So in the example below it would be after the Glucerna~
ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~~~
I’ll keep at it but while I’m getting close I have not gotten the values to go where I needed them. I can place them anywhere in the message other than the repeating area in which they need to go. I was hoping someone has done something similar and could chime in.
Thanks again for any help you can offer.
proc changeHL7_ORC { args } {
[code]
proc changeHL7_ORC { args } {
A bit confused about the requirement.
“added to the end of the supplement name after the tilde”
There are three tildes after the supplement name. After which one? Will the supplement name always be in the last populated iteration?
Are each of the values placed after the supplement~ joined together or in separate iterations? would it look like:
ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~orc7-1~orc_7_2 or what?
FWIW, to understand it I cleaned up the code a bit and removed what I consider some superfluous stuff. No message to test with so may be some fat-finger errors
changeHL7_ORC { args } {
keylget args MODE mode ;# Fetch mode
set dispList “CONTINUE $mh” ;# Continue message
switch -exact — $mode {
start {
# Nothing speific
return “”
}
run {
keylget args MSGID mh
set msg [msgget $mh]
echo “this is the msg $msg”
set fsep [string index $msg 3] ;# Field separator (|)
set csep [string index $msg 4] ;# Subfield separator (^)
set rsep [string index $msg 5] ;# Repetition separator (~)
# List of segments
set seglist [split $msg r]
# Location of ODS segment (First one only)
set ods_loc [lsearch -regexp $seglist {^ODS}]
# Don’t need location of ORC, just the data
# Split into fields
set ORC [split [lsearch -inline -regexp $seglist {^ORC}] $fsep]
# Get ODS fields
set ODS [split [lindex $seglist $ods_loc] $fsep]
# ODS.1.1
set ods_1 [lindex [split [lindex $ODS 1] $csep] 0]
# ODS 3.1
set ods_3 [lindex [split [lindex $ODS 3] $csep] 0]
# ORC 7.1
set orc_7_1 [lindex [split [lindex $ORC 7] $csep] 0]
# ORC 7.2
set orc_7_1 [lindex [split [lindex $ORC 7] $csep] 1]
echo “this is orc_7_1 $orc_7_1”
echo “this is orc_7_2 $orc_7_2”
if {$ods_3 eq 83282} {
# Replace OBS.1 wit “S”
set ODS [lreplace $ODS 1 1 S]
# Put new ODS back in segment list
set seglist [lreplace $seglist $ods_loc $ods_loc [join $ODS $fsep]]
echo “this is new msg $newmsg”
msgset $mh [join $seglist r]
} else {
# Send original message
echo “Nothing to do”
}
}
return $dispList
}
Thanks Charlie and your ODS was a lot shorter than my ods_new and did the same thing. Sorry I was not more clear on the orc part but yes this is correct
ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~orc7-1~orc_7_2
but instead of the tilde in between the two orc values it would be a carat
ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~orc7-1^orc_7_2~~
I was off Friday so I going to try and see if I can get the message to combine like it should. I’m sure I’m just not rejoining the message correctly because of the repeating segment.
You still did not answer as to whether the supplement would always be the last populated iteration of ODS.3.3?
I am making some assumptions her but here is the way I would do it: I made a test message which may or may not be right so test it with yours
As I suspected I had some really dumb errors in what I sent before like misspellings and setting dispList before I even set mh. Stupid!
Anyway see if it helps. I have attach a simple proc with no header for you to test. Named it after you 😀
Good thing I get bored enough to do stuff like this. Rainy season over here 🙁
Thanks and now I see the reasoning for your question with your trim statement, I was trying to squeeze the values in between the repeating separators. I did not think to use trim and just append it. I’ll have some more test supplements ordered and see how it goes.
Worse case I go back to my method, which is not as elegant and I have your code to help me out in the future; but I believe your strategy will work fine.
Thanks once again.