【Dev】Access VBA覚書@オボエタテ

開発ざれごと

access_1113-thumb

HDD内を掃除してたら出てきた。

大昔に書いた時のもので、Access VBAの開発時に学習用にメモった内容です。

これからAccess開発する方の参考にでもなればと公開します。VBAに限らず、余計な事も書いてるかもと思います。覚えてません。まとめてないので、使いにくいと思うけど(検索してくれ)

MS Office Accessに関する覚え書き(VBA主体)

●ACCESSは突然壊れる!
Accessは突拍子も無く突然に(よく)壊れる。壊れたら最後、修復は『不可能』である。
壊れ方は色々ある。MDB自体起動しなくなるや、VBE周りが一切起動しない等。
そのため、なにか不自然な事が起こったら、それ、であるので諦める他ない。
CVS/SVNなどのバージョン管理ツールは必須。細かくバージョン管理すべし。
また、Accessのサイドにテキストエディタを置いて、細かく修正ログを記載しておくのも有効
サイズ縮小のためにデータベース最適化の場合も注意が必要。

●Officeのインストール
フルインストールにすべき。各ユーティリティや、VBAヘルプなどが入らない。

●起動フォームから編集できない場合
起動オプションで、設定されているため、編集ができないようになっている場合がある。
その際は、MDB起動する時に、Shiftを押しながらすれば良い。
これは、OfficeやWindows全般においての共通操作。

●検索(Ctrl+F)について
如何なるところでも実行できる。覚えておくと便利。
フォーム内項目や、テーブルリストなど、わざわざクエリを作るまでもない。

●起動時の設定を行う
ツールの起動時の設定にて、スタート時に表示するフォームを設定できる。

●データベースウィンドウの表示の仕方
起動時の設定などで、データベースウィンドウが非表示にされている場合や
フォームの最大化などがされている場合がある。
この場合、F11を押下する事で、表示させる事ができる。

●VBAエディタの表示の仕方
Alt+F11にて一発で呼び出せる。覚えておくと楽。

●リンクテーブルのリンク先を調べる方法
データベースユーティリティ→リンクテーブルマネージャにて確認できる。
ただし、標準インストールでは入らない。

●データテーブルの一括編集だけをする
一時的に更新クエリを作成し、実行し、保存せずに終了すればいい。
実行は、「!」を押す。

●クエリ更新式での改行の使い方
デザイン式では改行を利用できないので、VBA Functionを利用する。

●フォームデザインで綺麗に並べる方法
合わせたい位置に、基準となる1個のフォームを移動して、
移動したい全てのフォームを選択して、配置指定すればいい。

●オプション(ラジオ)ボタンの利用
オプショングループを先に作り、その中に配置する

●ファイルサイズを小さくする
データベースの最適化にてかなり小さくできるが、
あまり実行はおすすめできない。壊れる時があるそう。

●デバッグトレースについて
コード内にブレークポイントを指定すれば良い。
あとは、F8キーと、Ctrl/Shift/Shiftの組み合わせで、トレースの動作を
制御できる。
また、ウォッチ式にて、ブレーク条件を設定できる。

●デバッグ出力について
デバッグの出力を表示するには、イミディエイトウインドウ(Ctrl+G)を利用する。
VBAコード内からは以下のようにして出力する。
Debug.Print MyWeekDay
このウィンドウ内では、このようにして、個別に実行できる。
?WeekdaySample() ←"?"はPrintと同等
サブプロシージャの場合は"?"が不要

●VBAコード検索
おなじみのコマンドCtrl+F4にて実行できる。
カレントモジュール内なのか、プロジェクト全体なのか、指定ができる。
外部エディタ編集ができないので、VBAエディタ依存になるのはしょうがない。
WindwosXP+Office2000はVBA開発には向いていない。
自分のところだけかもしれないが、日本語にてコード検索が利用できない。
文字が必ず化ける。コピペならできる
↑MSのIntelliPointが原因らしい。新しいVersionに上げると改善
↑上げても改善されない。分からない

