Delphi Tips 
-----------------------------

キーワード:データベース

>> Index

01/12 ファイルを作らずメモリ上で動作する TTable コンポーネント
04/05 Oracle の Number 型で入力値が化ける
01/02 TField.EditMask の y2k 回避
12/21 ランダムなレコードの移動
09/09 DLL 内で TDBCtrlGrid を使うときの注意事項
08/28 データコントロールのDataLinkオブジェクトを取得する方法(ReadOnlyプロパティのバグの解決法)
08/26 書式付きメモ型項目へアクセスしたい
02/11 DBGrid のスクロールバーを非表示に
02/08 クイックレポート関連記事
02/08 最新版クイックレポート(英語)の日本語化
02/08 MS-Access97 に接続できない
02/08 StringGrid/DBGrid でのセル編集の動作を細かく指定する

最終更新: 4060 日前

0129  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.4
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2007/01/12 RAN 編集
ファイルを作らずメモリ上で動作する TTable コンポーネント

>前どこかで TTable 互換でメモリ上で動作するコンポーネントを見かけたのです
>が、ご存知な方いらっしゃいませんか? (その時にダウンロードしておけばよかっ
>た...)

[1]

Delphi Super Pageに昔からあるコンポーネントです。
BDEのインメモリテーブルと一時テーブルの機能を使ったものです。

