[BlueLeaf1336]> PROGRAM> Natural Born Junk>

DAO36調査-2

historyTOP

2003/02/02:作成(参考:MSDNライブラリ)

overviewTOP

続きです。前回のページは、DAO36調査-1になります。

Fieldsコレクション・FieldオブジェクトTOP

これから、TableDef.FieldsコレクションとFieldオブジェクトについてループをまわすことにします。 Propertiesコレクションでループをまわす予定にしていますが、ついでですので、実際のプロパティについても調べておきます。

Fieldsコレクション
プロパティCountコレクションが持つオブジェクト数。整数型(Integer)。

Fieldオブジェクト
プロパティ AllowZeroLengthブール型(Boolean)
Attributes長整数型(Long)の定数の組み合わせ(※1参照)
CollatingOrder長整数型(Long)の値か、定数のいずれか(※2参照)
DataUpdatableブール型(Boolean)
DefaultValue半角255文字(255バイト)以内の文字列型(String)
FieldSize長整数型(Long)
ForeignName文字列型(String)
Name文字列型(String)
OrdinalPosition整数型(Integer)。既定値0
OriginalValueバリアント式(ODBCDirectワークスペースでのみ使用可)
Requiredブール型(Boolean)
Size整数型(Integer)
SourceField文字列型(String)
SourceTable文字列型(String)
Type操作の種類やデータ型を示す定数(前回のProperty.Typeに同じ)
ValidateOnSetブール型(Boolean)
ValidationRule文字列型(String)
ValidationText文字列型(String)
Valueバリアント型(Variant)
VisibleValueバリアント式(ODBCDirectワークスペースでのみ使用可)

これについては、タイプライブラリに載っている定数値もあわせて示しておきます。

(※1)Field.Attributes
dbFixedField$00000001フィールドサイズ固定。Numeric型(Numeric)フィールド既定値
dbVariableField$00000002フィールドサイズ可変(テキスト型(Text)フィールドのみ)
dbAutoIncrField$00000010自動的に増え一意な長整数型(Long)の値をとる。変更不可
dbUpdatableField$00000020フィールド値変更可
dbSystemField$00002000レプリカのレプリケーション情報を含む。削除不可
dbHyperlinkField$00008000ハイパーリンク情報を含む。(メモ型(Memo)フィールドのみ)
dbDescending$00000001降順(Z〜A、100〜0、ん〜あ)に並べ替えられる

同じくこれも。多分ほとんど関係ないだろうとは思いますが。

(※2)Field.CollatingOrder
dbSortNeutral$00000400上記以外
dbSortArabic$00000401アラビア語
dbSortCyrillic$00000419ロシア語
dbSortCzech$00000405チェコ語
dbSortDutch$00000413オランダ語
dbSortGeneral$00000409欧米標準(英語、フランス語、ドイツ語、ポルトガル語、イタリア語、現代スペイン語)
dbSortGreek$00000408ギリシャ語
dbSortHebrew$0000040Dヘブライ語
dbSortHungarian$0000040Eハンガリー語
dbSortIcelandic$0000040Fアイスランド語
dbSortNorwDan$00000406ノルウェー語、デンマーク語
dbSortPDXIntl$00000409ParadoxのInternationalの並べ替え順序
dbSortPDXNor$00000406Paradoxのノルウェー語とデンマーク語の並べ替え順序
dbSortPDXSwe$0000041DParadoxのスウェーデン語とフィンランド語の並べ替え順序
dbSortPolish$00000415ポーランド語
dbSortSpanish$0000040A古スペイン語
dbSortSwedFin$0000041Dスウェーデン語、フィンランド語
dbSortTurkish$0000041Fトルコ語
dbSortJapanese$00000411日本語
dbSortChineseSimplified$00000804中国語(中国)
dbSortChineseTraditional$00000404中国語(台湾)
dbSortKorean$00000412韓国語
dbSortThai$0000041Eタイ語
dbSortSlovenian$00000424スロベニア語
dbSortUndefined$FFFFFFFF未定義または不明な並べ替え順序

さて、これでまわす準備ができました。前回のコードにさらにひとつネストを加えていってみます。

var
    i, j, k: integer;
begin
    for i := 0 to daoDatabase.TableDefs.Count - 1 do
    begin
        for j := 0 to daoDatabase.TableDefs[i].Fields.Count - 1 do
        begin
            for k := 0 to daoDatabase.TableDefs[i].Fields[j].Properties.Count - 1 do
            begin
                try
                    Memo1.Lines.Add(
                        BoolToStr(daoDatabase.TableDefs[i].Fields[j].Properties[k].Inherited, True)
                        + ' : '
                        + daoDatabase.TableDefs[i].Fields[j].Properties[k].Name;
                        + ' : '
                        + PropertyTypeToStr(daoDatabase.TableDefs[i].Fields[j].Properties[k].Type)
                        + ' : '
                        + VarToStr(daoDatabase.TableDefs[i].Fields[j].Properties[k].Value)
                    );
                except
                    on E:Exception do
                    begin
                        AStrings.Add(Format('%d : %s', [i, E.Message]));
                    end;
                end;
            end;
        end;
    end;
