Как вывести сообщения из файла сообщений на экран с помощью rpgle?

Я разработал экран с использованием SDA в AS / 400, который принимает в качестве входных данных идентификационный номер и выполняет поиск в двух PF для этого идентификатора и отображает соответствующие значения, полученные из этих PF, в соответствующих полях на экране. Ниже приведен код DSPF:

 A*%%TS  SD  20180813  084626  PATELDH     REL-V7R1M0  5770-WDS 
 A*%%EC                                                         
 A                                      DSPSIZ(24 80 *DS3)      
 A          R HEADER                                            
 A*%%TS  SD  20180802  075026  PATELDH     REL-V7R1M0  5770-WDS 
 A                                  2  2USER                    
 A                                  2 30'PRODUCT INQUIRY SCREEN'
 A                                      COLOR(WHT)              
 A                                  2 63DATE                    
 A                                      EDTCDE(Y)               
 A                                  3 63TIME                    
 A          R FOOTER                                            
 A*%%TS  SD  20180802  074433  PATELDH     REL-V7R1M0  5770-WDS 
 A                                      OVERLAY                 
 A                                 22  4'F3=EXIT'               
 A          R DETAIL                                            
 A*%%TS  SD  20180813  073420  PATELDH     REL-V7R1M0  5770-WDS 
 A                                      CA03(03 'EXIT')         
 A                                      CA12(12 'PREVIOUS')     
 A                                      OVERLAY                             
 A                                  7 16'ID:'                               
 A                                 10 16'NAME:'                             
 A                                 12 16'CATEGORY:'                         
 A            @ID       R        I  7 20REFFLD(CATEGORIES/ID AS400KT2/RCATE-
 A                                      GORY)                               
 A            @NAME     R        O 10 22REFFLD(PRODUCTS/NAME AS400KT2/RPROD-
 A                                      UCTS)                               
 A            @CATEGORY R        O 12 26REFFLD(CATEGORIES/CATEGORY AS400KT2-
 A                                      /RCATEGORY)                         
 A          R MSGSFL                    SFL                                 
 A*%%TS  SD  20180803  054959  PATELDH     REL-V7R1M0  5770-WDS             
 A                                      SFLMSGRCD(24)                       
 A            MSGKEY                    SFLMSGKEY                           
 A            MSGQ                      SFLPGMQ(10)                         
 A          R MSGCTL                    SFLCTL(MSGSFL)                      
 A*%%TS  SD  20180813  084626  PATELDH     REL-V7R1M0  5770-WDS             
 A                                      OVERLAY                             
 A                                      SFLDSP                              
 A                                      SFLDSPCTL   
 A                                      SFLINZ      
 A  01                                  SFLEND      
 A                                      SFLSIZ(0002)
 A                                      SFLPAG(0001)
 A            MSGQ                      SFLPGMQ(10) 

Я написал код RPGLE в свободном формате, который заставляет этот экран работать. Ниже приведен код RPGLE:

 FDSPPRD    CF   E             WorkStn                   
 FRPRODUCTS IF   E           K DISK                      
 FRCATEGORY IF   E           K DISK                      
 FRPRODCATEGO  A E           K DISK                      
 DtempID           S                   LIKE(ID)          
 DmsgID            S              7A                     
 DmsgF             S             10A                     
 D getMsg          PR                  EXTPGM('MSGSFLCL')
 D  msgID                         7A                     
 D  msgF                         10A                     
  /Free                                                  
     DoW *In03 = *Off;                                   
      Write HEADER;                                      
      Write FOOTER;                                      
      ExFmt DETAIL;                                      
      If @ID = *Zeros;                                   
          msgID = 'MSG0001';                             
          msgF = 'ASGNMSGF';                             
          getMsg(msgID:msgF);                            
      Else;                       
       Chain @ID RPRODUCTS;       
       If %Found(RPRODUCTS);      
          @NAME = NAME;           
          Chain ID RCATEGORY;     
          If %Found(RCATEGORY);   
             @CATEGORY = CATEGORY;
          EndIf;                  
       EndIf;                     
      EndIf;                      
     EndDo;                       
      *InLR = *On;                
  /End-Free                       

Ниже приведена программа CL, вызываемая программой RPGLE для получения текста сообщения из файла msg:

         PGM       PARM(&MSGID &MSGF)             
         DCL       VAR(&MSGID) TYPE(*CHAR) LEN(7) 
         DCL       VAR(&MSGF)  TYPE(*CHAR) LEN(10)

         SNDPGMMSG MSGID(&MSGID) MSGF(&MSGF)      
         ENDPGM                                   

Ниже приведены два PF, из которых считываются записи:

