• <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        當(dāng)前位置:雨林木風(fēng)下載站 > 技術(shù)開發(fā)教程 > 詳細(xì)頁面

        用Delphi編寫數(shù)據(jù)報(bào)存儲(chǔ)控件

        用Delphi編寫數(shù)據(jù)報(bào)存儲(chǔ)控件

        更新時(shí)間:2022-05-09 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

        一、概述
        在用Delphi編寫數(shù)據(jù)庫程序時(shí),經(jīng)常涉及到數(shù)據(jù)的導(dǎo)入和導(dǎo)出操作,如:將大型數(shù)據(jù)庫中的數(shù)據(jù)存儲(chǔ)為便攜文件,以便于出外閱讀;將存儲(chǔ)在文件中的數(shù)據(jù)信息,導(dǎo)入到另外的數(shù)據(jù)庫中;而且,通過將數(shù)據(jù)庫中的數(shù)據(jù)存儲(chǔ)為數(shù)據(jù)文件,更便于程序內(nèi)部和程序間交換數(shù)據(jù),避免通過內(nèi)存交換數(shù)據(jù)的煩瑣步驟,例如在筆者編寫的通用報(bào)表程序中即以該控件作為數(shù)據(jù)信息傳遞的載體。
        二、基本思路
        作為數(shù)據(jù)報(bào)存儲(chǔ)控件,應(yīng)能夠存儲(chǔ)和讀入數(shù)據(jù)集的基本信息(如:字段名,字段的顯示名稱,字段的數(shù)據(jù)類型,記錄數(shù),字段數(shù),指定記錄指定字段的當(dāng)前值等),應(yīng)能夠提供較好的封裝特性,以便于使用。
        基于此,筆者利用Delphi5.0面向?qū)ο蟮奶攸c(diǎn),設(shè)計(jì)開發(fā)了數(shù)據(jù)報(bào)存儲(chǔ)控件。
        三、實(shí)現(xiàn)方法
        編寫如下代碼單元:
        unit IbDbFile;
        interface
        Uses Windows, SysUtils, Classes, Forms, Db, DbTables, Dialogs;
        Const
        Flag = '數(shù)據(jù)報(bào)-吉星軟件工作室';
        Type
        TDsException = Class(Exception);
        TIbStorage = class(TComponent)
        private
        FRptTitle: string; //存儲(chǔ)數(shù)據(jù)報(bào)說明
        FPageHead: string; //頁頭說明
        FPageFoot: string; //爺腳說明
        FFieldNames: TStrings; //字段名表
        FStreamIndex: TStrings; //字段索引
        FStream: TStream; //存儲(chǔ)字段內(nèi)容的流
        FFieldCount: Integer; //字段數(shù)
        FRecordCount: Integer; //記錄數(shù)
        FOpenFlag: Boolean; //流是否創(chuàng)建標(biāo)志
        protected
        procedure Reset; //復(fù)位---清空流的內(nèi)容
        procedure SaveHead(ADataSet: TDataSet; Fp: TStream); //存儲(chǔ)報(bào)表頭信息
        procedure LoadTableToStream(ADataSet: TDataSet); //存儲(chǔ)記錄數(shù)據(jù)
        procedure IndexFields(ADataSet: TDataSet); //將數(shù)據(jù)集的字段名保存到列表中
        procedure GetHead(Fp: TFileStream); //保存報(bào)表頭信息
        procedure GetIndex(Fp: TFileStream); //建立記錄流索引
        procedure GetFieldNames(Fp: TFileStream); //從流中讀入字段名表
        function GetFieldName(AIndex: Integer): string; //取得字段名稱
        function GetFieldDataType(AIndex: Integer): TFieldType;
        function GetDisplayLabel(AIndex: Integer): string; //取得字段顯示名稱
        procedure SaveFieldToStream(AStream: TStream; AField: TField); //將字段存入流中
        function GetFieldValue(ARecordNo, FieldNo: Integer): string; //字段的內(nèi)容
        public
        Constructor Create(AOwner: TComponent);
        Destructor Destroy; override;
        procedure Open; //創(chuàng)建流以準(zhǔn)備存儲(chǔ)數(shù)據(jù)
        procedure SaveToFile(ADataSet: TDataSet; AFileName: string); //存儲(chǔ)方法
        procedure LoadFromFile(AFileName: string); //裝入數(shù)據(jù)
        procedure FieldStream(ARecordNo, FieldNo: Integer; var AStream: TStream);
        property FieldNames[Index: Integer]: string read GetFieldName; //字段名
        property FieldDataTypes[Index: Integer]: TFieldType read GetFieldDataType;
        property FieldDisplayLabels[Index: Integer]: string read GetDisplayLabel;
        property Fields[RecNo, FieldIndex: Integer]: string read GetFieldValue;
        //property FieldStreams[RecNo, FieldIndex: Integer]: TStream read GetFieldStream;
        property RecordCount: Integer read FRecordCount write FRecordCount;
        property FieldCount: Integer read FFieldCount write FFieldCount;
        published
        property RptTitle: string read FRptTitle write FRptTitle;
        property PageHead: string read FPageHead write FPageHead;
        property PageFoot: string read FPageFoot write FPageFoot;
        end;

        function ReadAChar(AStream: TStream): Char;
        function ReadAStr(AStream: TStream): string;
        function ReadBStr(AStream: TStream; Size: Integer): string;
        function ReadAInteger(AStream: TStream): Integer;
        procedure WriteAStr(AStream: TStream; AStr: string);
        procedure WriteBStr(AStream: TStream; AStr: string);
        procedure WriteAInteger(AStream: TStream; AInteger: Integer);

        procedure Register;
        implementation

        procedure Register;
        begin
        RegisterComponents('Data Access', [TIbStorage]);
        end;

        function ReadAChar(AStream: TStream): Char;
        Var
        AChar: Char;
        begin
        AStream.Read(AChar, 1);
        Result := AChar;
        end;

        function ReadAStr(AStream: TStream): string;
        var
        Str: String;
        C : Char;
        begin
        Str := '';
        C := ReadAChar(AStream);
        While C <> #0 do
        begin
        Str := Str + C;
        C := ReadAChar(AStream);
        end;
        Result := Str;
        end;

        function ReadBStr(AStream: TStream; Size: Integer): string;
        var
        Str: String;
        C : Char;
        I : Integer;
        begin
        Str := '';
        For I := 1 to Size do
        begin
        C := ReadAChar(AStream);
        Str := Str + C;
        end;
        Result := Str;
        end;

        function ReadAInteger(AStream: TStream): Integer;
        var
        Str: String;
        C : Char;
        begin
        Result := MaxInt;
        Str := '';
        C := ReadAChar(AStream);
        While C <> #0 do
        begin
        Str := Str + C;
        C := ReadAChar(AStream);
        end;
        try
        Result := StrToInt(Str);
        except
        Application.MessageBox(' 當(dāng)前字符串無法轉(zhuǎn)換為整數(shù)!', '錯(cuò)誤',
        Mb_Ok + Mb_IconError);
        end;
        end;


        procedure WriteAStr(AStream: TStream; AStr: string);
        begin
        AStream.Write(Pointer(AStr)^, Length(AStr) + 1);
        end;

        procedure WriteBStr(AStream: TStream; AStr: string);
        begin
        AStream.Write(Pointer(AStr)^, Length(AStr));
        end;

        procedure WriteAInteger(AStream: TStream; AInteger: Integer);
        var
        S : string;
        begin
        S := IntToStr(AInteger);
        WriteAstr(AStream, S);
        end;

        Constructor TIbStorage.Create(AOwner: TComponent);
        begin
        inherited Create(AOwner);
        FOpenFlag := False; //確定流是否創(chuàng)建的標(biāo)志
        end;

        Destructor TIbStorage.Destroy;
        begin
        if FOpenFlag then
        begin
        FStream.Free;
        FStreamIndex.Free;
        FFieldNames.Free;
        end;
        inherited Destroy;
        end;

        procedure TIbStorage.Open;
        begin
        FOpenFlag := True;
        FStream := TMemoryStream.Create;
        FStreamIndex := TStringList.Create;
        FFieldNames := TStringList.Create;
        Reset;
        end;

        procedure TIbStorage.Reset; //復(fù)位
        begin
        if FOpenFlag then
        begin
        FFieldNames.Clear;
        FStreamIndex.Clear;
        FStream.Size := 0;
        FRptTitle := '';
        FPageHead := '';
        FPageFoot := '';
        FFieldCount := 0;
        FRecordCount := 0;
        end;
        end;

        //-------保存數(shù)據(jù)部分
        procedure TIbStorage.SaveToFile(ADataSet: TDataSet; AFileName: string);
        var
        Fp: TFileStream;
        I : Integer;
        Ch: Char;
        T1, T2: TDateTime;
        Str: string;
        begin
        if Not FOpenFlag then
        begin
        showmessage(' 對(duì)象沒有打開');
        Exit;
        end;
        try
        if FileExists(AFileName) then DeleteFile(AFileName);
        Fp := TFileStream.Create(AFileName, fmCreate);
        Reset;
        SaveHead(ADataSet, Fp); //保存頭部信息---附加說明
        IndexFields(ADataSet); //將數(shù)據(jù)集的字段信息保存到FFieldName
        LoadTableToStream(ADataSet); //保存數(shù)據(jù)集的數(shù)據(jù)信息
        WriteAStr(Fp, FFieldNames.Text); //存儲(chǔ)字段名信息
        Ch := '@';
        Fp.Write(Ch, 1);
        WriteAStr(Fp, FStreamIndex.Text); //存儲(chǔ)字段索引列表
        Ch := '@';
        Fp.Write(Ch, 1);
        Fp.CopyFrom(FStream, 0);
        finally
        Fp.Free;
        end;
        end;

        procedure TIbStorage.SaveHead(ADataSet: TDataSet; Fp: TStream);
        Var
        I : Integer;
        Ch: Char;
        begin
        if Not ADataSet.Active then ADataSet.Active := True;
        WriteAStr(Fp, Flag);
        WriteAStr(Fp, FRptTitle);
        WriteAStr(Fp, FPageHead);
        WriteAStr(Fp, FPageFoot);
        FFieldCount := ADataSet.Fields.Count;
        FRecordCount := ADataSet.RecordCount;
        WriteAStr(Fp, IntToStr(ADataSet.Fields.Count));
        WriteAStr(Fp, IntToStr(ADataSet.RecordCount));
        Ch := '@';
        Fp.Write(Ch, 1);
        end;

        procedure TIbStorage.IndexFields(ADataSet: TDataSet);
        var
        I : Integer;
        AField: TField;
        begin
        For I := 0 to ADataSet.Fields.Count - 1 do
        begin
        AField := ADataSet.Fields[I];
        //不用FFieldNames.Values[AField.FieldName] := AField.DisplayLabel;是考慮效率
        FFieldNames.Add(AField.FieldName + '=' + AField.DisplayLabel);
        FFieldNames.Add(AField.FieldName + 'DataType=' + IntToStr(Ord(AField.DataType)));
        end;
        end;

        procedure TIbStorage.LoadTableToStream(ADataSet: TDataSet);
        var
        No: Integer;
        I, J, Size: Integer;
        Tmp, Id, Str : string; //id=string(RecNO) + string(FieldNo)
        Len: Integer;
        Ch : Char;
        BlobStream: TBlobStream;
        begin
        if Not FOpenFlag then
        begin
        showmessage(' 對(duì)象沒有打開');
        Exit;
        end;
        try
        ADataSet.DisableControls;
        ADataSet.First;
        No := 0;
        FStreamIndex.Clear;
        FStream.Size := 0;
        While Not ADataSet.Eof do
        begin
        No := No + 1;
        For J := 0 to ADataSet.Fields.Count - 1 do
        begin
        Id := Inttostr(NO) + '_' + IntToStr(J);
        //建立流的位置的索引, 索引指向: Size#0Content
        FStreamIndex.Add(Id + '=' + IntToStr(FStream.Position));
        //存儲(chǔ)字段信息到流中
        SaveFieldToStream(FStream, ADataSet.Fields[J]);
        end;
        ADataSet.Next;
        end;
        finally
        ADataSet.EnableControls;
        end;
        end;

        //如果一個(gè)字段的當(dāng)前內(nèi)容為空或者BlobSize<=0,則只寫入字段大小為0, 不寫入內(nèi)容
        procedure TIbStorage.SaveFieldToStream(AStream: TStream; AField: TField);
        var
        Size: Integer;
        Ch: Char;
        XF: TStream;
        Str: string;
        begin
        if AField.IsBlob then
        begin
        //如何把一個(gè)TBlobField字段的內(nèi)容存儲(chǔ)為流
        Xf := TBlobStream.Create(TBlobField(AField), bmread);
        try
        if Xf.Size > 0 then
        begin
        Size := Xf.Size;
        WriteAInteger(AStream, Size);
        AStream.CopyFrom(Xf, Xf.Size);
        end
        else
        WriteAInteger(AStream, 0);
        finally
        XF.Free;
        end;
        end
        else
        begin
        Str := AField.AsString;
        Size := Length(Str);
        WriteAInteger(AStream, Size);
        if Size <> 0 then
        AStream.Write(Pointer(Str)^, Size);
        //WriteAstr(AStream, Str);
        end;
        Ch := '@';
        AStream.Write(Ch, 1);
        end;

        //------------Load Data
        procedure TIbStorage.LoadFromFile(AFileName: string);
        var
        Fp: TFileStream;
        Check: string;
        begin
        Reset;
        try
        if Not FileExists(AFileName) then
        begin
        showmessage(' 文件不存在:' + AFileName);
        Exit;
        end;
        Fp := TFileStream.Create(AFileName, fmOpenRead);
        Check := ReadAStr(Fp);
        if Check <> Flag then
        begin
        Application.MessageBox(' 非法文件格式', '錯(cuò)誤', Mb_Ok + Mb_IconError);
        Exit;
        end;
        GetHead(Fp);
        GetFieldNames(Fp);
        GetIndex(Fp);
        FStream.CopyFrom(Fp, Fp.Size-Fp.Position);
        finally
        Fp.Free;
        end;
        end;

        procedure TIbStorage.GetHead(Fp: TFileStream);
        begin
        FRptTitle := ReadAStr(Fp);
        FPageHead := ReadAstr(Fp);
        FPageFoot := ReadAstr(Fp);
        FFieldCount := ReadAInteger(Fp);
        FRecordCount := ReadAInteger(Fp);
        if ReadAChar(Fp) <> '@' then showmessage('GetHead File Error');
        end;

        procedure TIbStorage.GetFieldNames(Fp: TFileStream);
        var
        Ch: Char;
        Str: string;
        begin
        Str := '';
        Str := ReadAStr(Fp);
        FFieldNames.CommaText := Str;
        Ch := ReadAChar(Fp);
        if Ch <> '@' then Showmessage('When get fieldnames Error');
        end;

        procedure TIbStorage.GetIndex(Fp: TFileStream);
        var
        Ch: Char;
        Str: string;
        begin
        Str := '';
        Str := ReadAStr(Fp);
        FStreamIndex.CommaText := Str;
        Ch := ReadAChar(Fp);
        if Ch <> '@' then Showmessage('When Get Field Position Index Error');
        end;

        //---------Read Field's Value Part
        function TIbStorage.GetFieldValue(ARecordNo, FieldNo: Integer): string;
        var
        Id, T : string;
        Pos: Integer;
        Len, I : Integer;
        Er: Boolean;
        begin
        Result := '';
        Er := False;
        if ARecordNo > FRecordCount then
        Er := true; //ARecordNo := FRecordCount;
        if ARecordNo < 1 then
        Er := True; // ARecordNo := 1;
        if FieldNo >= FFieldCount then
        Er := True; // FieldNo := FFieldCount - 1;
        if FieldNo < 0 then
        Er := True; //FieldNo := 0;
        if Er then
        begin
        Showmessage('記錄號(hào)或者字段標(biāo)號(hào)越界');
        Exit;
        end;
        if FFieldCount = 0 then Exit;
        Id := Inttostr(ARecordNO) + '_' + IntToStr(FieldNo);
        Pos := StrToInt(FStreamIndex.Values[Id]);
        FStream.Position := Pos;
        //取得字段內(nèi)容的長(zhǎng)度
        Len := ReadAInteger(FStream);
        if Len > 0 then
        Result := ReadBStr(FStream, Len);
        if ReadAChar(FStream) <> '@' then
        Showmessage('When Read Field, Find Save Format Error');
        end;

        procedure TIbStorage.FieldStream(ARecordNo, FieldNo: Integer; var AStream: TStream);
        var
        Id, T : string;
        Pos: Integer;
        Len, I : Integer;
        Er: Boolean;
        begin
        Er := False;
        if ARecordNo > FRecordCount then
        Er := true; //ARecordNo := FRecordCount;
        if ARecordNo < 1 then
        Er := True; // ARecordNo := 1;
        if FieldNo >= FFieldCount then
        Er := True; // FieldNo := FFieldCount - 1;
        if FieldNo < 0 then
        Er := True; //FieldNo := 0;
        if Er then
        begin
        TDsException.Create('GetFieldValue函數(shù)索引下標(biāo)越界');
        Exit;
        end;
        if FFieldCount = 0 then Exit;
        Id := Inttostr(ARecordNO) + IntToStr(FieldNo);
        Pos := StrToInt(FStreamIndex.Values[Id]);
        FStream.Position := Pos;
        Len := ReadAInteger(FStream);
        AStream.CopyFrom(FStream, Len);
        end;

        function TIbStorage.GetFieldName(AIndex: Integer): string; //取得字段名稱
        begin
        //存儲(chǔ)的字段和數(shù)據(jù)類型各占一半
        if ((AIndex < 0) or (AIndex >= FFieldNames.Count div 2)) then
        Application.MessageBox(' 取字段名索引越界', '程序 錯(cuò)誤',
        Mb_Ok + Mb_IconError)
        else
        Result := FFieldNames.Names[AIndex*2];
        end;

        function TIbStorage.GetFieldDataType(AIndex: Integer): TFieldType; //取得字段名稱
        begin
        //存儲(chǔ)的字段和數(shù)據(jù)類型各占一半
        if ((AIndex < 0) or (AIndex >= FFieldNames.Count div 2)) then
        Application.MessageBox(' 取字段數(shù)據(jù)類型索引越界', '程序 錯(cuò)誤',
        Mb_Ok + Mb_IconError)
        else
        Result := TFieldType(StrToInt(FFieldNames.Values[FFieldNames.Names[AIndex*2+1]]));
        end;

        function TIbStorage.GetDisplayLabel(AIndex: Integer): string; //取得字段顯示名稱
        begin
        if ((AIndex < 0) or (AIndex >= FFieldNames.Count)) then
        Application.MessageBox(' 取字段名索引越界', '程序 錯(cuò)誤',
        Mb_Ok + Mb_IconError)
        else
        Result := FFieldNames.Values[GetFieldName(AIndex)];
        end;

        end.
        通過測(cè)試,該控件對(duì)Ttable,Tquery, TaodTable, TadoQuery, TibTable, TibQuery等常用的數(shù)據(jù)集控件等都能較好的支持,并且具有較好的效率(測(cè)試:1100條人事記錄,23個(gè)字段存儲(chǔ)為文件約用時(shí)2秒鐘)。

        四、控件的基本使用方法
        1.存儲(chǔ)數(shù)據(jù)集中的數(shù)據(jù)到文件
        IbStorage1.Open; //創(chuàng)建存儲(chǔ)流
        IbStorage1.SaveToFile(AdataSet, Afilename);
        2.從文件中讀出數(shù)據(jù)信息
        IbStorage1.Open;
        IbStorage1.LoadFromFile(AfileName);
        3.對(duì)數(shù)據(jù)報(bào)存儲(chǔ)控件中數(shù)據(jù)的訪問
        Value := IbStorage1.Fields[ArecNo, AfieldNo]; //字符串類型
        其它略。
        五、結(jié)束語
        通過編寫此數(shù)據(jù)報(bào)存儲(chǔ)控件,較好地解決了數(shù)據(jù)庫程序中數(shù)據(jù)的存儲(chǔ)和交換問題,為數(shù)據(jù)庫程序的開發(fā)提供了一種實(shí)用的控件。
        該控件在Windows98,Delphi5開發(fā)環(huán)境下調(diào)試通過。

        溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!

        本類教程下載

        系統(tǒng)下載排行

        主站蜘蛛池模板: 亚洲国产成人一区二区精品区| 欧美a级成人网站免费| 亚洲国产一区二区视频网站| 亚洲精品国产摄像头| 无人在线观看免费高清视频| 亚洲乱码一二三四五六区| 中文字幕在线观看免费视频| 亚洲欧洲中文日产| 9久9久女女免费精品视频在线观看| 亚洲人6666成人观看| 成人av免费电影| 亚洲日本va一区二区三区| 日韩中文无码有码免费视频 | 亚洲精品无码成人AAA片| 中文字幕免费观看视频| 日本红怡院亚洲红怡院最新 | 五月天婷婷免费视频| 亚洲开心婷婷中文字幕| 久久久久久国产精品免费免费男同 | 亚洲国产最大av| 国产gav成人免费播放视频| 一级黄色毛片免费看| 久久亚洲精品无码| 日本阿v免费费视频完整版| 亚洲男人的天堂网站| 亚洲欧洲久久av| 久久国产乱子伦免费精品| 在线精品亚洲一区二区| 亚洲精品无码av天堂| 一区二区免费视频| 亚洲欧美日韩综合俺去了| 亚洲日韩VA无码中文字幕| 午夜无码A级毛片免费视频| 国产亚洲玖玖玖在线观看| 亚洲精品无码久久久久AV麻豆| 日本视频免费高清一本18| 一区二区亚洲精品精华液| 伊人亚洲综合青草青草久热| 57PAO成人国产永久免费视频| 亚洲av成人一区二区三区在线播放| 国产成人A亚洲精V品无码|