Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2005年01月01日] [更新 2014年08月04日] Delphi サンプルプログラム集
560_画像や TRichEdit ワード文書をデータベースで読書き
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro + JET 4.0 + ADO
560_RichEditDB.zip [8,876 KB] 2014年08月04日版 (EXE 同梱)



  • 2013年12月10日
  • データベースの操作に ADO + JET 4.0 を使用
  • サンプルを対象のオブジェクトごとに分けた
  • データベース接続コードを、書き込みと読出しとで独立させた (コードのコピペ利用対策)
  • 項目コンポーネントを実行時に FieldByName で取得するコードに変更
  • 2014年08月04日
  • CreateBlobStream を使用したサンプルを追加
  • コードと記事の整備




画像や TRichEdit、ワード文書をデータベースで読書き


2013年12月10日の更新で、BDE 5.2 + Pardox ではなく、JET 4.0 データベースエンジン (以下 JET と略す) を使用するコードに変更しました。そのため、以下の変更があります。
  • データベースへの接続のコード
  • TQuery, TTable ではなく TADOConnection と TADOQuery を使用
データベースに記録したり、データベースから読み出すコードは基本的には変更ありません。該当するフィールド、項目コンポーネントに対して Assign メソッド、あるいはメモリストリームで操作します。それ以外にも、Value プロパティを使用する方法がありますが、掲載していません。
ネット上の掲示板に、TADOBlobStream の使用に関する質問がありましたので、これを使用したサンプルを追加しています。
本ページでは、データベースへの書き込みに 単に Post メソッドだけを使用しています。実際にはトランザクション等を実行することになるでしょう。

画像やリッチテキスト関係は、データベース対応コントロールとして TDBRichEdit、TDBImage があります。これらを使用することができますが、本ページのサンプルは、これらのコントロールを使用しない場合の参考コードということになります。
データベースあるいは、データベース用のコントロールによっては、バイナリデータや BLOB 型のデータを扱うための関数やメソッド類が実装されている場合があります。データベースあるいはデータベース用のコンポーネント類のマニュアルで確認してください。

画像等のファイルをデータベースで扱う場合、各々のフィールドに格納するのではなく、別の場所に保存し、データベース本体には、その保存場所のパス名だけを格納するという方法も考えられます。





01_テスト用のデータベースの表を作成


ADO を使用すると、Paradox の BLOB 型 (Binary Large OBject) のデータにアクセスできません。
Paradox の BLOB 型のデータは表本体とは別に、拡張子が .MB というファイルに格納されます。そのことが原因かどうかは分かりません。

そこで、本ページのサンプルでは、ADO を使用して JET を操作することにしました。JET であれば多くのコンピュータで実際に動作確認を行うことが可能です。
[630_ADO で JET データベースの新規作成と最適化] の記事を参考に BlobTest_BLOB.mdb というデータベースを作成しました。
このデータベースに以下のコードで表を作成しています。表には、3 つの BLOB 型の項目を作成しています。JET で BLOB 型に相当するのは、LONGBINARY 型です。これは Microsoft Access では OLE オブジェクト型と呼ばれている型のことです。

本サンプルの各ボタンの機能は、次のようになっています。

  • [Button1]  添付のデータベース BlobTest_BLOB.mdb に TEST という表を作成
  • [Button2]  表 TEST の内容を DBGrid1 に表示
  • [Button3]  表 TEST の先頭レコードのデータのみ削除 (レコードは削除しない)


図1
作成した JET DB の表
  • 以下の項目が BLOB 型
    BinData
    Graphic
    RichEdit
  • データが格納されていると (BLOB)
    空の時は (Blob) と表示される

リスト1
テスト用のデータベースの表の作成
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, StdCtrls, Grids, DBGrids, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    DBGrid1: TDBGrid;
    DataSource1: TDataSource;
    Button1: TButton;
    ADOQuery1: TADOQuery;
    ADOConnection1: TADOConnection;
    Button2: TButton;
    Button3: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  フォームを閉じる時の処理
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ADOQuery1.Close;
  ADOConnection1.Connected := False;
end;

//=============================================================================
//  JETエンジンデータベースに表を追加
//  BLOB型の項目を作成
//  BLOB型はデータのタイプをLONGBINARYとする
//  Microsoft AccessではOLEオブジェクト型という名前になっている
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  StrText : String;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;
  DataSource1.DataSet  := ADOQuery1;
  DBGrid1.DataSource   := DataSource1;


  strText := 'CREATE TABLE TEST (ID       INT CONSTRAINT KEY1 PRIMARY KEY,'
                              + 'STRTEXT  TEXT(30),'
                              + 'BinData  LONGBINARY,'
                              + 'Graphic  LONGBINARY,'
                              + 'RichEdit LONGBINARY)';

  ADOQuery1.SQL.Add(StrText);
  try
    ADOQuery1.ExecSQL;
  except
    on E: Exception do begin
      StrText := E.ClassName + sLineBreak + E.Message;
      Application.MessageBox(PChar(StrText), '情報', MB_ICONINFORMATION);
    end;
  end;
