Iatric Systems Webcast: Report Designer and NPR Tips ‘n’ Tricks

“An Old Dog is Still Learning New Tricks!” Joe Cocuzzo will present a variety of Report Designer and NPR tips and tricks, including (but not limited to):

• A Report Designer “search report for fields” equivalent
• Gray bars where you want them in RD
• “Two and a half tools” – a Rosetta stone of sorts for report writers using Magic NPR, C/S NPR, and RD
• Turn an NPR report into a procedure
• Exploit user activity data in a BAR report to track comments efficiently

Learn more and  register for this July 8 webcast, from 2-3PM ET.

 

NPR Tip (MAGIC or Client/Server) – Report to Download with “CSV” Extension Opens Immediately in Excel 

NPR Tip (MAGIC or Client/Server) – Report to Download with “CSV” Extension Opens Immediately in Excel

At MUSE 2014, the most popular “tip” was probably the demonstration of an NPR report that allows the user to send output to “DOWNLOAD” with a CSV extension on the file and two footnotes on the report allow the just created file to open automatically in Excel. No “End of Report” message to close. No need to find the report flat file and open with Excel.

All you need is a START footnote that suppresses the “END OF REPORT” message and a CLOSE.UP macro that closes the download file “early” and then runs Excel for the file just made by the report.

In MAGIC:

NPR Tip

NPR Tip

In Client/Server:

NPR Tip

If the user runs the report to a download file with the “.CSV” extension, assuming that file type is associated with Excel (almost always true), Excel will run automatically and open the file in a spreadsheet.

Notice that in both sets of footnotes, the name of the file is saved to a variable and then passed to either the %Z.link.to.shell program (MAGIC) or @Shell.execute macro (C/S).  That is because Z.rw.close.up(0) closes data file and dictionary prefixes and cleans up the temp file and if you don’t save the file name from slash to a variable, it won’t be there to pass to the program or macro after the “close up.”

The complete Powerpoint for our Tips and Tricks Session, all report examples (including this one) and some DR documentation of the DR example tip/trick are available here: http://www.iatric.com/MUSE2014

Try it. You’ll like it.

DR Tip -  Iatric DR SQL and Microsoft Reporting Services Tip ˜ Date Mnemonics

Thomas Harlan, Technical Team Lead – Data Repository at Iatric Systems

You’ve built a great query, wrapped it up in a beautiful Microsoft Reporting Services report and published it to the SSRS web portal, all ready for your end users to run anytime they want, with the parameters they want… perfection awaits!

  • Then the first user emails and says “how do I enter TODAY-1 in this report?”
  • And then the second user emails and says “how do I schedule this report to run for the last calendar month?”

And then you realize, to your horror, that Microsoft Reporting Services has a nice date-picker, but no equivalent of the MEDITECH Date Mnemonics, which make entering date parameters in NPR easy-peasy… and to schedule a report to run monthly, you have to set up a schedule for each month, with hard-coded dates!

That is when the Bill Gates dartboard comes out… but do not despair, we have a solution for you!

Note that this solution is specific to Microsoft Reporting Services. You can do the same in Crystal Reports/Business Objects but you can’t display the results of the date mnemonic like we do here.

First, we need a way to convert a date mnemonic string (like MB-1) into an actual date. Second, we need to pass that real date into your stored procedure that executes the query to get data for the report.

We wrote two versions of the date conversion code:

  • MIS_iatric_DateInterpreter_fn [code]
  • MIS_iatric_DateInterpreter_sp [code]

One is a function you can call inside your own queries, if needed, and the other is a stored procedure to call from the Parameter setup screen in Reporting Services. Both are available on the Iatric Systems Tip page. Both scripts assume you have a custom database container on your DR server(s) called zcus. If you have a different database container for custom code, you’ll need to update the script accordingly.

The function and stored procedure support these mnemonic patterns:

Mnemonic Pattern Notes

T

Today (t=today or datadate if passed, t+n, t-n)

W

Week (w=today or datadate if passed, w+n, w-n)

WB

Week Begin starting Sunday (wb, wb+n, wb-n)

WE

Week End ending Saturday (we, we+n, we-n)

M

Month (m=today or datadate if passed, m+n, m-n)

Y

Year  (y=today or datadate if passed, y+n, y-n)

MB

Month Begin (mb, mb-n, mb+n), relative to current date

ME

Month End (me, me+n, me-n), relative to current date

YB

Year Begin (yb, yb+n, yb-n), relative to current date

YE

Year End (ye, ye+n, ye-n), relative to current date

FYB

Fiscal Year Begin (fyb, fyb+n, fyb-n), relative to current date

FYE

Fiscal Year End (fye, fye+n, fye-n), relative to current date

WM