●VBAにてNULL値の扱い
極力Nz()を使用して、NULL値の扱いを制御する。
判断には、IsNullを利用する。
CStr/CDblなどで目的の型変換を忘れず。
IsEmpty()は、変数の初期化状態のチェック。
IsNumeric()は、式として利用可能かのチェック。これは便利。

●VB/VBA関数メソッドの書き方
他言語と違う部分なので、慣れるまで書き間違いが多い。
Sub or Functionを注視する。
なお、戻り値は、Returnではなく、関数名に代入する。

●VBA1行にまとめて書く場合
C/Perl/Javaなどと違い、行の終わり記述が無い。
続けて書く場合は、":"に繋げて書く。

●素早いコーディング方法
自分流のコーディングスタイルは維持できないと思い。
VBAエディタにお任せするのがベスト。
VBAが自動的にタイプしてくれる部分を早めに記憶しておくと良い。
Sub/End subやIf/End ifなど。
適度なスペースなどタイプせずそのまま記述し、次行に移ると良い。
自動的(勝手)に、フォーマットしてくれる。
また、Ctrl+Spaceにて入力候補や補完を表示させる。

●VBA RecordSet他オブジェクト指定方法
色々な書き方がある。
[forms]![form]![object]!value ←名前に空白や"-"などが有る場合
forms!form!object.value
forms.form.object.value
Forms("F_特記事項入力").Controls("LIST_CHECKLIST").MultiSelect = 0
などの書き方がある。
共通モジュールについては、フォーム指定はいらない。
この式内に、変数を用いる場合は、()を利用する。
Nz(Forms(sFormName)(sCaption & "2").Value, "")

●"."と"!"の参照の仕方の違い
(不確定情報)
"."はコンパイル時、"!"は実行時に解釈されるため、"."の方が、処理速度などの点
で有利。エラーなどでバグを見つけやすい。
ただし、この情報は未確定

●WORD&EXCEL連携
WORD差し込みやExcelファイル作成は、Access又
はOfficeの機能がそのまま利用できる。
言うまでもないが、直接テーブルからではなく、クエリを仲介した方が便利。

●Accessの機能呼び出し
これには、DoCmdコマンドを用いる。
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, stDocName, FileName, True
DoCmd.RunSQL "UPDATE [T_製品データ] SET [T_製品データ].送信済 = Yes WHERE [T_製品データ].送信対象外=No AND [T_製品データ].送信済 = No"
以上のようなもの(上から、Excel書き出し、SQL実行)

●OCX/ActiveXの利用
ターゲットのPCにインストール後、ツールの参照設定にてチェックを入れる。
大量にあるので、どれがどれか分からない、注意して操作すべき。
名前問題のために、MSでは、優先順位にて対処している。
オブジェクトのバージョンによる相違が多々あるので、注意。
OS標準機能でも注意。WSH関連でハマッた事がある。

●FROM句にサブクエリを書けるのはAccess2000から
ex)select tbl.item from (select * from table_name) as tbl
ex)select tbl.item from table_name as tbl2 right join (select * from hoge) as tbl1 on tbl1.id = tbl2.id

●TOPで上位行を取得できる(Access&SQLserverのみ?)
ex)select top 10 * from table_name 上位10件のみ

●Accessでは比較に文字の大小や全角半角は区別されない
特に記号などが絡むと、期待外に動作するため、かなり注意すべき。
バイナリデータは別。これは設定できない。SQLserverはインストール時可。

●マクロやフォーム内容を外部に書き出す
GREPなどが掛けられないため、解析には重宝する。
※なぜかmdbが破壊された経験があるため、実行の際は、バックアップ対象にて行う事
以下コードを実行する。C:に作成。

Private Sub Command0_Click()
    Dim db
    Dim c,d

    Set db = CurrentDb()

    ' Macro
    Set c = db.Containers("Scripts")

    For Each d In c.Documents
        If Left(d.Name, 1) <> "~" Then
            Application.SaveAsText acMacro, d.Name, "C:Macro_" & d.Name & ".txt"
        End If
    Next d

    ' Form
    Set c = db.Containers("Forms")

    For Each d In c.Documents
        If Left(d.Name, 1) <> "~" Then
            Application.SaveAsText acForm, d.Name, "C:Form_" & d.Name & ".txt"
        End If
    Next d
