⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 teestore.pas

📁 Delphi TeeChartPro.6.01的源代码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{*********************************************}
{  TeeChart Storage functions                 }
{  Copyright (c) 1997-2003 by David Berneda   }
{  All rights reserved                        }
{*********************************************}
unit TeeStore;
{$I TeeDefs.inc}

interface

Uses {$IFNDEF LINUX}
     Windows,
     {$ENDIF}
     Classes, TeeProcs, TeEngine, Chart;

{ Read a Chart from a file ( Chart1,'c:\demo.tee' ) }
Procedure LoadChartFromFile(Var AChart:TCustomChart; Const AFileName:String);

{ Write a Chart to a file ( Chart1,'c:\demo.tee' ) }
Procedure SaveChartToFile(AChart:TCustomChart; Const AFileName:String;
                          IncludeData:Boolean=True;
                          TextFormat:Boolean=False);

{ The same using TStream components (good for BLOB fields, etc)  }
Procedure LoadChartFromStream(Var AChart:TCustomChart; AStream:TStream);

Procedure SaveChartToStream(AChart:TCustomChart; AStream:TStream;
                            IncludeData:Boolean=True;
                            TextFormat:Boolean=False);

{ (Advanced) Read charts and check for errors  }
{ return True if ok, False to stop loading }
type TProcTeeCheckError=function(const Message: string): Boolean of object;

Procedure LoadChartFromStreamCheck( Var AChart:TCustomChart;
                                    AStream:TStream;
                                    ACheckError:TProcTeeCheckError=nil;

                                    // For compatibility with version 5 saved
                                    // charts.
                                    // Pass FALSE to skip past-reading
                                    TryReadData:Boolean=True  // 6.01
                               );

Procedure LoadChartFromFileCheck( Var AChart:TCustomChart;
                                  Const AName:String;
                                  ACheckError:TProcTeeCheckError
                                  );

// Convert a binary *.tee file to text format
Procedure ConvertTeeFileToText(Const InputFile,OutputFile:String);

// Convert a text *.tee file to binary format
Procedure ConvertTeeFileToBinary(Const InputFile,OutputFile:String);

type
  TSeriesData=class(TTeeExportData)
  private
    FIncludeColors : Boolean;
    FIncludeIndex  : Boolean;
    FIncludeHeader : Boolean;
    FIncludeLabels : Boolean;
    FChart         : TCustomChart;
    FSeries        : TChartSeries;

    IFormat        : TeeFormatFlag;
    Procedure Prepare;
  protected
    Function MaxSeriesCount:Integer;
    Function PointToString(Index:Integer):String; virtual;
  public
    Constructor Create(AChart:TCustomChart; ASeries:TChartSeries=nil); virtual;

    Function AsString:String; override;

    property Chart:TCustomChart read FChart write FChart;
    property IncludeColors:Boolean read FIncludeColors write FIncludeColors default False;
    property IncludeHeader:Boolean read FIncludeHeader write FIncludeHeader default False;
    property IncludeIndex:Boolean read FIncludeIndex write FIncludeIndex default False;
    property IncludeLabels:Boolean read FIncludeLabels write FIncludeLabels default True;
    property Series:TChartSeries read FSeries write FSeries;
  end;

  TSeriesDataText=class(TSeriesData)
  private
    FTextDelimiter : {$IFDEF CLX}WideChar{$ELSE}Char{$ENDIF};
  protected
    Function PointToString(Index:Integer):String; override;
  public
    Constructor Create(AChart:TCustomChart;
                       ASeries:TChartSeries=nil); override;
    Function AsString:String; override;
    property TextDelimiter:{$IFDEF CLX}WideChar{$ELSE}Char{$ENDIF}
           read FTextDelimiter write FTextDelimiter default TeeTabDelimiter;
  end;

  TSeriesDataXML=class(TSeriesData)
  public
    Constructor Create(AChart:TCustomChart; ASeries:TChartSeries=nil); override;
    Function AsString:String; override;
  published
    property IncludeHeader default True;
  end;

  TSeriesDataHTML=class(TSeriesData)
  protected
    Function PointToString(Index:Integer):String; override;
  public
    Function AsString:String; override;
  end;

  TSeriesDataXLS=class(TSeriesData)
  public
    Procedure SaveToStream(AStream:TStream); override;
  end;

Const TeeTextLineSeparator= #13#10;

// Makes sure AFileName contains the ".tee" extension
Function TeeCheckExtension(Const AFileName:String):String;

