Integer table for copy loop

If i want to create custom report that has the option tab with the noofcopies, is this code enough to do that?

here’s a sample report i am working on with three dataitems, Sales Header, Sales Lines and Integer. I copied this code from report 205, but it only prints 1 copy. Just to simplify things, i havent added any code to Sales Header and Sales Lines data item. Am i missing something?

CopyLoop - OnPreDataItem()
NoOfLoops := ABS(NoOfCopies) + 1;
CopyText := ‘’;
SETRANGE(Number,1,NoOfLoops);

CopyLoop - OnAfterGetRecord()
IF Number > 1 THEN
CopyText := Text003;
CurrReport.PAGENO := 1;

CopyLoop - OnPostDataItem()
IF NOT CurrReport.PREVIEW THEN
CurrReport.Break;

Code looks OK.

What do you have in Integer DataItem properties DataItemTableView and MaxIteration?

DataItemTableView : SORTING(Number)

MaxIteration: <0>

From given information everything seems OK. Are you sure that you variable NoOfCopies is not zero when you come to OnPreDataItem (have you checked that with debugger)?

If the DataItems are defined in the order You descripe, then that could be the reason.
By this order, Your report will do the looping after it has finished printing the Sales Lines, and no matter what value You give NoOfCopies-var, You will only get 1 print. (And maybe a lot of blank lines at the end, if You haven’t deleted Integer-Body section)

DataItems must be defined like this:

SalesHeader
Integer
SalesLine

This way, when ever the report finds a SalesHeader, it will run through SalesLines the same number of times, as the SETRANGE allows.

Remember to print header-info in the Integer-Body section, or in the SalesLine-Header section.
If You print it in the SalesHeader-Body section, You will end up with a report with 1 header-area, and NoOfCopies detail-areas.

I think you are right. its starting to make sense. But please tell me how do you this "Remember to print header-info in the Integer-Body section, or in the SalesLine-Header section. "

Thank you for all your help.

When You define a DataItem in the report, Navision automatically inserts a Body-section for that DataItem.

A Body-section is printed if a record is retrieved in that DataItem. And only once per record.

So Your report should already have an Integer-Body section.

How the report works is like this: ( I only use Body-sections for the simplicity)
When Your report runs, it finds a SalesHeader, and therefore prints the SalesHeader-Body section (if any are designed).
Next it goes into the Copyloop (Integer) DataItem, as that DataItem are indented. Lets say the SETRANGE is from 1 to 3 (2 copies besides the original).
Navision finds the record 1, and prints the Integer-Body section, before it goes into the SalesLine DataItem. (let’s say the invoice have 2 lines)
For every record found in SalesLine DataItem, Navision prints the SalesLine-Body section once.
Next it comes back to the Integer DataItem, and now it finds the record 2, prints the Integer-Body section, goes into SalesLine etc…
Every time Navision goes into an indented DataItem, it also prints a corresponding Header section, and when it finishes with that DataItem, and goes back out of the DataItem, it prints a corresponding footer section.

So the sections printed are:
SalesHeader-Header
SalesHeader-Body
Integer-Header
Integer-Body
SalesLine-Header
SalesLine-Body
SalesLine-Body
SalesLine-Footer
Integer-Body
SalesLine-Header
SalesLine-Body
SalesLine-Body
SalesLine-Footer
Integer-Body
SalesLine-Header
SalesLine-Body
SalesLine-Body
SalesLine-Footer
Integer-Footer
SalesHeader-Footer.

Now as You can see, only the Integer-Body, or the SalesLine-Header sections are repeated for every loop through SalesLine, and therefore must contain any info that needs to be repeated on every copy of the document.

Well, it didnt work as you had mentioned but rearranging dataitem this way worked.

Integer

SalesHeader

SalesLine

Thank you very much for all your explanations. I hope everyone can explain things in details as you did.

If you don’t mind, just to learn more, why didn’t it work the way you had mentioned?

I suppose You must have done something wrong [:D]
I don’t know what, but the obvious one (done it my self a number of times [:S]), is that You didn’t put the complete fieldname as SourceExpr in the controls about the header.
(e.g. SalesHeader.“Document Date”, instead of just “Document Date”)
That would definately have given a series of compilation-errors.
Otherwise I would need the object to see what is wrong.

The proper way to do this, in my opinion, is to arrange the DataItems as I descriped.
Because that way You have the possibility to have some info from the header, or the customer, define the number of copies.
In Your report the number of copies are defined up front, for all SalesHeaders printed no matter what.
(That could very well be perfectly OK in Your situation)

Look at report ID=206 to see how Navision does this.
Keep in mind that report ID=206 are a lot more complex, and the header-info are printed in yet another Integer-DataItem (CopyLoop), but the principles are the same.

I couldn’t attach the object but here is the text version of it. Let me know if you see the mistake. Thank you for all your help. You have been great.

