我参考了ReportMachine的WebReport(简单示例页面:http://jngs.3322.org/webreport/asp/simplelist.asp),正在尝试把FastReport封装成ActiveDLL,客户端利用B/S以ActiveX形式显示报表。基本想法是:1、服务器端的ActiveDLL动作:Load('.frf')->TfrReport.EMFPages.SaveToStream
这样包含数据的.frp文件就以流保存下来。
2、服务器端的ActiveDLL通过ASP的Reponse.Write "数据流",写到页面上隐藏的TextArea中;
3、客户端的ActiveX的动作:LoadFromStream,即可显示报表;但在第二步中,我遇到了问题,即TfrReport.EMFPages.SaveToStream得到的Stream是二进制数据,我的想法是把二进制数据流中的每个byte读出,然后转换为AnsiString(还可以继续压缩、加密),但是在客户端的ActiveX中如何把AnsiString还原成Binary Stream呢?目前我找到的例子是如果将文件在二进制格式和AnsiString格式之间转换,但很显然,通过文件转换在这里完全是多余的,因为我对Stream的操作不是很熟悉,所以想请教大家不吝解答!谢谢!题外话,除了ReportMachine是这样实现WebReport的,我在网上发现一个名叫数巨报表也是采用相同的方法实现的,我都觉得和FastReport都有点关系......

解决方案 »

  1.   

    附Binary Stream转换成AnsiString的例子:
    procedure TForm1.ConvertBinStream(var Data; 
                                      Count: Cardinal; 
                                      var inStr: AnsiString);
    var
        aStr: AnsiString;
        p: PChar;
        i: Integer;
    const 
        HexChars: PChar = '0123456789ABCDEF';
    begin
        p    := @Data;
        for i := 0 to Count - 1 do
        begin
            inStr   := inStr + HexChars[(Ord(p[i]) shr 4) and $F];
            inStr   := inStr + HexChars[Ord(p[i]) and $F];
        end;
    end;    ///////////////////////////////
        FrReport.PrepareReport;
        aStream := TMemoryStream.Create();
        FrReport.EMFPages.SaveToStream(aStream );
        aStream.seek(0, soFromBeginning);
        ConvertBinStream(aStream.Memory^, aStream.Size, sOutPut)
      

  2.   

    自己已经解决。function TEnginee.WriteBinaryStream(Value: TStream):AnsiString;
    var
        Text: AnsiString;
        Stream: TMemoryStream;
    begin
        SetLength(Text, (Value.Size - Value.Position) * 2);
        if Length(Text) > 0 then
        begin
            try
                if Value is TMemoryStream then
                    Stream := TMemoryStream(Value)
                else
                    Stream := TMemoryStream.Create;            if Stream <> Value then
                begin
                    Stream.CopyFrom(Value, Value.Size - Value.Position);
                    Stream.Position := 0;
                end;
                BinToHex(PChar(Integer(Stream.Memory) + Stream.Position), PChar(Text),
                Stream.Size - Stream.Position);
            finally
                if Value <> Stream then
                    Stream.Free;
            end;
        end;    result    := Text;
    end;procedure TEnginee.ReadBinaryStream(Text: AnsiString; Value: TStream);
    var
        Stream: TMemoryStream;
        Pos: Integer;
    begin
        if Text <> '' then
        begin
            if Value is TMemoryStream then
                Stream := TMemoryStream(Value)
            else
                Stream := TMemoryStream.Create;        try
                Pos := Stream.Position;
                Stream.SetSize(Stream.Size + Length(Text) div 2);
                HexToBin(PChar(Text), PChar(Integer(Stream.Memory) + Stream.Position), Length(Text) div 2);
                Stream.Position := Pos;
                if Value <> Stream then
                    Value.CopyFrom(Stream, Length(Text) div 2);
            finally
                if Value <> Stream then
                    Stream.Free;
            end;
        end;
    end;