none
クリスタルレポートビューアの印刷ボタンでユーザー定義したサイズのレポートを出力したいです RRS feed

  • 質問

  • いつもお世話になっています。
    今回、私では問題が解決できないため、質問されて頂きました
    解決方法をご存じの方がいれば、お助け願います。

    開発言語:VB.Net FrameWork4.0 
    帳票ツール:クリスタルレポート
    OS:Windouws7

    クラサバのシステムです。

    プリンターの用紙サイズに存在しない用紙で帳票を作成するため
    プリンターに横180mm 縦114mmの用紙を追加しました。
    クリスタルレポートのページ設定にもユーザー定義サイズとして
    上記のサイズを設定し、製造を行っております

    上記のレポートをプリントダイアログを経由し印刷を行った場合は
    正しく印刷ができたのですが、クリスタルレポートビューアに表示
    した後、ビューアにある印刷ボタンをクリックし、ユーザー定義したプリンターの詳細を確認すると、
    用紙の向きは設定値が正しくセットされているのですが、
    用紙サイズがLetterになってしまい定義したサイズが正しく設定されていません。

    どなたか解決方法をご存じないでしょうか?

    ビューアを経由していないソース
    Dim rpt As New CrystalReport1()
    Dim pdlg As New PrintDialog
    pdlg.PrinterSettings = New PrinterSettings()
    pdlg.PrinterSettings.PrinterName = "ユーザー定義を追加したプリンター名"
    If pdlg.ShowDialog() = DialogResult.OK Then
        rpt.PrintOptions.PrinterName = pdlg.PrinterSettings.PrinterName
        rpt.PrintOptions.PaperOrientation = CrystalDecisions.Shared.PaperOrientation.Landscape
        rpt.PrintOptions.PaperSize = CrystalDecisions.Shared.PaperSize.DefaultPaperSize
        rpt.PrintToPrinter(pdlg.PrinterSettings.Copies, True, 0, 0)
    End If

    ビューアを経由するソース
    Dim rpt As New CrystalReport1()
    Dim frmPreview1 As New frmPreview’クリスタルレポートビューアがあるフォーム
    rpt.PrintOptions.PrinterName = "ユーザー定義を追加したプリンター名"
    rpt.PrintOptions.PaperOrientation = CrystalDecisions.Shared.PaperOrientation.Landscape
    rpt.PrintOptions.PaperSize = CrystalDecisions.Shared.PaperSize.DefaultPaperSize
    'プレビューを表示(crvがクリスタルレポートビューアです)
    frmPreview1.crv.ReportSource = rpt
    frmPreview1.crv.Zoom(2)
    frmPreview1.WindowState = FormWindowState.Maximized
    frmPreview1.ShowDialog()

    • 編集済み Ninichi 2013年1月29日 10:56
    2013年1月29日 10:38