end;

//=============================================================================
//  作成した表の確認表示
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  StrText : String;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;
  DataSource1.DataSet  := ADOQuery1;
  DBGrid1.DataSource   := DataSource1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;
end;

//=============================================================================
//  データ削除
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
  StrText  : String;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;


  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;

  ADOQuery1.FieldByName('BinData').Assign(nil);
  ADOQuery1.FieldByName('Graphic').Assign(nil);
  ADOQuery1.FieldByName('RichEdit').Assign(nil);
  ADOQuery1.Post;

  ADOQuery1.Close;
end;

end.




02_JPEG 画像の書き込みと読出し


画像の場合です。ここでは JPEG 画像としています。Assing メソッドを使用しています。
データベースから読み出した画像は TImage に描画します。
メモリストリームを使用する方法は、添付の BDE 5.2 + Pradox のサンプルの中に TRichEdit の例があります。

この後のリッチテキストでも Assign メソッドで書き込みしています。しかし、JPEG 画像のデータをリッチテキストとしては読み出せません。データベースから読み出す時は、書き込んだ時と同じ型のオブジェクトでないと正常に読み出せないことになります。


図2
設計時画面
図3
実行結果
  • [Button1] は、画像をデータベースに書き込む
  • [Button2] は、画像をデータベースから読み出して表示する

リスト2
JPEG 画像の書き込みと読出し
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, StdCtrls, Grids, DBGrids, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    ADOQuery1: TADOQuery;
    ADOConnection1: TADOConnection;
    Button2: TButton;
    Image1: TImage;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses JPeg;

{$R *.dfm}

//=============================================================================
//  フォームを閉じる時の処理
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ADOQuery1.Close;
  ADOConnection1.Connected := False;
end;

//=============================================================================
//  データベースに接続してデータをセット
//  ディスクからJPEG画像を読み出してデータベースに記録
//  Assignメソッドを使用する例
//  TMemoryStreamを使用するコードは添付のBDE+Pradoxのコードを参照
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  StrText  : String;
  FilePath : String;
  Pict     : TJPEGImage;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の書き込みコード
  //---------------------------------------------------------------------------

  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;
  FilePath := ExpandFileName('../EARTH.jpg');
  Pict     := TJPEGImage.Create;
  try
    Pict.LoadFromFile(FilePath);
    ADOQuery1.FieldByName('Graphic').Assign(Pict);
    ADOQuery1.Post;
  finally
    FreeAndNil(Pict);
  end;

  ADOQuery1.Close;
end;

//=============================================================================
//  データベースに接続してデータを取得
//  Assignメソッドを使用する例
//  TMemoryStreamを使用するコードは添付のBDE+Pradoxのコードを参照
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  StrText : String;
  Pict    : TJPEGImage;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の取得のコード
  //---------------------------------------------------------------------------

  Image1.Picture.Assign(nil);
  //操作対象のレコード位置に移動
  ADOQuery1.First;
  if not (ADOQuery1.FieldByName('Graphic').IsNull) then begin
    Pict := TJPEGImage.Create;
    Try
      Pict.Assign(ADOQuery1.FieldByName('Graphic'));
      Image1.Picture.Graphic := Pict;
    finally
      FreeAndNil(Pict);
    end;
  end;

  ADOQuery1.Close;
end;

end.


次のように、画像ファイルから直接データベースのフィールドに書き込むこともできます。


  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;
  FilePath := ExpandFileName('../EARTH.jpg');

  TBlobField(ADOQuery1.FieldByName('Graphic')).LoadFromFile(FilePath);
  ADOQuery1.Post;

  ADOQuery1.Close;




03_TADOBlobStream を使用した画像の書き込みと読み出し


TADOBlobStream を使用した画像の場合です。このサンプルも JPEG 画像としています。
データベースから読み出した画像は TImage に描画します。

TADOBlobStream は、編集状態になってから生成し、Post する前に解放します。また、TADOBlobStream の Create メソッドの第 2 引数 Mode の値は、データベースに書き込む時は bmWrite に、読み出す時は bmRead とします。bmReadWrite にすると正常に機能しないことがあります。
特に書き込みの場合、bmRead があると TADOBlobStream には現在のオブジェクトのバイナリデータが格納されます。それが障害となるのかも知れません。TMemoryStream の SaveToStream メソッドで書き込む場合は bmReadWrite でも問題はないようです。


