Browse Source

* Open all datasets correctly, and initialize memo expressions correctly (bug ID 33405)

git-svn-id: trunk@38560 -
michael 7 years ago
parent
commit
6c3ac68f1a
1 changed files with 119 additions and 121 deletions
  1. 119 121
      packages/fcl-report/src/fpreport.pp

+ 119 - 121
packages/fcl-report/src/fpreport.pp

@@ -1519,7 +1519,7 @@ type
     { checks if children are visble, removes children if needed, and recalc Band.Layout bounds }
     { checks if children are visble, removes children if needed, and recalc Band.Layout bounds }
     procedure EmptyRTObjects;
     procedure EmptyRTObjects;
     procedure ClearDataBandLastTextValues(ABand: TFPReportCustomBandWithData);
     procedure ClearDataBandLastTextValues(ABand: TFPReportCustomBandWithData);
-    procedure ProcessAggregates(const APageIdx: integer; const AData: TFPReportData);
+    procedure ProcessAggregates(APage : TFPReportCustomPage; const AData: TFPReportData);
 
 
     { these three methods are used to resolve references while reading a report from file. }
     { these three methods are used to resolve references while reading a report from file. }
     procedure ClearReferenceList;
     procedure ClearReferenceList;
@@ -1547,8 +1547,9 @@ type
     procedure DoBeginReport; virtual;
     procedure DoBeginReport; virtual;
     procedure DoEndReport; virtual;
     procedure DoEndReport; virtual;
     procedure InitializeDefaultExpressions; virtual;
     procedure InitializeDefaultExpressions; virtual;
-    procedure InitializeExpressionVariables(const APage: TFPReportCustomPage;   const AData: TFPReportData); virtual;
-    procedure CacheMemoExpressions(const APageIdx: integer; const AData: TFPReportData); virtual;
+    procedure InitializeExpressionVariables; virtual;
+    procedure InitializePageAggregateData(const APage: TFPReportCustomPage; const AData: TFPReportData); virtual;
+    procedure CacheMemoExpressions(const APage: TFPReportCustomPage); virtual;
     procedure StartRender; override;
     procedure StartRender; override;
     procedure EndRender; override;
     procedure EndRender; override;
     // stores object instances for and during layouting
     // stores object instances for and during layouting
@@ -4279,12 +4280,14 @@ begin
 end;
 end;
 
 
 procedure TFPReportCustomMemo.ParseText;
 procedure TFPReportCustomMemo.ParseText;
+
 var
 var
   lCount: integer;
   lCount: integer;
   n: TFPExprNode;
   n: TFPExprNode;
   i: integer;
   i: integer;
   str: string;
   str: string;
   lStartPos: integer;
   lStartPos: integer;
+
 begin
 begin
   { clear array and then set the correct array size }
   { clear array and then set the correct array size }
   ClearExpressionNodes;
   ClearExpressionNodes;
@@ -4292,9 +4295,7 @@ begin
     lCount := TokenCount(Text)-1
     lCount := TokenCount(Text)-1
   else
   else
     exit;
     exit;
-
   SetLength(ExpressionNodes, lCount);
   SetLength(ExpressionNodes, lCount);
-
   str := '';
   str := '';
   n := nil;
   n := nil;
   for i := 1 to lCount do
   for i := 1 to lCount do
@@ -7458,18 +7459,15 @@ begin
 end;
 end;
 
 
 
 
-procedure TFPCustomReport.ProcessAggregates(const APageIdx: integer; const AData: TFPReportData);
-
+procedure TFPCustomReport.ProcessAggregates(APage : TFPReportCustomPage; const AData: TFPReportData);
 
 
 var
 var
   i: integer;
   i: integer;
-  P : TFPReportCustomPage;
 
 
 begin
 begin
-  P:=Pages[APageIdx];
-  for I := 0 to P.BandCount-1 do
-    if P.Bands[I] is TFPReportCustomBandWithData then
-      TFPReportCustomBandWithData(P.Bands[I]).ProcessAggregates(AData);
+  for I := 0 to aPage.BandCount-1 do
+    if (aPage.Bands[I] is TFPReportCustomBandWithData) then
+      TFPReportCustomBandWithData(aPage.Bands[I]).ProcessAggregates(AData);
 end;
 end;
 
 
 procedure TFPCustomReport.ClearReferenceList;
 procedure TFPCustomReport.ClearReferenceList;
