ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Printer files and how to make a spool file

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Printer files and how to make a spool file

    Hi all, first timer with printer files..

    I have created a PF in QTEMP and put data inside of it in my RPGLE program. I want to write the contents in that PF into a spool file.
    The direction I was given was "read that PF file in the program and print by using 'except' so that spool file will be generated"

    EDIPF = PF in QTEMP
    EMDID, EMBOX, MBCODE, EMDAT = field names
    I am making the printer file, like so:
    Code:
    0000.04      A                                      REF(EDIPF)            
    0000.06      A          R HDG1                                            
    0000.10      A                                                            
    0000.11      A                                      SKIPB(001)            
    0000.12      A                                     4                      
    0000.13      A                                      'DOC NAME'            
    0000.15      A                                    10                      
    0000.16      A                                      'MAILBOX ID'          
    0000.17      A                                     3                      
    0000.18      A                                      'DISPLAY CODE'        
    0000.19      A                                    10                      
    0000.20      A                                      'MAIL DATE'           
    0000.57      A*%%*********************************************************
    0000.58      A          R DETAIL                                          
    0000.59      A                                      SPACEA(001)           
    0000.60      A            EMDID     R        O     4                      
    0000.61      A            EMBOX     R        O    10                                      
    0000.62      A            MBCODE    R        O     3                                      
    0000.63      A            EMDAT     R        O    10                                      
    0001.04      A*%%***********************************************************************  
    0001.05      A          R FOOTER                                                          
    0001.09      A                                      SPACEB(001)                           
    0001.10      A                                     1                                      
    0001.11      A                                      '-----------------------------------  
    0001.12      A                                      End of Report-----------------------  
    0001.13      A                                      -----------------------'              
    0001.14      A                                      SPACEB(001)
    I was able to get this far. It is compiling successfully. Am I correct in doing this? Just the fact that its my first time, I am not 100% sure this is all correct.

    second thing is, in my RPGLE program I have to "read and print"
    the directions for this was : Print the heading, Read the first record, See if the page is full. If so, print the heading.
    Code:
    DCL-F EDIPRINT     Printer OFLIND(*In10);
    .
    .
    .
    Creates QTEMP/EDIPF with data in it
    .
    .
    .
    
    Print the heading                                                   
    0009.00 C                   Write     Hdg1
    Read the first record                                               
    0013.00 C                   Read      CSREC                                  90
    See if the page is full. If so, print the heading.                  
    0017.00 C                   If        *In10 = *On                              
    0018.00 C                   Write     Hdg1                                                                         
    0021.00 C                   Eval      *In10 = *Off                             
    0022.00 C                   EndIf                                              
    0023.00 C                   Write     Detail                                   
    0024.00 C                   Read      CSREC                                  90
    0025.00 C                   EndDo                                              
    0026.00 C*                                                                     
    0027.00 C                   Eval      *InLR = *On
    what I don't understand is where the CSREC came from, from the code I got, it is only found in these 2 places...and since I don't know the general procedure, I have no idea!
    why does it read the first record out of nowhere when it will read again after the "Write Detail" and what exactly does Write Detail do?

  • #2
    Skwon, greetings!

    Although you write of creating QTEMP/EDIPF, I don't see any code that creates that file and puts data into it. My suspicion is, that when QTEMP/EDIPF is created and filled with data, the Record Name of each individual record in that file is labeled CSREC.

    I can guess that the "general procedure" has the DCLF (or specific F-SPEC) using the file name EDIPF... which makes that file EDIPF available to the called program you have written, from that "general procedure" you mentioned.... along with the field names in your print file being auto-magically placed into the printfile.

    You see, your program isn't really reading a CSREC "out of nowhere", as the EDIPF/CSREC combination contains those records.

    Lastly, your posted program seems a bit incomplete... even though I see an "ENDDO" opcode, I don't see something like: DOW NOT(EOF(EDIPF)); or similar construction at the start of the program logic.

    Which is why this answer is basically a guess as to what your program is doing here, as I'm not seeing all the parts I would expect to see in a program like this.

    +++

    And by the way, the "Write Detail" is the piece that takes the DETAIL record and causes it to be written to the EDIPRINT file, which in this case is the spool file you're creating from your coded printer file above.


    Best Regards and Good Luck,
    Fred Williams

    Comment


    • #3
      Hi skwon

      You wrote:
      Originally posted by skwon9642 View Post
      ...
      The direction I was given was "read that PF file in the program and print by using 'except' so that spool file will be generated"
      ...
      This sounds like a college task. If so, your task is to use the EXCEPT opcode. This means using the O-specs and not an externally described printer file.
      Regards

      Kit
      http://www.ecofitonline.com
      DeskfIT - ChangefIT - XrefIT
      ___________________________________
      There are only 3 kinds of people -
      Those that can count and those that can't.

      Comment


      • #4
        Originally posted by Whitecat27 View Post
        Skwon, greetings!

        Although you write of creating QTEMP/EDIPF, I don't see any code that creates that file and puts data into it. My suspicion is, that when QTEMP/EDIPF is created and filled with data, the Record Name of each individual record in that file is labeled CSREC.

        I can guess that the "general procedure" has the DCLF (or specific F-SPEC) using the file name EDIPF... which makes that file EDIPF available to the called program you have written, from that "general procedure" you mentioned.... along with the field names in your print file being auto-magically placed into the printfile.

        You see, your program isn't really reading a CSREC "out of nowhere", as the EDIPF/CSREC combination contains those records.

        Lastly, your posted program seems a bit incomplete... even though I see an "ENDDO" opcode, I don't see something like: DOW NOT(EOF(EDIPF)); or similar construction at the start of the program logic.

        Which is why this answer is basically a guess as to what your program is doing here, as I'm not seeing all the parts I would expect to see in a program like this.

        +++

        And by the way, the "Write Detail" is the piece that takes the DETAIL record and causes it to be written to the EDIPRINT file, which in this case is the spool file you're creating from your coded printer file above.


        Best Regards and Good Luck,
        Fred Williams
        Thank you, from reading this, I was able to populate the spool file with some data.
        I did not show the code that creates the file in QTEMP and puts data into it because it already works like how I want it to, the matter at hand was putting the contents of that PF into the printer file EDIPRINT.
        I have also re-positioned the headers and details so it does not overlap.

        The data however, is not exactly the same as the EDIPF.
        I have coded this to populate the printer file. EDIPFR is the reference name of EDIPF.
        Code:
        .
        .
        .
        For loop
        code here to populate data into QTEMP/EDIPF
        .
        // copying QTEMP/EDIPF to ISE/EDIPF. I am doing this because I could not get the printer file to copy from the qtemp EIDPF.
            Exec SQL                                            
                INSERT INTO ISE/EDIPF SELECT * FROM QTEMP/EDIPF;                                              
        .
        .
        .
        0100.58 C                   Write     HDG1                                    
        0100.59 C                   Read      EDIPFR                               90
        0100.60 C                   DoW     *In90 = *Off                            
        0100.61 C                   If           *In10 = *On                            
        0100.62 C                   Write     HDG1                                    
        0100.63 C                   Eval      *In10 = *Off                            
        0100.64 C                   EndIf                                            
        0100.65 C                   Write     Detail                                  
        0100.66 C                   Read      EDIPFR                               90
        0100.67 C                   EndDo                                            
        0100.68 C                   Eval      *InLR = *On                            
        0100.69 C                   Return                                            
        end for loop
        .
        .
        this code currently populates the printer file in what seems like an infinite loop. So the error I get is CPF 5116
        Message . . . . : Number of records written by program exceeds 100000.
        Cause . . . . . : An attempt was made to exceed the maximum number of
        records allowed for file EDIPRINT in ISE.
        I have attached the full job log...
        so it must not be stopping after it reaches the end of the file...any help would be appreciated!
        Attached Files

        Comment


        • #5
          For your READ operations, you have indicator 90 in the LO position, which means to turn on indicator 90 if there is an error. It should be in the EQ position, which means to turn on the indicator if it reaches end of file.

          I think your code would be much more understandable if you used free-form calculations. Then you wouldn't have to worry any positions. You could just check for %EOF.

          Code:
                   Write HDG1;
                   Read EDIPFRp;
                   DoW not %eof(EDIPF);
                      If *In10 = *On;
                         Write HDG1;
                         *In10 = *Off;
                      EndIf;
                      Write Detail;
                      Read EDIPFR;
                   EndDo;
                   *InLR = *On;
                   Return;

          Comment


          • #6
            Originally posted by Barbara Morris View Post
            For your READ operations, you have indicator 90 in the LO position, which means to turn on indicator 90 if there is an error. It should be in the EQ position, which means to turn on the indicator if it reaches end of file.

            I think your code would be much more understandable if you used free-form calculations. Then you wouldn't have to worry any positions. You could just check for %EOF.

            Code:
            Write HDG1;
            Read EDIPFRp;
            DoW not %eof(EDIPF);
            If *In10 = *On;
            Write HDG1;
            *In10 = *Off;
            EndIf;
            Write Detail;
            Read EDIPFR;
            EndDo;
            *InLR = *On;
            Return;
            Thank you Barbara. This cleared up a lot of things for me.

            further questions:
            1. right now, I am having to write the QTEMP/EDIPF into the ISE/EDIPF in order to write to the printer file. Is there a way to eliminate that process and write straight from QTEMP/EDIPF to the printer file? I tried to do this by commenting out the INSERT INTO ISE/EDIPF SELECT * FROM QTEMP/EDIPF part, and using EDIPF instead of it's record format name EDIPFR but it writes nothing into the printer file, but there is clearly data in QTEMP/EDIPF. Does QTEMP/EDIPF have an actual record format name?

            Code:
            0099.88     Write HDG1;                  
            0099.89     For x = 1 to %Elem(RankArray);
            0099.90     WrkRank = RankArray(x);      
            0099.91                                  
            0099.92     Exec SQL                                                            
            0099.93         //Logic here to insert records into QTEMP/EDIPF                                        
            0099.94         //     depending on the integer of the element in the array                                    
            0100.07                                                                          
            0100.08     Exec SQL                                                            
            0100.09         INSERT INTO ISE/EDIPF SELECT * FROM QTEMP/EDIPF;                
            0100.53                                                                          
            0100.55 /* Copy to Printer File (Spool)                                                                                    
            0100.58     Read EDIPFR;                            
            0100.59     DoW not %eof(EDIPF);                    
            0100.60         If *In10 = *On;                    
            0100.61             Write HDG1;                    
            0100.62             *In10 = *Off;                  
            0100.63         EndIf;                              
            0100.64         Write Detail;                      
            0100.65         Read EDIPFR;                        
            0100.66     EndDo;                                  
            0100.67     *InLR = *On;                            
            0100.68                                            
            0101.12     EndFor;                                
            0101.21     Write FOOTER;
            2. as the code above suggests, I need to do this in a for loop. so before starting the loop, I write the header, then write to ISE/EDIPF, copy to printer file, end loop, then write the footer. Doing this only copies the records from the first element. To be more detailed, the Array is [1,1,1,1,2,3,0,0,0,0] but it only copies the records that are retrieved from the first "1" but I need it to copy into the print file for 1,2 and 3. I must be not placing the start and/or end of loops in the correct order to make this happen. I've tried several different orders to no avail...From debugging, I found that after the first run, the compiler thinks that it is end of file, so it skips that whole if...

            EDIT: I put a SETLL *START EDIPF; before the first Read EDIPFR, in an attempt to put the pointer back to the beginning, and it did include the records from the other elements, BUT it also repeated the first one 4 times...I believe this is because my array is [1,1,1,1,2,3,0,0,0,0], so it is repeating that 1 four times.
            In rpg, is there a way to look at individual elements? the logical next step seems like making an IF statement saying, "if current element is the same as the previous element, skip to the next element"

            Comment


            • #7
              Originally posted by skwon9642 View Post
              In rpg, is there a way to look at individual elements? the logical next step seems like making an IF statement saying, "if current element is the same as the previous element, skip to the next element"
              ??? You're already doing this.
              Code:
              0099.89     For x = 1 to %Elem(RankArray);
              0099.90     WrkRank = RankArray(x);
              RankArray(x) is referring to an individual element in the RankArray array...

              Comment


              • skwon9642
                skwon9642 commented
                Editing a comment
                I guess I should have been more specific, I know that part already does the "looking at elements individually" but I was wondering if there is a way to say something like "if current element is the same as the previous element, skip to the next element" since I am not too familiar with rpg syntax.

                I was thinking something like:

                If RankArray(x) = RankArray(x-1);
                //skip to next element
                Else
                //do normal operation
                EndIf

            • #8
              I guess I should have been more specific, I know that part already does the "looking at elements individually" but I was wondering if there is a way to say something like "if current element is the same as the previous element, skip to the next element" since I am not too familiar with rpg syntax.

              I was thinking something like:

              If RankArray(x) = RankArray(x-1);
              //skip to next element
              Else
              //do normal operation
              EndIf
              That would work as long as you don't test the first time through the array because when it evaluates X - 1, it will end up to be zero which is an invalid array index. This example code should work:

              Code:
              If x > 1 and RankArray(x) = RankArray(x-1);  // Skip test of first element
                 Iter;                                     // Skip to next element if same as previous
              EndIf;

              Comment


              • #9
                Simple to do as has been mentioned.
                All that is required is for the value between the parenthesis to evaluate out to an integer that is from 1 to the number of array elements. For example, it could be an absolute value (e.g. RankArray(1) ), a more complex expression (e.g. RankArray((x*y-a*b)/(f-g)*2) ), even a call to a subprocedure (e.g. RankArray(GetMyIndex() ). The computed value of the index (the bit in the parenthesis) just needs to meet the criteria of an integer value within the arrays boundaries.

                Comment


                • #10
                  So, I was trying all afternoon today to have it skip the extra 1's. The method above did not work nor 4 other methods I came up with...so I resorted to just not including the first three 1's. so it would be [skip, skip, skip, 1,2,0,0,0,0,0], that still achieves what I want, reporting rank 1 only one time in addition to rank 2 report,
                  so I have

                  The Array [1,1,1,1,2,0,0,0,0,0]
                  Code:
                  Write HDG1;                  
                  
                  For x = 1 to %Elem(RankArray); WrkRank = RankArray(x);        
                  
                  Exec SQL                                                            
                  //Logic here to insert records into QTEMP/EDIPF                                        
                  //depending on the integer of the element in the array                    
                  
                   Exec SQL                                                            
                  INSERT INTO ISE/EDIPF SELECT * FROM QTEMP/EDIPF;          
                  
                    If x <= 3;
                      Iter;
                  else;    
                  SETLL *START EDIPF;
                  Read EDIPFR;        
                  DoW not %eof(EDIPF);
                      If *In10 = *On;
                         Write HDG1;  
                         *In10 = *Off;
                      EndIf;          
                      Write Detail;  
                      Read EDIPFR;
                  EndDo;          
                  *InLR = *On;    
                  EndIf;          
                  
                  EndFor;
                  
                  Write Footer;
                  and doing this is still not giving me the results that I need. Instead I am getting the rank 1 report 10 times, then rank 2 report once. not to mention the (what seems like random) HDG1 writes in between the records...I tested my IF logic with simple "write HDG1" statements, and that came out correctly (rank 1 report once, rank 2 report once) so that leads me to believe that something is wrong with my actually copying to printer file statement...do you guys see any problems with this??

                  Comment


                  • #11
                    Have you tried stepping through in debug so you can understand what is happening?

                    Comment


                    • #12
                      Originally posted by Scott M View Post
                      Have you tried stepping through in debug so you can understand what is happening?
                      I have, there was no problem with my IF statements, but there seemed to be a problem with how I am copying the records. I resorted to fixing the array to not repeat so it would give [1.2.0.0.0.0.0.0.0.0]. problem is now solved. Thank you!

                      Comment

                      Working...
                      X