End Sub

●VBA内にてデータベースから簡単にデータを取得
DLookupが最も簡単。ただし、複数ヒットする場合は、最初のみ。ただし遅い。
例)備考1 = DLookup("DES", "Q_PDP_LIST_CF", "PDP_No= PDP_No_COMBO")
※引数:取得項目名、テーブル、Where文
他にDMax/DMin/DSum/DAvg/DCountなどがある。

●イベントの順番
以下、転載。実際に調べてません。
≪開くとき≫
(サブフォーム) : Open → Load → Resize → Current
(サブフォーム内コントロール) : → Enter → GotFocus
(メインフォーム) : → Open → Load → Resize → Activate → Current
(メインフォーム内のコントロール) : → Enter
≪値変更のとき≫
(サブフォーム内コントロール) : GotFocus
→ KeyDown → KeyUp → KeyDown → KeyPress
→ Dirty → Change → KeyUp → KeyDown
→ BeforeUpdate → AfterUpdate → Exit → LostFocus
(サブフォーム) : → BeforeUpdate → AfterUpdate → Current
≪閉じるとき≫
(メインフォーム内のコントロール) : Exit
(メインフォーム) : → Unload → Deactivate Close
(サブフォーム) : → Unload → Close
これらのイベントは必ず発生するものもありますが、発生しない場合もあります。
入力によっては複数回発生するイベントもあります。

●一つのフォームに配置できる最大数
768個。ラベルやシェープもカウントされる。

●フォームの動的生成
以下のようにしてコントロールを動的に生成できる。
CreateControl(フォーム名, コントロールの種類[, コントロールの配置場所[, 親コントロール[, 連結フィールド名[, 位置(左)[, 位置(上端)[, 幅[, 高さ]]]]]]])
参考:CreateForm()

●排他ポップアップウィンドウの表示(Windowsでいうモーダルウィンドウ)
作業ウィンドウの固定をTrue、ポップアップをTrueに設定する。

●リストボックスの選択系のプロパティ
ItemsSelected
ItemsSelected.Count    ←選択されているアイテム
ItemsSelected.Item(n)
ItemData(n)    ←内容
ListCount    ←リスト数
Selected(n)    ←状態
選択内容取得
For Each varItem In Me!リスト.ItemsSelected
    msgbox Me!リスト.ItemData(varItem)
Next varItem
チェック外し
For Each varItem In Me!リスト.ItemsSelected
    Me!リスト.Selected(varItem) = False
Next varItem

●TrimやSpaceなどの標準関数が利用できなくなった
VBAの参照設定が外れてしまったのが原因。バージョンが違う環境に移すと良く起こる。
参照設定にて、エラーが起きていないかチェックし、可能なら、古いバージョンのOCXを
設定するなどで動作を確認する。

●EXCELを操作する一例
Set oApp = CreateObject("Excel.Application")
oApp.Visible = True    ←見える様に
oApp.UserControl = True
oApp.Workbooks.Open FileName:=Excel_Path
oApp.Worksheets("T_100C").Select
oApp.Columns("A:AQ").AutoFit    ←自動幅調整
Excelへエクスポート例
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "T_100C", Excel_Path, True

●サブフォーム間の参照
≪サブフォームの「小計」の値を親フォームから参照する場合≫
Forms![frm_受注]![frm_S明細]![小計] 若しくは Forms![frm_受注].[frm_S明細].[小計]
≪逆にサブフォームから、親フォームの、「受注コード」を参照する場合≫
Parent![受注コード]
これは、 Forms![frm_受注]![受注コード] と記述するのと、同様の結果になります。

●メモリーが足りないエラー
●クエリが複雑すぎます。エラー
物理メモリが十分でも、メモリエラーが表示される。
これは、Accessエンジンの

開発ざれごと

Posted by nabe