2018年5月29日火曜日

印刷するプリンター・印刷設定をプログラムで動的に設定 [ACCESS]

ACCESSのレポートのプリンター設定を動的に設定したい!

標準モジュールにレポート印刷関数を作成。
--------------------------------------------------------------------

'==================================================
'レポートを印刷orプレビュー
'
'ReportName:レポート名
'PrintKbn:0=印刷 0<>プレビュー
'==================================================
Public Function PrintReport(ReportName As String, PrintKbn As Variant)
 
    Dim prtName     As String
    Dim setPrt      As Printer
    Dim rpt         As Report

    '警告非表示
    DoCmd.SetWarnings False

    'レポートを開く
    DoCmd.OpenReport ReportName, acViewPreview

    prtName = "プリンター名"
    Set setPrt = Application.Printers(prtName)
         
    Set rpt = Reports(ReportName)

    'レポートにプリンターを設定
    rpt.Printer = setPrt

    '用紙サイズ
    rpt.Printer.PaperSize = acPRPSA4
    '給紙用法
    rpt.Printer.PaperBin = acPRBNAuto
    '印刷向き
    rpt.Printer.Orientation = acPRORPortrait '縦
    rpt.Printer.Orientation = acPRORLandscape '横
    '余白
    rpt.Printer.TopMargin = Round(10 * 56.7, 2)
    rpt.Printer.BottomMargin = Round(20 * 56.7, 2)
    rpt.Printer.LeftMargin = Round(30 * 56.7, 2)
    rpt.Printer.RightMargin = Round(40 * 56.7, 2)

    If PrintKbn = 0 Then
        '印刷
        DoCmd.PrintOut
        'プレビューを閉じる
        DoCmd.Close acReport, ReportName, acSaveNo
    End If

    DoCmd.SetWarnings True

End Function

--------------------------------------------------------------------

後は各印刷の"DoCmd.OpenReport"を"PrintReport"に変更
--------------------------------------------------------------------
Private Sub Button_Click()

'DoCmd.OpenReport "レポート名", PrintKbn

'↑を↓に変更

  PrintReport "レポート名", PrintKbn
 
End Sub
--------------------------------------------------------------------

これでデータベースにプリンター名や印刷設定を登録し、PrintReport内でセットすれば、ユーザー毎に印刷するプリンターを切り替えれる。

プログラムのリリース時もACCESSごと上書きで大丈夫!

用紙サイズ・給紙方法がなかったり文字列で指定したい場合は↓
用意されていない用紙サイズ・給紙方法を文字列で取得

用意されていない用紙サイズ・給紙方法を文字列で取得 [ACCESS]

ACCESSの印刷設定で用紙サイズや給紙方法が用意されていない場合、簡単に設定できない・・・。

用紙サイズや給紙方法は割り当てられている数字をセットすれば良いみたいで、WindowsAPIを使って取得できるようなので、色々参考にして↓の関数を作成。

共通モジュールに取得関数を作成。
--------------------------------------------------------------------
Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, ByVal pDefault As Long) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

' プリンタデバイスドライバの能力を取得する関数の宣言
Private Declare Function DeviceCapabilities Lib "winspool.drv" Alias "DeviceCapabilitiesA" (ByVal pDevice As String, ByVal pPort As String, ByVal fwCapability As Long, pOutput As Any, pDevMode As Any) As Long
' ある位置から別の位置にメモリブロックを移動する関数の宣言
Private Declare Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
'PC名を取得する関数の宣言
Private Declare Function GetComputerName Lib "kernel32.dll" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long

Private Const DC_PAPERNAMES = 16
Private Const DC_PAPERS = 2
Private Const DC_BINNAMES = 12
Private Const DC_BINS = 6