implementation

Uses {$IFDEF CLX}
     QGraphics, QClipbrd,
     {$ELSE}
     Graphics, Clipbrd,
     {$ENDIF}
     SysUtils, TeCanvas, TeeConst;

Const MagicTeeFile  =$3060;
      {$IFDEF D7}
      VersionTeeFile=$0157; { Delphi 7 }
      {$ELSE}
      {$IFDEF CLX}
      VersionTeeFile=$0145; { Delphi 6 CLX / Kylix }
      {$ELSE}
      {$IFDEF D6}
      VersionTeeFile=$0150; { Delphi 6 }
      {$ELSE}
      {$IFDEF C5}
      VersionTeeFile=$0140; { C++ Builder 5 }
      {$ELSE}
      {$IFDEF D5}
      VersionTeeFile=$0130; { Delphi 5 }
      {$ELSE}
      {$IFDEF C4}
      VersionTeeFile=$0125; { C++ Builder 4 }
      {$ELSE}
      {$IFDEF D4}
      VersionTeeFile=$0120; { Delphi 4 }
      {$ELSE}
      {$IFDEF C3}
      VersionTeeFile=$0110; { C++ Builder 3 }
      {$ELSE}
      VersionTeeFile=$0100; { Delphi 3 }
      {$ENDIF}
      {$ENDIF}
      {$ENDIF}
      {$ENDIF}
      {$ENDIF}
      {$ENDIF}
      {$ENDIF}
      {$ENDIF}


type
  TTeeFileHeader=Packed Record
    Magic   : Word; { secure checking }
    Version : Word; { Chart file version }
  end;

  TSeriesAccess=class(TChartSeries);

// compatibility with previous versions saved *.tee files
Procedure ReadChartData(AStream:TStream; AChart:TCustomChart);
Var t : Integer;
begin { read each Series data }
  for t:=0 to AChart.SeriesCount-1 do TSeriesAccess(AChart[t]).ReadData(AStream);
end;

{ Special reader to skip Delphi 3 or 4 new properties when
  reading Charts in Delphi 1.0 or 2.0 }
type TChartReader=class(TReader)
     protected
       function Error(const Message: string): Boolean; override;
     public
       CheckError:TProcTeeCheckError;
     end;

function TChartReader.Error(const Message: string): Boolean;
begin
  if Assigned(CheckError) then result:=CheckError(Message)
                          else result:=True;
end;

function TeeFileIsValid(Stream:TStream):Boolean;
var Pos : Integer;
    Header  : TTeeFileHeader;
begin
  Pos := Stream.Position;
  Stream.Read(Header,SizeOf(Header));
  { check is a valid Tee file }
  result:=Header.Magic=MagicTeeFile;
  if not result then
     result:=Char(Header.Magic) in ['o','O'];
  Stream.Position := Pos;
end;

function TeeFileIsBinary(Stream:TStream):Boolean;
var Pos : Integer;
    Header  : TTeeFileHeader;
begin
  Pos := Stream.Position;
  Stream.Read(Header,SizeOf(Header));
  { check is a valid Tee file }
  result:=Header.Magic=MagicTeeFile;
  Stream.Position := Pos;
end;

Procedure TeeWriteHeader(AStream:TStream);
var Header  : TTeeFileHeader;
begin
  { write file header, with "magic" number and version }
  Header.Magic:=MagicTeeFile;
  Header.Version:=VersionTeeFile;
  AStream.Write(Header,SizeOf(Header));
end;

Procedure ConvertTeeToBinary(SInput,SOutput:TStream);
begin
  if TeeFileIsValid(SInput) then
  begin
    if not TeeFileIsBinary(SInput) then
    begin
      TeeWriteHeader(SOutput);
      ObjectTextToBinary(SInput,SOutput);
    end
    else
       SOutput.CopyFrom(SInput,SInput.Size);
  end
  else Raise ChartException.Create(TeeMsg_WrongTeeFileFormat); { 5.01 }
end;

Procedure ConvertTeeToText(SInput,SOutput:TStream);
var Header  : TTeeFileHeader;
begin
  if TeeFileIsValid(SInput) then
  begin
    if TeeFileIsBinary(SInput) then
    begin
      SInput.Read(Header,SizeOf(Header));
      ObjectBinaryToText(SInput,SOutput);
    end
    else SOutput.CopyFrom(SInput,SInput.Size);
  end
  else Raise ChartException.Create(TeeMsg_WrongTeeFileFormat); { 5.01 }
