14
Mon, Oct
6 New Articles

Message Description: Do You Copy?

Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Most AS/400 programmers are familiar with message descriptions and message files, which provide a centralized repository to store messages used by programs to communicate with users. In many AS/400 shops, message descriptions also store text presented on screens and reports. The use of message descriptions, rather than hard-coded text, in programs facilitates the use of common text, phrases, and terms, which helps ensure a more consistent user interface.

Message descriptions can be used in several ways. The most common use for message descriptions is to store messages used to communicate errors and status. Application programs send these messages using CL commands or message APIs. The best way to display messages is in a message subfile. (For more information on sending messages and using message subfiles, see “RPG Building Blocks: ILE Message Handling” in the November 1998 issue of Midrange Computing.) Another way to use message descriptions is to store constant text used on screens, printer files, and command prompts. To use message descriptions to store constant screen or printer text, you use the DDS MSGCON keyword, supplying a message ID. When defining a command, you can supply a message ID in place of hard-coded prompt text.

Many international companies have to support multiple languages. One good way to separate language-specific information from applications is to use message descriptions. Message files are set up for each language supported. A translator familiar with the applications then duplicates and translates messages into language-specific message files. Each language’s message file contains messages sent to users as well as messages containing constant screen and printer text. You can use the message description support procedures provided with this article to extend multilanguage support to applications that do not use DDS to define their user interface.

Even though messages and message descriptions are a central part of the AS/400, the tools provided to maintain message descriptions lack one important feature: the ability to copy message descriptions. In organizations that use message descriptions, the ability to copy messages can save time and help ensure consistent messages. If your company uses message descriptions to provide support for multiple languages, the ability to copy a message can be especially useful, particularly when message descriptions contain replacement values. I originally wrote the message description and message file support toolkit that accompany this article to provide better support for message descriptions in

applications. Soon after, I used the toolkit to write the Copy Message Description (CPYMSGD) command presented here. Both the toolkit and command are now an integral part of my development toolset.

A Couple of New Tools

The Message Description Toolkit (MSGDTKT) procedures make it easier to incorporate message description support into your applications. This toolkit contains two procedures. The first is the Retrieve Message Description (RTVMSGD) subprocedure, which the CPYMSGD command uses. The second is the Retrieve Message File Attributes (RTVMSGFA) subprocedure. These procedures are easier to use than a direct call to the system APIs because they hide some of the underlying API’s complexity by providing default values, parsing return values, and handling errors.

The RTVMSGD subprocedure returns information about a message description using the Retrieve Message (QMHRTVM) API. There are two ways that this subprocedure is used. The first way retrieves information about a particular message description. You can also use RTVMSGD to retrieve information for multiple message descriptions by specifying *FIRST or *NEXT for the message ID to retrieve. The QMHRTVM API returns message description information in a single return value. Length and offset values at the beginning of the return value describe several variable-length values returned by the API. RTVMSGD uses these lengths and offsets to extract variable-length values returned by the API.

The other toolkit subprocedure, RTVMSGFA, returns message file information. Some of the message file attributes are message file text, the current file size, and the coded character set ID (CCSID). RTVMSGFA calls the Retrieve Message File Attributes (QMHRMFAT) API to retrieve this information.

Copying Message Descriptions

The CPYMSGD command combines API calls with a command interface to provide functionality missing from the AS/400. This command prompts for a copy-from message ID and message file as well as a target message ID and message file. When the CPYMSGD command runs, a validity check program first ensures that the parameters are valid. Next, the CPYMSGD command processing program (CPP) retrieves information about the message being copied and uses this information to prompt the Add Message Description (ADDMSGD) command.

The first thing I do when I create a new command is enter the command definition source and then create the command. Figure 1 (page 112) shows the source for the CPYMSGD command definition. Next, I prompt the command and create the panel group help text to better understand how the command will work. The panel group help text included with this command has the look and feel of a native AS/400 command. You can download the source for the CPYMSGD command, including the panel group help text, from www.midrangecomputing.com.

Once the command interface and help text is complete, the next step is to write the CPP. Figure 2 (page 113) shows the source for the CPYMSGD CPP, which is a CL module. The CPYMSGD CPP first calls the RTVMSGD subprocedure from the MSGDTKT to retrieve the copy-from message’s description. This call illustrates a problem with one-character return variables when CL modules call RPG IV subprocedures. To get around this problem, the CL program passes a two-character return variable and uses the %SST built-in to extract the first character.

