14歳の自分に衝撃の事実を告げてください

みなさん、おはようございます。
データベースアクセスについて質問させていただきます。参考書やこちらの質問等もしらべましたが回答が得られなかったので質問致します。

現在、アクセスで病院のベッドを管理するアプリを開発中です。
ひとつのフォームに全病棟のベッドを表示するため500以上のコントロールを配置しておりますが、
すべて非連結にして、フォームを開くときのイベントプロシージャーにクエリを開いてすべてコントロールにテーブルのデータをはめていくように設計しています。
で、問題はこのフォームを開いたまま最新のデータに更新させたいのですが、再クエリーではうまくいきませんでした。
なぜうまくいかないのか理由はわかっていません(プログラマーの方ならうまくいかなくて当然とおっしゃるかもしれませんが)
で、仕方なく、一定間隔の時間ごとにフォームを閉じて開くという方法を取っています。
この方法では遅いマシンだと再表示に時間がかかるのできっとほかにスマートなよい方法があるとおもっているのですがプログラミングのスキルが乏しいため詰まっております。
お知恵をお借りできれば幸いです。

A 回答 (11件中1~10件)

平面的に表示し、定期的に情報を更新するフリーのアプリケーションを見つけました。


http://awplus.jp/soft/page1/aj/bedmng.html
プロトタイプということなので、実用にはならないでしょうが、ソースコードが公開されているために、参考にはなりそうです。オブジェクトを配列で管理しています。言語はデルファイみたいですが。
    • good
    • 0

>>おぼろげに、配列を使えばきっとシンプルにできるんだろうな~と感じていましたが. . . .



配列とオブジェクト指向を組み合わせるのに、好適なケースかもしれません

1.エディットから派生させたクラスに、データベースとのI/Oなどを追加する
2.エディットの替わりにパネルなどから派生させれば、複数の情報を、テキストボックスだけではなく、ラジオボタン、チェックボックス、コンボボックスなどを使って多彩な表示ができる
3.オブジェクト(病床)にフォーカスがあるとき、当該レコードとつながるようにすれば、マルチユーザーによるデータの矛盾もデータベースが面倒をみてくれる
4.表示位置情報などはデータベースで管理すれば、フォーム上への配置は動的に行え、それ以後の管理は配列でできる
5.病床の増減もプログラムをいじらずにデータだけで処理できる
6.改修工事などによる一時的病床の使用不可も、フラッグなどで簡単に処理できる
7.コードは基本的な部分は数十行ですむ(?)

興味深いです。プロトタイプを作ってみたくなった。
しかし、VBAではほとんど不可能だと思います。一般的にはC++とかC#、ジャバあたりですかね?
    • good
    • 0

>>おぼろげに、配列を使えばきっとシンプルにできるんだろうな~と感じていましたが、まったくスキルがなくどうすればいいのかわからないのでコードが大きくなることを承知で簡単なコードをベッドごとに書きました。



 その配列を使った共通ルーチンを最初に作った人は、オフコン画面の操作性を実現しようという発想でした。でも、簡単にはできあがらず、その会社(当時いた会社)の社長は、売上が無いため「こりゃ首をくくるしかないか?」と枝ぶりのいい木を探したそうです。だから、ちょっと考えて、できそうに思えても、完成するまでの道は長いですね。
 それから、私もVBの書籍をたまに見ることありますが、同様なロジックで作ったものは見たことありません(探す範囲が狭いかも?)。ちなみに、似たような考え方のルーチンは、アメリカのデータベースソフトの画面入力関数(C言語)で目にしたことはあります。でも、膨大な関数群で構成されていて、またポインタのてんこ盛り状態で、これは、「天才の仕事だ。絶対自分には作れない!」と思い知らされたもんでした。
    • good
    • 0

全部のベッドを見せなくても、


退院、手術、検査等の監視の必要があるベッドだけ表示させ、
変更がかかったら再表示させたらどうでしょうか?
今日、明日、明後日、一週間以内などを色別に表示させるのも良いでしょう。
    • good
    • 0

補足です。



>>「500以上のコントロール」などというのもすごい力業だし。

私の場合は、コントロールを配列で操作し、基本的な処理を共通ルーチン化して処理していましたね。
ですので、コントロールが3つでも、500でも、その部分のコード増大はありませんでした。でも、フィールドによってチェック内容が増えるなどは当然あるので、コントロール数に応じて、コードは大きくなりました。
    • good
    • 0
この回答へのお礼

おぼろげに、配列を使えばきっとシンプルにできるんだろうな~と感じていましたが、まったくスキルがなくどうすればいいのかわからないのでコードが大きくなることを承知で簡単なコードをベッドごとに書きました。ベッドのコントロールの修正が発生すると多大な労力になるのは辛いですが・・・
配列の勉強してみようと思います。