(wm,wm+n,wm-n, +/- n is months) Week of the Month (3rd Tue, 2nd Fri, 4th Thu, 5th Wed) returns date for @WeekNo for @sDayOfWeek in the month of current date

Once the function and stored procedure are in place, you can update your MS Reporting Services report like so:

Step Description

Screen Shot(s)

Update the report (RDL) to include two new parameters: cFromDate and cThruDate with a data type of Text (right-click Parameters > Add Parameter). DR Tip

DR Tip

In the Parameter listing use the Arrow icon on the Report Data header to move the two new parameters up before dStartDate and dEndDate. You want your date mnemonic fields to be active before the actual date parameters are. DR Tip
Add a new Dataset to the report (Right click Datasets > Add Dataset) to convert cFromDate into dStartDate.

On the Query screen, name it ConvertFromDateDs.

Set the Data Source to reports DR connection. Query Type is Stored Procedure. Then select or pick MIS_iatric_DateInterpreter_sp.

On the Parameters screen, set the Parameter Value for the @cDateIn parameter to [@cFromDate].

Click OK when done to save this dataset.

DR Tip

DR Tip

Add a second Dataset to the report (Right click Datasets > Add Dataset) to convert cThruDate into dEndDate.

On the Query screen, name it ConvertThruDateDs.

Set the Data Source to reports DR connection. Query Type is Stored Procedure. Then select or pick MIS_iatric_DateInterpreter_sp.

On the Parameters screen, set the Parameter Value for the @cDateIn parameter to [@cThruDate].

Click OK when done to save this dataset.

DR Tip

DR Tip

Now change the parameter properties for dStartDate (right-click dStartDate > Edit Parameter).

On the Available Values screen, select Get values from a query.

Pick ConvertFromDateDs as the Dataset.

Set the Value and Label fields to Result.

Switch to the Default Values screen and select Get values from a query.

Pick ConvertFromDateDs as the Dataset.

Set the Value field to Result.

Click OK to save your changes.

DR Tip

DR Tip

Make the same changes for dEndDate (right-click dEndDate > Edit Parameter).

On the Available Values screen, select Get values from a query.

Pick ConvertThruDateDs as the Dataset.

Set the Value and Label fields to Result.

Switch to the Default Values screen and select Get values from a query.

Pick ConvertThruDateDs as the Dataset.

Set the Value field to Result.

Click OK to save your changes.

DR Tip

DR Tip

You’re done!

Now when you run your report, the cFromDate and cThruDate fields — and the mnemonics entered there — will control what values appear in the dStartDate and dEndDate fields. Those two fields are then passed to the query when it executes.

DR Tip

Note that this approach does not require changing your query/stored procedure at all (assuming it has parameters for the date range) and leverages the pre-built function and stored procedure at the report level.

Extra Credit!

  • Try out hiding the dStartDate and dEndDate parameters (each parameter has a Visibility setting).
  • Expand the function to use additional mnemonic patterns of use to your site!

Cheers, Jen Kelly and Thomas Harlan

Visit our report library at http://www.iatric.com/Information/NPRReportLibrarySearch.aspx to look them up.

You can find additional Report Writing Tips on our website at http://www.iatric.com/Information/NPRTips.aspx, as well as information about our on-site Report Writer Training and Report Writing Services.

To subscribe for email notifications for new Report Writing classes, please follow this link:

http://www.iatric.com/Information/Classes.aspx.

For more information, please contact Karen Roemer at 978.805.3142 or email
karen.roemer@iatric.com
.

This article originally appeared in the June 2014 issue of Iatric Systems Updates! newsletter.

DR Tip – Finding fields across MAGIC/M-AT/DR Using the DR Data Def Tables

Thomas Harlan, Technical Team Lead – Data Repository at Iatric Systems

One of the challenges of DR-based report development is the same as for NPR or RD… where is the data you want stored? One way to find out is to go into MEDITECH and find the field, and – if you are lucky – you can do:

Platform Hotkey
MAGIC Shift-F8, down-arrow, down-arrow
Client/Server Shift-F9
MT6 Shift-F9

Which will get you a pop-up like this:

The top section shows you were the data element is in NPR or RD, and the bottom shows the Table (MisLoc_Main) and Column (Phone) in the DR.

This requires that you know what module/screen/field you want in the front-end, and that the field you cursor into is editable and it has a DR table/column attached. There is, however, another, more flexible, way to get at this information with SQL. In each DR database (livedb, livendb, and so on) there are two tables that hold the data definitions:

SysDrColumns
SysDrTables

Note that if you have more than one DR database (a MAGIC one, a C/S one, a M/AT one…) then you will have multiple versions of these tables. It would be convenient, therefore to have a single query (saved as a handy stored procedure) to query all of these tables for what you want.