回答

  • ビューアにある印刷ボタンを押下した時に実行されるイベントやメソッド
    を調査してオーバーライド出来れば、なんとかなりそうな気がします。

    ビュアーからカスタム用紙を印刷するのに、印刷ボタンの機能を入れ替えてやったことがあります。
    ビュアー内部のツールバーのボタンだったので、元の印刷ボタンを非表示にして別の印刷ボタンを挿入してやりました。

    また、カスタム用紙の選択はReportDocument.PrintOptions.PageContentHeight/Width , PageMarginsから用紙寸法を計算して、実行環境の用紙一覧から(だいたい)一致する用紙を設定してやる方法をとりました。

    昔のバージョンでやったので、最新のCrystalReportでできるかはわかりませんが。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク Ninichi 2013年1月31日 0:48
    2013年1月30日 3:55
  • 私がやったビュアーのカスタマイズ方法が掲載されているサイトは知りません。

    "defaultAnimation.gif"がありませんというエラーメッセージが
    表示され、フォームにカスタマイズしたビューアを配置すること
    すらできません。

    VS2008pro付属のだとエラーにならないのですが、Crystal Reports For .NetFramework 4.0だとエラーになりますね。
    調べてみたところ、初期化時にクラスが配置されているアセンブリ内のリソースからDefaultAnimation.gifを取り出しているようです。継承した場合、継承クラスが配置されているアセンブリ内のリソースを探してしまい、存在しないためにエラーになっています。
    ですから、継承したうえで回避するには、継承したクラスのアセンブリにDefaultAnimation.gifという画像ファイル(読み込み中にぐるぐる回っているgifアニメ)を「埋め込まれたリソース」として含めてやることで可能になります。
    (new Bitmap(GetType(継承クラス),"DefaultAnimation.gif")でリソースが取れる状態にする)

    継承しなくても以下のコードで印刷ボタンを乗っ取れることは確認しました。

    Imports CrystalDecisions.Shared
    Imports CrystalDecisions.CrystalReports.Engine
    Imports CrystalDecisions.Windows.Forms
    Public Class Form1
        Sub New()
            ' この呼び出しはデザイナーで必要です。
            InitializeComponent()
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            crvex = New CrystalReportViewerEx(Me.CrystalReportViewer1)
        End Sub
            Private crvex As CrystalReportViewerEx
    End Class
    Public Class CrystalReportViewerEx
        'Inherits CrystalReportViewer '元のCrystalReportViewerに継承できないバグがあるので
        'Public Sub New()
        '    MyBase.New()
        '    ReplacePrintButton(Me)
        '    '以下のコードがでリソースが取れない場合は継承したクラスは使い物になりません。
        '    Dim t As Type
        '    t = GetType(CrystalReportViewerEx)
        '    Dim manifestResourceStream As System.IO.Stream = t.Assembly.GetManifestResourceStream(t, "DefaultAnimation.gif")
        'End Sub
        Public Sub New(ByVal target As CrystalReportViewer)
            baseCrystalReportViewer = target
            ReplacePrintButton(target)
        End Sub
        Private baseCrystalReportViewer As CrystalReportViewer
        Private basePrintButton As ToolStripItem
        Private thisPrintButton As ToolStripButton
        Private Sub ReplacePrintButton(ByVal target As CrystalReportViewer)
            Dim baseToolstrip As ToolStrip
            baseToolstrip = FindControl(Of ToolStrip)(target)
            If (baseToolstrip IsNot Nothing) Then
                For Each item As ToolStripItem In baseToolstrip.Items
                    If (item.ToolTipText.Contains("印刷") OrElse item.ToolTipText.Contains("Print")) Then
                        basePrintButton = item
                        thisPrintButton = New ToolStripButton()
                        thisPrintButton.Text = item.Text
                        thisPrintButton.Image = item.Image
                        thisPrintButton.Size = item.Size
                        thisPrintButton.Padding = item.Padding
                        thisPrintButton.Margin = item.Margin
                        thisPrintButton.DisplayStyle = item.DisplayStyle
                        thisPrintButton.ImageScaling = item.ImageScaling
                        thisPrintButton.ForeColor = item.ForeColor
                        thisPrintButton.BackColor = item.BackColor
                        thisPrintButton.ToolTipText = item.ToolTipText
                        thisPrintButton.AccessibleName = item.AccessibleName
                        thisPrintButton.Tag = item.Tag
                        AddHandler thisPrintButton.Click, AddressOf thisPrintButton_Click
                        Dim index As Integer
                        index = baseToolstrip.Items.IndexOf(basePrintButton)
                        baseToolstrip.Items.Insert(index, thisPrintButton)
                        'baseToolstrip.Items.Remove(basePrintButton)
                        basePrintButton.Visible = False
                        Exit For
                    End If
                Next
            End If
        End Sub
        Private Sub thisPrintButton_Click(ByVal sender As Object, ByVal e As EventArgs)
            MessageBox.Show("印刷")
            'baseCrystalReportViewer.PrintReport()
        End Sub
        Private Function FindControl(Of T As Control)(ByVal ctl As Control) As T
            If (TypeOf ctl Is T) Then
                Return CType(ctl, T)
            End If
            Dim retval As T = Nothing
            For Each child As Control In ctl.Controls
                System.Diagnostics.Debug.Print(child.GetType().ToString())
                retval = FindControl(Of T)(child)
                If (retval IsNot Nothing) Then
                    Exit For
                End If
            Next
            Return retval
        End Function
    End Class


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク Ninichi 2013年1月31日 4:15
    2013年1月31日 3:47