end;

こんなところですか。実行してみると、速い早い(前回の最後と比べてですが)。 ループネストが1段深くなっているので、もっと遅くなるだろうと思っていたんですが、そんなことなかったです。 あと、邪魔くさいのでココには乗せませんが、上のField.AttributesとField.CollatingOrderの文字列への変換関数は作っておくことにします。

CreateXXXXXXXメソッドTOP

ところで、ループの中で、何度も同じ変数とインデックスでオブジェクトにアクセスしているのですが、 Variant変数に収めてすっきりさせたくなることがあります。 でも、実際にやってみると、エラーになります。

var
    i, j, k: integer;
    objTableDefs, objTableDef: Variant;
begin
    objTableDefs := daoDatabase.TableDefs;
    for i := 0 to objTableDefs.Count - 1 do
    begin
        for j := 0 to objTableDefs[i].Fields.Count - 1 do
        begin

上のコードは、3段ネストプロパティアクセステスト用コードの、最初の一部分を勝手に変数に代入したものです。 このコード、実は、2行目の.Countはエラーにならずに通り抜けます。 しかし、4行目で、変数にインデックスをつけて各オブジェクトにアクセスしようとすると怒られます。 まああたりまえのような気もしますが...

これはおそらく、objTableDefs変数が、TableDefs型のコレクションであるということがもうひとつ示しきれていないところに原因があるように思います。 早い話全然だめということじゃないかと。 じゃあどうするか。うっとうしく長い長いプロパティアクセスを奈落ネストまでつなげるか。 というとそうでもないです。それが、...続きます。

いや、だめなようです。 OpenRecordSetというのがあるので、おんなじ感じで、既に存在しているテーブルやフィールドを参照するためのメソッドもあるだろうと勝手に考えていたのですが、甘かったです。 ひょっとしたらあるのかもしれないけども、わかりませんでした。 この長い長いプロパティアクセスで最後まで押し通すことにしましょう。

mdb構造解析プログラムを作ってみようTOP

というわけで、テーブル自体の情報、テーブルのフィールドの情報は取得できるようになりましたので、構造解析プログラム(というほどでもない?)を作ってみることにしましょう。 名前も決めてます。mdber(えむでばー)です。 「mdb」+「er(する人)」で、「mdbを解析するもの」ということにします。嘘っぱちな英語ですが。

で、何を出力するか?についてまず表にまとめておきます。

テーブル自体(TableDefオブジェクトの贈り物)
Attributesテーブルの属性
DateCreated作成された日付と時刻
LastUpdated最後に変更された日付と時刻
Nameテーブル名
RecordCountレコード総数
SourceTableNameリンクテーブル名

テーブルのフィールド(Fieldオブジェクトの贈り物)
AllowZeroLength長さ 0 の文字列("")を設定できるかどうか
Attributesフィールドの属性
DefaultValue既定値
FieldSizeメモ型(Memo)の文字数またはロングバイナリ型(LongBinary)のバイト数
Nameフィールド名
OrdinalPositionフィールドの表示順序
RequiredNull値を使用できるか
Sizeメモ型(Memo)以外の文字データからなるフィールドの場合は、保持できる最大の文字数。数値フィールド場合は、保存に必要なバイト数
SourceFieldデータソースのフィールド名
SourceTableデータソースのテーブル名
Typeデータ型

こんな感じにしておきます。 それから、上の表に挙げた項目を保持するための構造体の構造(?)も決めておきます。

type
    //TableDef用構造体
    TTableDef = record
        Attributes      : string;
        DateCreated     : TDateTime;
        LastUpdated     : TDateTime;
        Name            : string;
        RecordCount     : integer;
        SourceTableName : string;
    end;

    //TableDef.Field用構造体
    TTableDefField = record
        AllowZeroLength : Boolean;
        Attributes      : string;
        DefaultValue    : string;
        Name            : string;
        OrdinalPosition : integer;
        Required        : Boolean;
        Size            : integer;
        SourceField     : string:
        SourceTable     : string;
        FieldType       : string;
    end;

また、TableDefオブジェクトは、TableDefsコレクションによって管理され、FieldオブジェクトがFieldsコレクションによって管理されていることから、それぞれTTableDefList、TTableDefFieldListを用意しといたほうがよいような気がします。 ココでのListがなんなのかについてはまだ考えていません。

今の段階では、本当の出力の方法(HTMLで吐き出すとか、画面上でタブごとに1テーブルのデータを表示するとか、Gridに表示するとか)については、まったく考えていません。 とりあえず、mdbの構造をとりだして、自分で定義した構造体(やその他)に格納しようとしている段階です。 データとして持っとけばどんな形だろうがいけるだろう、いけるんじゃないか、いけるかも、みたいに思っているわけです。

と、ここまで考えてきてひょっとしてクラスにしてしまったほうがいいかも、とも思ってきました。何の根拠もないですが。

....できました。スレッドにしたりいろいろしましたが、邪魔くさくなってしまってますが、とりあえず、HTMLに吐き出します。 せっかくなので、DOWNLOADページにおきました。

EOFTOP