So we’ve built: MIS_dd_query_sp to do just that. (A copy is in the library, set up for an MT6 site with a zcus database container to store the query in). If your custom database container is not named zcus, you’ll need to edit the script appropriately. You will also need to update the code to reflect your database container name(s) for LIVE. The example uses Livendb and Livefdb, as they are common, but your specific implementation may vary.

Once the script has been run and the query translated and saved into the database, you call the query like this:

EXEC [zcus].[dbo].[MIS_dd_query_sp] ‘%MisLoc_Main%’ — Table Name
,’%Phone%’ — Column name
,’%’ — DPM Name
,’%’ — Segment Name
,’%’ — Element Name
,’%MIS%’ — Application Name
,’Livendb’ — NPR Schema
,’Livefdb’ — Focus Schema
,0 — 1 is only table name, 0 is all columns

The first set of parameters:

@cTableName
@cColumnName
@cDpmName
@cSegmentName
@cElementName
@cApplication

…are set up in the query to do wildcard search, where you can use % for any number of characters and _ for a single character.

The next two parameters:

@cNPRSchema
@cFocusSchema

…are a convenience – they let the query build a fully-qualified table name (container.owner.tablename) in the query results, so that you can copy and paste that field into your code. A time saver!

The last parameter:

@nMode

Changes the output arrangement of the query. If you set this to 1, then you get a listing of only the Table Name and the Module the table(s) were found in:

DR_TABLE_NAME

MT_APP

Livefdb.dbo.MisLoc_Main

MIS

If a zero (0) then you get a listing of each column that matches your criteria, as well as supporting detail.

DR_
SOURCE
_ID

DR_TABLE
_NAME

DR_
COLUMN
_NUMBER

DR_
COLUMN
_NAME

DR_
COLUMN
_TYPE

DR_
COLUMN
_LENGTH

MT_
APP

NPR_
DPM

NPR
_SEGMENT

NPR
_ELEMENT

IAT

Livefdb.dbo.MisLoc_Main

7

Phone

varchar

40

MIS

MisLoc

Main

3

Note that this listing includes both the DR location and the RD location (MisLoc.Main.3). This stored procedure does triple duty, letting you do wildcard searches against all three data-definitions (DR, NPR and RD). But beware! These data-defs only include elements that are in the DR.

Notes

MT also publishes the NPR and RD datadefs on-line:

NPR

https://customer.meditech.com/en/d/prwrw/pages/rw6basdatadef.htm

MT 6 DR

https://www.meditech.com/prdr/Pages/DRxbASTables.htm

CS DR

https://customer.meditech.com/en/d/prwdr/pages/drcbasdbmodels.htm

MAGIC DR

https://customer.meditech.com/en/d/prwdr/pages/drmbasdbmodels.htm

Often you can find what you’re looking for by browsing the models. If you find the data element is in NPR, then you can use the search query to find the matching DR table/column.

Extra Credit

This version of the query only handles two database containers – maybe you only have one! Or maybe you have three, or more… You can easily copy/paste the code inside of the example SP to handle multiple databases.

If you have SQL Server Reporting Services or Crystal Reports you can then easily built a report to manage the presentation of the data and prompt your analysts for what they are searching for.

Visit our report library athttp://www.iatric.com/Information/NPRReportLibrarySearch.aspx to look them up.

You can find additional Report Writing Tips on our website at http://www.iatric.com/Information/NPRTips.aspx, as well as information about our on-site Report Writer Training and Report Writing Services.

To subscribe for email notifications for new Report Writing classes, please follow this link:

http://www.iatric.com/Information/Classes.aspx.

For more information, please contact Karen Roemer at 978.805.3142 or email karen.roemer@iatric.com.

This article originally appeared in the May 2014 issue of Iatric Systems Updates! newsletter.

NPR Tip (MAGIC) – Default Segment and Directory in “MOVE REPORTS”

Joe Cocuzzo, Senior Vice President – Report Writing Services

Last month we had a Client/Server only tip about a handy Page 1 of N utility. At MUSE our Tips and Tricks session will include an updated version of an approach that will do this for MAGIC NPR reports as well.  For this May tip, I will show you how to solve the minor annoyance of having to guess about the NPR master segment and directory for the MOVE REPORTS routine.

Anyone who works at multiple hospitals, or who forgets the exact combinations of dots and numbers cooked up in the naming of the latest test directory, has experienced the fun of guessing for the NPR Master Segment and NPR Directory in the MOVE routine. If you are in an HCA site, you have the added fun of dealing with segments with long cryptic names, instead of the typical A..B..C – you might have 50 choices from TNNANVA  to TNNANVZX.

This month, we will show you a report you can place on a Hot Key menu for NPR that you can use to quickly find out the name of the NPR master segment and directory you need to use for the MOVE routine.

