株式会社シスアナコム

情報システムに関することなら、どんなことでも適切に助言いたします!

この投稿は1年以上前に公開されました。
現在では状況や内容が変わっている可能性があります。
ご注意下さい。m(_ _)m

Microsoft ACCESS を使って情報システムを作る際の注意点は?

      2014/06/11

回答の概要

  • 利用者部門に自由にデータベースを作らせないようにしましょう。
  • テーブルとテーブル以外の2つに分割して、サーバとクライアントへ別々に配置しましょう。
  • 基本的にマクロは使わないで、VBAでプログラムを作りましょう。
  • 汎用的に利用できると思うVBAプログラムを公開します。

回答

Microsoft ACCESS(以下、ACCESS)は、簡単にデータベースを作成できるソフトウェアです。

画面を作成するための「フォーム」や帳票を作成するための「レポート」という機能も含んでいます。

さらに、VBA という言語でプログラムを作成することもできます。

Microsoft Office(以下、Office)の上位版に含まれるので、高機能な割には安価に利用できます。

EXCEL ほどではないと思いますが、使っている人が非常に多いアプリケーションの一つだと思います。

個人的にも非常に良くできたソフトウェアだと思っています。

ACCESSで情報システムを作れるのか?

「ACCESS では、ちゃんとした情報システムなんか作れない」という人もいます。

確かに不特定多数の人たちを相手にした情報システムを作るのには向いてないですが、社内向けの情報システムであれば十分です。

以前にも書きましたが、私が勤務している会社でも ACCESS を使って社内向け情報システムをいくつか構築して活用しています。

そこで、今まで蓄積した ACCESS で情報システムを構築するためのノウハウの一部を公開したいと思います。

これからも ACCESS を使って社内向け情報システムを構築する人たちの参考になればと思います。

注意点1:情報システム部門が主導する

まず第一に、ACCESS のデータベースは利用者部門で自由に作らせないで、情報システム部門で開発・保守しましょう。

ACCESS を使えば様々な処理を自動化できますが、その内容(プログラム)は内部に隠蔽されてしまいます。

利用者部門で作った複雑な処理を行うデータベースは、作った本人が異動になったら誰も内部の処理がわからなくなります

そのため、情報システム部門で保守できる体制をつくるべきなのです。

運用は利用者部門にやってもらった方がいいでしょう。

社内に情報システム部門がない(または、存在しても ACCESS の開発・保守ができない)場合は、残念ながら ACCESS は会社のパソコンにインストールしないか、外部のシステムインテグレータに作ってもらった方がいいでしょう。

一度でも ACCESS を使って仕事の流れを簡素化したり高速化したりすると、もう元には戻れません。

何らかの修正が発生した時点で、すぐに対応できなければ仕事が止まってしまいます。

手作業の仕事に戻れと言っても無理です。

実を言うと、以前は、私が勤務している会社でも利用者部門の人たちに自由に ACCESS でデータベースを作ってもらっていました。

でも「利用者部門でなんともならなくなった時点で情報システム部門に泣きが入る」ということが多々あったので、やめてもらいました。

私の経験から言うと、EXCEL の方が利用者側の人たちだけでなんとかなるので、EXCEL を使うように推奨しています。

注意点2:データベースを分割する

第二に、データベースは必ず2つに分割しましょう。

一つはサーバ上に配置する主要なテーブルの部分。

もう一つは、クライアントパソコンに配置する主要なテーブル以外の部分(作業用テーブルやクエリー、レポート、モジュールなど)です。

クライアントパソコンに配置するデータベースは、「MDE」の形式に変換します。

そして、サーバとクライアント間のデータベースにテーブルのリンクを作成します。

このように2つに分割しておけば、将来的にプログラムを修正することになっても、データベースに影響を与えることなくプログラムを更新することができます

また、複数の人が同時に利用した場合の動作が速くなりますし、データベースのバックアップもとりやすいはずです。

注意点3:複雑なマクロ機能は使わない

第三に、「マクロ」を使うのはやめましょう。

簡単に処理を自動化できるマクロ機能なのですが、保守の面から見ると効率が非常に悪いです。

なぜなら、各行にカーソルを合わせないと、処理の詳細が把握できないから。