lv4uさんのお話と同じで、当院でも一画面で直感的に空きベッドを把握したいのと、転室処理の場合にもすべてのベッドが表示されていなければ、いちいちが画面操作が必要では面倒この上ないのです。
現場はできるだけ操作がないに越したことはないですから。

余談ですが、ちなみにこの病棟画面は40インチモニタに表示します。

お礼日時:2006/09/20 21:48

回答への批判は禁止されていますが、私も同様に思ったことがあるので、補足として回答します。



No.5さんが
>>120床を一度に見せる必要があるのかが疑問です。

と疑問をもたれていますが、私も介護のシステムを検討していたとき「なんで一度に見せないといけないの?」と思ったことがありました。
でも運用シーンでは、別の仕事をしていて手が離せず、TVを見るように、何の操作もしないで1画面だけに全ての情報を盛り込んで表示させておき、近くを通ったとき、「ちらっと見る」という使い方をすることもあるとのことで、納得しました。

No.4さんが
>>そもそも非連結にしているためにいろいろ問題が発生すると考えます。

と問いかけられています。私も初めてちょっと凝ったマルチユーザでの利用を想定したアプリをアクセスで作成したとき、「非連結にするんだよ」と先輩に指導され「コードが増えるのに・・・」と思ったものです。でも、ちょっと凝った処理では、そうしないとプログラムの作成は不可能でした。もちろん、その影響でコーディング量はいやというほど増えましたね。「これって、ほとんどVisualBasicで作っているパッケージのルーチンからコピっているじゃあないですか?」って状態でした。
    • good
    • 0

120床を一度に見せる必要があるのかが疑問です。


メインフォームの詳細セクションにリスト表示させ、ここに入力用のボタンを置き、
これをクリックすると別フォームで入力用フォームが表示されるようにし、
入力完了後「登録」ボタンを押すとテーブルを更新するようにすれば如何でしょう。
    • good
    • 0

そもそも非連結にしているためにいろいろ問題が発生すると考えます。

マルチユーザーでの表示で整合性を取ろうと苦労されているようですが、表示はうまくいっても、複数ユーザーがデータを書き換えたときの不整合にはどのように対応されるのでしょうか?通常ここら辺はデータベースがそれなりに処理してくれる部分ですが、非連結となれば、設計者が処理しなければならない。
「500以上のコントロール」などというのもすごい力業だし。
このようなハードルがあっても、なお非連結にしなければならない理由は何でしょう?
これを明らかにされると別のアドバイスもあるかと考えます。
    • good
    • 0
この回答へのお礼

500以上になる理由は、120床あるベッド情報を一度に表示する必要があるためです。
患者氏名、退院予定日等1ベッドあたり4項目の情報を表示します。
また、トップの要望で分りやすいインタフェースでベッド情報の並びが不規則にならざるおえず、単純に帳票フォームを使えないからです。

非連結にするのは、1ユーザがテーブルを開いてデータを握ったままにしておきたくなかったからです。
追加、更新、削除はすべてクエリーで行います。
整合性については、ベッドごとにフラグ用フィールドを設けて、フラグを立てたユーザ以外はデータの参照しかできないようにする予定です。
このシステムは一日に10名も動かない入退院情報を管理するので、競合の発生率はきわめて低いと考えております。
以上が私なりの設計構想ですが忌憚ないアドバイスを頂ければ幸いです。

お礼日時:2006/09/19 21:33

>>フォームを開いたときに記述した内容のコードをそっくりタイマーイベントに記述すればいよいとおもったのですが、そうすると修正する場合、2箇所も変更する必要があるので、汎用モジュール化して、それをフォームを開くときとタイマーイベントに設定すればよいと思いましたがいかがでしょうか?



 汎用モジュール化でもいいのですが、そこまでしなくとも、普通のプロシージャを作成して、フォームオープン時とタイマーイベント時の両方のイベントから呼び出すようにすれば、コードの2重化は防げると思います。イベント共用がうまくいかない場合は、それぞれの小さなイベントプロシージャから、画面設定のプロシージャを呼び出すという手もありますね。