The next step that the CPYMSGD CPP does is build an ADDMSGD command string using the copy-from message description’s information and selective prompt characters. To prompt the command string, the Check Command Syntax (QCMDCHK) API is used. This API returns the ADDMSGD command string along with any changes made during prompting. During the call to QCMDCHK, a monitor message for CPF6801

allows the program to determine if prompting was cancelled with F3 or F12. If the user did not cancel, the returned command string runs using a call to the Execute Command (QCMDEXC) API.

Validity check programs check command prompt values for errors before a command’s CPP is called. Figure 3 shows the validity check program CPYMSGDV for the CPYMSGD command. This program checks to see that the copy-from message ID exists, the message files exist, and the copy-from and copy-to values differ. If an error is found, an error flag is set and a diagnostic-type message is sent to the validity check program. After checking all of the parameters for errors, the validity check program receives and returns any diagnostic messages to the calling program using the message ID CPD0006. Next, the validity check program sends CPF0002 as an escape message to indicate that a problem has occurred.

Why Didn’t IBM Do That?

Rather than lament the fact that IBM did not anticipate the needs of every user, you can use APIs to create support for features that IBM did not predict. The AS/400 provides hundreds of APIs that you can use to build support for these missing features. Access to these APIs is easier than ever from ILE programs written in RPG. If you use a command interface for this support and follow system conventions, your enhancements will integrate seamlessly with the operating system. To me, the comment “When did IBM add this command to the operating system?” is the highest form of compliment.

Storing the text and messages used in your applications in message descriptions can help you create a more consistent interface for your applications. Message descriptions are also a good way to support multiple languages in AS/400 applications. The procedures found in the message description toolkit use encapsulation to hide the underlying complexity of the supported APIs. These toolkit procedures make it easier to use message descriptions in applications that do not use DDS.

REFERENCES AND RELATED MATERIALS

• AS/400 Information Center Overview 5 (SC41-5315-01, QA3AIC01)

• OS/400 CL Programming 4R5 (SC41-5721-03, CD-ROM QB3AUO03)

 CMD PROMPT(‘Copy Message Description’)
PARM KWD(FROMMSGID) TYPE(*NAME) LEN(7) MIN(1) +
FULL(*YES) EXPR(*YES) PROMPT(‘Message +
identifier’)
PARM KWD(FROMMSGF) TYPE(QMSGF) MIN(1) +
CHOICE(*NONE) PROMPT(‘Message file’)
PARM KWD(TOMSGID) TYPE(*NAME) LEN(7) +
DFT(*FROMMSGID) SPCVAL((*FROMMSGID +
*FROMMS)) FULL(*YES) EXPR(*YES) +
PROMPT(‘To message identifier’)
PARM KWD(TOMSGF) TYPE(QTOMSGF) DFT(*FROMMSGF) +
SNGVAL((*FROMMSGF)) CHOICE(*NONE) +
PROMPT(‘To message file’)
QMSGF: QUAL TYPE(*NAME) LEN(10) MIN(1) EXPR(*YES)
QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) +
SPCVAL((*LIBL) (*CURLIB)) EXPR(*YES) +
PROMPT(‘Library’)
QTOMSGF: QUAL TYPE(*NAME) LEN(10) EXPR(*YES)
QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) +
SPCVAL((*LIBL) (*CURLIB)) EXPR(*YES) +
PROMPT(‘Library’)
PGM (&FromMsgID &FromMsgF &ToMsgID &ToMsgF)

Figure 1: To create the new command, first enter the Copy Message Description command definition source.

 DCL &FromMsgID *CHAR LEN(7) /* Message ID */
