FieldByNameのような関数を自作したい

解決


ahsan  2007-12-03 19:00:16  No: 28797

自作のバイナリデータにTTableにあるFieldByNameの
ようなクラスとメソッドを自作しアクセスしたいのですが、
作り方がよくわかりません。
TMyTbl = class
  private
  var
    fName : array[0..255] of string;//'CUSTID','CUSTNAME','CUSTTEL'等が入る
    dataS : array[0.255,0..999] of string;//fName毎のデータ。0-999の最大1000行
    FDatabaseName : string;
    FTableName : string;
  protected
  public
    property DatabaseName : string Read FDatabaseName Write FDatabaseName;
    property TableName : string Read FTableName Write FTableName;
    function Open;
    function Close;
    function FieldByName(fieldName:string):???;
  end;
DatabaseName,tableNameにそれぞれバイナリデータベースのパス、名前設定後
Openで、配列fName,dataSに読み込み、FiledByNameで、引数のfieldNameで
渡した項目名で変数:fNameを調べ、該当するdataSのデータを返してたいのですが。
TTableではAsStringで値を取得(設定)できますが、これはどのようにコーディング
すればよいのですか?
var
  myTbl:TMyTbl;
begin
  myTbl:=TMyTbl.Create;
  Memo1.Lines.Add(myTbl.FieldByName('CUSTNAME').AsString);
  Memo1.Lines.Add(myTbl.FieldByName('CUSTNAME').AsString);
  myTbl.Close;
お願い致します。


それは  2007-12-03 19:27:16  No: 28798

VCLのソースを見た方がイイと思うけど。
TBinaryField.GetAsString
TBinaryField.SetAsString


KHE00221  2007-12-03 20:20:30  No: 28799

Memo1.Lines.Add(MyTabel.FieldByName('CUSTOM'));

のように単純に関数で返すのならば

Fname を StringList にして

function First;
begin
    Index := 0;
end;

function Next;
begin
   Inc(Index);
end;

function FieldByName(FieldName:String):String;
begin
  FieldIndex := StringList.IndexOf(FieldName);
  if FiledIndex <> -1 then 
  begin
    Result := DataS[FiledIndex,Index];
  end
  else
  begin
    //Fieldが存在しない
  end;
end;

.AsString で返すのならば TMyField だけでは無理です

TBinaryFieldみたいのを作成して下さい


ahsan  2007-12-04 21:00:46  No: 28800

それはさん、KHE00221さん、早速ありがとうございます。
TBinaryFieldみたいにしようとVCLソースを見ましたが
よく分かりませんでした。
function FieldByNameAsString(FieldName:String):String;
function FieldByNameAsInteger(FieldName:String):Integer;
のように、.As〜のやめて、関数名にいれます。


KHE00221  2007-12-04 21:57:19  No: 28801

あきらめちゃいましたか・・・

FieldByName は オブジェクト FieldByName2 はレコードを使用した場合です

unit MyTable;

interface

uses
  SysUtils, Classes;

type

  TMyField = class(TComponent)
  private
    FAsString : String;
  published
    property asString :String read fAsString;
  end;

  TMyField2 = record
    asString : String;
  end;

  TMyTable = class(TComponent)
  private
    FMyField  : TMyField;
    FMyField2 : TMyField2;
    FIndex  : Integer;
    FName : array[0..255] of string;
    FData : array[0..255,0..999] of string;
  protected
    procedure SetNames(Index:Integer;Value:String);
    function  GetNames(Index:Integer):String;
    procedure SetDatas(Index1,Index2:Integer;Value:String);
    function  GetDatas(Index1,Index2:Integer):String;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function FieldByName(AName:String):TMyField;
    function FieldByName2(AName:String):TMyField2;
    property Names [Index:Integer] : String read GetNames write SetNames;
    property Datas [Index1,Index2:Integer] : String read GetDatas write SetDatas;
    procedure First;
    procedure Next;
  published
    property Index : Integer read FIndex write FIndex;
  end;

procedure Register;

implementation

procedure TMyTable.SetNames(Index: Integer; Value: string);
begin
    FName[Index] := Value;
end;

function TMyTable.GetNames(Index: Integer):String;
begin
    Result := FName[Index];
end;

procedure TMyTable.SetDatas(Index1,Index2: Integer; Value: string);
begin
    FData[Index1,Index2] := Value;
end;

function TMyTable.GetDatas(Index1,Index2: Integer):String;
begin
    Result := FData[Index1,Index2];
end;

procedure TMyTable.First;
begin
    FIndex := 0;
end;

procedure TMyTable.Next;
begin
    Inc(FIndex);
end;

function TMyTable.FieldByName(AName:String):TMyField;
var
    I,J : Integer;
begin
    //ANameに一致するFNameを探す
    J := -1;
    for I:=0 to High(FName) -1 do
    begin
      if FName[I] = AName then J := I;
    end;
    if J <> -1 then
    begin
      //見付かったら
      FMyField.FAsString := Datas[J,Index];
    end
    else
    begin
      //見付からなければ
      FMyField.FAsString := '';
    end;
    Result := FMyField;
end;

function TMyTable.FieldByName2(AName:String):TMyField2;
var
    I,J : Integer;
begin
    //ANameに一致するFNameを探す
    J := -1;
    for I:=0 to High(FName) -1 do
    begin
      if FName[I] = AName then J := I;
    end;
    if J <> -1 then
    begin
      //見付かったら
      FMyField2.AsString := Datas[J,Index];
    end
    else
    begin
      //見付からなければ
      FMyField2.AsString := '';
    end;
    Result := FMyField2;
end;

constructor TMyTable.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);

    FMyField := TMyField.Create(Self);
end;

destructor TMyTable.Destroy;
begin
    FMyField.Free;
    inherited Destroy;