図4
設計時画面
図5
実行結果
  • [Button1] は、画像をデータベースに書き込む
  • [Button2] は、画像をデータベースから読み出して表示する

リスト3
TADOBlobStream を使用した画像の書き込みと読み出し
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, StdCtrls, Grids, DBGrids, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    ADOQuery1: TADOQuery;
    ADOConnection1: TADOConnection;
    Button2: TButton;
    Image1: TImage;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses JPeg;

{$R *.dfm}

//=============================================================================
//  フォームを閉じる時の処理
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ADOQuery1.Close;
  ADOConnection1.Connected := False;
end;

//=============================================================================
//  データベースに接続してデータをセット
//  ディスクからJPEG画像を読み出してデータベースに記録
//  TADOBlobStreamを使用する例
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  StrText   : String;
  FilePath  : String;
  Stream    : TMemoryStream;
  adoStream : TADOBlobStream;
  BlobField : TBlobField;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の書き込みコード
  //---------------------------------------------------------------------------

  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;
  FilePath := ExpandFileName('../501.jpg');
  Stream   := TMemoryStream.Create;
  try
    Stream.LoadFromFile(FilePath);
    BlobField := TBlobField(ADOQuery1.FieldByName('Graphic'));
    adoStream := TADOBlobStream.Create(BlobField, bmWrite);
    try
      Stream.SaveToStream(adoStream);
    finally
      FreeAndNil(adoStream);
    end;
    ADOQuery1.Post;
  finally
    FreeAndNil(Stream);
  end;

  ADOQuery1.Close;
end;

//=============================================================================
//  データベースに接続してデータを取得
//  TADOBlobStreamを使用する例
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  StrText   : String;
  Stream    : TMemoryStream;
  adoStream : TADOBlobStream;
  Pict      : TJPEGImage;
  BlobField : TBlobField;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の取得のコード
  //---------------------------------------------------------------------------

  Image1.Picture.Assign(nil);
  //操作対象のレコード位置に移動
  ADOQuery1.First;
  if not (ADOQuery1.FieldByName('Graphic').IsNull) then begin
    Stream := TMemoryStream.Create;
    Pict   := TJPEGImage.Create;
    Try
      BlobField := TBlobField(ADOQuery1.FieldByName('Graphic'));
      adoStream := TADOBlobStream.Create(BlobField, bmRead);
      try
        Pict.LoadFromStream(adoStream);
        Image1.Picture.Graphic := Pict;
      finally
        FreeAndNil(adoStream);
      end;
    finally
      FreeAndNil(Stream);
      FreeAndNil(Pict);
    end;
  end;

  ADOQuery1.Close;
end;

end.


次のように、LoadFromStream で、メモリストリームから読み込んで、データベースのフィールドに書き込みこともできます。TMemoryStream を使用した方法は汎用性があります。



  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;
  FilePath := ExpandFileName('../501.jpg');
  Stream   := TMemoryStream.Create;
  try
    Stream.LoadFromFile(FilePath);
    BlobField := TBlobField(ADOQuery1.FieldByName('Graphic'));
    adoStream := TADOBlobStream.Create(BlobField, bmWrite);
    try
      adoStream.LoadFromStream(Stream);
    finally
      FreeAndNil(adoStream);
    end;
    ADOQuery1.Post;
  finally
    FreeAndNil(Stream);
  end;

  ADOQuery1.Close;


また、次のようにファイルから直接読み込むこともできます。
これらはデータベースに書き込む際のバリエーションですが、データベースから読み出す時もいろいろなコーディングが考えられます。



  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;
  FilePath := ExpandFileName('../501.jpg');

  BlobField := TBlobField(ADOQuery1.FieldByName('Graphic'));
  adoStream := TADOBlobStream.Create(BlobField, bmWrite);
  try
    adoStream.LoadFromFile(FilePath);
  finally
    FreeAndNil(adoStream);
  end;
  ADOQuery1.Post;

  ADOQuery1.Close;




04_CreateBlobStream を使用した画像の書き込みと読み出し


≪コードで直接 BLOB ストリームを作成するよりも CreateBlobStream を呼び出すことをお勧めします。≫ という記述が、下記の Delphi のオンラインヘルプにあります。
そこで、CreateBlobStream を使用するコードもテストしてみました。使用する画像は上のサンプルと同じにしています。したがって、結果も上のサンプルと同じです。