OBJECT Report 50011 CopyLoop Sample
{
OBJECT-PROPERTIES
{
Date=09/12/07;
Time=12:23:41 PM;
Modified=Yes;
Version List=;
}
PROPERTIES
{
}
DATAITEMS
{
{ PROPERTIES
{
DataItemTable=Table2000000026;
DataItemTableView=SORTING(Number)
WHERE(Number=FILTER(1…));
NewPagePerRecord=Yes;
DataItemVarName=copyloop;
OnPreDataItem=BEGIN
NoOfLoops := ABS(NoOfCopies) + 1;
CopyText := ‘’;
SETRANGE(Number,1,NoOfLoops);
END;

OnAfterGetRecord=BEGIN
IF Number > NoOfCopies THEN
CurrReport.QUIT;
CopyText := Text003;
CurrReport.PAGENO := 1;
END;

OnPostDataItem=BEGIN
IF NOT CurrReport.PREVIEW THEN
CurrReport.BREAK;
END;

}
SECTIONS
{
{ PROPERTIES
{
SectionType=Body;
SectionWidth=20250;
SectionHeight=846;
}
CONTROLS
{
}
}
}
}
{ PROPERTIES
{
DataItemIndent=1;
DataItemTable=Table36;
DataItemTableView=SORTING(Document Type,No.);
NewPagePerRecord=Yes;
ReqFilterFields=No.;
}
SECTIONS
{
{ PROPERTIES
{
SectionType=Body;
SectionWidth=20250;
SectionHeight=2115;
}
CONTROLS
{
{ 1000000000;TextBox;150 ;1269 ;1500 ;423 ;SourceExpr=“No.” }
{ 1000000001;Label ;150 ;0 ;1500 ;846 ;ParentControl=1000000000;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000002;TextBox;1800 ;1269 ;1500 ;423 ;SourceExpr=“Bill-to Customer No.” }
{ 1000000003;Label ;1800 ;0 ;1500 ;846 ;ParentControl=1000000002;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000004;TextBox;3450 ;1269 ;4500 ;423 ;SourceExpr=“Bill-to Name” }
{ 1000000005;Label ;3450 ;0 ;4500 ;846 ;ParentControl=1000000004;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000006;TextBox;8100 ;1269 ;1200 ;423 ;SourceExpr=“Posting Date” }
{ 1000000007;Label ;8100 ;0 ;1200 ;846 ;ParentControl=1000000006;
HorzAlign=Right;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000008;TextBox;9450 ;1269 ;1500 ;423 ;SourceExpr=“Prescription No.” }
{ 1000000009;Label ;9450 ;0 ;1500 ;846 ;ParentControl=1000000008;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000010;TextBox;11100;1269 ;1500 ;423 ;SourceExpr=“Job Id” }
{ 1000000011;Label ;11100;0 ;1500 ;846 ;ParentControl=1000000010;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
}
}
}
}
{ PROPERTIES
{
DataItemIndent=2;
DataItemTable=Table37;
DataItemTableView=SORTING(Document No.);
DataItemLink=Document No.=FIELD(No.);
}
SECTIONS
{
{ PROPERTIES
{
SectionType=Body;
SectionWidth=20250;
SectionHeight=5499;
}
CONTROLS
{
{ 1000000012;TextBox;0 ;1692 ;1500 ;423 ;SourceExpr=“Location Code” }
{ 1000000013;Label ;0 ;423 ;1500 ;846 ;ParentControl=1000000012;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000014;TextBox;1650 ;1692 ;1500 ;423 ;SourceExpr=“Unit of Measure” }
{ 1000000015;Label ;1650 ;423 ;1500 ;846 ;ParentControl=1000000014;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000016;TextBox;3300 ;1692 ;1800 ;423 ;SourceExpr=Quantity }
{ 1000000017;Label ;3300 ;423 ;1800 ;846 ;ParentControl=1000000016;
HorzAlign=Right;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
{ 1000000018;TextBox;5250 ;1692 ;1800 ;423 ;SourceExpr=“Unit Price” }
{ 1000000019;Label ;5250 ;423 ;1800 ;846 ;ParentControl=1000000018;
HorzAlign=Right;
VertAlign=Bottom;
FontBold=Yes;
MultiLine=Yes }
}
}
}
}
}
REQUESTFORM
{
PROPERTIES
{
Width=9020;
Height=3410;
}
CONTROLS
{
{ 1000000000;Label ;0 ;0 ;3300 ;440 ;ParentControl=1000000001;
CaptionML=[ENU=Number of Copies;
ESM=N£mero de copias;
FRC=Nombre de copies;
ENC=Number of Copies] }
{ 1000000001;TextBox;3410 ;0 ;1650 ;440 ;SourceExpr=NoOfCopies }
}
}
CODE
{
VAR
NoOfCopies@1000000002 : Integer;
NoOfLoops@1000000001 : Integer;
CopyNo@1000000000 : Integer;
Text003@1000000003 : TextConst ‘ENU=COPY;ESM=COPIA;FRC=COPIER;ENC=COPY’;
CopyText@1000000004 : Text[10];
SalesPrinted@1000000005 : Codeunit 313;

BEGIN
END.
}
}

There are fine, working examples of how to implement this functionality in the standard Reports 204…208.

The standard object ste is alwyas my first point of referrence…

Hi Jolly,

I believe the error is to be found in the OnAfterGetRecord-trigger of the integer-dataitem…

You have a variable called NoOfCopies, wich the user is prompted to define in the request-form…
From this variable You calculate another variable, called NoOfLoops, as being 1 greater than NoOfCopies…
Then You, just as You should, do a SETRANGE on the Integer-dataitem, from 1 to NoOfLoops…
(btw, I don’t see why You also define filter in the Properties of Integer, in this case that’s not necessary)
BUT, You also quit the report, as soon as Number is same as NoOfCopies…
This way You will always quit the report before You would expect.

I have a copy of Your report, where I have corrected this error, and also put Sales Header before Integer, as I mean it should be done.
Throw me a mail on alexanderpallesen@hotmail.com, and I will reply to You with the object.
(Or try to catch me on MSN messenger with the same adress)