すべての返信

  • プリントダイアログ経由だとWindowsがプリンターを理解しているので、正しく用紙が選べるのかもしれませんね。一方、CrystalReprotViewer経由ですと、CrystalReport内で判断しなければならず、判断するための情報が足りないのかもしれません。とりあえず、以下辺りが参考になるかもしれません。

    Crystal Reports でユーザー設定用紙の印刷を行う場合。
    http://garfie.weblogs.jp/life_of_dev/crystal-report-2008/

    Programming: Crystal report custom papersize printout
    http://www.infoct.net/programming-crystal-report-custom-papersize-printout-121/

    custom paper size cannot be used on other machine?
    http://go4answers.webhost4life.com/Example/custom-paper-size-other-machine-29071.aspx


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2013年1月30日 2:11
    モデレータ
  • trapemiyaさん
    返信ありがとうございます

    http://garfie.weblogs.jp/life_of_dev/crystal-report-2008/
    のサイトはここに書込む前に試したのですが、用紙サイズは
    Letterのままでした。
    また、以前に似たような質問があり、そこでも結論として
    用紙サイズの問題は解決されませんでした。

    もう少し、違う方法を模索してみます。

    ビューアにある印刷ボタンを押下した時に実行されるイベントやメソッド
    を調査してオーバーライド出来れば、なんとかなりそうな気がします。

    ありがとうございました


    • 編集済み Ninichi 2013年1月30日 2:51
    2013年1月30日 2:46
  • ビューアにある印刷ボタンを押下した時に実行されるイベントやメソッド
    を調査してオーバーライド出来れば、なんとかなりそうな気がします。

    ビュアーからカスタム用紙を印刷するのに、印刷ボタンの機能を入れ替えてやったことがあります。
    ビュアー内部のツールバーのボタンだったので、元の印刷ボタンを非表示にして別の印刷ボタンを挿入してやりました。

    また、カスタム用紙の選択はReportDocument.PrintOptions.PageContentHeight/Width , PageMarginsから用紙寸法を計算して、実行環境の用紙一覧から(だいたい)一致する用紙を設定してやる方法をとりました。

    昔のバージョンでやったので、最新のCrystalReportでできるかはわかりませんが。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク Ninichi 2013年1月31日 0:48
    2013年1月30日 3:55
  • gekkaさん
    返信ありがとうございます。

    ビューアのカスタマイズ方法が乗っているサイトをご存じなら
    教えていただけないでしょうか?

    私の方で、ビューアをカスタマイズしたまではよかったのですが、
    カスタマイズしたビューアをDLLとしてビルド、その後
    参照設定に追加を行い、フォームにビューアをドラッグした時点で
    "defaultAnimation.gif"がありませんというエラーメッセージが
    表示され、フォームにカスタマイズしたビューアを配置すること
    すらできません。

    宜しくお願いします。

    2013年1月30日 8:57
  • 私がやったビュアーのカスタマイズ方法が掲載されているサイトは知りません。

    "defaultAnimation.gif"がありませんというエラーメッセージが
    表示され、フォームにカスタマイズしたビューアを配置すること
    すらできません。

    VS2008pro付属のだとエラーにならないのですが、Crystal Reports For .NetFramework 4.0だとエラーになりますね。
    調べてみたところ、初期化時にクラスが配置されているアセンブリ内のリソースからDefaultAnimation.gifを取り出しているようです。継承した場合、継承クラスが配置されているアセンブリ内のリソースを探してしまい、存在しないためにエラーになっています。
    ですから、継承したうえで回避するには、継承したクラスのアセンブリにDefaultAnimation.gifという画像ファイル(読み込み中にぐるぐる回っているgifアニメ)を「埋め込まれたリソース」として含めてやることで可能になります。
    (new Bitmap(GetType(継承クラス),"DefaultAnimation.gif")でリソースが取れる状態にする)

    継承しなくても以下のコードで印刷ボタンを乗っ取れることは確認しました。

    Imports CrystalDecisions.Shared
    Imports CrystalDecisions.CrystalReports.Engine
    Imports CrystalDecisions.Windows.Forms
    Public Class Form1
        Sub New()
            ' この呼び出しはデザイナーで必要です。
            InitializeComponent()
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            crvex = New CrystalReportViewerEx(Me.CrystalReportViewer1)
        End Sub
            Private crvex As CrystalReportViewerEx
    End Class
    Public Class CrystalReportViewerEx
        'Inherits CrystalReportViewer '元のCrystalReportViewerに継承できないバグがあるので
        'Public Sub New()
        '    MyBase.New()
        '    ReplacePrintButton(Me)
        '    '以下のコードがでリソースが取れない場合は継承したクラスは使い物になりません。
        '    Dim t As Type
        '    t = GetType(CrystalReportViewerEx)
        '    Dim manifestResourceStream As System.IO.Stream = t.Assembly.GetManifestResourceStream(t, "DefaultAnimation.gif")
        'End Sub
        Public Sub New(ByVal target As CrystalReportViewer)
            baseCrystalReportViewer = target
            ReplacePrintButton(target)
        End Sub
        Private baseCrystalReportViewer As CrystalReportViewer
        Private basePrintButton As ToolStripItem
        Private thisPrintButton As ToolStripButton
        Private Sub ReplacePrintButton(ByVal target As CrystalReportViewer)
            Dim baseToolstrip As ToolStrip
            baseToolstrip = FindControl(Of ToolStrip)(target)
            If (baseToolstrip IsNot Nothing) Then
                For Each item As ToolStripItem In baseToolstrip.Items
                    If (item.ToolTipText.Contains("印刷") OrElse item.ToolTipText.Contains("Print")) Then
                        basePrintButton = item
                        thisPrintButton = New ToolStripButton()
                        thisPrintButton.Text = item.Text
                        thisPrintButton.Image = item.Image
                        thisPrintButton.Size = item.Size
                        thisPrintButton.Padding = item.Padding
                        thisPrintButton.Margin = item.Margin
                        thisPrintButton.DisplayStyle = item.DisplayStyle
                        thisPrintButton.ImageScaling = item.ImageScaling
                        thisPrintButton.ForeColor = item.ForeColor
                        thisPrintButton.BackColor = item.BackColor
                        thisPrintButton.ToolTipText = item.ToolTipText
                        thisPrintButton.AccessibleName = item.AccessibleName
                        thisPrintButton.Tag = item.Tag
                        AddHandler thisPrintButton.Click, AddressOf thisPrintButton_Click
                        Dim index As Integer
                        index = baseToolstrip.Items.IndexOf(basePrintButton)
                        baseToolstrip.Items.Insert(index, thisPrintButton)
                        'baseToolstrip.Items.Remove(basePrintButton)
                        basePrintButton.Visible = False
                        Exit For
                    End If
                Next
            End If
        End Sub
        Private Sub thisPrintButton_Click(ByVal sender As Object, ByVal e As EventArgs)
            MessageBox.Show("印刷")
            'baseCrystalReportViewer.PrintReport()
        End Sub
        Private Function FindControl(Of T As Control)(ByVal ctl As Control) As T
            If (TypeOf ctl Is T) Then
                Return CType(ctl, T)
            End If
            Dim retval As T = Nothing
            For Each child As Control In ctl.Controls
                System.Diagnostics.Debug.Print(child.GetType().ToString())
                retval = FindControl(Of T)(child)
                If (retval IsNot Nothing) Then
                    Exit For
                End If
            Next
            Return retval
        End Function
    End Class


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク Ninichi 2013年1月31日 4:15
    2013年1月31日 3:47
  • gekkaさん

    ソースまで記載して頂きありがとうございます。
    頂いたソースで製造を進めていきます。

    返信、ありがとうございました。

    2013年1月31日 4:15