DCL &FromMsgF *CHAR LEN(20) /* Message File */
DCL &ToMsgID *CHAR LEN(7) /* To message ID */
DCL &ToMsgF *CHAR LEN(20) /* To Message File */
DCL &FromMsgFN *CHAR LEN(10) /* Message File Name */
DCL &FromMsgFL *CHAR LEN(10) /* Message File Library */
DCL &ToMsgFN *CHAR LEN(10) /* Message File Name */
DCL &ToMsgFL *CHAR LEN(10) /* Message File Library */
DCL &RtnMsgID *CHAR LEN(7) /* Returned Message ID */
DCL &MsgTxt *CHAR LEN(134) /* Variable Message text */
DCL &MsgTxtLen *DEC LEN(5) /* Message text length */
DCL &SecLvl *CHAR LEN(3002) /* Variable Second level text */
DCL &SecLvlLen *DEC LEN(5) /* Second level text length */
DCL &Fmt *CHAR LEN(792) /* Variable format */
DCL &Len *CHAR LEN(198) /* Variable length */
DCL &Dec *CHAR LEN(198) /* Variable decimal pos */
DCL &Sev *DEC LEN(2) /* Message severity */
DCL &Ele *DEC LEN(5) /* Element */
DCL &StrLen *DEC LEN(5) /* String length */
DCL &Off *DEC LEN(5) /* Offset */
DCL &Off2 *DEC LEN(5) /* Offset */
DCL &Tst *CHAR LEN(2) /* Test character */
DCL &DecVal5 *DEC LEN(5) /* Decimal value */
DCL &DecAlp5 *CHAR LEN(5) /* Alpha decimal value */
DCL &DecVal2 *DEC LEN(2) /* Decimal value */
DCL &DecAlp2 *CHAR LEN(2) /* Alpha decimal value */
DCL &Cmd *CHAR LEN(4000) /* Command to execute */
DCL &ErrFlg *CHAR LEN(2) /* Return error flag */
DCL &Msgid *CHAR LEN(7) /* Status message */
DCL &MsgF *CHAR LEN(10) /* Status message */
DCL &MsgFLib *CHAR LEN(10) /* Status message */
DCL &MsgDta *CHAR LEN(60) /* Status message */
DCL &Qte *LGL /* Quote flag */
DCL &EscFlg *LGL /* Escape flag */
MONMSG CPF0000 EXEC(GOTO Error)
CHGVAR &FromMsgFN %SST(&FromMsgF 1 10)
CHGVAR &FromMsgFL %SST(&FromMsgF 11 10)
IF (&ToMsgID = '*FROMMS') THEN(DO)
CHGVAR &ToMsgID &FromMsgID
ENDDO
IF (&ToMsgF = '*FROMMSGF') THEN(DO)
CHGVAR &ToMsgFN &FromMsgFN
CHGVAR &ToMsgFL &FromMsgFL
ENDDO
ELSE DO
CHGVAR &ToMsgFN %SST(&ToMsgF 1 10)
CHGVAR &ToMsgFL %SST(&ToMsgF 11 10)
ENDDO
CALLPRC PRC(RtvMsgD) PARM(&FromMsgID &FromMsgFN &FromMsgFL *NULL *YES +
&RtnMsgID &MsgTxt &SecLvl &Fmt &Len &Dec &Sev)+
RTNVAL(&ErrFlg)
IF (%SST(&ErrFlg 1 1) = '1') THEN(GOTO Error)
CHGVAR &MsgTxtLen %BIN(&MsgTxt 1 2) /* Set length of varying parameter */
CHGVAR &SecLvlLen %BIN(&SecLvl 1 2)
CHGVAR &DecAlp2 &Sev /* Convert to alpha */
/* Build required part of add message command */
CHGVAR &Cmd ('ADDMSGD +
?-MSGF(' *CAT &ToMsgFL *TCAT '/' *CAT &ToMsgFN *TCAT ') +
MSGID(' *CAT &ToMsgID *TCAT ') +
MSG(''' *CAT %SST(&MsgTxt 3 &MsgTxtLen) *TCAT ''') +
SEV(' *CAT &DecAlp2 *CAT ')')
/* Add second level text if any is found */
IF (&SecLvlLen *NE 0) THEN(DO)
CHGVAR &Cmd (&Cmd *BCAT +
'SECLVL(''' *CAT %SST(&SecLvl 3 &SecLvlLen) *TCAT ''')')
ENDDO
/* Add message data fields if any are found */
IF (%SST(&Fmt 1 8) *NE ' ') THEN(DO)
CHGVAR &Ele 1 /* Inz element for format variables */
CHGVAR &Cmd (&Cmd *BCAT 'FMT(')
NextFmt:
CHGVAR &Off (&Ele * 8 - 7) /* Set off to format variable */
IF ((&Off < 792) *AND (%SST(&Fmt &Off 8) *NE ' ')) THEN(DO)
CHGVAR &Cmd (&Cmd *TCAT '(' *CAT %SST(&Fmt &Off 8))
CHGVAR &Off (&Ele * 2 - 1) /* Set off to length variable */
CHGVAR &DecVal5 %BIN(&Len &Off 2)
CHGVAR &DecAlp5 &DecVal5
CHGVAR &Cmd (&Cmd *BCAT &DecAlp5)
CHGVAR &Off (&Ele * 2 - 1) /* Set off to decimal variable */
CHGVAR &DecVal2 %BIN(&Dec &Off 2)
CHGVAR &DecAlp2 &DecVal2
CHGVAR &Cmd (&Cmd *BCAT &DecAlp2 *TCAT ')')
CHGVAR &Ele (&Ele + 1) /* Next format variable */
GOTO NextFmt
ENDDO
CHGVAR &Cmd (&Cmd *TCAT ')')
ENDDO
GOTO RepApost /* Replace apostrophe */
Retry:
CHGVAR &CMD ('?' *CAT &CMD)
CALL PGM(QCMDCHK) PARM(&CMD 4000)
MONMSG CPF6801 EXEC(GOTO Resend) /* F3/12 pressed */
CALL PGM(QCMDEXC) PARM(&CMD 4000)
MONMSG CPF0000 EXEC(DO)
RCVMSG MSGTYPE(*LAST) MSGDTA(&MsgDta) +
MSGID(&MsgID) MSGF(&MsgF) +
MSGFLIB(&MsgFLib) RMV(*YES)
SNDPGMMSG MSGID(&MsgID) MSGF(&MsgFLib/&MsgF) +
MSGDTA(&MsgDta) TOPGMQ(*EXT)
RCVMSG PGMQ(*EXT) MSGTYPE(*LAST) RMV(*YES)
GOTO Retry
ENDDO
/* No errors end program. */
GOTO CMDLBL(Resend)
/* Replace single with double apostrophe. */
RepApost:
CHGVAR &Off 1
NextPos:
CHGVAR &Tst %SST(&Cmd &Off 2)
/* Set flag if in quoted string */
IF (&Tst = '(''') THEN(DO)
CHGVAR &Off (&OFF + 2) /* Skip this quote */
CHGVAR &Qte '1'
ENDDO
ELSE DO
IF (&Tst = ''')' *AND &Qte) THEN(CHGVAR &Qte '0')
ENDDO
/* Set flag at end of quoted string */
/* Replace apostrophe with two appostrophies */
IF (&Qte *AND %SST(&Cmd &Off 1) = '''') THEN(DO)
CHGVAR &Off (&Off + 1)
CHGVAR &Off2 (&Off + 1)
CHGVAR &StrLen (4000 - &Off)
CHGVAR %SST(&Cmd &Off2 &StrLen) (%SST(&Cmd &Off &StrLen))
CHGVAR %SST(&Cmd &Off 1) ''''
ENDDO
/* Next position */
CHGVAR &Off (&Off + 1)
/* Not end of command */
IF (&Off < 4000) THEN(GOTO NextPos)
GOTO Retry
/* Errors, resend messages and end program. */
Error:
IF &EscFlg THEN(GOTO Escape)
CHGVAR &EscFlg '1' /* Severe errors */
Resend:
CALLPRC PRC(MovMsg)
Escape:
IF &EscFlg DO
CALLPRC PRC(SndEscMsg) PARM('CPF0001' 'CPYMSG')
MONMSG CPF0000 /* To prevent endless loop */
ENDDO /* &EscFlg */
ENDPGM
PGM (&FromMsgID &FromMsgF &ToMsgID &ToMsgF)
DCL &FromMsgID *CHAR LEN(7) /* Message ID */
DCL &FromMsgF *CHAR LEN(20) /* Message File */
DCL &ToMsgID *CHAR LEN(7) /* To message ID */
DCL &ToMsgF *CHAR LEN(20) /* To Message File */
DCL &EscFlg *LGL /* Escape flag */
DCL &FromMsgFN *CHAR LEN(10) /* Message File Name */
DCL &FromMsgFL *CHAR LEN(10) /* Message File Library */
DCL &ToMsgFN *CHAR LEN(10) /* Message File Name */
DCL &ToMsgFL *CHAR LEN(10) /* Message File Library */
DCL &RtnMsgID *CHAR LEN(7) /* Message ID */

Figure 2: The Copy Message Description command processing program is a CL module.

 DCL &MsgIDErr *CHAR LEN(2) /* Return error flag */
DCL &ErrFlg *LGL /* Error found */
DCL &EscFlg *LGL /* Escape processing */
DCL &Msg *CHAR LEN(132) /* Error message */
DCL &RtnType *CHAR LEN(2) /* Message return type */
DCL &KeyVar *CHAR LEN(4) /* Message key */
CHGVAR &FromMsgFN %SST(&FromMsgF 1 10)
CHGVAR &FromMsgFL %SST(&FromMsgF 11 10)
IF (&ToMsgID = '*FROMMS') THEN(DO)
CHGVAR &ToMsgID &FromMsgID
ENDDO
IF (&ToMsgF = '*FROMMSGF') THEN(DO)
CHGVAR &ToMsgFN &FromMsgFN
CHGVAR &ToMsgFL &FromMsgFL
ENDDO
ELSE DO
CHGVAR &ToMsgFN %SST(&ToMsgF 1 10)
CHGVAR &ToMsgFL %SST(&ToMsgF 11 10)
ENDDO
CHKOBJ OBJ(&FromMsgFL/&FromMsgFN) OBJTYPE(*MSGF)
MONMSG CPF0000 EXEC(DO)
CHGVAR &ErrFlg '1'
ENDDO
IF (*NOT &ErrFlg) THEN(DO) /* Message file OK, check the ID */
CALLPRC PRC(RtvMsgD) PARM(&FromMsgID &FromMsgFN &FromMsgFL *NULL *YES +
&RtnMsgID) RTNVAL(&MsgIDErr)
IF (%SST(&MsgIDErr 1 1) = '1' *OR &RtnMsgID *NE &FromMsgID) THEN(DO)
CHGVAR &ErrFlg '1'
ENDDO
ENDDO
CHKOBJ OBJ(&ToMsgFL/&ToMsgFN) OBJTYPE(*MSGF)
MONMSG CPF0000 EXEC(DO)
CHGVAR &ErrFlg '1'
ENDDO
IF ((&FromMsgFL *EQ &ToMsgFL) *AND (&FromMsgFN *EQ &ToMsgFN)) +
THEN(DO)
CHGVAR &ErrFlg '1'
SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) TOPGMQ(*SAME) +
MSGDTA('From and to message file and library must be +
different.') MSGTYPE(*DIAG)
ENDDO
/* No errors end program. */
IF (*NOT &ErrFlg) THEN(GOTO EndPgm)
/* Errors, resend messages and end program. */
Error:
IF &EscFlg THEN(GOTO Escape)
CHGVAR &EscFlg '1' /* Severe errors */
CHGVAR &KEYVAR '*TOP'
Resend:
RCVMSG MSGTYPE(*NEXT) MSGKEY(&KeyVar) KEYVAR(&KeyVar) MSG(&Msg) +
RTNTYPE(&RtnType)
IF (&RtnType *NE ' ') DO
IF ((&RtnType *EQ '02') *OR +
(&RtnType *EQ '04') *OR +
(&RtnType *EQ '15')) THEN(DO) /* *DIAG,*INFO,*ESCAPE */
SNDPGMMSG MSGID(CPD0006) MSGF(QCPFMSG) MSGDTA('0000' *CAT &Msg) +
MSGTYPE(*DIAG)
ENDDO
GOTO Resend /* Get next message */
ENDDO
Escape:
IF &EscFlg DO
CALLPRC PRC(SndEscMsg) PARM('CPF0002')
MONMSG CPF0000 /* To prevent endless loop */
ENDDO /* &EscFlg */
EndPgm: ENDPGM

Figure 3: The Copy Message Description validity check program prompts values for errors before the command’s CPP is called.

DAVID MORRIS
David Morris has worked with and written about a variety of technologies, including ILE, RPG, business intelligence, SQL, security, and genetic programming. Today, David is developing Web applications that run on the iSeries using RPG, Java, and XML as well as writing about these technologies for technical journals.

MC Press books written by David Morris available now on the MC Press Bookstore.

 

XML for eServer i5 and iSeries XML for eServer i5 and iSeries

In this book, you will learn about Extensible Markup Language (XML), but with an IBM eServer i5/iSeries twist.

List Price $64.95
Now On Sale
 
BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: