お世話になります。
<質問分類>
Access2007のVBA言語、リソースメモリの使用量と開放方法について
<私のテストで使用しているパソコンです>
OS 名 Microsoft Windows XP Professional
バージョン 5.1.2600 Service Pack 3 ビルド 2600
OS 製造元 Microsoft Corporation
システム名 POWEREDGE600SC
システム製造元 Dell Computer Corporation
システムモデル PowerEdge 600SC
システムの種類 X86-ベース PC
プロセッサ x86 Family 15 Model 2 Stepping 9 GenuineIntel ~2399 Mhz
BIOS バージョン/日付 Dell Computer Corporation A06, 2003/05/19
SMBIOS バージョン 2.3
Windows ディレクトリ C:\WINDOWS
システム ディレクトリ C:\WINDOWS\system32
ブート デバイス \Device\HarddiskVolume1
ロケール 日本
ハードウェア アブストラクション レイヤ バージョン = "5.1.2600.5512 (xpsp.080413-2111)"
ユーザー名 SYSB\FUDANO
タイム ゾーン 東京 (標準時)
合計物理メモリ 2,816.00 MB
利用可能な物理メモリ 1.93 GB
合計仮想メモリ 2.00 GB
利用可能な仮想メモリ 1.96 GB
ページ ファイルの空き容量 5.35 GB
ページ ファイル C:\pagefile.sys
相当古いマシンですが、問題なく正常に動作しております。Access2007は最新でWindows UPdate 済みです。
<概要>
Access2007で、伝票を発行するシステムを作成しました。ボタンを押して、伝票を印刷する。この様な使用方法では全く問題はないのですが、
ボタンを押して、自動で、1000枚程印刷すると、リソースメモリが不足して、Access2007の文字が消える。応答がなくなると言う状態になります。
調査しますと、『DoCmd.OpenReport レポート名, acViewNormal』のVBA命令を実行した後、メモリが開放されない事が判明しました。
<Windowsタスクマネージャでのメモリ使用量の確認結果です>
1)Access2007起動 30,184KB
2)印刷ボタン押下 38,676KB
3)1件目印刷 40,000KB
4)10件目印刷 65,000KB
5)50件目印刷 118,600KB
6)100件目印刷 205,794KB
7)200件目印刷 371,372KB
8)300件目印刷 428,508KB
このようにメモリ使用量が増大して、『DoCmd.Close』などで、メモリ開放を試みましたが無駄でした。このメモリを開放するには、Access2007を終了し
再度起動すると、メモリが開放されます。
何か、良い方法はないのでしょうか?
現在、印刷部分を別のプロセスにして、Access2007の起動、印刷、Access2007の終了を繰り返す方法を試験しております。非常に、効率が悪く、印刷用の
子プロセスのAccess2007で、レポート表示中に、システムの終了(右上Xボタン)で抜けられると、Private Sub Report_Unload(Cancel As Integer)の
イベントが発生するタイプのOSとしないOSなどが有り、親のプロセスに終了状態を通知出来ずに、私のプログラムでは、このプロセスが残ているような状態
と間違って判断してしまいます。改良を加え、この方法で、実用に耐えられるか検討しております。
<レポート表示中、右上の×印 システム終了押下時のイベント Report_Unloadイベント>
Windows2003Server Report_Unloadイベントは発生しない
WindowsXP Professional Report_Unloadイベントは発生する
<親プロセスから子プロセスを作成しレポートを印刷する方法>
Function MyOpenReport(ByRef strReportName As String, ByVal acFlag As Integer)
Dim Access As Object
Dim strPass As String
Set Access = CreateObject("Access.Application")
strPass = CurrentProject.path
Access.OpenCurrentDatabase strPass & "" & "印刷DB01.accdb"
If (acFlag = 0) Then
'印刷する
Access.Visible = False
On Error Resume Next
Access.DoCmd.OpenReport strReportName, acFlag
Access.CloseCurrentDatabase
Access.Quit
Err.Clear 'エラークリア
'MSACCESS.EXEの消滅待ち処理
DoEvents
DoEvents
DoEvents
DoEvents
Else
'プレビュー印刷する
Access.Visible = True
Access.DoCmd.OpenReport strReportName, acFlag
'MSACCESS.EXEの消滅待ち処理(レポートの終了×ボタン押下待ち)
On Error GoTo exitLoop
While Access.Visible = True
DoEvents
Wend
exitLoop:
Err.Clear 'エラークリア
DoEvents
DoEvents
DoEvents
DoEvents
End If
End Function
現在は、親プロセスの『XXXX伝票印刷.accdb』より、印刷ボタンを押下し、イベントプロシージャの中から、
If Me.印刷チェック.Value = True Then
'レポート表示を実行する
MyOpenReport レポート名, acViewPreview
Else
'レポート印刷する
MyOpenReport レポート名, acViewNormal
End If
と呼び出して使用しております。 使用する準備としては、子プロセス側の『印刷DB01.accdb』では、親プロセスのデータテーブルへ印刷で必要なテーブル
をリンクさせてあります。親プロセスにあったレポートは、子プロセスに移動してあります。
<Windowsタスクマネージャ メモリ使用量>
- Access2007起動直後 31,968KB
- 印刷ボタン押下 35,668KB
3) 010件印刷 37,164KB
- 050件印刷 37,676KB
- 135件印刷 39,228KB
- 200件印刷 40,068KB
7) 300件印刷 41,524KB
メモリ効率は改善されるのですが、問題点として、先に書きました。親プロセスで、子プロセスの生成と消滅の管理くいちがいが出た場合の対応が
VBAだけで正確に処理することが課題となってます。(環境設定に左右されたくないのでVBAにこだわっております)
親プロセスと連携するように、データテーブルで「印刷使用中」、「印刷空き」などと持たせておりますが、子プロセスで、右上のX印、システム終了で抜け
られた場合が、VBAでは何もできない場合もあり、困りものです。
従って、もっと、単純で効率の良い方法を模索しているというしだいです。よろしくご教授お願い致します。