ただし、非常に簡単な処理を行うために使うのはいいと思います。

例えば、AutoExecマクロで初期設定を行うのは良い方法だと思います。

でも、複雑な処理は VBA (モジュール)を使うべきです。

まとめ

以上ですが、すでに ACCESS を使っている人には、当たり前すぎることばかりだったと思います。

でも、この3つの注意点は ACCESS を使う場合だけに通用するノウハウなので、あえて書きました。

例えば、プログラムにコメントを入れた方がいいとか、コメントの書き方は統一した方がいいとか、基本仕様書は必ず作るとか、画面上の操作方法は統一するとか...というノウハウは、何を使って情報システムを作っても必要になるノウハウですから。

汎用的に使えそうなVBAを公開します

最後に、ちょっと長くなりますが、今まで構築した情報システムの中で利用した VBA プログラムで、汎用的に利用できそうなものを公開します。

自由に使ってください。

ただし、不具合があっても責任は取りませんし、何か問題があれば各自で修正して使ってください。


テーブルのリンク先を変更する関数

テーブル名、データベースが存在するパス名、パスワードを指定して呼び出します。

戻り値は通常は True、データベースが存在しなければ False です。

複数のデータベースを切り替えて使う場合などには便利です。

また、サーバ側のデータベースにパスワードをつけて、クライアント側のデータベースをMDE形式にして、この関数を使えば、利用者側に対してパスワードを隠蔽できます。

Public Function ChangeLink(TableName As String, PathAndDBName As String, PWD As String) As Boolean

     Dim DB As Database
     Dim TBLDef As TableDef

     If Dir(PathAndDBName, vbNormal) = "" Then
         ChangeLink = False
         Exit Function
     End If

     Set DB = CurrentDb
     Set TBLDef = DB.TableDefs(TableName)
     TBLDef.Connect = ";PWD=" & PWD & ";DATABASE=" & PathAndDBName
     TBLDef.RefreshLink

     ChangeLink = True

 End Function

指定したデータベースを圧縮(最適化)

フルパスのデータベース名とパスワードを引数にして呼び出します。

圧縮すべきデータベースは誰も利用していないことが条件です。

C:¥を一時的に利用します。

戻り値は圧縮処理が成功すれば True、失敗すれば False です。

ACCESS のデータベースは、結構よく破損します。

複数のデータベースを切り替えて使うような情報システムの場合、この処理を利用者側で実行できる仕組みを作っておくと便利です。

Function CompactDB(DBName As String, PWD As String) As Boolean

     CompactDB = False

     If Dir(DBName) = "" Then Exit Function

     On Error GoTo CompactDB_ERR

     DBEngine.CompactDatabase DBName, "C:\Compact.mdb", dbLangJapanese, , ";pwd=" & PWD
     ''データベースを最適化する

    Kill DBName
     ''最適化前のデータベースを消去する

    FileCopy "C:\Compact.mdb", DBName
     ''元のファイル名で最適化後のファイルをコピー

    Kill "C:\Compact.mdb"
     ''最適化後のデータベースを消去する

    CompactDB = True

 CompactDB_ERR:
     On Error GoTo 0

 End Function

エクセルの指定したワークシートの特定の位置にデータを記入

データ、エクセルのファイル名(フルパス)、シート名、列名、行数を引数にしてこの関数を呼び出します。

戻り値は処理が成功すれば True、失敗すれば False です。

この関数を実行するためには、「Microsoft EXCEL 9.0 Object Library」の参照設定が必要です。

ほとんどの場合、ACCESS が使える状態ならば EXCEL も使えるでしょう。

相互に連携する場合など便利だと思います。

Function OutputExcel(V As Variant, FN As String, SN As String, CL As String, RW As Long) As Boolean

     Dim ExcelApp As New Excel.Application
     Dim ExcelFile As Excel.Workbook
     Dim ExcelSheet As Excel.Worksheet

     OutputExcel = False
     ''返り値の初期値をセット

    On Error GoTo OutputExcel_ERR

     Set ExcelFile = ExcelApp.Workbooks.Open(FN)
     Set ExcelSheet = ExcelFile.Worksheets(SN)
     ''エクセルを起動して、ファイル開く

    With ExcelSheet
     .Activate
     .Range(CL & CStr(RW)).Value = V
     End With
     ''シートの指定した位置にデータを格納する

    ExcelFile.Save
     ExcelFile.Close
     ''シートを保存して閉じる

    ExcelApp.Quit
     ''EXCELを終了する

    OutputExcel = True

 OutputExcel_ERR:
     On Error GoTo 0

 End Function

 