The first problem is how to know about segments and directories you aren’t in. What if we take a look at MIS.signon and see how that program does it? After all, when you manage a device to that program, the user sees a list of both LIVE and TEST directories.

Just hit F4 while editing any macro of any report and look at the MEDITECH source code of MIS.signon, like so:

We see in this program that MIS.signon loops through NPR.MIS.DB.npr.mis.remote.index to show the user a list of “npr.mis.remote.title” fields to pick from.

Even though we cannot use the DPM NPR.MIS.DB on page 1 of a report, we can see its segments and fields in a macro with F9, and we can write code to loop through the entries and build an MV array for our report.

(Note to C/S report writers, the C/S field lookup program will not show you DPMs unless they are flagged Customer Report Writer access = Y. You can still use them in macros, but you have to figure out the names from listing MEDITECH reports or getting to the data definitions by other means.)

So, if we write a report in NPR.REP in the npr.rep.main segment and set up the selects to just print one record like this:

This is just a “trick” to force the report to select exactly one record by selecting the last report urn, regardless of what that is.

Then build an MV array in the picture:

Then write a macro “detail” to be called from an AL D footnote:

The macro does the same looping as MIS.signon, but show the user segment and directory rather than MIS title information:

Here is the report output. Notice the current segment/directory is flagged in the third MV column.

The report NPR.REP.zcus.is.move has been loaded to our MAGIC NPR report library. So you can just grab it “as is” and use it on your custom hot key menu attached to the NPR application.

Visit our report library at http://www.iatric.com/Information/NPRReportLibrarySearch.aspx to look them up.

You can find additional Report Writing Tips on our website at http://www.iatric.com/Information/NPRTips.aspx, as well as information about our on-site Report Writer Training and Report Writing Services.

To subscribe for email notifications for new Report Writing classes, please follow this link:

http://www.iatric.com/Information/Classes.aspx.

For more information, please contact Karen Roemer at 978.805.3142 or email 
karen.roemer@iatric.com
.

This article originally appeared in the May 2014 issue of Iatric Systems Updates! newsletter.

C/S NPR Tip & DR/SQL Tip

Joe Cocuzzo, Senior Vice President – Report Writing Services

This month we have a quick tip for NPR fans (Client/Server only) and a SQL /DR tip written by Thomas Harlan my DR Technical Team Lead.  If only we had a RD tip, we’d have a trifecta.

C/S NPR Tip: Page 1 of N via MEDITECH utility program

We recently found out that MEDITECH has a utility you can call from the footnote of a report and print a Page X of Y message on your NPR reports. The utility is called:

%Z.rw.page.count(XPOS,YPOS,STRING) where

XPOS = KB article and program say this is X dot position @300DPI, but I think it is COL

YPOS = KB article and program say this is Y dot position, but I find it to be line of page header with first line =0

STRING is an option string to use for message, default is Page XX of YY, but you could send “Pg XX with exciting conclusion on YY” if you wanted a different message.

MEDITECH has a KB article on the utility: 47296. This utility is very handy, although it is not sufficient compensation for other sins of the Print Manager in C/S (no trays, no legal size paper, no print direction, no overlay macros, and so on).

Neither MAGIC nor RD has this feature. Years ago, we showed a way to do this for MAGIC that involved diverting print output to a file and doing a search/replace and then sending the data out to the printer. Back then (before print on VIEW), this worked even when spooling or downloading, but the technique needs updating for MAGIC to cope with spooling’s multiple SAFs (one per page to support VIEW).  Stay tuned for an updated MAGIC report showing how to do Page X of Y including when spooling.

If you just stick a footnote on your report like this:

You’ll get this on your page header:

DR/SQL Revamping ADM Patient Events into Patient Flow

One of the challenges in working with data structures developed for NPR (or M/AT) in the DR is that both NPR and M/AT retrieve data via a loop, while DR expects things to be arranged so they can be fetched in a set. A good example of this is AdmVisitEvents.

AdmVisitEvents has multiple kinds of data embedded within one table, including when the patient is bedded, and then moved from room to room, and then discharged.

Inevitably you’ll need to pull an inpatient location at a point in time and there won’t be a handy field with the Location/Room/Bed where the patient was when something occurred. And when you turn to AdmVisitEvents to find that situational information… you realize that the structure of the table is just not what you want.

The immediate way to get the patient Location is to embed a sub-query into your main SQL SELECT to fetch the patient Room:

SELECT TOP 1 AVE.LocationID

FROM   Livedb.dbo.AdmVisitEvents AVE

WHERE RX.SourceID = AVE.SourceID

AND RX.VisitID = AVE.VisitID

AND  AVE.UndoneSeqID IS NULL