@@ -7675,6 +7673,52 @@ begin
     FExpr.Identifiers.AddFunction('PageCount', 'I', '', @BuiltinGetPageCount);
     FExpr.Identifiers.AddFunction('PageCount', 'I', '', @BuiltinGetPageCount);
 end;
 end;
 
 
+procedure TFPCustomReport.InitializePageAggregateData(const APage: TFPReportCustomPage; const AData: TFPReportData);
+
+var
+  i: Integer;
+  f: string;
+  r: TResultType;
+  d: string;
+  v: TFPReportVariable;
+  df: TFPReportDataField;
+
+begin
+  // Sanity check
+  if Not (APage.Data = AData) then
+    exit;
+  For I:=0 to FVariables.Count-1 do
+    begin
+    v:=FVariables[I];
+    v.ReleaseExpressionNodes;
+    if v.Expression<>'' then
+      begin
+      FExpr.Expression:=v.Expression;
+      FExpr.ExtractNode(v.FExpressionNode);
+      v.FIsAggregate:=v.FExpressionNode.IsAggregate;
+      if v.FExpressionNode.HasAggregate and
+      not v.FExpressionNode.IsAggregate then
+        raise EReportError.CreateFmt(SErrExprVarisbleAggregateOnWrongLevel, [v.FExpressionNode.AsString]);
+      if not v.FIsAggregate then
+        begin
+        v.FResetType:=rtNone;
+        v.FResetValueExpression:='';
+        end;
+      end;
+    if v.ResetValueExpression<>'' then
+      begin
+      FExpr.Expression := v.ResetValueExpression;
+      FExpr.ExtractNode(v.FResetValueExpressionNode);
+      end;
+    end;
+  For I:=0 to FVariables.Count-1 do
+    begin
+    v:=FVariables[I];
+    if v.Expression<>'' then
+      FExpr.Identifiers.AddVariable(v.Name, v.DataType, @v.GetRTExpressionValue);
+    end;
+end;
+
 
 
 Class function TFPCustomReport.ReportKindToResultType(const AType: TFPReportFieldKind): TResultType;
 Class function TFPCustomReport.ReportKindToResultType(const AType: TFPReportFieldKind): TResultType;
 begin
 begin
@@ -7691,104 +7735,71 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TFPCustomReport.InitializeExpressionVariables(const APage: TFPReportCustomPage; const AData: TFPReportData);
+procedure TFPCustomReport.InitializeExpressionVariables;
 
 
 var
 var
-  i: Integer;
+  i,j: Integer;
   f: string;
   f: string;
   r: TResultType;
   r: TResultType;
   d: string;
   d: string;
   v: TFPReportVariable;
   v: TFPReportVariable;
   df: TFPReportDataField;
   df: TFPReportDataField;
+  aData : TFPReportData;
 
 
 begin
 begin
-  {$ifdef gdebug}
-  writeln('********** TFPCustomReport.InitializeExpressionVariables');
-  {$endif}
-  F:='';
-  For I:=0 to FExpr.Identifiers.Count-1 do
-    f:=f+FExpr.Identifiers[i].Name+'; ';
-  if FDataAdded.IndexOf(AData)=-1 then
-  begin
-    for i := 0 to AData.DataFields.Count-1 do
+  For J:=0 to ReportData.Count-1 do
     begin
     begin
-      d := AData.Name;
-      df := AData.DataFields[i];
-      f := df.FieldName;
-      df.OnGetUsePrevValue := @DoGetUsePrevValue;
-      r := ReportKindToResultType(df.FieldKind);
-      if d <> '' then
-      begin
-        {$ifdef gdebug}
-        writeln('registering (dotted name)... '+ d+'.'+f);
-        {$endif}
-        df.ExprIdentierDef := FExpr.Identifiers.AddVariable(d+'.'+f, r, @df.GetRTValue);
-      end
-      else
-      begin
-        {$ifdef gdebug}
-        writeln('registering... '+ f);
-        {$endif}
-        df.ExprIdentierDef := FExpr.Identifiers.AddVariable(f, r, @df.GetRTValue);
-      end;
-    end;
-    FDataAdded.Add(AData);
-  end;
-  if APage.Data = AData then
-  begin
-    For I:=0 to FVariables.Count-1 do
-    begin
-      v:=FVariables[I];
-      v.ReleaseExpressionNodes;
-      if v.Expression<>'' then
+    aData:=ReportData[J].Data;
+    {$ifdef gdebug}
+    writeln('********** TFPCustomReport.InitializeExpressionVariables');
+    {$endif}
+    F:='';
+    For i:=0 to FExpr.Identifiers.Count-1 do
+      f:=f+FExpr.Identifiers[i].Name+'; ';
+    if FDataAdded.IndexOf(AData)=-1 then
       begin
       begin