これ以下のプログラムは、全て Windows API を呼び出しています。

全ての Windows で動作するかは不明ですが、Windows 2000では動作確認済みです。

プロセスが存在するかどうかチェック

例えば、ACCESS から SHELL 関数などを使って外部プログラムを起動したときに、その処理が確実に終了したかどうかチェックできます。

プロセスID(SHELL関数の戻り値)を引数にしてこの関数を呼び出します。

戻り値は、まだ処理が終わっていなければ(=プロセスが存在すれば) YES、処理が終了していれば(=プロセスが存在しなければ) NO を返します。

Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'
Public Const PROCESS_QUERY_INFORMATION = &H400&
Public Const STILL_ACTIVE = &H103&

Function CheckProcessAlive(L As Long) As String

Dim hProcess As Long
Dim lExitCode As Long
Dim lret As Long

CheckProcessAlive = "ERR"
If L = 0 Then Exit Function
''プロセスIDが0ならエラー

hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 1, L)
''プロセスハンドラを取得

lret = GetExitCodeProcess(hProcess, lExitCode)
''プロセスが存在するかチェックする

If lExitCode = STILL_ACTIVE Then
CheckProcessAlive = "YES"
Else
lret = CloseHandle(hProcess)
CheckProcessAlive = "NO"
End If

End Function

クライアントパソコンにログオンしているユーザ名を取得

引数は不要で、ユーザ名が戻り値になります。

Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Function LsGetUserName() As String
Dim lpBuffer As String, nSize As Long, rtn As Long
nSize = 255
lpBuffer = Space$(nSize)
rtn = GetUserName(lpBuffer, nSize)
LsGetUserName = LsNullTrim(lpBuffer)
End Function

'Null文字以降を削除
Function LsNullTrim(strExp As String) As String
Dim i As Integer
i = InStr(strExp, vbNullChar)
If i > 1 Then
LsNullTrim = Left$(strExp, i - 1)
Else
LsNullTrim = strExp
End If
End Function

ユーザが特定のグループに所属しているかチェック

グループ名を引数にしてこの関数を呼び出します。

戻り値は、グループに所属していれば True、所属していなければ False です。

この関数を実行するためには、「CheckProcessAlive」と「LsGetUserName」関数が必要です。

このプログラムは見れば分かりますが、かなり「力わざ」でやってます。

「C:¥」に一時的にファイルを作成します。

Function CheckUsersGroup(GroupName As String) As Boolean

Dim L As Long
Dim FNUM As Integer
Dim TXT As String
Dim UN As String

UN = LsGetUserName()
''ユーザ名を取得する

L = Shell("command.com /c NET GROUP """ & GroupName & """ /DOMAIN >C:\NetGroup.TXT", vbHide)
Do Until CheckProcessAlive(L) = "NO"
DoEvents
Loop
''対象のグループに所属するユーザ名の一覧をテキストファイルへ出力する
''この処理が終わるまで待つ

FNUM = FreeFile()
Open "C:\NetGroup.TXT" For Input Access Read As #FNUM
''「NET GROUP」処理の結果ファイルを開く

Do Until EOF(FNUM)
Line Input #FNUM, TXT
If InStr(TXT, UN) <> 0 Then Exit Do
Loop
''「NET GROUP」処理結果ファイル内にログオンユーザ名の文字列があるかチェック

If EOF(FNUM) Then
CheckUsersGroup = False
Else
CheckUsersGroup = True
End If
''ファイルが最後なら(ファイル内にユーザ名がないので)グループに所属していない
''ファイルが途中なら(ファイル内にユーザ名があるので)グループに所属している

Close #FNUM
''ファイルを閉じる

End Function

 - ひとこと, ひとこと(情報化)

↓ブログランキングに参加しています!


ネット・PC(全般) ブログランキングへ
にほんブログ村 IT技術ブログ ITコンサルティングへ
にほんブログ村

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です