AND  AVE.EffectiveDateTime <= RXA.AdministrationDateTime

AND  AVE.LocationID IS NOT NULL

ORDER BY AVE.EffectiveDateTime DESC, AVE.EventSeqID DESC

(In this snippet, we’re starting from PhaRx (RX) / PhaRxAdministrations RXA) to find the patient unit at the time of a medication administration.)

This answers the immediate question — where was the patient at the time of the administration. But it has issues… first, with a sub-query structured this way, we can only get one (1) field back (LocationID), and second, we have to create a loop in SQL (which SQL does not perform terribly well) with that ORDER BY and TOP 1 structure.

If we wanted to get LocationID, RoomID, and Bed in three separate fields – we would have to do three sub-queries, each returning one field. And as we add more sub-queries, the performance of our report begins to drop off precipitously!

What we want instead is a way to get at the AdmVisitEvents data so that we can JOIN to a table where each patient flow event (a stay in a location/room/bed) is in a single row, so we can do something like:

LEFT JOIN #tFlow ADT ON ( ADT.VisitID = RX.VisitID

AND ADT.SourceID = RX.SourceID

AND RXA.AdministrationDateTime >= ADT.FromDateTime

AND RXA.AdministrationDateTime <= ADT.ThruDateTime )

That is very clean! And now any field we need from #tFlow, we can reference in our query via the ADT alias — and since no sub-queries are involved, it’s fast.

The challenge now is creating this #tFlow table when we need it. And we only want to write that code once, in a reusable way. We need either a stored procedure or a table-valued function to go process AdmVisitEvents for us and create a nice flattened temporary table we can use.

You can download a copy of IatricPatientFlow.sql from iWeb and implement it on your DR server to get a pre-packaged function to do just this. That table-valued function works like so:

  1. First we look for any patient in-house during the date range we are interested in.
  2. Then we take that list of patient visits and fetch all of their Events into a temp table. When we do that, we only look for Events with a Location, that are not un-done, are not ‘FIXED’ records, and there are some kind of Event codes that are excluded.
  3. We sweep that raw list of Events and look for events where there is a change of location or status, and we create yet another temp table that captures the start and end times of the patient being in a specific place.
  4. Finally we create our nice summary table and address some data quirks where the last patient status isn’t correct (unless we correct it… ) and extra discharge rows are discarded.

That process takes a set of Event data that looks like this:

EffectiveDateTime

NewLocationID

NewRoomID

NewBed

NewStatus

OldLocationID

OldRoomID

OldBed

OldStatus

2014-01-20 18:29:00

ED

REG ER

2014-01-21 03:22:00

IC

ICU01

1

ADM IN

ED

REG ER

2014-01-21 21:50:00

M/S

MS24

1

ADM IN

IC

ICU01

1

2014-01-22 05:17:00

IC

ICU01

1

ADM IN

M/S

MS24

1

2014-01-22 14:50:00

M/S

MS16

1

ADM IN

IC

ICU01

1

And makes it look like this:

FromDateTime

ThruDateTime

VisitStatus

LocationID

RoomID

Bed

StayInMinutes

2014-01-20 18:29:00

2014-01-21 03:21:59

REG ER

ED

MS16

1

533

2014-01-21 03:22:00

2014-01-21 21:49:59

ADM IN

IC

ICU01

1

1,108

2014-01-21 21:50:00

2014-01-22 05:16:59

ADM IN

M/S

MS24

1

447

2014-01-22 05:17:00

2014-01-22 14:49:59

ADM IN

IC

ICU01

1

573

2014-01-22 14:50:00

2014-01-26 12:15:00

DIS IN

M/S

MS16

1

5,605

At any given point in time during the stay, we can then immediately find which Location, Room, Bed, and Status. We also get a summary of the time spent in the location.

To use this, in your reporting stored procedure (you are using a stored procedure for each report, aren’t you?) you create a little on-the-fly temp table:

SELECT ADT.*

INTO   #tFlow

FROM   zcus.dbo.IatricPatientFlow( ‘IAT’      — Change to your site SourceID to test

,’IATRIC’  — Change to your facility ID to test

,’2014-01-01′

,’2014-01-31′ ) ADT

;

And then use the JOIN above to bring that data into your query.

Don’t forget to clean up afterwards at the end of your stored procedure!

DROP TABLE #tFlow ;

Performance Note: The patient flow function runs at a test site, with 1.3 million rows in AdmVisitEvents, for a month of visits, in three seconds. It could have a bit better performance after being recast as a stored procedure using temp tables (rather than variables) inside IatricPatientFlow, but then it would require more setup and cleanup code, and could not be nested as deeply as a function.

Extra Credit! You can adapt the code to break out the patient by the day, calculating their stay in each location by day, which then makes calculating Patient Day Equivalent metrics for Nursing Quality Measures very easy.

