I have the following set up in a Text component and it works great when it is initially added to the encounter but after the encounter is put on hold and then re-opened it produces an error. What can I do to prevent the error?
Current Medications:
{!fn fnPrettyMeds(){
local m4SummDashList = ""
local m4SummDashList2 = ""
local m4SummDashASort = ""
local m4SummDashArray = getfield(MEDS_AFTER("delimited"),"|","")
for i = 1, i <= size(m4SummDashArray), i = i + 1
do
m4SummDashArray[i] = getfield(m4SummDashArray[i],"^","")
m4SummDashList = m4SummDashList + (if m4SummDashList == "" then "" else "|" endif) + m4SummDashArray[i][1] + " ("+ m4SummDashArray[i][2] + ") " + tolower(m4SummDashArray[i][7])
endfor
m4SummDashASort = getfield(m4SummDashList,"|","")
m4SummDashASort = sort(m4SummDashASort,TRUE)
for z = 1, z <= size(m4SummDashASort), z = z + 1
do
m4SummDashList2 = m4SummDashList2 + if m4SummDashASort[z] == "" then "" else str(z) + ") " + m4SummDashASort[z] + HRET endif
endfor
return m4SummDashList2
}}
{'{if MEDS_AFTER() == "" then "No known medications" else fnPrettyMeds() endif}'}
Error that is produced when encounter is re-opened:
Current Medications:
{if MEDS_AFTER() == "" then "No known medications" else fnPrettyMeds() endif <-FUNCTION DEFINITION IS NOT EXECUTABLE
If it works okay when opened the first time, the function is probably falling out of scope. Try wrapping the function definition in {' [function definition] '} like you do with the call. So it starts with
{' {!fn PrettyMeds(){ .....
I have tried that and it doesn't solve the problem.
Hmm, I'll admit I have never done this before. For functions I want to use in a text component I place them in the userlib.txt files and they don't fall out of scope. I tried this though and it worked for me after putting it on hold.
{' {fn test(){ return "Hello World" }}{test()} '}
Darn. That didn't work for me either. Now I will have to admit that I have never done anything with the userlib.txt files before. Could you enlighten me on how that works or guide me to an educational source?
Can you turn on mel tracing (Ctrl-Alt-M) then reproduce the error. You can leave mel tracing off when you initially create the document, just turn it on before reproducing the error and then turn it off immediately after the error.
Either upload the trace file here or send me an email with it and I will take a look. Make sure you use a test patient.
Two things stand out:
1) Declare the variables 'i' and 'z' as local.
i.e.
local i
local z
Remember: ALWAYS account for and make local your function variables, otherwise they will creep into the global space and produce unexpected results.
2) I think another problem may be that the quotes are not ascii(34) characters. MEL is very sensitive to the curly single and double quotes. It looks like they are curly here, but that could just be the way they were typed in. Be certain they are the straight single and double quote characters. I used your outline, fixed the quotes, and it worked fine.
"" (good) vs. ”” (evil)
Bonus: On occasion, MEL does not properly assign values when being initialized as local. To avoid this, always declare local on one line and assign on a separate line.
i.e.
local m4SummDashArry = ""
m4SummDashArry = getfield(MEDS_AFTER("delimited"),"|","")
This works:
{!fn fnPrettyMeds()
{
local tmpStr = ""
local tmpStr2 = ""
local strBuf = ""
local strTemp = ""
local i
local z
strTemp = getfield(MEDS_AFTER("delimited"),"|","")
for i = 1, i <= size(strTemp), i = i + 1 do
strTemp[i] = getfield(strTemp[i],"^","")
tmpStr = tmpStr + (if tmpStr == "" then "" else "|" endif) + strTemp[i][1] + " ("+ strTemp[i][2] + ") " + tolower(strTemp[i][7])
endfor
strBuf = getfield(tmpStr,"|","")
strBuf = sort(strBuf,TRUE)
for z = 1, z <= size(strBuf), z = z + 1 do
tmpStr2 = tmpStr2 + if strBuf[z] == "" then "" else str(z) + ") " + strBuf[z] + HRET endif
endfor
return tmpStr2
}
}
Edit - forgot to address the main issue:
Lastly, the thing you are looking for:
The failure of the function when re-entering the udpate indicates that the function is no longer in memory , so you need a command to ensure it is added each time the update is opened. In other words, when an update is re-opened, the text component must be reloaded as well. The best method to do this is to use the library functionality in VFE (VFE auto-inserts the MEL needed for you).
Note: Use of the userlib.txt file places the function in the global memory space. I advise against the use of the userlib for occasionally used functions. Remember - the content of the user lib remains in memory, even after the udpate is put on hold (unlike a text component - aka function library). This means you have an increased risk of variable collision/hijacking and even crossing data between charts. Additionally, the more you put into the userlib, the more 'weight' the EMR must carry around doing what it does - this can become problematic if the load gets too large (think in terms of watcher/execution cost ratios on the CPU). One should only use the userlib.txt file if they are sure they can identify and mitigate the risks involved.
Hope this helps!
usrlib.txt are functions that are loaded into memory when Centricity first starts. It is best to put functions in here that you plan on reusing throughout Centricity. If you update the file you must completely exit Centricity before your updates will take effect.
Your trace file gives you the error that is actually causing the "FUNCTION DEFINITION IS NOT EXECUTABLE" error. The error causing it is:
COMPILER ERROR NEARBY: Expect LEFT CURLY BRACKET. Instead had ERROR after RIGHT PAREN
Unfortunately, I do not know what is causing this error. My first step would be to eliminate ALL white space after every close Parenthesis ")" and the next character then add the white space back in.
Hopefully Lee will comment again after seeing the trace file as he is the expert.
Hi Lee,
Can you take a look at this trace and see if anything stands out to you as what is causing the error?
I can get the text encounter to work correctly of I just use
{'{if MEDS_AFTER() == "" then "No known medications" else ccc_add_num_with_carriage_ret(MEDS_AFTER()) endif}'}
So if I can't make it work with the prettymeds function I am not at a complete loss. The providers just prefer the prettymeds function because it puts the meds in alphabetical order.
As Ryan pointed out, there are issues with the code itself. In the trace, the up-tack character (looks like and inverted-short capital T) appears in place of what should be blank spacing. This will cause MEL to fail since it has issues with that non-standard character set. Those issues translate into the inability to see trailing code and produce unexpected results.
Recommendation: Copy and paste all of the code into NOTEpad, copy it from notepad and paste it back into your text component. This will remove most hidden characters from the text. If you still see strange characters or simply want to be certain they are eliminated, you might consider rewriting the code in a fresh notepad session to ensure removal of all non-standard characters.
As an added measure, after copying the code out of the text component, delete it from the text component itself, close the text component, then reopen it and paste the 'cleaned' code back into it. This will aid in removing any hidden characters you missed in the initial removal. Alternatively, rewrite the entire text component in notepad and paste it into a new text component, to be sure.
Secondly, try moving the function definition itself outside of the watcher braces; i.e. change:
{'{fn fnPrettyMeds()
{
....
}}'}
To:
{fn fnPrettyMeds()
{
...
}}
Only keep the function call itself in the watcher braces but add a trigger to keep it active:
{'{fnPrettyMeds(MEDS_AFTER("delimited"))}'}
The function itself should remain in memory as long as the text component is added each time the update is opened. If it is not, then you should use the watcher braces as you have them.
Note that by adding the trigger to the function call, you ensure that the list is updated appropriately when the list changes, essentially making full use of the code being in a 'watcher status'.
I suspect that if that is done, the code may work as you are hoping.
PS: No expert here, just one who has struggled a tad longer than most. 🙂
You rock!! I was able to get it to work as shown below. I added it to the encounter so that it loads each time the encounter is opened and it works perfectly. I was previously just testing it by adding it to a blank encounter and then putting it on hold and re-opening. That is where I kept getting the error. Putting as part of the encounter fixed the problem. Thank you, Thank you!!
{fn fnPrettyMeds(){
local m4SummDashList = ""
local m4SummDashList2 = ""
local m4SummDashASort = ""
local m4SummDashArray = getfield(MEDS_AFTER("delimited"),"|","")
for i = 1, i <= size(m4SummDashArray), i = i + 1
do
m4SummDashArray[i] = getfield(m4SummDashArray[i],"^","")
m4SummDashList = m4SummDashList + (if m4SummDashList == "" then "" else "|" endif) + m4SummDashArray[i][1] + " ("+ m4SummDashArray[i][2] + ") " + tolower(m4SummDashArray[i][7])
endfor
m4SummDashASort = getfield(m4SummDashList,"|","")
m4SummDashASort = sort(m4SummDashASort,TRUE)
for z = 1, z <= size(m4SummDashASort), z = z + 1
do
m4SummDashList2 = m4SummDashList2 + if m4SummDashASort[z] == "" then "" else str(z) + ") " + m4SummDashASort[z] + HRET endif
endfor
return m4SummDashList2
}}
Current Medication List:
{'{fnPrettyMeds(MEDS_AFTER("delimited"))}'}
Excellent! Now, let's do one more thing to optimize the code.
Change the function definition header from:
fnPrettyMeds()
To:
fnPrettyMeds(strList)
Then change:
local m4SummDashArray = getfield(MEDS_AFTER("delimited"),"|","")
To:
local m4SummDashArray = getfield(strList,"|","")
This will limit the call to MEDS_AFTER to a single instance coming into the function making it more efficient (all those data symbol calls can weigh a database down). 🙂
One more note:
Localize (declare) those counter variables to avoid unexpected index issues in code outside of the function.
local i
local z