ПРОДУКТЫ-

 A          R PRODUCTS           
 A            ID             2P 0
 A            NAME          16A  
 A          K ID                 

КАТЕГОРИЯ-

 A          R CATEGORIES         
 A            ID             2P 0
 A            CATEGORY      15A  
 A          K ID                 

Все приведенные выше коды успешно компилируются. Но проблема в том, что сообщение из msgf не появляется на экране. Остальное все работает. Просто сообщение из msgf не отображается, когда я нажимаю клавишу «Enter» с пустым идентификатором на экране. Может ли кто-нибудь предложить источник информации, из которого я могу изучить концепции таких приложений. Также будет оценена помощь с этим.

К какому ID в строке If ID = *Zeros; идет речь?

Mike 10.08.2018 16:28

Вы запускали это через отладчик? Он должен довольно быстро сказать вам, работают ли ваши CHAIN, например. Также я заметил некоторые странные и, вероятно, ненужные строки, такие как NAME = NAME; и CATEGORY = CATEGORY;. Если вызовы CHAIN сработали, эти поля уже должны быть заполнены.

Player1st 10.08.2018 17:48

@Mike - Я добавил к имени поля символ, и теперь поля заполняются. Нужна помощь относительно msgf

Rahul 14.08.2018 12:56

@ Player1st - Спасибо за подсказку!

Rahul 14.08.2018 12:57

Начните с просмотра сообщений о вакансиях из другого сеанса. Посмотрите, куда идут сообщения.

danny117 17.08.2018 16:08
2
5
2 043
1

Ответы 1

Вы не пишете запись MSGCTL. Если вы этого не напишете, то подфайл сообщения отображаться не будет. Вы также не предоставляете значение для MSGQ.

При использовании подфайла сообщения я обычно беру имя программы из структуры данных состояния программы и помещаю его в MSGQ во время инициализации программы. Это никогда не должно меняться. Я также передаю это своей процедуре, которая отправляет сообщение в очередь сообщений. Таким образом, я знаю, что оба значения будут одинаковыми. В противном случае сообщения отображаться не будут.

Вот мое определение подфайла сообщения:

 A* ========================================================================
 A* Message Subfile
 A* ------------------------------------------------------------------------
 A          R MSGSFL                    SFL
 A                                      SFLMSGRCD(27)
 A            MSGKEY                    SFLMSGKEY
 A            PGMQ                      SFLPGMQ(10)
 A* ------------------------------------------------------------------------
 A* Message Subfile Control
 A* ------------------------------------------------------------------------
 A          R MSGCTL                    SFLCTL(MSGSFL)
 A                                      SFLPAG(1)
 A                                      SFLSIZ(2)
 A                                      SFLDSP SFLDSPCTL
 A                                      SFLINZ
 A  53
 AON53                                  SFLEND
 A            PGMQ                      SFLPGMQ(10)

Отличий от твоего мало. Давайте пройдемся по ним.

 A                                      SFLMSGRCD(27)

Это 27, потому что я использую размер экрана *DS4. Не ошибка.

Вы используете OVERLAY, я не потому, что я сначала пишу этот формат, но до тех пор, пока вы пишете MSGCTL после того, как вы пишете HEADER, у вас должно быть хорошо там.

Вы используете SFLCLR. Это не нужно, удалите это.

 A  53
 AON53                                  SFLEND

