Hi Kevin,

I had a go at knocking up a dataport from form 302, and here it is. its not complete but hopefully a starting point for you. As always E&OE it was only a quick go.

I still can’t work out how to add the “code” tag in here.

OBJECT Dataport 50000 Exp Form 302

{

OBJECT-PROPERTIES

{

Date=12/01/07;

Time=16:27:56;

Modified=Yes;

Version List=;

}

PROPERTIES

{

Import=No;

}

DATAITEMS

{

{ PROPERTIES

{

DataItemTable=Table18;

DataItemVarName=CustomerFilters;

OnPreDataItem=BEGIN

CurrDataport.BREAK;

END;

}

FIELDS

{

}

}

{ PROPERTIES

{

DataItemTable=Table2000000026;

DataItemTableView=SORTING(Number);

OnPreDataItem=BEGIN

Customer.RESET;

Customer.SETVIEW(CustomerFilters.GETVIEW());

SETRANGE(Number,1,Customer.COUNT*6);

Customer.FIND(’-’);

ExportText[1] := ‘Payment’;

ExportText[2] := ‘Invoice’;

ExportText[3] := ‘Credit Memo’;

ExportText[4] := ‘Reminder’;

ExportText[5] := ‘Financial Charge Memo’;

ExportText[6] := ‘Refund’;

END;

OnBeforeExportRecord=BEGIN

X += 1;

IF X = 7 THEN BEGIN

IF Customer.NEXT = 0 THEN

CurrDataport.SKIP;

X := 1;

END;

IF X = 1 THEN BEGIN

WITH Customer DO BEGIN

//CLEARALL;

NewClearAll;

FOR j := 1 TO 6 DO BEGIN

CustLedgEntry[j].SETCURRENTKEY(“Document Type”,“Customer No.”,“Posting Date”);

CustLedgEntry[j].SETRANGE(“Document Type”,j); // Payment,Invoice,Credit Memo,Finance Charge Memo,Reminder,Refund

CustLedgEntry[j].SETRANGE(“Customer No.”,“No.”);

IF CustLedgEntry[j].FIND(’+’) THEN

CustLedgEntry[j].CALCFIELDS(Amount,“Remaining Amount”);

END;

CustLedgEntry2.SETCURRENTKEY(“Customer No.”,Open);

CustLedgEntry2.SETRANGE(“Customer No.”,“No.”);

CustLedgEntry2.SETRANGE(Open,TRUE);

IF CustLedgEntry2.FIND(’+’) THEN

REPEAT

j := CustLedgEntry2.“Document Type”;

IF j > 0 THEN BEGIN

CustLedgEntry2.CALCFIELDS(“Remaining Amt. (LCY)”);

TotalRemainAmountLCY[j] := TotalRemainAmountLCY[j] + CustLedgEntry2.“Remaining Amt. (LCY)”;

END;

UNTIL CustLedgEntry2.NEXT(-1) = 0;

DateFilterCalc.CreateAccountingPeriodFilter(CustDateFilter[1],CustDateName[1],WORKDATE,0);

DateFilterCalc.CreateFiscalYearFilter(CustDateFilter[2],CustDateName[2],WORKDATE,0);

DateFilterCalc.CreateFiscalYearFilter(CustDateFilter[3],CustDateName[3],WORKDATE,-1);

FOR i := 1 TO 3 DO BEGIN

CustLedgEntry2.RESET;

CustLedgEntry2.SETCURRENTKEY(“Customer No.”,“Posting Date”);

CustLedgEntry2.SETRANGE(“Customer No.”,“No.”);

CustLedgEntry2.SETFILTER(“Posting Date”,CustDateFilter[i]);

CustLedgEntry2.SETRANGE(“Posting Date”,0D,CustLedgEntry2.GETRANGEMAX(“Posting Date”));

DtldCustLedgEntry2.SETCURRENTKEY(“Customer No.”,“Posting Date”);

CustLedgEntry2.COPYFILTER(“Customer No.”,DtldCustLedgEntry2.“Customer No.”);

CustLedgEntry2.COPYFILTER(“Posting Date”,DtldCustLedgEntry2.“Posting Date”);

DtldCustLedgEntry2.CALCSUMS(“Amount (LCY)”);

CustBalanceLCY := DtldCustLedgEntry2.“Amount (LCY)”;

HighestBalanceLCY[i] := CustBalanceLCY;

DaysToPay := 0;

NoOfInv := 0;

CustLedgEntry2.SETFILTER(“Posting Date”,CustDateFilter[i]);

IF CustLedgEntry2.FIND(’+’) THEN

REPEAT

j := CustLedgEntry2.“Document Type”;

IF j > 0 THEN

NoOfDoc[i][j] := NoOfDoc[i][j] + 1;

CustLedgEntry2.CALCFIELDS(“Amount (LCY)”);

CustBalanceLCY := CustBalanceLCY - CustLedgEntry2.“Amount (LCY)”;

IF CustBalanceLCY > HighestBalanceLCY[i] THEN

HighestBalanceLCY[i] := CustBalanceLCY;

// Optimized Approximation

IF (CustLedgEntry2.“Document Type” = CustLedgEntry2.“Document Type”::Invoice) AND

NOT CustLedgEntry2.Open

THEN

IF CustLedgEntry2.“Closed at Date” > CustLedgEntry2.“Posting Date” THEN

UpdateDaysToPay(CustLedgEntry2.“Closed at Date” - CustLedgEntry2.“Posting Date”)

ELSE

IF CustLedgEntry2.“Closed by Entry No.” <> 0 THEN BEGIN

IF CustLedgEntry3.GET(CustLedgEntry2.“Closed by Entry No.”) THEN

UpdateDaysToPay(CustLedgEntry3.“Posting Date” - CustLedgEntry2.“Posting Date”);

END ELSE BEGIN

CustLedgEntry3.SETCURRENTKEY(“Closed by Entry No.”);

CustLedgEntry3.SETRANGE(“Closed by Entry No.”,CustLedgEntry2.“Entry No.”);

IF CustLedgEntry3.FIND(’+’) THEN

UpdateDaysToPay(CustLedgEntry3.“Posting Date” - CustLedgEntry2.“Posting Date”);

END;

UNTIL CustLedgEntry2.NEXT(-1) = 0;

IF NoOfInv <> 0 THEN

AvgDaysToPay[i] := DaysToPay / NoOfInv;

END;

END;

END;

CASE X OF

1,3: BEGIN

Amt := -CustLedgEntry[X].Amount;

RemAmt := -CustLedgEntry[X].“Remaining Amount”;

TotRemAmt := -TotalRemainAmountLCY[X];

END;

2,3,4,6 : BEGIN

Amt := CustLedgEntry[X].Amount;

RemAmt := CustLedgEntry[X].“Remaining Amount”;

TotRemAmt := -TotalRemainAmountLCY[X];

END;

END;

END;

}

FIELDS

{

{ ; ;ExportText[X] }

{ ; ;CustLedgEntry[X].“Posting Date” }

{ ; ;CustLedgEntry[X].“Document No.” }

{ ; ;CustLedgEntry[X].“Currency Code” }

{ ; ;Amt }

{ ; ;RemAmt }

{ ; ;NoOfDoc[1][X] }

{ ; ;NoOfDoc[2][X] }

{ ; ;NoOfDoc[3][X] }

{ ; ;TotRemAmt }

}

}

}

REQUESTFORM

{

PROPERTIES

{

Width=9020;

Height=3410;

}

CONTROLS

{

}

}

CODE

{

VAR

CustLedgEntry2@1101353015 : Record 21;

CustLedgEntry3@1101353014 : Record 21;

DtldCustLedgEntry2@1101353013 : Record 379;

DateFilterCalc@1101353012 : Codeunit 358;

CustLedgEntry@1101353011 : ARRAY [6] OF Record 21;

CustDateFilter@1101353010 : ARRAY [3] OF Text[30];

CustDateName@1101353009 : ARRAY [3] OF Text[30];

TotalRemainAmountLCY@1101353008 : ARRAY [6] OF Decimal;

NoOfDoc@1101353007 : ARRAY [3,6] OF Integer;

AvgDaysToPay@1101353006 : ARRAY [3] OF Decimal;

DaysToPay@1101353005 : Decimal;

NoOfInv@1101353004 : Integer;

HighestBalanceLCY@1101353003 : ARRAY [3] OF Decimal;

CustBalanceLCY@1101353002 : Decimal;

i@1101353001 : Integer;

j@1101353000 : Integer;

Customer@1101353016 : Record 18;

ExportText@1101353017 : ARRAY [6] OF Text[30];

X@1101353018 : Integer;

“//ExpFields”@1101353022 : Integer;

Amt@1101353019 : Decimal;

RemAmt@1101353020 : Decimal;

TotRemAmt@1101353021 : Decimal;

LOCAL PROCEDURE