>>おっしゃるとおり、アクセスでの運用は正直怖いのですが、そこまで病院全体がシステムを使いこなせるようになったら、本格的にオーダリングや電子カルテを導入するようになると思います。いつのことやらですが。

 開発の分量を考えてみると、病院のベテラン担当者が協力会社のSEやPGさんを使いまくっても、ちょっと難しいと思いますよ。日本を代表する巨大なメーカでさえ、納品したシステムがトラブルをおこして、大病院のカルテシステムが停止し、薬が出せない状態になったこともありますしね。別のところでは、システムの保守担当が、トラブル対応が激務なため、どんどん辞めていったとか、ダウンして、その病院にお世話になった話など聞きます。(しかも、システムがまともに動作しないわけだから、徹夜などで頑張っても医師や看護師からは冷たい目で見られる)
 政府は、全国共通な電子カルテシステムを作る構想があるようですから、それを待ったほうがいい気もします。ただ、丸投げ体質、ゼネコン体質の日本のIT業界で、まともなシステムが作れるか?すごく疑問なんですけどね。
    • good
    • 0

非連結フォームは、多少、専用の関数を用意しないと開発が面倒です。



DisplayRecord()
UpdateRecord()
DeleteRecord()

などです。
これらの関数一発で、フォームへの表示、書き込みも可能です。
また、抽出すべき主キーを配列変数にすれば、レコード移動ボタンの全ても自作することが可能です。
もちろん、サブフォームまで非連結にすると大変ですので主フォーム程度がお勧めです。

Private Sub Form_Load()
  Dim StopNow As Boolean
  
  StopNow = Not DisplayRecord(Me, "SELECT * FROM id管理表 WHERE id_name='Test'")
  If Not StopNow Then
    Message "フォームが正常に表示されました。"
  End If
End Sub

 StopNow = Not UpdateRecord(Me, "SELECT * FROM id管理表 WHERE id_name='Test'")

 UpdateRecord関数は、いわゆる非連結フォームに入力されたデータをデータベースに書き込む関数です。書き込む表の列とフォームに配置したコントロールとの対応関係は、DisplayRecord関数と同じようにコントロールの名前で判断します。

? DeleteRecord("SELECT * FROM id管理表")
True

まあ、一介のデザイナーに過ぎない素人が考えた関数です。
が、多分、非連結フォームで開発するのに必要なアイデアが含まれています。
なお、その他に、採番テーブルを管理する関数が必要なのは言うまでもありません。

 Private Sub 仕入先名_BeforeUpdate(Cancel AS Integer)
    Dim strShiiresaki AS String
    Dim strWhere   AS String
    
    strShiiresaki = Nz(Me.仕入先名, "")
    strWhere = "仕入先名='" & strShiiresaki & "' AND id<>" & Me.ID
    Cancel = CBool(DBLookup("id", "仕入先", strWhere, 0) <> 0)
    If Cancel Then
      Message "[仕入先名]が重複しています。" & chr$(13) & chr$(13) & _
          "・{Esc}{Esc} で入力を取り消すことができます。"
    ElseIf isNewRecord And Me.ID = 0 Then
      Me.ID = NewID("仕入先_id")
      SetFieldEnabled Me, True
    End IF
  End Sub

' -----------------------------------------------------------------------------------------
' フォームに読み込んだ列情報を表示します。
'
' 【要件】 ファームのフィールド名が、<"field_" + 列名>であること。
' -----------------------------------------------------------------------------------------
Public Function DisplayRecord(ByVal frm As Form, _
               ByVal strQuerySQL As String) As Boolean

On Error GoTo Err_DisplayRecord
  Dim isOK As Boolean
  Dim I  As Integer
  Dim N  As Integer
  Dim rst As ADODB.Recordset
  Dim fld As ADODB.Field

  isOK = True
  Set rst = New ADODB.Recordset
  rst.Open strQuerySQL, _
       CurrentProject.Connection, _
       adOpenStatic, _
       adLockReadOnly
  If Not rst.BOF Then
    ' =================
    ' Begin With: frm
    ' -----------------
    With frm
      N = .Controls.Count - 1
      For Each fld In rst.Fields
        For I = 0 To N
          If Mid$(.Controls(I).Name, 7) = fld.Name Then
            .Controls(I).Value = fld.Value
            Exit For
          End If
        Next I
      Next fld
    End With
    ' ---------------
    ' End With: frm
    ' ===============
  Else
    MsgBox " フォームに表示する情報はありません。(DisplayRecord)", vbInformation, " お知らせ"
  End If
Exit_DisplayRecord:
On Error Resume Next
  rst.Close
  Set rst = Nothing
  DisplayRecord = isOK
  Exit Function
Err_DisplayRecord:
  isOK = False
  MsgBox "実行時エラーが発生しました。(DisplayRecord)" & Chr$(13) & Chr$(13) & _
      "・Err.Description=" & Err.Description & Chr$(13) & _
      "・SQL Text=" & strQuerySQL, _
      vbExclamation, " 関数エラーメッセージ"
  Resume Exit_DisplayRecord
End Function

Public Function UpdateRecord(ByVal frm As Form, _
             ByVal strSQL As String, _
             Optional Echo As Boolean = False) As Boolean