http://sunsite.icm.edu.pl/delphi/
(2007年現在はhttp://delphi.icm.edu.pl/authors/a0000561.htm に移動)
ファイル名:inmemory.zip および inmem32.zip
※サンプル付きです。

Delphi1.0用のほうを、Delphi3で使用するときの修正点は以下のとおりです。32ビット版が出ているのでもう必要無いのかな?
#Inmemユニット:
#  TypeMapで配列の最後に「, fldCURSOR」を追加。
#  SubTypeMapで配列の最後に「, 0」を追加。
#TempTblユニット:
#  TypeMapで配列の最後に「, fldCURSOR」を追加。
#  SubTypeMapで配列の最後に「, 0」を追加。
※Register手続きがありませんので、追加してください。

>これがあればテンポラリのテーブルをいちいちディスクに作成しなくても済んで
>しまうため(結果的に作られるとしても)、便利なのですが...

 そうなんですが、デバッグのとき、値を確認しにくいと思いますよ。

[2]

> ひょっとして http://delphideli.com/dlnbde.htm にある TMemTable のことでしょうか。

僕が前見たのは確かシェアウエアだったのですが、これはフリーでしかもソース付き。嬉しい限りです。

[3]

最近のDelphi では標準でMyBase が利用できます。
http://hp.vector.co.jp/authors/VA028375/delphi/db.html が分かりやすいです。
参照: [Delphi-ML:22981] [Delphi-ML:22983] <DataAccess> <コンポーネント >

0202  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/13 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2001/04/05 濱野 編集
Oracle の Number 型で入力値が化ける

BDE の 5.01 よりも前のバージョンで、Oracle 8.0.4 のテーブルのNUMBER型で桁数が7,2の項目に 99.999 と入力すると 10.00 になってしまいます。これは、BDE のバグです。
http://www.borland.co.jp/download/other.html
で BDE を 5.01 以上にバージョンアップすることで回避されます。詳しくは [Delphi-ML:41554] から始まるスレッドを参照してください。
参照: [Delphi-ML:41554] <バグ>

0296  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 2000/01/02 osamu rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2000/01/02 osamu 編集
TField.EditMask の y2k 回避

> DBEditで日付入力させるのですが、関連付けているTTable側の
> 日付フィールドのTFieldのEditMaskプロパティで

>  !99/99/00;1;_

>  ・・とマスクをかけています。
>  すると、西暦を下2桁で打つマスクが有効になるのですが
> 2000/05/05 の意で 00/05/05 とか打つと、期待した
> 2000/05/05にならずに、1900/05/05と表示されてしまいます。

OnCreate イベントハンドラ内で

    TwoDigitYearCenturyWindow := 50;
    ShortDateFormat := 'yyyy/mm/dd';

の設定を行うと,現在の年が1999年のとき,1999年の前後50年である
1949/1/1 から 2048/12/31 の100年を変換の対象として扱います.
ただし D4 からの機能のようです。

詳しくはヘルプか以下のサイトをご覧になられるとよいと思います.

    http://www.inprise.com/devsupport/y2000/

【追記】
Delphi 5 になってから TwoDigitYearCenturyWindow グローバル変数の初期値が「0」から「50」に変更されました。UI 簡略化等で西暦2桁年を使っているような場合、TwoDigitYearCenturyWindow 変数を設定しないまま日付型に変換しているような処理では、処理結果がD4以前と変わる場合があります。

ヘルプの記述(初期値は0)は誤っていますので、ご注意ください。
参照: [Delphi-ML:37908] [Delphi-ML:43093] <コンポーネント > <DataControls>

0294  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/12/21 濱野 rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/12/21 濱野 編集
ランダムなレコードの移動

Random関数とMoveByメソッドを使います。
MaxRecordはあらかじめRecordCountプロパティやSELECT * FROM文などで
求めておきます。
利用目的としてテストデータの作成や練習問題の出題などに活用
出来ると思います。


procedure RandomMove(Dataset: TDataSet; MaxRecord: Integer);
var
  X : Integer;
begin
  X := Random(MaxRecord);
  DataSet.First;
  DataSet.MoveBy(X);
end;
参照:

0246  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/09 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/09 osamu 編集
DLL 内で TDBCtrlGrid を使うときの注意事項

>DLL化したアプリのフォームにDBCtrlGrid,DBCheckBoxを置いてローカルDB
>の内容を表示させているのですが、DLL化した途端にカレントレコードしか
>表示されなくなってしまいました。

この現象は以下の理由で発生します。

1.DLLの中では、何もしなければApplication.Handle=0です。
2.DBCtrlGridに配置されるコンポーネントの一部(DBCheckBoxを含む)はカレントレコード以外へ複製表示を行うために、Application.Handleを利用しています。

具体的にはDBCtrls.pasのTPaintControl.GetHandleで、次のようなコードで表示用の別ウインドウを生成しています。
  with Params do
    FHandle := CreateWindowEx(ExStyle, PChar(FClassName),
      PChar(TWinControlAccess(FOwner).Text), Style or WS_VISIBLE,
      X, Y, Width, Height, Application.Handle, 0, HInstance, nil);

Application.Handle=0 だと CreateWindowEXは失敗し、FHandle=0となるので複製表示が正常に行われないのです。

対処方法としては、Delphiヘルプの TApplication.Handle に書いてありますが、EXE ホストのメインウィンドウのウィンドウハンドルを DLL の Application.Handleに割り当てます。

別の方法としては、上記の TPaintControl.GetHandle の Application.Handle を FOwner.Handle に書き換えてもいいでしょう。

このスレッドではさらに、TApplication.MainForm.Handle を渡すべきか、TApplication.Handle を渡すべきか。また、TApplication.Handle を渡す際には、DLL 側の uses から Forms を削除しなければ、など、使い方に関する細かい注意点が議論されています。
参照: [Delphi-ML:33636] [Delphi-ML:33791] <コンポーネント > <DataControls>

0222  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/28 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/28 西坂良幸 編集
データコントロールのDataLinkオブジェクトを取得する方法(ReadOnlyプロパティのバグの解決法)


VCLでは、DataControlのFDataLinkは、プロパティになっていないので、アクセスできませんが、
DataControlにCM_GETDATALINKメッセージを投げる事で取得(参照)できます。[Delphi-ML:41387]田原
多重継承ができないので、こうなっているそうです。

これによって、MLでも多い質問ですが、いわゆる「極東仕様」問題、すなわち、TDBEdit の ReadOnly と継承元の TCustomEdit のReadOnly の同期がとれないバグを解決することができます。[Delphi-ML:41051]藤中

以下は、藤中さんの例示コード(省略部あり)です。

// このデータコントロール(フィールド対応)は編集可能か?
function IsCanModifyFieldDataControl(Control: TControl) : Boolean;
var
  DataLink : TFieldDataLink;
begin
  // データリンクを取得
  DataLink := TFieldDataLink(Control.Perform(CM_GETDATALINK,0,0));
  if (DataLink = nil) then
     DatabaseError('CM_GETDATALINK は無効', Control);
  // データリンクが編集可能かどうか調べる
  Result := DataLink.CanModify and
          ( DataLink.DataSource.AutoEdit or
           (DataLink.DataSource.State in [dsInsert, dsEdit]) );
end;

// たとえば、Table1のAfterScrollイベントなどで動的にReadOnlyを変更する

type TCustomEditCracker = class(TCustomEdit);

procedure TForm1.Table1AfterScroll(DataSet: TDataSet);
var
  Flg :Boolean;
begin
  // 条件
  if DataSet.FieldByName('制御フラグ').AsString = '1' then
    Flg := True
  else
    Flg := False;
  // 以下でReadOnlyを変更
  DBEdit1.ReadOnly := Flg;
  if (Flg = False) then
  begin
    TCustomEditCracker(DBEdit1).ReadOnly :=
               not IsCanModifyFieldDataControl(DBEdit1);
  end
  else begin
    TCustomEditCracker(DBEdit1).ReadOnly := True;
  end;
end;

参照: [Delphi-ML:41387] [Delphi-ML:17611] [Delphi-ML:41051] <バグ> <コンポーネント > <DataControls>

0217  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/26 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/26 西坂良幸 編集
書式付きメモ型項目へアクセスしたい


ヘルプなどでは、Streamをつかった方法が紹介されています。

DataSet.FieldByName('Field1').AsString := RichEdit1.Text;

DataSet.FieldByName('Field1').AsVariant := RichEdit1.Text;

では、PlainText となり、書式が保存されません。

 Field1  書式付きメモ型とし、
 DataSetは開かれているとします。

// リッチエディットからフィールドへの書き込み
procedure TForm1.Button8Click(Sender: TObject);
var
  Stream1 : TMemoryStream;
begin
  Stream1 := TMemoryStream.Create;
  try
    RichEdit1.Lines.SavetoStream(Stream1);
    Query1.Edit;
    TBlobField(Query1.FieldByName('Field1')).LoadFromStream(Stream1);
    Query1.Post;
  finally
    Stream1.Free;
  end;
end;

// フィールドからリッチエヂットへの読み出し
procedure TForm1.Button4Click(Sender: TObject);
var
  Stream1 : TBlobStream;
begin
  Stream1 := TBlobStream.Create(TBlobField(Query1.FieldByName('Field1')), bmRead);
  try
    RichEdit1.Lines.LoadFromStream(Stream1);
  finally
    Stream1.Free;
  end;
end;


TRichEdit系は、いくつかのバグが報告されています。
データが大きくなるとヤバイという噂です。
D4では、大部改善されたようですが、気をつけて下さい。

バグ情報は
http://www.dataweb.nl/~r.p.sterkenburg/indexpag.htm
参照: [Delphi-ML:5484] [Delphi-ML:41858] <DataAccess> <コンポーネント >

0165  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
DBGrid のスクロールバーを非表示に

この DBGrid のスクロールバーを力で消す方法,大変参考になりました。じっと見ているとちらりと映りますが,言われなければたぶん誰も気づかないでしょう(^^)

>   private
>     { Private 宣言 }
>     FCellBottom : Integer;
>
> procedure TForm1.DBGrid1DrawColumnCell
> (Sender: TObject; const Rect: TRect;
> DataCol: Integer; Column: TColumn; State: TGridDrawState);
> begin
>   if (FCellBottom < Rect.bottom) then FCellBottom := Rect.bottom;
> end;
>
> procedure TForm1.Query1BeforeInsert(DataSet: TDataSet);
> begin
>   Abort;
> end;
>
> procedure TForm1.Query1AfterScroll(DataSet: TDataSet);
> begin
>   ShowScrollBar(DBGrid1.Handle, SB_VERT, False);
> end;
>
> procedure TForm1.Button1Click(Sender: TObject);
> begin
>   DBGrid1.Height := FCellBottom - DBGrid1.Top + 6;
> end;
参照: [Delphi-ML:31864] <コンポーネント > <DataControls>

0094  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
クイックレポート関連記事

まだ未整理ですが、クイックレポート関連の記事をまとめてみました。

[Delphi-ML:8148]
[Delphi-ML:11010]
[Delphi-ML:11263]
[Delphi-ML:11456]
[Delphi-ML:11433]
[Delphi-ML:11648]
[Delphi-ML:11767]
[Delphi-ML:11943]
[Delphi-ML:12824]
[Delphi-ML:14205]
[Delphi-ML:14319]
[Delphi-ML:14484]
[Delphi-ML:14543]
[Delphi-ML:15080]
[Delphi-ML:15901]
[Delphi-ML:16160]
[Delphi-ML:16317]
[Delphi-ML:16364]
[Delphi-ML:16390]
[Delphi-ML:16486]
[Delphi-ML:16664]
[Delphi-ML:16679]
[Delphi-ML:17066]
[Delphi-ML:17256]
[Delphi-ML:17393]
[Delphi-ML:17511]
[Delphi-ML:17503]
[Delphi-ML:17578]
[Delphi-ML:17677]
[Delphi-ML:17942]
[Delphi-ML:18073]
[Delphi-ML:19112]
[Delphi-ML:19316]
[Delphi-ML:19362]
[Delphi-ML:19447]
参照: [Delphi-ML:8148] [Delphi-ML:11010] [Delphi-ML:11263] [Delphi-ML:11456] [Delphi-ML:11433] [Delphi-ML:11648] [Delphi-ML:11767] [Delphi-ML:11943] [Delphi-ML:12824] [Delphi-ML:14205] [Delphi-ML:14319] [Delphi-ML:14484] [Delphi-ML:14543] [Delphi-ML:15080] [Delphi-ML:15901] [Delphi-ML:16160] [Delphi-ML:16317] [Delphi-ML:16364] [Delphi-ML:16390] [Delphi-ML:16486] [Delphi-ML:16664] [Delphi-ML:16679] [Delphi-ML:17066] [Delphi-ML:17256] [Delphi-ML:17393] [Delphi-ML:17511] [Delphi-ML:17503] [Delphi-ML:17578] [Delphi-ML:17677] [Delphi-ML:17942] [Delphi-ML:18073] [Delphi-ML:19112] [Delphi-ML:19316] [Delphi-ML:19362] [Delphi-ML:19447] <印刷>

0100  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
最新版クイックレポート(英語)の日本語化

クイックレポートの最新版を、
    http://www.qusoft.com/scripts/download.dll
から落としてきて、Delphiにインストールすることができます。
但し、プレビューのボタンなどが英語になります。

以前のバージョン(2.0g)のdfmファイルをlibディレクトリにコピーするだけで、実行時パッケージを使用しない場合に限り、実行時に日本語で表示できます。

これを、設計時や実行時パッケージを使ったときにも日本語で表示させる方法が、[Delphi-ML:20984]に紹介されています。
参照: [Delphi-ML:20984] <印刷>

0113  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
MS-Access97 に接続できない

Delphi3.1についているBDE4.5だとまだACCESS97に対応していなかったと思います。
BDE4.51にバージョンアップすると大丈夫だったと思いいます。
詳しくはインプライズのページを見てみてください。
バージョンアップデータが配布されているはずです。

http://www.inprise.co.jp/bde/
参照: [Delphi-ML:21943]

0009  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
StringGrid/DBGrid でのセル編集の動作を細かく指定する

下のような関数を使って、TCustomGridで定義されているインプレースエディタを取得すれば、

    GetGridEditor(StringGrid1).SelStart:=0;

などとできます。

function GetGridEditor(Grid: TCustomGrid): TCustomEdit;
var i: Integer;
begin
    Result:=nil;
    for i:=0 to Grid.ControlCount-1 do
        if Grid.Controls[i] is TCustomEdit then begin
            Result:=TCustomEdit(Grid.Controls[i]);
            Exit;
        end;
end;
参照: [Delphi-ML:18726] <Additional> <コンポーネント > <DataControls>

[新規作成] [最新の情報に更新]

How To
Lounge
KeyWords

Tips
Delphi
Home
Osamu Takeuchi osamu@big.or.jp