ADO の場合、CreateBlobStream は次のように、TADODBlobStream を生成しています。したがって、実際には前項のサンプルとほとんど違いはありません。


function TCustomADODataSet.CreateBlobStream(Field: TField;
  Mode: TBlobStreamMode): TStream;
begin
  Result := TADOBlobStream.Create(Field as TBlobField, Mode);
end;


リスト4
CreateBlobStream を使用した画像の書き込みと読み出し
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, StdCtrls, Grids, DBGrids, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    ADOQuery1: TADOQuery;
    ADOConnection1: TADOConnection;
    Button2: TButton;
    Image1: TImage;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses JPeg;

{$R *.dfm}

//=============================================================================
//  フォームを閉じる時の処理
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ADOQuery1.Close;
  ADOConnection1.Connected := False;
end;

//=============================================================================
//  データベースに接続してデータをセット
//  ディスクからJPEG画像を読み出してデータベースに記録
//  CreateBlobStreamを使用する例
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  StrText   : String;
  FilePath  : String;
  MStream   : TMemoryStream;
  Stream    : TStream;
  BlobField : TBlobField;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の書き込みコード
  //---------------------------------------------------------------------------

  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;
  FilePath := ExpandFileName('../501.jpg');
  MStream  := TMemoryStream.Create;
  try
    MStream.LoadFromFile(FilePath);
    BlobField := TBlobField(ADOQuery1.FieldByName('Graphic'));
    Stream    := ADOQuery1.CreateBlobStream(BlobField, bmWrite);
    try
      MStream.SaveToStream(Stream);
    finally
      FreeAndNil(Stream);
    end;
    ADOQuery1.Post;
  finally
    FreeAndNil(MStream);
  end;

  ADOQuery1.Close;
end;

//=============================================================================
//  データベースに接続してデータを取得
//  CreateBlobStreamを使用する例
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  StrText   : String;
  Stream    : TStream;
  Pict      : TJPEGImage;
  BlobField : TBlobField;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の取得のコード
  //---------------------------------------------------------------------------

  Image1.Picture.Assign(nil);
  //操作対象のレコード位置に移動
  ADOQuery1.First;
  if not (ADOQuery1.FieldByName('Graphic').IsNull) then begin
    Pict   := TJPEGImage.Create;
    Try
      BlobField := TBlobField(ADOQuery1.FieldByName('Graphic'));
      Stream    := ADOQuery1.CreateBlobStream(BlobField, bmRead);
      try
        Pict.LoadFromStream(Stream);
        Image1.Picture.Graphic := Pict;
      finally
        FreeAndNil(Stream);
      end;
    finally
      FreeAndNil(Pict);
    end;
  end;

  ADOQuery1.Close;
end;

end.




05_ワードの文書等のファイルの書き込みと読み出し


ディスク上のファイルをデータベースに格納する例です。
データベースから読出した時は、名前を付けてディスクに保存します。
ここではワードの文書をデータベースに格納し、データベースらか読出した時は、ディクスに保存し、保存したたファイルを ShellExecute 関数で表示します。


図6
設計時画面
図7
実行画面
  • [Button1] は、ワードの文書をデータベースに書き込む
  • [Button2] は、ワードの文書をデータベースから読み出して表示する

リスト5
ワードの文書等のファイルの書き込みと読み出し
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, StdCtrls, Grids, DBGrids, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    ADOQuery1: TADOQuery;
    ADOConnection1: TADOConnection;
    Button2: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses ShellAPI;

{$R *.dfm}

//=============================================================================
//  フォームを閉じる時の処理
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ADOQuery1.Close;
  ADOConnection1.Connected := False;
end;

//=============================================================================
//  データベースに接続してデータをセット
//  ディスク上のファイルを記録。ここではワードの文書ファイル
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  StrText  : String;
  FilePath : String;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の書き込みコード
  //---------------------------------------------------------------------------

  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;

  FilePath := ExpandFileName('../LoadWord.doc');
  TBlobField(ADOQuery1.FieldByName('BinData')).LoadFromFile(FilePath);
  ADOQuery1.Post;

  ADOQuery1.Close;
end;

//=============================================================================
//  データベースに接続してデータを取得
//  記録したデータを取り出してディスクに保存
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  StrText  : String;
  FilePath : String;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の取得のコード
  //---------------------------------------------------------------------------

  //操作対象のレコード位置に移動
  ADOQuery1.First;
  FilePath := ExtractFilePath(Application.ExeName) + 'WordDoc.doc';

  if not (ADOQuery1.FieldByName('BinData').IsNull) then begin
    TBlobField(ADOQuery1.FieldByName('BinData')).SaveToFile(FilePath);

    //ワードの文書を表示してみる
    ShellExecute(Handle, nil, PChar(FilePath), nil, nil, SW_SHOW);
  end;

  ADOQuery1.Close;
end;

end.


ディスクからファイルを読み込んでデータへースに格納するこのサンプルも、メモリストリームを使用して、例えば次のようにも書けます。
もちろん、画像を扱ったサンプルのように、他のストリームも使用できます。


  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;

  FilePath := ExpandFileName('../LoadWord.doc');
  Stream   := TMemoryStream.Create;
  try
    Stream.LoadFromFile(FilePath);
    TBlobField(ADOQuery1.FieldByName('BinData')).LoadFromStream(Stream);
    ADOQuery1.Post;
  finally
    FreeAndNil(Stream);
  end;

  ADOQuery1.Close;


また、上の画像のサンプルで使用した TADOBlobStream を使用して、次のようにも書けます。


  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;

  FilePath := ExpandFileName('../LoadWord.doc');
  Stream   := TMemoryStream.Create;
  try
    Stream.LoadFromFile(FilePath);
    BlobField := TBlobField(ADOQuery1.FieldByName('BinData'));
    adoStream := TADOBlobStream.Create(BlobField, bmWrite);
    try
      Stream.SaveToStream(adoStream);
    finally
      FreeAndNil(adoStream);
    end;
    ADOQuery1.Post;
  finally
    FreeAndNil(Stream);
  end;

  ADOQuery1.Close;




06_TRichEdit のリッチテキストの書き込みと読み出し


フォームに配置した TRichEdit のリッチテキストをデータベースに格納する例です。
リッチテキストは、EXE 起動時に読み込んでいます。
ストリームを使用する方法については、これまでのサンプルを参考にしてください。
メモリストリームを使用するコードが、添付の BDE 5.2 + Pradox のサンプルの中にあります。


図8
設計時画面
  • [Button1] は、リッチテキストをデータベースに書き込む
  • [Button2] は、リッチテキストをデータベースから読み出して表示する
図9
サンプルの EXE 起動時
  • ディスクからリッチテキストファイルを読み出して表示
  • [Button1] クリックで、このリッチテキストがデータベースに保存される
図10
実行結果
  • テキストの一部を削除してデータベースに記録した後、読み出して表示した結果

リスト6
TRichEdit のリッチテキストの書き込みと読み出し
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, DBTables, StdCtrls, ExtCtrls, ComCtrls, ADODB;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    Button2: TButton;
    RichEdit1: TRichEdit;
    ADOConnection1: TADOConnection;
    ADOQuery1: TADOQuery;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
  FilePath : String;
begin
  FilePath := ExpandFileName('../テスト文書.rtf');
  RichEdit1.Lines.LoadFromFile(FilePath);
end;

//=============================================================================
//  フォームを閉じる時の処理
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ADOQuery1.Close;
  ADOConnection1.Connected := False;
end;

//=============================================================================
//  データベースに接続してデータをセット
//  TRichEditの書式付テキストをデータベースに記録
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  StrText : String;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;
  ADOConnection1.Mode             := cmReadWrite;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の書き込みコード
  //---------------------------------------------------------------------------

  //操作対象のレコード位置に移動して編集可能にする
  ADOQuery1.First;
  ADOQuery1.Edit;

  ADOQuery1.FieldByName('BinData').Assign(RichEdit1.Lines);
  ADOQuery1.Post;

  ADOQuery1.Close;
end;

//=============================================================================
//  データベースに接続してデータを取得
//  書式付テキストをデータベースから読み出して表示
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  StrText : String;
begin
  ADOConnection1.Connected   := False;
  ADOConnection1.LoginPrompt := False;

  StrText := 'Provider=Microsoft.Jet.OLEDB.4.0';
  StrText := StrText + ';Data Source=' + '../BlobTest_BLOB.mdb';

  ADOConnection1.ConnectionString := StrText;

  ADOQuery1.Connection := ADOConnection1;

  ADOQuery1.Close;
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SELECT * FROM TEST ');
  ADOQuery1.Open;

  //---------------------------------------------------------------------------
  //  上はデータベースへの接続用コード
  //  以下が実際の読み込みのコード
  //---------------------------------------------------------------------------

  RichEdit1.Lines.Clear;
  RichEdit1.Update;
  Sleep(2000);

  //操作対象のレコード位置に移動
  ADOQuery1.First;
  if not ADOQuery1.FieldByName('BinData').IsNull then begin
    RichEdit1.Lines.Assign(ADOQuery1.FieldByName('BinData'));
  end;

  ADOQuery1.Close;
end;

end.