こんにちは、なかぜんです。Access案件を受け持つと「こんな仕様、よく聞くなあ」と感じることがありませんか?たとえば「得意先マスタにユーザーに応じて異なる入力制御をかけてほしい」とか「見積もり画面で売上実績が見えるように」とか…そんな“あるある”な要求が、実は効率よくパターン化できるってご存じですか?この記事では、そんな“Accessあるある”な要求仕様を、上級者の目線でパターン化して整理し、VBAコード例とともにお届けします。「やってみたい!」と思える安心感と、すぐに業務で役立つ実践性を目指しています。
1. 権限に応じた入力制御パターン
1‑A. ユーザー属性ごとの制御
たとえば、営業部は“単価編集OK”、経理部は“不可”など、ユーザーの所属によって入力可否を変えたいことがあります。これはUserIDや部署IDをフォーム起動時に取得して、コントロールのEnabledプロパティで制御します。
<コード例>
Private Sub Form_Open(Cancel As Integer)
Dim userDept As String
userDept = CurrentUserDepartment() ' 独自関数で部署取得
If userDept = "営業" Then
Me!txtUnitPrice.Enabled = True
Else
Me!txtUnitPrice.Enabled = False
End If
End Sub
解説:UserDepartment 関数でユーザーの部署を取得し、フォームオープン時に単価テキストボックスのEnabledプロパティを切り替えています。上級者なら、さらにエラー処理やログ出力も追加できますね。
1‑B. 時間帯・期間による制御
月末締め前だけ特定項目をロックする、など時期や時間に応じた制御もよくある要求です。
Private Sub Form_Current()
Dim today As Date
today = Date
If Day(today) > 25 Then
Me!btnSubmit.Locked = True
Me!lblNotice.Caption = "月末締め準備中のため、提出不可です"
Else
Me!btnSubmit.Locked = False
Me!lblNotice.Caption = ""
End If
End Sub
解説:Day 関数で日付を取得し、25日以降はボタンをロック。ユーザーにわかりやすい通知メッセージを表示しています。
2. 顧客別レイアウト変更パターン
2‑A. フィールド表示切り替え
顧客Aには「納品先コード」が、顧客Bには「配送指示」が必要…といった場合、フォーム上のフィールドを動的に表示/非表示にします。
Private Sub Form_Open(Cancel As Integer)
Select Case Me!cmbCustomer
Case "顧客A"
Me!txtShipToCode.Visible = True
Me!txtDeliveryInstruction.Visible = False
Case "顧客B"
Me!txtShipToCode.Visible = False
Me!txtDeliveryInstruction.Visible = True
Case Else
Me!txtShipToCode.Visible = False
Me!txtDeliveryInstruction.Visible = False
End Select
End Sub
解説:顧客コードによって適切なフィールドを表示。フォーム設計を統一しつつ柔軟な対応が可能です。
2‑B. レポート項目の動的切り替え
印刷時に明細形式を切り替えたい…という要望にも対応できます。
Private Sub Report_Open(Cancel As Integer)
If Me!chkDetailed Then
Me!DetailSection.Visible = True
Me!SummarySection.Visible = False
Else
Me!DetailSection.Visible = False
Me!SummarySection.Visible = True
End If
End Sub
解説:真偽値チェックボックスで印刷レイアウトを切り替えるアプローチです。
3. データ整合チェックパターン
3‑A. 入力時の即時チェック
Private Sub txtQuantity_AfterUpdate()
If Me!txtQuantity < 0 Then
MsgBox "数量は 0 以上を入力してください", vbExclamation
Me!txtQuantity.Undo
End If
End Sub
解説:ネガティブ数量の入力を即座に検出して Undo。ユーザーにすぐ気づいてもらえる優しい仕掛けです。
3‑B. 保存前の一括チェック
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsNull(Me!txtOrderDate) Then
MsgBox "注文日は必須です", vbCritical
Cancel = True
ElseIf Me!txtDeliveryDate < Me!txtOrderDate Then
MsgBox "納品日は注文日以降にしてください", vbCritical
Cancel = True
End If
End Sub
解説:重要項目の未入力や論理矛盾を防ぐため、保存前に必ずチェックするのが鉄則です。
4. 外部連携/インポートパターン
4‑A. Excelからの明細インポート
Private Sub btnImport_Click()
Dim xl As Object
Set xl = CreateObject("Excel.Application")
Dim wb As Object, ws As Object
Set wb = xl.Workbooks.Open(ThisWorkbook.Path & "\import.xlsx")
Set ws = wb.Sheets(1)
Dim i As Long, v As Variant
For i = 2 To ws.Cells(ws.Rows.Count, "A").End(-4162).Row
v = ws.Cells(i, 1).Value
' …レコード追加処理…
Next i
wb.Close False
xl.Quit
Set xl = Nothing
End Sub
解説:Excelの内容を読み込んで、ループでレコード追加。上級者なら Power Query や ADO 経由での効率化も検討できます。
4‑B. 外部DB/CSV連係
ODBC接続やテキストファイルから読み込むケースも多いです。
Private Sub btnImportCSV_Click()
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
rs.Open "C:\data\import.csv", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\data\;Extended Properties=""Text;HDR=Yes;FMT=Delimited"";", , , "SELECT * FROM import.csv"
While Not rs.EOF
'…レコード処理…
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
End Sub
解説:ADODB 経由で CSV を読み込む手法。ファイル形式やヘッダー有無の指定なども細かく設定できます。
5. 注意点やよくあるミス
- Null や未入力の扱いに弱いコード:AfterUpdate や BeforeUpdate では Null チェックをしっかり。
- ハードコーディング of 部署名/日付:部署名や日数などは定数化して柔軟設計に。
- Excel 終了漏れ:インポート後に Excel を Quit せずに残してしまうとメモリ喰いバグに。
- エラーハンドリングがない:VBA の基本として、必ずエラー処理(On Error~)を入れておくこと。
- パフォーマンスの見落とし:大量データ処理では、レコード操作より SQL。 6. 応用ポイント
- **パラメータテーブル化**:部署名・日数などは設定テーブルに切り出して、VBA はそこを参照するだけの設計に。
- **テンプレートフォームの利用**:類似フォームが多い場合は、テンプレートフォームをベースに、要素差分だけを動的に当て込む仕組みに。
- **クラスモジュールによる共通処理の集約**:ロギング、入力チェック、外部連携など共通機能は Class にまとめて再利用。
- **ADO を活用したバッチ処理**:ループを減らし、INSERT INTO SELECTなどの SQL バッチで大量処理を高速化。
