Estimating the height of Expanding Bands

The following code will allow you to estimate the height of an expanding band before it prints.

Estimating the height of Expanding Bands
========================================

The following code will allow you to estimate the height of an expanding band before it prints.


This is an unofficial change to QR3 source code.
It will break compatibility with TChart.

This adds a procedure 'ExpandedHeight' to class TQRCustomBand.
You can use it to stop a band busting a page like this -

procedure Trepform.DetailBand1BeforePrint(Sender: TQRCustomBand;
  var PrintBand: Boolean);
var
    th : extended;
begin
    detailband1.ExpandedHeight( th );
    // force a new page if required.
    if th > quickrep1.availablespace then
             quickrep1.NewColumn;

end;

The Changes.
Two files are amended - qrctrls.pas and quickrpt.pas

1. quickrpt.pas

1.1 declare a new Private var in class TQRCustomBand
private
    FExpandedHeight : extended;
    ..
    ..
    
1.2 Move the declaration of 'Function AvailableSpace' to Public.
    
1.3
Add this Public method to the class TQRCustomBand

procedure TQRCustomBand.ExpandedHeight( var NewHeight : extended );
var
  BottomGap, I : integer;
  OrgLength, ScrToPrinter  : extended;
  theight : extended;
begin
      ScrToPrinter := parentreport.qrprinter.yfactor *254 / screen.pixelsperinch;
      FExpandedheight := 0;
      bottomgap := 0;
      for I := 0 to ControlCount - 1 do
      begin
          if Controls[I] is TQRDBText then
          begin
             if TQRDBText(Controls[I]).Enabled and TQRDBText(Controls[I]).Autostretch then
             begin
                TQRDBText(Controls[I]).GetExpandedHeight( theight );
                theight := theight + (TQRDBText(Controls[I]).top*ScrToPrinter);
                if theight > FExpandedheight then
                begin
                   FExpandedheight := theight;
                   // bottomgap is in SCREEN pixels
                   bottomgap := self.height -TQRDBText(Controls[I]).top -
                                              TQRDBText(Controls[I]).height + 1;
                end;
            end;
          end;
      end;
      if bottomgap < 0 then bottomgap := 0;
      if (parentreport.qrprinter.Destination = qrdMetafile) then
      begin
              theight := bottomgap + trunc(FExpandedheight);
              theight := theight / ParentReport.QRPrinter.YFactor;
      end
      else
      begin
              // FExpandedheight is in printer pixels
              bottomgap := trunc(bottomgap * ScrToPrinter); // -> printer pixels
              theight := bottomgap + trunc(FExpandedheight);
      end;
      newheight := theight;
end;


2. qrctrls.pas

2.1 Add public method 'GetExpandedHeight' to Class TQRDBText.

procedure TQRDBText.GetExpandedHeight(var newheight : extended );
var
     Nlines : integer;
     lineheight : extended;
begin
      self.getfieldstring( FPrintCaption );
      FormatLines;
      if parentreport.QRPrinter.canvas <> nil then
      begin
             parentreport.QRPrinter.canvas.font := self.font;
             LineHeight := parentreport.QRPrinter.Canvas.TextHeight('W');
      end
      else
             LineHeight := self.Canvas.TextHeight('W');

      Nlines := FFormattedLines.Count;
      newheight := nlines * (lineheight + 2);
end;

2.2 Add this new public method to class TQRDBText

procedure TQRDBText.GetFieldString( var DataStr : string);
begin
  if IsEnabled then
  begin
    if FieldOK then
    begin
      if FDataSet.DefaultFields then
        Field := FDataSet.Fields[FieldNo];
    end
    else
      Field := nil;
    if assigned(Field) then
    begin
      try
        if (Field is TMemoField) or
           (Field is TBlobField) then
        begin
          Lines.Text := TMemoField(Field).AsString;
        end
        else
          if (Mask = '') or (Field is TStringField) then
            if not (Field is TBlobField) then
              DataStr := Field.DisplayText
            else
              DataStr := Field.AsString
          else
          begin
            if (Field is TIntegerField) or
               (Field is TSmallIntField) or
               (Field is TWordField) then
               DataStr := FormatFloat(Mask, TIntegerField(Field).Value * 1.0)
            else
              if (Field is TFloatField) or
                 (Field is TCurrencyField) or
                 (Field is TBCDField) then
                 DataStr := FormatFloat(Mask,TFloatField(Field).Value)
              else
                if (Field is TDateTimeField) or
                   (Field is TDateField) or
                   (Field is TTimeField) then
                  DataStr := FormatDateTime(Mask,TDateTimeField(Field).Value);
          end;
      except
        DataStr := '';
      end;
    end else
      DataStr := '';
  end;
end;