-        FExpr.Expression:=v.Expression;
-        FExpr.ExtractNode(v.FExpressionNode);
-        v.FIsAggregate:=v.FExpressionNode.IsAggregate;
-        if v.FExpressionNode.HasAggregate and
-        not v.FExpressionNode.IsAggregate then
-          raise EReportError.CreateFmt(SErrExprVarisbleAggregateOnWrongLevel, [v.FExpressionNode.AsString]);
-        if not v.FIsAggregate then begin
-          v.FResetType:=rtNone;
-          v.FResetValueExpression:='';
+      for i := 0 to AData.DataFields.Count-1 do
+        begin
+        d := AData.Name;
+        df := AData.DataFields[i];
+        f := df.FieldName;
+        df.OnGetUsePrevValue := @DoGetUsePrevValue;
+        r := ReportKindToResultType(df.FieldKind);
+        if d <> '' then
+          begin
+          {$ifdef gdebug}
+          writeln('registering (dotted name)... '+ d+'.'+f);
+          {$endif}
+          df.ExprIdentierDef := FExpr.Identifiers.AddVariable(d+'.'+f, r, @df.GetRTValue);
+          end
+        else
+          begin
+          {$ifdef gdebug}
+          writeln('registering... '+ f);
+          {$endif}
+          df.ExprIdentierDef := FExpr.Identifiers.AddVariable(f, r, @df.GetRTValue);
+          end;
         end;
         end;
+      FDataAdded.Add(AData);
       end;
       end;
-      if v.ResetValueExpression<>'' then
-      begin
-        FExpr.Expression := v.ResetValueExpression;
-        FExpr.ExtractNode(v.FResetValueExpressionNode);
-      end;
-    end;
-    For I:=0 to FVariables.Count-1 do
-    begin
-      v:=FVariables[I];
-      if v.Expression<>'' then
-        FExpr.Identifiers.AddVariable(v.Name, v.DataType, @v.GetRTExpressionValue);
-    end;
-  end;
+   end;
 end;
 end;
 
 
-procedure TFPCustomReport.CacheMemoExpressions(const APageIdx: integer; const AData: TFPReportData);
+procedure TFPCustomReport.CacheMemoExpressions(const APage: TFPReportCustomPage);
+
 var
 var
   b: integer;
   b: integer;
   c: integer;
   c: integer;
   m: TFPReportCustomMemo;
   m: TFPReportCustomMemo;
-begin
-  for b := 0 to Pages[APageIdx].BandCount-1 do
-  begin
-    if Pages[APageIdx].Bands[b] is TFPReportCustomBandWithData then
-    begin
-      if TFPReportCustomBandWithData(Pages[APageIdx].Bands[b]).Data <> AData then
-        Continue;  // band is from a different data-loop
-    end;
 
 
-    for c := 0 to Pages[APageIdx].Bands[b].ChildCount-1 do
-      if Pages[APageIdx].Bands[b].Child[c] is TFPReportCustomMemo then
-      begin
-        m := TFPReportCustomMemo(Pages[APageIdx].Bands[b].Child[c]);
+begin
+  for b := 0 to aPage.BandCount-1 do
+    for c := 0 to aPage.Bands[b].ChildCount-1 do
+      if aPage.Bands[b].Child[c] is TFPReportCustomMemo then
+        begin
+        m := TFPReportCustomMemo(aPage.Bands[b].Child[c]);
         m.ParseText;
         m.ParseText;
-      end;
-  end; { bands }
+        end;
 end;
 end;
 
 
 constructor TFPCustomReport.Create(AOwner: TComponent);
 constructor TFPCustomReport.Create(AOwner: TComponent);
@@ -10886,27 +10897,16 @@ begin
       if not lData.IsOpened then
       if not lData.IsOpened then
         begin
         begin
         lData.Open;
         lData.Open;