Это немного другое. Я делаю это, потому что для SFLEND требуется индикатор кондиционирования, но мне все равно, я хочу, чтобы SFLEND был активен, независимо от того, что говорит этот индикатор. (Я использую *In53 как свой SFLEND и для обычных субфайлов, и мне не нужно беспокоиться о том, включен он или выключен.

Я использую подпроцедуру для отправки сообщения: вот мой код для этого:

// ----------------------------------------
// SndDspfMsg - sends an *INFO message to the
//     message subfile in a display file.
//
// Parameters:
//  StackEntry - The program call stack entry to which the message is sent.
//               Usually the program name. This must be the same value that
//               is placed in the SFLPGMQ variable in the message subfile
//               control format.
//  MsgId - The Message ID from message file JCMSGF to be sent to the program
//               message Queue.
//  MsgDta - (optional) Data to be used by the message to provide dynamic
//               message content. Defaults to blank.
//  MsgDtaLen - (optional) The length of the message data provided above.
//               This parameter is required if MsgDta is provided. Defaults
//               to zero. If this is not provided or is zero, MsgDta is ignored.
// ----------------------------------------
dcl-proc SndDspfMsg Export;
  dcl-pi *n;
    StkEnt      Char(10)  Const;
    MsgId       Char(7)   Const;
    MsgDta      Char(512) Const Options(*VarSize: *NoPass);
    MsgDtaLen   Int(10)   Const Options(*NoPass);
  end-pi;

  dcl-s Name_t           Char(10) Template Inz('');

  // Call Stack Qualifier - used by message handling APIs
  dcl-ds CallStackQual_t  Qualified Template Inz;
    Module                Like(Name_t) Inz('*NONE');
    Program               Like(Name_t) Inz('*NONE');
  end-ds;

  // Qualified Name
  dcl-ds QualName_t       Qualified Template Inz;
    Name                  Like(Name_t) Inz('');
    User                  Like(Name_t) Inz('');
  end-ds;

  // Standard Error Code Format
  dcl-ds ErrorCdType1_t   Qualified Template Inz;
    BytesProv             Int(10)   Inz(%size(ErrorCdType1_t));
    BytesAvail            Int(10);
    MsgId                 Char(7);
    Data                  Char(1024) Pos(17);
  end-ds;

  dcl-ds MsgFile       LikeDs(QualName_t) Inz(*LikeDs);
  dcl-ds ErrorCd       LikeDs(ErrorCdType1_t) Inz(*LikeDs);

  dcl-s pmMsgDta         Char(512) Inz('');
  dcl-s pmMsgDtaLen      Int(10)   Inz(0);
  dcl-s pmMsgTyp         Char(10)  Inz('*INFO');
  dcl-s pmStkCnt         Int(10)   Inz(0);
  dcl-s pmMsgKey         Char(4)   Inz('');

  // Send Program Message
  dcl-pr qmhsndpm        ExtPgm('QMHSNDPM');
    MessageId            Char(7)    Const;
    MessageFile          LikeDs(QualName_t) Const;
    MessageDta           Char(512)  Const Options(*Varsize);
    MessageLen           Int(10)    Const;
    MessageType          Char(10)   Const;
    StackEntry           Char(4102) Const Options(*Varsize);
    StackCounter         Int(10)    Const;
    MessageKey           Char(4);
    Error                LikeDs(ErrorCdType1_t);
    StackEntryLen        Int(10)    Const Options(*NoPass);
    StackEntryQual       LikeDs(CallStackQual_t)
                                    Const Options(*NoPass);
    ScreenWaitTime       Int(10)    Const Options(*NoPass);
    StackEntryType       Char(10)   Const Options(*NoPass);
    Ccsid                Int(10)    Const Options(*NoPass);
  end-pr;      

  // Handle *NoPass Parms
  if %parms() >= %parmnum(MsgDtaLen);
    pmMsgDtaLen = MsgDtaLen;
  endif;

  // if Message Data is provided,
  if pmMsgDtaLen > 0;
    pmMsgDtaLen = min(%size(pmMsgDta): pmMsgDtaLen);
    pmMsgDta = %subst(MsgDta: 1: pmMsgDtaLen);
  endif;

  MsgFile.Name = 'JCMSGF';
  qmhsndpm(MsgId: MsgFile: pmMsgDta: pmMsgDtaLen:
           pmMsgTyp: StkEnt: pmStkCnt: pmMsgKey:
           ErrorCd);
end-proc;

Это должно заставить работать подфайл сообщения. Что касается того, почему другие поля не заполняются, возможно, ваш идентификатор продукта и идентификатор категории не найдены в файле. Обратите внимание, что идентификатор продукта и идентификатор категории будут иметь одно и то же значение при запуске этой программы, поскольку ID сопоставлен с файлом отображения, файлом продукта и файлом категории. Кажется, это не то, что вам нужно. Если у вас возникли проблемы с этим, задайте новый вопрос.

RPGLE. Это вариант в свободной форме. Он стал доступен с версии 7.1. Эта версия сейчас не обслуживается.

jmarkmurphy 14.08.2018 12:21

Мне очень трудно понять ваш код. Вы можете мне помочь с версией, которую я использую? Кроме того, знаете ли вы о каких-либо онлайн-курсах, где я могу изучить эту последнюю версию RPGLE

Rahul 14.08.2018 13:00

Просто посмотрите руководства IBM в Центр знаний. Единственное, что должно быть для вас новым - это спецификации P и D в свободной форме.

jmarkmurphy 14.08.2018 13:13

Что ты не понимаешь?

jmarkmurphy 14.08.2018 13:15

Поддерживается ли эта версия RPG в AS / 400?

Rahul 16.08.2018 11:30

Какая версия у вашей операционной системы? У меня версия 7.1 (самая ранняя, которая поддерживает спецификации произвольной формы D и P). v7.1 также поддерживает **free, который снимает все ограничения столбцов. Оба этих обновления доступны на разных технических уровнях выпуска, но я не знаю, какой конкретный уровень требуется для каждого.

jmarkmurphy 16.08.2018 16:29

Другие вопросы по теме