'==================================================
'用紙サイズの番号を取得
'
'paraPrinterName:プリンタ名
'paraPaperName:用紙名
'==================================================
Public Function GetPaperSizeNumber(paraPrinterName As String, paraPaperName As String) As Integer

    Dim lPaperCount As Long
    Dim lCounter As Long
    Dim hPrinter As Long
    Dim sDevicePort As String
    Dim bytPaper() As Byte
    Dim strPaperName As String * 64
    Dim aintNubytPaper() As Integer
    Dim onePaperName As String
 
    GetPaperSizeNumber = -1
 
    sDevicePort = ""
 
    If OpenPrinter(paraPrinterName, hPrinter, 0) <> 0 Then

        ' バッファに必要なサイズ(用紙数)を取得
        lPaperCount = DeviceCapabilities(paraPrinterName, sDevicePort, DC_PAPERNAMES, ByVal vbNullString, 0)
        ReDim bytPaper(64 - 1, lPaperCount - 1)
        ReDim aintNubytPaper(1 To lPaperCount)
     
        '用紙名を取得
        Call DeviceCapabilities(paraPrinterName, sDevicePort, DC_PAPERNAMES, bytPaper(0, 0), 0)
        '用紙番号を取得
        Call DeviceCapabilities(paraPrinterName, sDevicePort, DC_PAPERS, aintNubytPaper(1), ByVal vbNullString)
        For lCounter = 0 To lPaperCount - 1
            ' 用紙名コピー
            MoveMemory ByVal strPaperName, bytPaper(0, lCounter), 64
            ' 用紙名追加
            onePaperName = Left(strPaperName, InStr(strPaperName, vbNullChar) - 1)
            ' 指定の用紙名が入っていたらその用紙番号を返す
            If InStr(LCase(onePaperName), LCase(paraPaperName)) > 0 Then
                GetPaperSizeNumber = aintNubytPaper(lCounter + 1)
                Exit For
            End If
        Next lCounter
     
        ClosePrinter (hPrinter)
    End If
End Function

'==================================================
'給紙方法の番号を取得
'
'paraPrinterName:プリンタ名
'paraPaperName:給紙方法
'==================================================
Public Function GetBinNumber(paraPrinterName As String, paraBinName As String) As Integer

    Dim lBinCount As Long
    Dim lCounter As Long
    Dim hPrinter As Long
    Dim sDevicePort As String
    Dim bytBin() As Byte
    Dim strBinName As String * 24
    Dim aintNubytBin() As Integer
    Dim oneBinName As String
 
    GetBinNumber = -1
 
    sDevicePort = ""
 
    If OpenPrinter(paraPrinterName, hPrinter, 0) <> 0 Then

        ' バッファに必要なサイズ(給紙方法数)を取得
        lBinCount = DeviceCapabilities(paraPrinterName, sDevicePort, DC_BINNAMES, ByVal vbNullString, 0)
        ReDim bytBin(24 - 1, lBinCount - 1)
        ReDim aintNubytBin(1 To lBinCount)
     
        '給紙方法名を取得
        Call DeviceCapabilities(paraPrinterName, sDevicePort, DC_BINNAMES, bytBin(0, 0), 0)
        '給紙方法番号を取得
        Call DeviceCapabilities(paraPrinterName, sDevicePort, DC_BINS, aintNubytBin(1), ByVal vbNullString)
        For lCounter = 0 To lBinCount - 1
            ' 給紙方法名コピー
            MoveMemory ByVal strBinName, bytBin(0, lCounter), 24
            ' 給紙方法名追加
            oneBinName = Left(strBinName, InStr(strBinName, vbNullChar) - 1)
            ' 指定の給紙方法名が入っていたらその給紙方法番号を返す
            If InStr(LCase(oneBinName), LCase(paraBinName)) > 0 Then
                GetBinNumber = aintNubytBin(lCounter + 1)
                Exit For
            End If
        Next lCounter
     
        ClosePrinter (hPrinter)
    End If
End Function

--------------------------------------------------------------------

これを使用してレポート設定時に↓のように文字列で用紙サイズや給紙方法が設定出来る!
--------------------------------------------------------------------
    '用紙サイズ
    rpt.Printer.PaperSize = GetPaperSizeNumber(prtName, "用紙名")
    '給紙用法
    rpt.Printer.PaperBin = GetBinNumber(prtName, "給紙方法名")
--------------------------------------------------------------------

2018年5月17日木曜日

~AspAccessCheck_26e88bde7472.tmp' へのアクセスが拒否されました。[ASP.net]

ASPプロジェクトをDebugではなくReleaseで実行すると、

が出てくる。

"間違えて[マイコードのみ]を無効にして続行"を押してしまったら、
Debugでもエラーで実行できなく・・・。


外がスローされました: 'System.UnauthorizedAccessException' (mscorlib.dll の中)

追加情報:パス 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\~AspAccessCheck_26e88bde7472.tmp' へのアクセスが拒否されました。


何のエラーかよく分からないけど、

Visual Studioの
[ツール]→[オプション]→[デバッグ]→[全般] の一覧の中に、
[マイ コードのみを有効にする]
があるのでこれをチェックしたら直った。

マイコードって何のこと・・・。