The SQL code has been uploaded to our report library as IatricPatientFlow.txt.

Visit our report library at http://www.iatric.com/Information/NPRReportLibrarySearch.aspx to look them up.

You can find additional Report Writing Tips on our website at http://www.iatric.com/Information/NPRTips.aspx, as well as information about our on-site Report Writer Training and Report Writing Services.

To subscribe for email notifications for new Report Writing classes, please follow this link:

http://www.iatric.com/Information/Classes.aspx.

For more information, please contact Karen Roemer at 978.805.3142 or email
karen.roemer@iatric.com
.

This article originally appeared in the April 2014 issue of Iatric Systems Updates! newsletter.)

Report Writing Tip: March 2014 – Run Report for Period without prompting for date range (Client/Server or MAGIC)

Joe Cocuzzo, Senior Vice President – Report Writing Services

Run Report for Period without prompting for date range (Client/Server or MAGIC)

It is common to have a report that should be run for a GL period (here we assume this is a calendar month) and the easiest way to program this is to prompt for a date range and let the user figure out how many days in the month. You can add some error checking to reject an ending date that is not the last day of the month with an “FCL” attribute, but another approach would be to prompt them for the GL period and write some code to get the start and end dates based on the period selected.

This month we will show you how to add this programming to your report in a “start” macro and, for extra credit, show how to have the report run automatically for the prior month for the case where it is scheduled to run after month end.

First we set up a report with a date based index, in this example we want to go through BAR transactions in BAR.BCH:

MAGIC:

NPT Tip

Client/Server:

NPT Tip

Next we set up selections to prompt for a period, to restrict to “RCP” transactions, and to limit the report to a date range we will create from the GL period selected.

NPT Tip

We need to write a small “start” macro to use the period that the user has selected to put the start date of the period in /FROM and the end date in /THRU.

When you prompt for field, the value supplied by the user at run time is stored in the temp file and the value is stored in a variable which has a name based on a “b”, “c” or “e” based on the selection operator. “b” for GT and GE. “e” for “LT and LE” and “c” for EQ or IG. When you are prompting for a field that is in some other DPM (not the DPM of the report), the screen translator puts the “b”, “c”, or “e” after the DPM.

So we will have the user selected period in MIS.GL.PERIOD.c.period.

All we need to do is to put that value into MIS.GL.PERIOD.period (the subscript of the GL period dictionary) and then we have the ending date in @MIS.GL.PERIOD.ending.date to put into /FROM.

Then cut the YYYYMMDD off  that value (using $6) and add a “01″ and you have the start date to put in /THRU.

NPT Tip

Then add a footnote to call the macro at “START”

The AL = ALGORITHM, the START is where the code gets called and “start” is the name of the macro on this report that is going to be incorporated into the report program by the translator at the “start” point (after printer and some report setup, but before any looping on indexes and record selection).

NPT Tip

You might think this footnote is from the Department of Redundancy Department, but it actually is far better (in my opinion) to name your macros based on where they are called (or included in report translation) than with some invented name about what they do.

Two advantages:

  1. If you look at a report written by someone else, you know that a macro called “detail” is called per record. If you see a macro called “guts” and another called “process” what does that tell you about where the code is executed?
  2. After you write the macro and are about to write the footnote reference, with my method you do not have to remember what you just called the macro, you just have to remember what you always would call it.

Extra Credit:

What if you schedule the report for the 5th day of the next month, allowing five days for any Month End snafus. How can we have the report run from the scheduler and automatically run for the prior month?

There is a scheduler convention to run for a calendar month, including a way to run for the prior calendar month, but I do not think there is a “prior period” convention, so we’d need to created a date range prompt version of the report to get that functionality.  Instead, we can schedule the report with no period selected and modify our macro code to automatically run for the prior month.

In keeping with the MEDITECH practice of creating small annoying differences in the report writer between platforms, if you use the IG operator in MAGIC, the fields remains required, but if you use IG in C/S the field is optional.  So, in MAGIC we need to go into the “Edit Elements” routine and change REQ=1 to REQ=N or REQ=”” to avoid:

NPT Tip

NPT Tip

NPT Tip

If we look at the C/S version of the report we see that the screen translator has already done things this way for us:

NPT Tip

Now we need to modify our “start” macro so we use the MIS.GL.PERIOD.c.period selected if the report was run by the user (and a period was selected) or we use the current date and figure out the prior month if no period is selected. This adds a bit of convenience for the user because if they typically run for the prior month, then they can just leave the period blank and run the report and it will automatically do this.