end;

{ Reads Series and Points from a Stream into a Chart }
Procedure LoadChartFromStreamCheck( Var AChart:TCustomChart;
                                    AStream:TStream;
                                    ACheckError:TProcTeeCheckError=nil;
                                    TryReadData:Boolean=True);
var Reader  : TChartReader;
    tmp     : TCustomChart;
    tmpName : TComponentName;
    DestStream : TStream;
    Header  : TTeeFileHeader;
begin

  { 5.01 commented: This allows saving more things to the AStream
                    before calling here.
  AStream.Position:=0; <--- commented out
  }

  if AStream.Size=0 then
     raise ChartException.Create(TeeMsg_EmptyTeeFile);

  if TeeFileIsValid(AStream) then
  begin
    { disable auto-repaint }
    AChart.AutoRepaint:=False;

    { remove all child Series and Tools }
    AChart.FreeAllSeries;
    AChart.Tools.Clear;

    DestStream:=AStream;

    if not TeeFileIsBinary(AStream) then
    begin
      AStream:=TMemoryStream.Create;
      ConvertTeeToBinary(DestStream,AStream);
      AStream.Position:=0;
    end;

    AStream.Read(Header,SizeOf(Header));

    { read the Chart, Series and Tools properties }
    Reader:=TChartReader.Create(AStream, 4096);
    try
      Reader.CheckError:=ACheckError;
      tmp:=AChart;
      try
        tmpName:=tmp.Name; { 5.01 preserve the Chart Name }
        Reader.ReadRootComponent(AChart);
      finally
        AChart:=tmp;
      end;

      if tmpName<>'' then
         AChart.Name:=tmpName; { 5.01 set back the same Chart Name }
    finally
      Reader.Free;
    end;

    if Assigned(AChart) then
    begin
      // compatibility with previous versions saved *.tee files
      // read the Series points
      if TryReadData and (AStream.Size>AStream.Position) then
         ReadChartData(AStream,AChart);

      (*
      { change each Series ownership }
      { 5.01 Doing this breaks TeeFunction objects as DataSource !! }
      if AChart.Owner<>nil then
      for t:=0 to AChart.SeriesCount-1 do
      begin
        AChart[t].Owner.RemoveComponent(AChart[t]);
        AChart.Owner.InsertComponent(AChart[t]);
      end;
      *)

      { restore AutoRepaint }
      AChart.AutoRepaint:=True;
      AChart.Invalidate;
    end
    else raise ChartException.Create(TeeMsg_InvalidTeeFile);

    if DestStream<>AStream then AStream.Free;
  end
  else { is the Stream.Position maybe not zero ? }
    raise ChartException.Create(TeeMsg_WrongTeeFileFormat);
end;

Procedure LoadChartFromStream(Var AChart:TCustomChart; AStream:TStream);
begin
  LoadChartFromStreamCheck(AChart,AStream);
end;

Function TeeCheckExtension(Const AFileName:String):String;
begin  // Append ".tee" to filename if the extension is missing
  if ExtractFileExt(AFileName)='' then
     result:=AFileName+'.'+TeeMsg_TeeExtension
  else
     result:=AFileName;
end;

Procedure LoadChartFromFileCheck( Var AChart:TCustomChart;
                                  Const AName:String;
                                  ACheckError:TProcTeeCheckError );
Var tmp : TFileStream;
begin
  tmp:=TFileStream.Create(TeeCheckExtension(AName),fmOpenRead or fmShareDenyWrite);
  try
    LoadChartFromStreamCheck(AChart,tmp,ACheckError);
  finally
    tmp.Free;
  end;
end;

Procedure LoadChartFromFile(Var AChart:TCustomChart; Const AFileName:String);
begin
  LoadChartFromFileCheck(AChart,AFileName,nil);
end;

Procedure ConvertTeeFile(Const InputFile,OutputFile:String; ToText:Boolean);
var SInput  : TFileStream;
    SOutput : TFileStream;
begin
  SInput:=TFileStream.Create(InputFile,fmOpenRead);
  try
    SOutput:=TFileStream.Create(OutputFile,fmCreate);
    try
      if ToText then ConvertTeeToText(SInput,SOutput)
                else ConvertTeeToBinary(SInput,SOutput);
    finally
      SOutput.Free;
    end;
  finally
    SInput.Free;
  end;
end;

{ Create a text file from a binary *.tee file }
Procedure ConvertTeeFileToText(Const InputFile,OutputFile:String);
begin
  ConvertTeeFile(InputFile,OutputFile,True);