On Error GoTo Err_UpdateRecord
  Dim isOK  As Boolean
  Dim I    As Integer
  Dim N    As Integer
  Dim fldName As String
  Dim cnn   As ADODB.Connection
  Dim rst   As ADODB.Recordset
  Dim fld   As ADODB.Field

  isOK = True
  Set cnn = CurrentProject.Connection
  ' =================
  ' Begin With: cnn
  ' -----------------
  With cnn
    .Errors.Clear
    .BeginTrans
  
    Set rst = New ADODB.Recordset
    rst.Open strSQL, _
         cnn, _
         adOpenStatic, _
         adLockOptimistic
    ' =================
    ' Begin With: rst
    ' -----------------
    With rst
      If Not .BOF Then
        N = frm.Controls.Count - 1
        For Each fld In .Fields
          For I = 0 To N
            fldName = frm.Controls(I).Name
            If Left$(fldName, 6) = "field_" Then
              If Mid$(fldName, 7) = fld.Name Then
                fld.Value = frm.Controls(I).Value
                Exit For
              End If
            End If
          Next I
        Next fld
        .Update
      End If
    End With
    ' ---------------
    ' End With: rst
    ' ===============
    .CommitTrans
  End With
  ' ---------------
  ' End With: cnn
  ' ===============
  If Echo Then
    MsgBox " 1件のレコードを更新または保存しました。", vbInformation, " お知らせ"
  End If
Exit_UpdateRecord:
On Error Resume Next
  rst.Close
  Set rst = Nothing
  UpdateRecord = isOK
  Exit Function
Err_UpdateRecord:
  isOK = False
  If cnn.Errors.Count > 0 Then
    ErrMessage cnn.Errors(0), strSQL
    cnn.RollbackTrans
  Else
    MsgBox "プログラムエラーが発生しました。(UpdateRecord)" & Chr$(13) & Chr$(13) & _
        "・Err.Description=" & Err.Description & Chr$(13) & _
        "・SQL Text=" & strSQL, _
        vbExclamation, " 関数エラーメッセージ"
  End If
  Resume Exit_UpdateRecord
End Function

Public Function DeleteRecord(ByVal strSQL As String, _
               Optional ByVal Echo As Boolean = True, _
               Optional ByVal LockType As Integer = adLockPessimistic) _
               As Boolean
On Error Goto Err_DeleteRecord
   Dim isOK As Boolean
   Dim N  As Integer
   Dim cnn As ADODB.Connection
   Dim rst As ADODB.Recordset
  
   isOK = True
   Set cnn = CurrentProject.Connection
   ' =================
   ' Begin With: cnn
   ' -----------------
   With cnn
     .Errors.Clear
     .BeginTrans
     ' ----------------
     ' Recordset Open
     ' ----------------
     Set rst = New ADODB.Recordset
     ' =================
     ' Begin with: rst
     ' -----------------
     With rst
       .Open strSQL, _
          cnn, _
          adOpenStatic, _
          LockType
       If Not .BOF Then
         .MoveFirst
         Do Until .EOF
           N = N + 1
           .Delete
           .MoveNext
         Loop
       End If
     End With
     ' ---------------
     ' End With: rst
     ' ===============
     If Echo Then
       MsgBox N & " 件のレコードを削除しました。", vbInformation, " お知らせ"
     End If
     .CommitTrans
   End With
   ' ---------------
   ' End With: cnn
   ' ===============
Exit_DeleteRecord:
On Error Resume Next
   rst.Close     ← rst、cnn は、関数から抜け出すと自動的に閉じられ破棄されます。
   cnn.Close       よって、これらのコードは省いても支障のないものです。
   Set rst = Nothing
   Set cnn = Nothing
   DeleteRecord = isOK
   Exit Function
Err_DeleteRecord:
   isOK = False
   If cnn.Errors.Count > 0 Then
     ErrMessage cnn.Errors(0), strSQL
     cnn.Rollbacktrans
   Else
     MsgBox "プログラムエラーが発生しました。" & _
        "システム管理者に報告して下さい。(DeleteRecord)", _
        vbExclamation, " 関数エラーメッセージ"
   End If
   Resume Exit_DeleteRecord
    • good
    • 0
この回答へのお礼

>>s_huskyさん

回答ありがとうございます。

このコードの山は厳しいですね^^;
マクロ主体で自動化している私には正直???です。
ごめんなさい。
シンプルな方法があると思っていたものですから。
こういうやり方もあるっていうことは参考にさせていただきます。

お礼日時:2006/09/18 16:45

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す


おすすめ情報

このQ&Aを見た人がよく見るQ&A