First we write an IF statement and call two “sub-macros” based on whether we detect a period in the temp field or not. The way to break your macro into sub-macros is to call the submacro using an @ sign followed by some label, which should be all upper case with no spaces. Then these submacros are in the macro code separated by a single blank line and the same label with no leading @. This makes your code more readable and easier to maintain. Also you can use the same sub-macro in multiple places. You can nest these calls and have a macro call a sub-macro which then calls another sub-macro.

Warning – do not create infinite recursion like this:

IF{CONDITION  @SUBMACRO}

SUBMACRO

@DO.STUFF

DO.STUFF

@SUBMACRO

If you do this, your translation will crash. If you submerge the translation, you can run your (MAGIC at least) system out of space.

Here is our new macro (C/S version, but MAGIC is identical) with the code to run for either the selected period or the prior month when no period is selected:

NPT Tip

So if we run the report for no period:

NPT Tip

Or if we run the report for a user-selected period:

NPT Tip

This example report BAR.BCH.zcus.is.eupdate.run.for.period has been uploaded to both our MAGIC and C/S report libraries.

Visit our report library at http://www.iatric.com/Information/NPRReportLibrarySearch.aspx to look them up.

You can find additional Report Writing Tips on our website at http://www.iatric.com/Information/NPRTips.aspx, as well as information about our on-site Report Writer Training and Report Writing Services.

To subscribe for email notifications for new Report Writing classes, please follow this link:

http://www.iatric.com/Information/Classes.aspx.

For more information, please contact Karen Roemer at 978.805.3142 or email
karen.roemer@iatric.com
.

This article originally appeared in the January 2014 issue of Iatric Systems Updates! newsletter.)

Report Writing Tip: January 2014 – NPR Hot Key Report to See Activity (MAGIC only)

How often do you need to go change something about “the census report” only to go into Process Reports and see the following in your lookup:

Image

Most of you know that you can get out of Process Reports, and then go over to #57 “List Report Usage” on the customization menu:

Image

It isn’t terribly convenient to go over to this other option, and then deal with the never wanted BEGINNING/END defaults that MEDITECH application programmers like to include in standard reports:

Image

We can delete out the BEGINNING and type in the first of our list of suspects, then delete out the END and put in the last of our list (assuming no squirrels have run past our office window, causing distraction and loss of report internal name from short term memory).

Image

For the MAGIC platform, we can create a report in NPR.REP that can go on an NPR “hot key” menu and automatically use the last DPM and last procedure from the temporary file to provide an much more convenient activity list.

Image

We write our NPR report in the usage log segment:

Image

We can take advantage of the “spacebar – return” feature of Process Reports on the MAGIC platform, where the last DPM and the last procedure edited are kept in /.SV.DPM and /.SV.PROC respectively.

We set up selections on Page 2 for a report range:

Image

Then we can use the “Edit Elements” routine to add custom defaults.

Image

For the start of the default range, we use this:

Image

Note that unlike for CDS default attributes, you use DFT2 (not DFT).

For the end of the range we add a “zzz” to the procedure, and loop backward 1x on the procedure global to be likely to get all the copies of the report without having to type our own range.

Image

If we go to our hot key menu while editing “ADM.PAT.zcus.is.census.report”,” we get the following default range of reports:

Image

We build a simple report to list the title and procedure urn in a header and the saved activity in the detail line. We need to use two computed fields to deal with the fact that the run.time field is an “S(0)” time stamp, holding the number of seconds since March 1, 1980. To change this into a date, we use the Z program %Z.date.in.magic(run.time) in a “DATE” type computed field:

Image

You might wonder why there is no @ sign on the field @run.time. You can actually write it either way, since it is a subscript of the report activity segment, @run.time and run.time (with no @ sign) translate to exactly the same local variable.

For an HHMM (time) field from the S(0) run.time value, we use %Z.time.out(run.time):

Image

The @run.user and @run.dir are just fields and we can use the possessive @run.user’s.name also.

When we run the report for the default range, we can see that the ADM.PAT.zcus.is.census.report2 is the current version:

Image

The NPR.REP.zcus.is.hot.key.report has been uploaded to our MAGIC report library. Unfortunately, Client/Server does not have “hot key” menus and does not have the “spacebar return” recall feature. You can launch a new MEDITECH session from the session management button, but managing to peek back at the original session and figure out which report was being processed is just too hard, sorry!

Visit our report library athttp://www.iatric.com/Information/NPRReportLibrarySearch.aspx to look them up.

You can find additional Report Writing Tips on our website athttp://www.iatric.com/Information/NPRTips.aspx, as well as information about our on-site Report Writer Training and Report Writing Services.

To subscribe for email notifications for new Report Writing classes, please follow this link:
http://www.iatric.com/Information/Classes.aspx.

For more information, please contact Karen Roemer at 978.805.3142 or email karen.roemer@iatric.com.