end;

procedure Register;
begin
  RegisterComponents('KHE00221', [TMyTable]);
end;

end.

-------------------------------------------------------------------

MyTable を使用した例

------------------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);
var
    I,J : Integer;
begin
    //データ初期化
    for I:=0 to 10 do
    begin
      for J:=0 to 99 do
      begin
        MyTable1.Names[I] := 'Name'+IntToStr(I);
        MyTable1.Datas[I,J] := 'Data'+IntToStr(I)+'/'+IntToStr(J);
      end;
    end;
    //表示
    Memo1.Lines.Add(MyTable1.FieldByName('Name1').asString);
    Memo1.Lines.Add(MyTable1.FieldByName('Name20').asString);
    MyTable1.Next;
    Memo1.Lines.Add(MyTable1.FieldByName2('Name2').asString);
    Memo1.Lines.Add(MyTable1.FieldByName2('Name30').asString);
end;


ahsan  2007-12-05 01:22:05  No: 28802

KHE00221さん、
大変貴重なソースをありがとうございます。
あきらめて、お恥ずかしい次第です。
これで、自作DBアクセスクラス作成してみます。
VCLも理解できるようになるかもわかりません。
大変ありがとうございました。


ahsan  2007-12-06 01:33:44  No: 28803

何度もすみません。
FieldByName内で、read時(現状)は、
FMyField.FAsString := Datas[J,Index];
でよいのですが、write時は逆に、
Datas[J,Index]:=FMyField.FAsString;
と思うのです、readなのか、writeなのか
FieldByName内でどのように判断すればよいのでしょうか?


KHE00221  URL  2007-12-06 02:19:40  No: 28804

書き込みは一切考慮してませんでしたので書き込みできるように修正しました

unit MyTable;

interface

uses
  SysUtils, Classes;

type

  TMyTable = class;

  TMyField = class(TComponent)
  private
    FMyTable : TMyTable;
    FAsString : String;
    FIndex : Integer;
  protected
    procedure SetAsString(Value:String);
  public
    constructor Create(AOwner:TComponent);
    destructor Destroy; override;
  published
    property asString :String read fAsString write SetAsString;
    property Index : Integer read FIndex write FIndex;
  end;

  TMyTable = class(TComponent)
  private
    FMyField  : TMyField;
    FIndex  : Integer;
    FName : array[0..255] of string;
    FData : array[0..255,0..999] of string;
  protected
    procedure SetNames(Index:Integer;Value:String);
    function  GetNames(Index:Integer):String;
    procedure SetDatas(Index1,Index2:Integer;Value:String);
    function  GetDatas(Index1,Index2:Integer):String;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function FieldByName(AName:String):TMyField;
    property Names [Index:Integer] : String read GetNames write SetNames;
    property Datas [Index1,Index2:Integer] : String read GetDatas write SetDatas;
    procedure First;
    procedure Next;
  published
    property Index : Integer read FIndex write FIndex;
  end;

procedure Register;

implementation

constructor TMyField.Create(AOwner:TComponent);
begin
    inherited Create(AOwner);
    FMyTable := TMyTable(AOwner);
end;

destructor TMyField.Destroy;
begin
    inherited Destroy;
end;

procedure TMyField.SetAsString(Value: string);
begin
    FMyTable.Datas[FIndex,FMyTable.Index] := Value;
end;

procedure TMyTable.SetNames(Index: Integer; Value: string);
begin
    FName[Index] := Value;
end;

function TMyTable.GetNames(Index: Integer):String;
begin
    Result := FName[Index];
end;

procedure TMyTable.SetDatas(Index1,Index2: Integer; Value: string);
begin
    FData[Index1,Index2] := Value;
end;

function TMyTable.GetDatas(Index1,Index2: Integer):String;
begin
    Result := FData[Index1,Index2];
end;

procedure TMyTable.First;
begin
    FIndex := 0;
end;

procedure TMyTable.Next;
begin
    Inc(FIndex);
end;

function TMyTable.FieldByName(AName:String):TMyField;
var
    I,J : Integer;
begin
    //ANameに一致するFNameを探す
    J := -1;
    for I:=0 to High(FName) -1 do
    begin
      if FName[I] = AName then J := I;
    end;
    if J <> -1 then
    begin
      //見付かったら
      FMyField.FAsString := Datas[J,Index];
    end
    else
    begin
      //見付からなければ
      FMyField.FAsString := '';
    end;
    FMyField.Index := J;
    Result := FMyField;
end;

constructor TMyTable.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);

    FMyField := TMyField.Create(Self);
end;

destructor TMyTable.Destroy;
begin
    FMyField.Free;
    inherited Destroy;
end;

procedure Register;
begin
  RegisterComponents('KHE00221', [TMyTable]);
end;

end.

--------------------
 使い方
--------------------

    MyTable1.First;
    MyTable1.FieldByName('Name1').asString := '1111';
    MyTable1.Next;
    MyTable1.FieldByName('Name1').asString := '2222';

    MyTable1.First;
    Memo1.Lines.Add(MyTable1.FieldByName('Name1').asString);
    MyTable1.Next;
    Memo1.Lines.Add(MyTable1.FieldByName('Name1').asString);
    MyTable1.Next;
    Memo1.Lines.Add(MyTable1.FieldByName('Name1').asString);


ahsan  2007-12-06 19:06:44  No: 28805

KHE00221さん、早速ありがとうございます。
実行させましたところ、Memo1に値が表示されました。
ありがとうございました。
ソースを見て勉強させていただきます。
(FieldByNameの戻り値のTMyFieldのプロパティasStringのSetAsStringが
  FieldByNameの最後で呼び出されるのですね。
  FieldByNameの中で判定するものと思い込んでいたので、
  想像もつきませんでした。)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加