end;

{ Create a binary file from a text *.tee file }
Procedure ConvertTeeFileToBinary(Const InputFile,OutputFile:String);
begin
  ConvertTeeFile(InputFile,OutputFile,False);
end;

{
Procedure WriteChartData(AStream:TStream; AChart:TCustomChart);
Var t : Integer;
begin
  for t:=0 to AChart.SeriesCount-1 do TSeriesAccess(AChart[t]).WriteData(AStream);
end;
}

{$IFDEF D5}
type TWriterAccess=class(TWriter);
{$ENDIF}

Procedure SaveChartToStream(AChart:TCustomChart; AStream:TStream;
                            IncludeData:Boolean=True;
                            TextFormat:Boolean=False);
var tmp      : TCustomChart;
    OldName  : TComponentName;
    {$IFDEF D5}
    Writer   : TWriter;
    tmpOwner : TComponent;
    {$ENDIF}
    DestStream : TStream;
    t          : Integer;
begin
  DestStream:=AStream;

  if TextFormat then AStream:=TMemoryStream.Create;

  TeeWriteHeader(AStream);

  { write the Chart, Series and Tools properties }
  tmp:=AChart;
  if not (csDesigning in AChart.ComponentState) then
  begin
    OldName:=AChart.Name;
    AChart.Name:='';
  end;

  for t:=0 to AChart.SeriesCount-1 do
  with TSeriesAccess(AChart[t]) do
      if IncludeData then ForceSaveData:=True
                     else DontSaveData:=True;

  try
    {$IFDEF D5}
    Writer := TWriter.Create(AStream, 4096);
    try
      tmpOwner:=AChart.Owner;
      if not Assigned(tmpOwner) then tmpOwner:=AChart;
      TWriterAccess(Writer).SetRoot(tmpOwner);  { 5.01 }
      Writer.WriteSignature;
      Writer.WriteComponent(AChart);
    finally
      Writer.Free;
    end;
    {$ELSE}
    AStream.WriteComponent(AChart);
    {$ENDIF}

  finally
    for t:=0 to AChart.SeriesCount-1 do
    with TSeriesAccess(AChart[t]) do
    begin
      ForceSaveData:=False;
      DontSaveData:=False;
    end;
  end;

  AChart:=tmp;
  if not (csDesigning in AChart.ComponentState) then
     AChart.Name:=OldName;

  { write the Series data points }
  //if IncludeData then WriteChartData(AStream,AChart);

  if TextFormat then
  begin
    AStream.Position:=0;
    ConvertTeeToText(AStream,DestStream);
    AStream.Free;
  end;
end;

Procedure SaveChartToFile(AChart:TCustomChart; Const AFileName:String;
                          IncludeData:Boolean=True;
                          TextFormat:Boolean=False);
Var tmp : TFileStream;
begin
  tmp:=TFileStream.Create(TeeCheckExtension(AFileName),fmCreate);
  try
    SaveChartToStream(AChart,tmp,IncludeData,TextFormat);
  finally
    tmp.Free;
  end;
end;

Function ColorToHex(Color:TColor):String;
begin
  with RGBValue(ColorToRGB(Color)) do
    result:=Format('#%.2x%.2x%.2x',[rgbtRed,rgbtGreen,rgbtBlue]);
end;

{ TSeriesData }
Constructor TSeriesData.Create(AChart:TCustomChart; ASeries:TChartSeries=nil);
begin
  inherited Create;
  FChart:=AChart;
  FSeries:=ASeries;
  FIncludeLabels:=True;
end;

Procedure TSeriesData.Prepare;
var tmp : TChartSeries;
begin
  if Assigned(FSeries) then tmp:=FSeries
                       else if FChart.SeriesCount>0 then tmp:=Chart[0]
                                                    else tmp:=nil;
  if Assigned(tmp) then IFormat:=SeriesGuessContents(tmp);
  if not IncludeLabels then Exclude(IFormat,tfLabel);
  if not IncludeColors then Exclude(IFormat,tfColor);
end;

Function TSeriesData.AsString:String;
Var tmp : Integer;
    t   : Integer;
begin
  Prepare;
  result:='';
  tmp:=MaxSeriesCount;
  for t:=0 to tmp-1 do result:=result+PointToString(t)+TeeTextLineSeparator;
end;

Function TSeriesData.MaxSeriesCount:Integer;
var t : Integer;
begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -