ActiveX でのデータ辞書メソッドの使用
この章では、以下の項目について説明します。
ActiveX データ ソース コントロールによる DDF の処理
データ辞書ファイル(DDF)は、Zen データに対する列レベルのアクセスを行うために、Zen アプリケーションや多数のサードパーティ アプリケーションで使用されます。ActiveX アクセス方法は、Zen 開発者が DDF の作成、読み取りおよび変更を容易に行えるようにする多数のメソッドを提供します。
辞書ファイル処理のほとんどで、コントロールへの新しいメソッドの追加が必要です。ただし、旧バージョンの ActiveX データ ソース コントロールはデータ辞書を認識したため、既存のプロパティとメソッドの動作にいくつかの変更が加えられました。旧バージョンとの互換性は保たれていますが、RefreshLocations などのように拡張されたプロパティがある一方、FieldInde や FieldName などのように使用が推奨されなくなったものもあります。
ファイルの内容とメモリ イメージ
ActiveX データ ソース コントロールは DDF から情報を読み取り、必要に応じて内容をキャッシュに格納します。つまり、辞書には、DDF 自体の内容と、DDF ファイルに関する ActiveX アクセス方法コントロールのメモリ イメージの内容という 2 つのバージョンが常に存在します。ActiveX コントロールのバージョン 3 では、コントロールが DDF 情報を DDF 自体から読み取るか、または、保持しているメモリ イメージから読み取り、アプリケーションの起動時間を節約するかを RefreshLocations プロパティが決定していました。
この機能は維持されていますが、RefreshLocations の意味は、オペレーションを実行するために DDF 自体を使用するか、あるいは辞書情報に関する ActiveX コントロールのメモリ イメージを使用するかを示すように拡張されました。
言い換えると、オペレーションがコントロールのメモリ イメージまたは DDF を参照できる場合は、RefreshLocations を False に設定すれば、コントロールはメモリ イメージのみを使ってオペレーションを処理するように制限されます。RefreshLocations が True である場合、オペレーションはメモリ イメージとファイル自体に作用します。したがって、RefreshLocations は ActiveX コントロールの DDF 処理用メソッドとプロパティの多くに作用する優先プロパティです。
メモ:RefreshLocations を True に設定して DDF を編集するときは、DDF を上書きしないように注意してください。
辞書ファイルの読み取り
以前のバージョンの ActiveX アクセス方法は、DDF に含まれる情報の大部分を公開していましたが、特定の情報を取り出すのが非常に困難であったり、ときには不可能なことがありました。また、項目ごとに複数のプロパティ設定が必要だったので、情報の複数の項目を検索することは面倒でした。本バージョンの ActiveX アクセス方法では、これらの問題の解決にバリアント配列を使用しました。バリアントとは、複数のデータ型を表すことができ、かつどのデータ型を現在表しているかがわかる変数の一種です。ActiveX アクセス方法コンテナーはバリアントをサポートします。
バリアント配列はバリアントの一種で、実質的にはバリアントのリストへの参照であり、リストの各項目に異なる型の情報を保持できるものです。この配列は、コード環境によって異なる方法で表されます。Visual Basic では、バリアント配列は myArray(1, 1)のような単なる通常の配列として表示されます。しかし、Visual C++ では、バリアント配列は VT_ARRAY|VT_VARIANT 型のバリアントにすぎず、"SafeArray" システム API を使用して配列の内容を処理する必要があります。
既に述べたように、ActiveX アクセス方法はバリアント配列を使用してコア DDF 情報を公開します。ActiveX インターフェイスが使用する配列は、1 次元として列、2 次元として行を持つ 2 次元配列です。この配列では、Visual Basic ユーザーは ReDim Preserve 関数を使用して行数を変更することができます。列は要求された情報のさまざまな面を表すのに対して、行は項目の集合を表します。たとえば、GetTableList は 2 次元配列を返します。1 次元は 3 つの情報、つまり、TableID、TableName、および TableLocation から構成されているのに対して、2 次元は辞書内のテーブルごとに 1 行を含んでいます。したがって、Visual Basic におけるテーブル名のリストの取得は以下のように行われます。
►リスト ボックスに現在の辞書内のテーブル名を設定するには
Dim tableList as Variant
Dim tableCount as integer
'すべての情報をファイル自体から読み取ることを確認する
VAccess1.RefreshLocations = True
'DdfPath を設定 - これにより辞書を開く
VAccess1.DdfPath = "c:\mydata"
'バリアント配列を取得
tableList = VAccess1.GetTableList
'リスト ボックスに名前を入力 - 配列の上限に達するまでループ
For tableCount = 0 to UBound(tableList, 2)
'リストボックスに配列の正しいメンバーを追加
List1.AddItem tableList(1, tableCount)
Next tableCount
FieldList と
IndexList は、ほとんど同じ機能を果たします。ただし、これらはプロパティであるため、配列のエントリを変更したり、エントリを追加することができます。各配列の 1 次元の構造については、
「FieldList」 と
「IndexList」 を参照してください。言うまでもなく、各配列の 2 次元はフィールド数またはインデックス数を表します。
辞書ファイルの変更
ActiveX メモリ イメージでのファイルの変更は、DDF の新しい定義を追加または変更してコミットする最初の段階として、また、間違った DDF の情報を修正する場合において有用です。必要とされる変更のほとんどは、FieldList プロパティおよび IndexList プロパティを使用して行うことができます。
DDF を変更する場合は、すべての変更がコミットできる状態になるまで ActiveX メモリ イメージに変更情報を保管しておき、その後 DdfAddTable を使用してファイルに変更情報をコミットする方が効率的です。したがって、FieldList または IndexList を設定するときは RefreshLocations を False に設定することをお勧めします。Visual Basic では、ReDim 関数で Preserve オプションを使用すれば、既存の定義にフィールドを追加することができます。また、DdfModifyTableName と DdfModifyLocation を使用して、現在のメモリ イメージまたは DDF ファイル自体に含まれるテーブルを変更することもできます。たとえば、次のようにします。
►既存のテーブル定義にフィールドを追加するには
Option Base 0
Dim fields as Variant
'DDF から直接現在の情報を取得
VAccess1.RefreshLocations = True
'VAccess を正しい DDF とテーブルに設定
VAccess1.DdfPath = "c:\myData"
VAccess1.TableName = "TableShortAField"
'フィールド リストを取得
fields = VAccess1.FieldList
'配列の次元の変更およびフィールドの追加
ReDim Preserve fields(7, UBound(fields, 2) + 1)
'これで、前と同じ配列の最後に空のフィールドが追加されました
'空のフィールドを定義
fields(1, UBound(fields, 2)) = "NewComment"
fields(2, UBound(fields, 2)) = 0 '文字列
fields(3, UBound(fields, 2)) = VAccess1.DataLength
fields(4, UBound(fields, 2)) = 20 '20 バイトの文字列
fields(7, UBound(fields, 2)) = "This is a new comment"
'この変更をまだファイルに書き込まない
VAccess1.RefreshLocations = False
'空のフィールドを ActiveX メモリ イメージに保存
VAccess1.FieldList = fields
....
<そのほかの DDF 処理>
....
'さて、テーブルは希望どおりに設定されました
'テーブルの名前を変更しましょう
DdfModifyTableName "TableWithAllFields"
'次の操作を DDF に直接作用させるため、
'RefreshLocations を設定してもかまいませんが、
'DdfAddTable はメモリ イメージではなく DDF にのみ作用するため、
'RefreshLocations は無視されます(リファレンスの DdfAddTable を参照)
'テーブルをファイルに保存 - 既存の定義を上書き
DdfAddTable True
メモ:上記の例で示した変更は DDF のみに作用します。この追加フィールドの領域がテーブル自体になければ、フィールドはファイル自体に存在しません。データ ファイルの構造の変更については、以下のセクションを参照してください。
テーブル定義の作成
ActiveX アクセス方法のメモリ イメージ(および DDF)でテーブルを作成することは、データ ファイルに関連付けられた DDF エントリがない場合や、新しいテーブルを作成する場合に有用です。このプロセスには、以下の 3 つの基本的な手順があります。
1 ActiveX アクセス方法のメモリ イメージで空のテーブルを作成します。
2 ActiveX アクセス方法のメモリ イメージに適切なテーブル情報、フィールド情報、およびインデックス情報を設定します。
3 新しいテーブルを DDF に保存します。
新しいテーブルを作成する場合は、この後に第 4 の手順、つまり、データ ファイルの作成を行います。
メモ:同じディレクトリに、ファイル名が同一で拡張子のみが異なるようなファイルを置かないでください。たとえば、同じディレクトリ内のデータ ファイルの 1 つに Invoice.btr、もう 1 つに Invoice.mkd という名前を付けてはいけません。このような制限が設けられているのは、データベース エンジンがさまざまな機能でファイル名のみを使用し、ファイルの拡張子を無視するためです。ファイルの識別にはファイル名のみが使用されるため、ファイルの拡張子だけが異なるファイルは、データベース エンジンでは同一のものであると認識されます。
空のテーブルを作成するとき、ActiveX アクセス方法は現在のメモリ イメージに作業テーブルがなく、すべてのフィールドおよびインデックス情報が消去されていることを認識できる必要があります。DdfAddTableName がこの機能を果たします。現在のテーブル メモリ イメージを DDF に追加する DdfAddTable や、現在のテーブル名を変更しても他のすべての情報を保つ DdfModifyTableName と違い、DdfAddTableName は現在のテーブル リストに追加スロットを作成し、空のテーブルに関連するすべてのフィールドおよびインデックス情報を消去します。この作業を行うときは、DDF に空のテーブルを作らないよう、RefreshLocations を False に設定することをお勧めします。
DdfModifyLocation、FieldList および IndexList オペレーションを使用して、新しい空のメモリ イメージを作成することができます。次に、DdfAddTable を使用して DDF にそのイメージを書き出すことができます。
►辞書に新しいテーブルを追加するには
Option Base 0
'DDF から直接現在の情報を取得
VAccess1.RefreshLocations = True
'VAccess を正しい DDF に設定
VAccess1.DdfPath = "c:\myData"
'テーブル設定中はメモリ イメージでのみ作業する
VAccess1.RefreshLocations = False
'現在のメモリ イメージに新しいテーブル スロットを作成
VAccess1.DdfAddTableName "NewTable"
'場所を設定
VAccess1.DdfModifyLocation "newTable.mkd"
....
<フィールドとインデックス情報を設定>
....
'テーブルをファイルに保存 - 既存の定義を上書きしない
'この定義はまだ存在しないはずであるため
DdfAddTable False
メモ:DdfDropTable への 1 回の呼び出しで、テーブル定義全体を削除することができます。当然のことながら、このオペレーションは決定的な事態を引き起こすため、注意して使用する必要があります。
辞書の作成
アプリケーションで辞書自体を作成しなければならない場合があります。たとえば、アプリケーションが初めて実行されたときに必要な DDF を作成するようにアプリケーションを書いて、ベンダーがアプリケーションと一緒に DDF を出荷および更新しなくて済むようにすることができます。このタスクを行うメソッドとして、DdfCreateDictionary があります。このメソッドは、DdfPath ディレクトリに空の辞書ファイル(COMMENT.DDF と FIELDEXT.DDF も含む)を作成します。
メモ:overwrite パラメーターを True に設定すると、DdfCreateDictionary は現在のディレクトリ内の DDF を破壊して回復不能にしてしまうので、注意して使用してください。
データ ファイルの変更
これまで説明してきた変更はすべて、DDF または DDF の ActiveX メモリ イメージにだけ当てはまるものです。ただし、DDF を変更しても、データ ファイル内の実際のレコードの長さや構造は変更されません。この変更を行うには、データ ファイルに直接影響を与える関数を使用する必要があります。
データ ファイルの長さの変更は、1 つの操作で済む問題ではありません。基本的には、データ ファイルを破壊し、新しい長さで再構築する必要があります。既存のファイルに対してこの変更を行う場合は、2 つの VAccess コントロールとテンポラリ ファイルを使用してレコードをコピーする必要があります。たとえば、次のようにします。
►テーブルとデータ ファイルにフィールドを追加するには
Dim totalRecs as Integer
Dim currRec as Integer
'DDF を読めるようにする
VAccess1.RefreshLocations = True
VAccess2.RefreshLocations = True
'DDFPath を設定
VAccess1.DdfPath = "c:\myData"
VAccess2.DdfPath = "c:\myData"
'テーブルを設定
VAccess1.TableName = "MyTable"
VAccess2.TableName = "MyTable"
'メモリ イメージのみを使用
VAccess1.RefreshLocations = False
VAccess2.RefreshLocations = False
'上記ルーチンを使用して VAccess2 メモリ イメージに新規フィールドを追加
AddNewField
'実際のデータ ファイルを作成し DDF を更新
'VAccess1 のメモリ イメージは更新されない
VAccess2.RefreshLocations = True
VAccess2.DdfCreateTable True
'テーブルを一時的に別の場所に割り当てる
VAccess2.RefreshLocations = False
VAccess2.DdfModifyLocation "tempdata.mkd"
'ファイルを開き最初のレコードを取得
VAccess1.Open
VAccess2.Open
VAccess1.GetFirst
'レコードを一方から他方へコピー
totalRecords = VAccess1.TotalRecords
currRec = 0
While currRec < totalRecords
VAccess2.Buffer(0) = VAccess1.Buffer(0)
VAccess2.Insert 'ここにエラー処理を追加
VAccess1.GetNext
currRec = currRec + 1
Wend
VAccess1.Close
VAccess2.Close
'2 つのデータ ファイルができた(古いデータと新しいデータ)
'言語 API を使用して古いデータ ファイルを削除し、
'新しいデータ ファイル名を古い名前に変更する
RenameTempDataFile
'正しい場所に置き直す - DDF は既に設定されているので変更しない
VAccess2.DdfModifyLocation VAccess1.Location
その他にも、データ ファイルのインデックス構造に対して直接行える変更があります。これらの操作は
ActiveX メソッド リファレンスに示されており、
DdfAddIndex、
DdfDropIndex、および
DdfDropIndexMaintain などがあります。
その他の DDF 操作
ここで説明するメソッドを使用して、さまざまな目的で DDF を処理することができます。
オーナー ネームによる DDF の保護
オーナー ネームで DDF をセキュリティ保護することができます。この機能を果たすために、以下の 2 つの方法が用意されています。
•DdfSetOwner。このメソッドは、VAccess メモリ イメージに現行の有効な DDF オーナー ネームを設定します。つまり、すべての DDF ファイル操作はこのオーナー ネームを使用します。RefreshLocations が True である場合、この呼び出しを行う際のアクセスについては前の DDF オーナー ネームを使用し、このオーナー ネームが DDF 自体に適用されます。このメソッドは、データ ファイルとの関連でのみ使用される OwnerName プロパティには影響を与えません。
•DdfTestOwnerName。このメソッドでは、有効な DDF オーナー ネームを設定し、その名前で許される権限を決定することができます。
これらの 2 つの方法の詳細については、
ActiveX メソッド リファレンスを参照してください。
既存のフィールドとインデックス情報の削除
DdfClearFields と DdfClearIndexes は、現在のテーブルの既存のフィールド情報およびインデックス情報をすばやく消去できる便利な方法を提供します。
メモ:RefreshLocations が True である場合、これらの変更内容は DDF に書き込まれるので、注意して使用してください。
永続的な DDF メモリ イメージによるコメントの強制設定
DdfGetComments。このメソッドの用途は非常に限定的です。RefreshLocations が False である場合、DDF 以外のテーブルを開いているときは永続的なメモリ イメージが読み取られます。ただし、永続的なメモリ イメージにはコメント情報が含まれていません。DdfGetComments は RefreshLocations を無視するため、このメソッドを使用してコメント情報を永続的な DDF の情報と同調させるように ActiveX を強制設定することができます。
広範囲に影響が及ぶ ActiveX メソッド
最後に、次の 2 つのメソッドは DDF を扱うオペレーションに対して広範囲の影響を与えます。
•DdfTransactionMode。このメソッドが True である場合、DDF に直接書き込みを行うように要求されるすべての DDF 処理関数はトランザクションの適用範囲内で書き込みを行います。つまり、ある部分の書き込みが行えないと、すべての書き込みが行えなくなるため、たとえば、FIELD.DDF と INDEX.DDF の間の関係は破壊されません。
•DdfKeyUseIndexDDFOnly。このメソッドは、True に設定されている場合のみ、コントロールに INDEX.DDF を使用させます。ActiveX は通常、ステータス バッファーで指定されたファイル自体に格納されているインデックス情報によって DDF 情報を増補します。これは、正しくない INDEX.DDF エントリを処理する場合のコントロールの信頼性を高めます。しかし、この動作は同時に、コントロールを使って正しくない INDEX.DDF エントリを修復することを困難にします。それは、ファイルを開くときに実際の DDF 情報の一部が上書きされるからです。
DdfKeyUseIndexDDFOnly を True に設定すると、コントロールはインデックス情報をステータス バッファー内のインデックス情報で上書きしません。つまり、正しくない INDEX.DDF エントリがあると、コントロールはファイル内をナビゲートできませんが、DDF の現在の状態を反映します。このため、正しくないエントリの診断と修復が容易になります。