-        Report.InitializeExpressionVariables(lPage, lData);
-        for j := 0 to Report.ReportData.Count-1 do
-          begin
-          oData:=Report.ReportData.Data[j].Data;
-          if Assigned(oData) and (oData<>lData) then
-            Report.InitializeExpressionVariables(lPage, oData);
-          end;
-        Report.CacheMemoExpressions(RTCurDsgnPageIdx, lData);
-        for j := 0 to Report.ReportData.Count-1 do
-          begin
-          oData:=Report.ReportData.Data[j].Data;
-          if Assigned(oData) and (oData<>lData) then
-            Report.CacheMemoExpressions(RTCurDsgnPageIdx, oData);
-          end;
+        // Report.InitializeExpressionVariables;
+        Report.InitializePageAggregateData(lPage,lData);
+        // Report.CacheMemoExpressions(lPage);
         end;
         end;
       lData.First;
       lData.First;
       if (not lData.EOF) and (lDsgnDetailBand.HeaderBand <> nil) then
       if (not lData.EOF) and (lDsgnDetailBand.HeaderBand <> nil) then
         ShowDataHeaderBand(lDsgnDetailBand.HeaderBand);
         ShowDataHeaderBand(lDsgnDetailBand.HeaderBand);
       while not lData.EOF do
       while not lData.EOF do
         begin
         begin
-        Report.ProcessAggregates(RTCurDsgnPageIdx,lData);
+        Report.ProcessAggregates(lPage,lData);
         Report.Variables.PrepareExpressionValues;
         Report.Variables.PrepareExpressionValues;
         inc(FDataLevelStack);
         inc(FDataLevelStack);
         ShowDataBand(lDsgnDetailBand);
         ShowDataBand(lDsgnDetailBand);
@@ -11113,31 +11113,29 @@ Var
   I : integer;
   I : integer;
   lBand : TFPReportCustomBand;
   lBand : TFPReportCustomBand;
   oData : TFPReportData;
   oData : TFPReportData;
+  lPage : TFPReportCustomPage;
+
 begin
 begin
+  lPage:=Pages[aPageIdx];
   if Assigned(aPageData) then
   if Assigned(aPageData) then
     begin
     begin
     if not aPageData.IsOpened then
     if not aPageData.IsOpened then
       aPageData.Open;
       aPageData.Open;
+    For I:=0 to Report.ReportData.Count-1 do
+      begin
+      oData:=Report.ReportData[i].Data;
+      if Assigned(oData) and (oData<>aPageData) and (not odata.IsOpened) then
+        oData.Open;
+      end;
     if IsFirstPass then
     if IsFirstPass then
       begin
       begin
-      Report.InitializeExpressionVariables(Pages[aPageIdx], aPageData);
-      for I := 0 to Report.ReportData.Count-1 do
-        begin
-        oData:=Report.ReportData.Data[i].Data;
-        if Assigned(oData) and (oData<>aPageData) then
-          Report.InitializeExpressionVariables(Pages[RTCurDsgnPageIdx],oData);
-        end;
-      Report.CacheMemoExpressions(aPageIdx, aPageData);
-      for I := 0 to Report.ReportData.Count-1 do
-        begin
-        oData:=Report.ReportData.Data[i].Data;
-        if Assigned(oData) and (oData<>aPageData) then
-          Report.CacheMemoExpressions(RTCurDsgnPageIdx, oData);
-        end;
+      Report.InitializeExpressionVariables;
+      Report.InitializePageAggregateData(lPage, aPageData);
+      Report.CacheMemoExpressions(lPage);
       end;
       end;
     aPageData.First;
     aPageData.First;
     end;
     end;
-  InitBandList(Pages[aPageIdx],aPageData);
+  InitBandList(lPage,aPageData);
   if Not Assigned(aPageData) then
   if Not Assigned(aPageData) then
     StartNewPage
     StartNewPage
   else
   else
@@ -11152,11 +11150,11 @@ begin
       if FHasGroups then
       if FHasGroups then
         HandleGroupBands;
         HandleGroupBands;
       // This must be done after the groups were handled.
       // This must be done after the groups were handled.
-      Report.ProcessAggregates(aPageIdx,aPageData);
+      Report.ProcessAggregates(lPage,aPageData);
       HandleDataBands;
       HandleDataBands;
       aPageData.Next;
       aPageData.Next;
       end;
       end;
-    Report.ProcessAggregates(aPageIdx,aPageData);
+    Report.ProcessAggregates(lPage,aPageData);
     PrepareRecord;
     PrepareRecord;
     end;
     end;
   CheckNewOrOverFlow(True);
   CheckNewOrOverFlow(True);