This article originally appeared in the January 2014 issue of Iatric Systems Updates! newsletter.)

Report Writing Services: December 2013 – NPR Sunday Puzzler solved with NPR report (MAGIC example)

Joe Cocuzzo, Senior Vice President – Report Writing Services

NPR Sunday Puzzler solved with NPR report (MAGIC example)

There is a “Sunday Puzzler” feature of Weekend Edition on NPR Radio on Sundays. The host is Will Shortz, crossword editor of the New York Times.  Occasionally, he provides a puzzle that can be solved by exploiting MAGIC string operators and the spell check dictionary, or this week, using the Zip code dictionary and a specially rigged MPI.

The listener challenge from December 8th; deadline for submission Thursday, December 12th at 3pm ET.

“Next week’s challenge from listener Pete Collins of Ann Arbor, Michigan: Name a U.S. city in nine letters. Shift the third letter six places later in the alphabet. Then shift the last letter seven places later in the alphabet. The result will be a family name featured in the title of a famous work of fiction. What is the city, and what is the family name?”

We have, in effect, a dictionary of US cities in the MIS.ZIP dictionary and we can check the MRI name index for a last name match to find family names that might solve the puzzle. We will need to cheat a bit on the last count.

First we write an MRI.PAT report using the “actual.name.index” as follows:

Image 1

We set up the report so that we do an LI selection against a list of last names:

Image 2

Next, we write a start macro that loops through all the zip codes in MIS.ZIP, picking out all the cities that are nine characters long, and then changing the 3rd and the 9th character as specified and trying to match that new string to any last names in the MPI.

If we get a match, we will build a structure like this:

CITY^/LAST[NEWSTRING]  where NEWSTRING has a 3rd and 9th character changed per the puzzle rules.

Hint: I started the report at a hospital in Oregon that appeared to have a complete Zip code dictionary, but found it lacking and had to move the report to a Michigan hospital to solve the puzzle.

The first part of the macro creates a list of nine character cities in a temporary array:

Image 3

Remember that MAGIC numbers characters in a string starting from zero, so when we need to change the 3rd and 9th characters, we get the characters like this:

CITY#2 = third character

CITY#8 = ninth character

Before we change the string, we change it to all upper case like this:

@MIS.ZIP.city~$L.TO.U^CITY

The ~ is the translate operator and the $L.TO.U is a system string for MAGIC hospitals that will allow the translate to change a to A, b to B, and so on.

In C/S you would use the @Trl2u function like this:

@MIS.ZIP.city@Trl2u^CITY

We are supposed to move six down the alphabet for the third character (A becomes G, for example) and seven down the alphabet for the ninth character.

If we take the E(ncode) value of the third character and add six and then take the D(ecode) of that number, we will move six “down” the alphabet.  To avoid going past “Z” we check to make sure we are under 91 in the ASCII table.

We make a new string “NEWCITY” by using the $ and % operators to take everything to the left of the 2nd position $2, concatenating the new third character, then concatenating everything to the right of the 2nd position.

We do the same thing with the 9th character, but adding seven rather than six.  Because this is the last character, we can just do NEWCITY$8_CHAR^NEWCITY to make the final change.

Image 4

The final step is to use the new string in the actual name index as the “last.name.indexed” subscript and use the @First() operation to see if there are any patients with that last name in the MPI. You could also use @Next if you did it like this:

NEWCITY^last.name.indexed

“”^first.name.indexed,

IF{@Next(first.name.indexed,@actual.name.index) CITY^/LAST[last.name.indexed]}

@First loops from nil and does not assign back to the subscript

Looking at the object code for @First vs @Next will illustrate:

Image 5

If we run this report in just the right hospital (with a certain city in the Zip code dictionary) and just the right set of folks in the MPI, we can solve the puzzle:

Image 6

You have until Thursday 3pm ET to submit an entry.

I actually gave up on the cities in the Oregon hospital’s zip code dictionary after reviewing all the changed nine character strings manually and finding no likely solutions. Next, I got a list of US cities from some internet crossword puzzle dictionary and ran the string transformation against that list and saw that I’d need to find a customer in Michigan and also register some of just the right brothers in their test MPI to get my puzzle report to work.

Visit our report library at http://www.iatric.com/Information/NPRReportLibrarySearch.aspx to look them up.

You can find additional Report Writing Tips on our website at http://www.iatric.com/Information/NPRTips.aspx, as well as information about our on-site Report Writer Training and Report Writing Services.

To subscribe for email notifications for new Report Writing classes, please follow this link:

http://www.iatric.com/Information/Classes.aspx.

For more information, please contact Karen Roemer at 978.805.3142 or email
karen.roemer@iatric.com
.

This article originally appeared in the December 2013 issue of Iatric Systems Updates! newsletter.)