字段是动态生成的,字段多少也不固定啊,我想动态生成一个报表,谁源码的请让我看看,小弟在这里感激不尽啊.

解决方案 »

  1.   

    unit PrintUnit;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons, ExtCtrls,DB, ADODB, Grids, DBGrids,Printers;type
      TPrintForm = class(TForm)
        Panel1: TPanel;
        ScrollBox1: TScrollBox;
        PrintImage: TImage;
        Panel2: TPanel;
        RetBt: TBitBtn;
        BitBtn1: TBitBtn;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure RetBtClick(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
         uDataSet: TDataSet;
         uTitle,uTopLeft, uFooter: String;
         uPrintFields: array[0..36] of Integer;
         uFieldN, uPageN: Integer;
         uIsCurrency:array[0..36] of Boolean;
         uShowSum,uShowTableLine: Boolean;
         uBoots:TStringList;
        procedure PreviewDataSet(DataSet:TDataSet;Title,TopLeft,Footer:String;PrintFields:array of Integer;FieldN,PageN:Integer;IsCurrency:array of Boolean;ShowSum:Boolean;Boots:TStringList;ShowTableLine:Boolean=True;PreIt:Boolean=False);
        procedure PrintDataSet(DataSet:TDataSet;Title,TopLeft,Footer:String;PrintFields:array of Integer;FieldN,PageN:Integer;IsCurrency:array of Boolean;ShowSum:Boolean;Boots:TStringList;ShowTableLine:Boolean=True);
        procedure DrawOnCanvas(DataSet:TDataSet;Title,TopLeft,Footer:String;PrintFields:array of Integer;FieldN,PageN:Integer;IsCurrency:array of Boolean;ShowSum:Boolean;Ca:TCanvas;Boots:TStringList;ShowTableLine:Boolean=True);
      end;var
      PrintForm: TPrintForm;implementation{$R *.dfm}procedure TPrintForm.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
         Action:=caFree;
    end;procedure TPrintForm.PreviewDataSet(DataSet: TDataSet; Title,TopLeft,Footer: String;PrintFields:array of Integer;FieldN,PageN:Integer;IsCurrency:array of Boolean;ShowSum:Boolean;Boots:TStringList;ShowTableLine:Boolean=True;PreIt:Boolean=False);
    begin
         uDataSet:=DataSet;
         uTitle:=Title;
         uFooter:=Footer;
         CopyMemory(@uPrintFields,@PrintFields,SizeOf(uPrintFields));
         CopyMemory(@uIsCurrency,@IsCurrency,SizeOf(uIsCurrency));
         uBoots:=Boots;
         uFieldN:=FieldN;
         uPageN:=PageN;
         uShowSum:=ShowSum;
         uTopLeft:=TopLeft;
         uShowTableLine:=ShowTableLine;
         if PreIt then
         begin
              DrawOnCanvas(DataSet,Title,TopLeft,Footer,PrintFields,FieldN,PageN,IsCurrency,ShowSum,PrintImage.Canvas,Boots,ShowTableLine);
              ShowModal;
         end
         else
         begin
              PrintImage.Free;
              PrintDataSet(uDataSet,uTitle,uTopLeft,uFooter,uPrintFields,uFieldN,uPageN,uIsCurrency,uShowSum,uBoots,uShowTableLine);
              Close;
         end;
    end;
      

  2.   

    procedure TPrintForm.DrawOnCanvas(DataSet: TDataSet; Title,TopLeft,Footer: String;PrintFields:array of Integer;
      FieldN,PageN: Integer;IsCurrency:array of Boolean;
    ShowSum:Boolean; Ca: TCanvas;Boots:TStringList;ShowTableLine:Boolean=True);
    var
         LDiv,CellDiv,CellLeft,CellTop,ypos,PageWidth,h,w,sw,i:Integer;
         FW:array[0..36] of Integer;
         SUM:array[0..36] of Currency;
         TopPos,LeftPos:Integer;
    begin
         TopPos:=60;
         LeftPos:=80;
         CellLeft:=10;
         CellTop:=3;
         CellDiv:=20;
         LDiv:=15;
         //统计列宽度
         with Ca do
         begin
              Font.Name:='宋体';
              Font.Size:=-11;
              h:=TextHeight('奇');//求行高
              for i:=0 to FieldN-1 do
              begin
                   SUM[i]:=0;
                   FW[i]:=TextWidth(DataSet.Fields[PrintFields[i]].DisplayLabel)+CellDiv;
              end;
              DataSet.First;
              while Not DataSet.Eof do
              begin
                   for i:=0 to FieldN-1 do
                   begin
                        w:=TextWidth(Trim(DataSet.Fields[PrintFields[i]].AsString));
                        if IsCurrency[i] And ShowSum then
                        begin
                             SUM[i]:=SUM[i]+DataSet.Fields[PrintFields[i]].AsCurrency;
                             sw:=TextWidth(CurrToStr(SUM[i]));
                             if sw>w then w:=sw;
                        end;
                        Inc(w,CellDiv);
                        if w>FW[i] then FW[i]:=w;
                   end;
                   DataSet.Next;
              end;
         end;//统计列宽度结束     //定位每列起始位置,求行宽
         PageWidth:=0;
         for i:=0 to FieldN-1 do
         begin
              Inc(PageWidth,FW[i]);
              FW[i]:=LeftPos+PageWidth-FW[i]+i*CellDiv;
         end;
         PageWidth:=pagewidth+FieldN*CellDiv;//定位每列起始位置,求行宽--结束
         DataSet.First;
         with Ca do
         begin
              //绘制标题
              Pen.Width :=3;
              Pen.Color :=RGB(255,0,0);
              Font.Size :=-16;
              Font.Style := Font.Style+[fsBold];
              TextOut(LeftPos+(PageWidth-TextWidth(Title))div 2,TopPos,Title);
              ypos:=TextHeight('奇')+TopPos;
              MoveTo(LeftPos+(PageWidth-TextWidth(Title))div 2,ypos+LDiv);
              LineTo(LeftPos+((PageWidth-TextWidth(Title))div 2)+TextWidth(Title),ypos+LDiv);
              Font.Style := Font.Style-[fsBold];
              //绘制标题结束
              Inc(ypos,3*LDiv);  //定位第一行垂直位置
              Font.Size :=-12;
              Font.Style :=[fsBold];
              TextOut(LeftPos,ypos-2,TopLeft);
              Inc(ypos,TextHeight('奇')+2);
              Font.Style :=[];
              //绘制报表
              Font.Size :=-11;
              DataSet.First;
              if not ShowTableLine then
              begin
                   MoveTo(LeftPos,ypos-1);
                   LineTo(LeftPos+PageWidth,ypos-1);
                   Inc(ypos,LDiv Div 2);
              end;
              MoveTo(LeftPos,ypos-1);
              LineTo(LeftPos+PageWidth,ypos-1);
              //绘制列表头
              for i:=0 to FieldN-1 do
              begin
                   TextOut(FW[i]+CellLeft,ypos+CellTop,DataSet.Fields[PrintFields[i]].DisplayLabel);
                   if ShowTableLine then
                   begin
                        MoveTo(FW[i],ypos);
                        LineTo(FW[i],ypos+h+LDiv);
                   end;
              end;
              if ShowTableLine then
              begin
                   MoveTo(LeftPos+PageWidth,ypos);
                   LineTo(LeftPos+PageWidth,ypos+h+LDiv);
              end;
              //绘制列表头结束
              Inc(ypos,h+LDiv);
              while Not DataSet.Eof do
              begin
                   if ShowTableLine then
                   begin
                        MoveTo(LeftPos,ypos-1);
                        LineTo(LeftPos+PageWidth,ypos-1);
                   end;
                   for i:=0 to FieldN-1 do
                   begin
                        TextOut(FW[i]+CellLeft,ypos+CellTop,DataSet.Fields[PrintFields[i]].AsString);
                        if ShowTableLine then
                        begin
                             MoveTo(FW[i],ypos);
                             LineTo(FW[i],ypos+h+LDiv);
                        end;
                   end;
                   if ShowTableLine then
                   begin
                        MoveTo(LeftPos+PageWidth,ypos);
                        LineTo(LeftPos+PageWidth,ypos+h+LDiv);
                   end;
                   inc(ypos,h+LDiv);
                   DataSet.Next;
              end;
              Pen.Width :=2;
              Pen.Color :=clBlue;
              if ShowTableLine then
              begin
                   Pen.Width :=3;
                   Pen.Color :=clRed;
              end;
              MoveTo(LeftPos,ypos-1);
              LineTo(LeftPos+PageWidth,ypos-1);
              Pen.Width :=3;
              Pen.Color :=clRed;
              if ShowSum then
              begin
                   TextOut(FW[0]+CellLeft,ypos+CellTop,'合计');
                   if ShowTableLine then
                   begin
                        MoveTo(FW[0],ypos);
                        LineTo(FW[0],ypos+h+LDiv);
                   end;
                   for i:=1 to FieldN-1 do
                   begin
                        if IsCurrency[i] then TextOut(FW[i]+CellLeft,ypos+CellTop,CurrToStr(SUM[i]));
                        if ShowTableLine then
                        begin
                             MoveTo(FW[i],ypos);
                             LineTo(FW[i],ypos+h+LDiv);
                        end;
                   end;
                   if ShowTableLine then
                   begin
                        MoveTo(LeftPos+PageWidth,ypos);
                        LineTo(LeftPos+PageWidth,ypos+h+LDiv);
                   end;
                   inc(ypos,h+LDiv);
                   MoveTo(LeftPos,ypos);
                   LineTo(LeftPos+PageWidth,ypos);
                   if not ShowTableLine then
                   begin
                        Inc(ypos,LDiv Div 2);
                        MoveTo(LeftPos,ypos);
                        LineTo(LeftPos+PageWidth,ypos);
                   end;
              end;//绘制报表结束
              Font.Size :=-11;
              if Boots<>nil then
              for i:=0 to Boots.Count-1 do
              begin
                   TextOut(LeftPos,ypos+Round(LDiv*1.8),Boots[i]);
                   Inc(ypos,TextHeight('奇'));
              end;
              Font.Size :=-12;
              Font.Style :=[fsBold];
              TextOut(LeftPos+(PageWidth-TextWidth(Footer))div 2,ypos+Round(LDiv*1.8)+20,Footer);//绘制页尾
         end;
    end;procedure TPrintForm.RetBtClick(Sender: TObject);
    begin
         Close;
    end;procedure TPrintForm.PrintDataSet(DataSet: TDataSet; Title,TopLeft, Footer: String;
      PrintFields: array of Integer; FieldN, PageN: Integer;
      IsCurrency: array of Boolean; ShowSum: Boolean;Boots:TStringList;ShowTableLine:Boolean=True);
    begin
         Printer.BeginDoc;
         DrawOnCanvas(DataSet,Title,TopLeft,Footer,PrintFields,FieldN,PageN,IsCurrency,ShowSum,Printer.Canvas,Boots,ShowTableLine);
         Printer.EndDoc;
    end;procedure TPrintForm.BitBtn1Click(Sender: TObject);
    begin
         PrintDataSet(uDataSet,uTitle,uTopLeft,uFooter,uPrintFields,uFieldN,uPageN,uIsCurrency,uShowSum,uBoots,uShowTableLine)
    end;procedure TPrintForm.FormCreate(Sender: TObject);
    begin
         PrintImage.Width :=Printer.PageWidth;
    end;end.
      

  3.   

    这个可以满足你的要求!下载地址:http://www.sailprint.com
    简介:  SailPrint打印组件是一套VCL打印控件。目前最新版本是3.0,可以打印DBGrid,StringGrid,ListView以及直接打印数据源。SailPrint有以下几大特点:    一、SailPrint的特点是快速生成报表,灵活易用,只需几分钟即可完成漂亮的报表。    二、最终用户可以修改报表,开发人员只需调用setoption 这个过程即可让最终用户设置报表。   SailPrint并且保留了设置窗口的源代码,开发人员也可以自己订制设置窗口,这样可以可以跟系统   风格更为一致。包括打印预览窗口也保留了源代码,窗口样式可以随意修改。    三、自动折行功能,估计大家都理解不用多说了,好不好用一试便知。    四、主细表功能,这是新加入的功能,并且支持公式统计。支持的函数有:sum,count,avg以及函数之间   的加减乘除。        例如:sum([字段1])/count([字段2])    五、支持流存储,可以将报表的设置或者将整个报表保存为流,这样可以简单的将报表设置保存到数据   库中,当然也可以保存成文件。这样最终用户修改了报表设置可以方便的保存。    六、多表头功能,设置方法可能与其他控件不一样。大家可以下载试一下。    以上是一些主要特点,还有一些细小功能就不一一列举了,大家下载体验一下吧。