س:
كيف يمكن طباعة تقرير مباشرة بدون عرضه أولا في الأداة ReportViewer؟
ج:
يمكن فعل هذا بكتابة فئة خاصة تقوم بهذا الأمر.. وقد بحثت على الإنترنت ووجدت
بالفعل هذه الفئة مكتوبة واسمها AutoPrintCls، لكن كان بها عيب أنها لا تطبع الورقة العرضية Landscape بشكل صحيح، فقمت ببعض التصحيحات فيها،
وهي تعمل الآن بشكل صحيح.. كما أنني وضعت هذه الفئة داخل فئة أخرى اسمها ReportPrinter لإخفاء تفاصيلها،
بحيث يمكن تنفيذ أمر الطباعة مباشرة بسطر واحد باستدعاء الوسيلة المشتركة ReportPrinter.Print.
ملحوظة:
لكي يعمل هذا الكود يجب أن تضيف إلى المشروع مرجعا Reference إلى النطاقين التاليين:
Microsoft.ReportViewer.Common
Microsoft.ReportViewer.WinForms
لفعل هذا اضغط القائمة الرئيسية Project ومنها اضغط الأمر Add References.. وفي النافذة التي ستظهر، اختر من القائمة اليسرى
العنصر Extensions.. لاحظ أنك ستجد
إصدارين من الملف Microsoft.ReportViewer.WinForms. اختر الإصدار
الأحدث (رقم 11) كما تظهر تفاصيله في الجزء الأيمن من النافذة عند اختيار العنصر.
Imports Microsoft.VisualBasic
Imports System
Imports System.IO
Imports System.Text
Imports System.Globalization
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Drawing.Printing
Imports Microsoft.Reporting.WinForms
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.Diagnostics
Imports System.ComponentModel
Imports System.Data
Imports System.Linq
Imports System.Threading.Tasks
Imports System.Windows.Forms
Public Class ReportPrinter
Public Shared Sub Print(Report As LocalReport)
Dim AuroPrint As New AutoPrintCls(Report)
AuroPrint.Print()
End Sub
Public Shared Sub Print(Report As ServerReport)
Dim AuroPrint As New AutoPrintCls(Report)
AuroPrint.Print()
End Sub
Private Class AutoPrintCls
Inherits PrintDocument
Private m_pageSettings As PageSettings
Private m_currentPage As Integer
Private m_pages As New List(Of Stream)()
Friend Sub New(ByVal serverReport As ServerReport)
Me.New(CType(serverReport, Report))
RenderAllServerReportPages(serverReport)
End Sub
Friend Sub New(ByVal localReport As LocalReport)
Me.New(CType(localReport, Report))
RenderAllLocalReportPages(localReport)
End Sub
Private Sub New(ByVal report As Report)
Dim reportPageSettings As ReportPageSettings = report.GetDefaultPageSettings()
m_pageSettings = New PageSettings()
m_pageSettings.PaperSize = reportPageSettings.PaperSize
m_pageSettings.Margins =
reportPageSettings.Margins
m_pageSettings.Landscape =
reportPageSettings.IsLandscape
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
MyBase.Dispose(disposing)
If disposing Then
For Each s As Stream In m_pages
s.Dispose()
Next s
m_pages.Clear()
End If
End Sub
Protected Overrides Sub OnBeginPrint(ByVal e As PrintEventArgs)
MyBase.OnBeginPrint(e)
m_currentPage = 0
End Sub
Protected Overrides Sub OnPrintPage(ByVal e As PrintPageEventArgs)
MyBase.OnPrintPage(e)
Dim pageToPrint As Stream = m_pages(m_currentPage)
pageToPrint.Position = 0
' Load each
page into a Metafile to draw it.
Using pageMetaFile As New Metafile(pageToPrint)
Dim adjustedRect As New Rectangle(e.PageBounds.Left - CInt(Fix(e.PageSettings.HardMarginX)), e.PageBounds.Top - CInt(Fix(e.PageSettings.HardMarginY)),
e.PageBounds.Width, e.PageBounds.Height)
' Draw a
white background for the report
e.Graphics.FillRectangle(Brushes.White, adjustedRect)
' Draw the
report content
e.Graphics.DrawImage(pageMetaFile, adjustedRect)
' Prepare
for next page. Make sure we haven't hit
the end.
m_currentPage += 1
e.HasMorePages = m_currentPage <
m_pages.Count
End Using
End Sub
Protected Overrides Sub OnQueryPageSettings(ByVal e As QueryPageSettingsEventArgs)
e.PageSettings = CType(m_pageSettings.Clone(), PageSettings)
End Sub
Private Sub RenderAllServerReportPages(ByVal serverReport As ServerReport)
Try
Dim deviceInfo As String = CreateEMFDeviceInfo(0, 0)
'
Generating Image renderer pages one at a time can be expensive. In order
' to
generate page 2, the server would need to recalculate page 1 and throw it
'
away. Using PersistStreams causes the
server to generate all the pages in
' the
background but return as soon as page 1 is complete.
Dim firstPageParameters As New NameValueCollection()
firstPageParameters.Add("rs:PersistStreams", "True")
'
GetNextStream returns the next page in the sequence from the background process
' started
by PersistStreams.
Dim nonFirstPageParameters As New NameValueCollection()
nonFirstPageParameters.Add("rs:GetNextStream", "True")
Dim mimeType As String
Dim fileExtension As String
Dim pageStream As Stream = serverReport.Render("IMAGE", deviceInfo, firstPageParameters, mimeType,
fileExtension)
' The
server returns an empty stream when moving beyond the last page.
Do While pageStream.Length > 0
m_pages.Add(pageStream)
pageStream =
serverReport.Render("IMAGE", deviceInfo, nonFirstPageParameters, mimeType,
fileExtension)
Catch e As Exception
MessageBox.Show("possible missing
information :: " & e.Message)
End Try
End Sub
Private Sub RenderAllLocalReportPages(ByVal localReport As LocalReport)
Try
Dim deviceInfo As String = CreateEMFDeviceInfo(0, 0)
Dim warnings() As Warning
localReport.Render("IMAGE",
deviceInfo, AddressOf LocalReportCreateStreamCallback, warnings)
Catch e As Exception
MessageBox.Show("error :: " & e.Message)
End Try
End Sub
Private Function LocalReportCreateStreamCallback(ByVal name As String, ByVal extension As String, ByVal encoding As Encoding, ByVal mimeType As String, ByVal willSeek As Boolean) As Stream
Dim stream As New MemoryStream()
m_pages.Add(stream)
Return stream
End Function
Private Function CreateEMFDeviceInfo(startPage As Integer, endPage As Integer) As String
Dim hundrethsOfInch As Integer = If(m_pageSettings.Landscape,
m_pageSettings.PaperSize.Height, m_pageSettings.PaperSize.Width)
Dim hundrethsOfInch2 As Integer = If(m_pageSettings.Landscape, m_pageSettings.PaperSize.Width,
m_pageSettings.PaperSize.Height)
Dim _text As String = String.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3} {4} {5} ", New Object() {ToInches(m_pageSettings.Margins.Top),
ToInches(m_pageSettings.Margins.Left), ToInches(m_pageSettings.Margins.Right),
ToInches(m_pageSettings.Margins.Bottom), ToInches(hundrethsOfInch2),
ToInches(hundrethsOfInch)})
Return String.Format(CultureInfo.InvariantCulture, "emf {0} {1} {2} ", New Object() {startPage, endPage, _text})
End Function
Private Shared Function ToInches(ByVal hundrethsOfInch As Integer) As String
Dim inches As Double = hundrethsOfInch / 100.0
Return inches.ToString(CultureInfo.InvariantCulture) & "in"
End Function
End Class
End Class
وسأشرح
لكم كيفية استخدام هذه الفئة في الموضوع التالي.
جزاك الله كل خير أستاذ حمدي على هذه المعلومات , لدي سؤال اذا تكرمت , كيف يمكنني ان اركب سلسلة نصية من عدة حروف بحيث يكون كل حرف منها بلون مختلف عن الأخر عند عرض النص في textbox, وكيف يمكن تغير لون حرف معين في سلسلة نصية دون الحروف الأخرى
ردحذفالكود يعمل عند تشغيل المشروع في بيئة الفيجوال ولكن عند تشغيل البرنامج خارج بيئة الفيجوال لا يعمل وتظهر رسالتين الأولى "error : An error occurred during local report processing" والرسالة الثانية "الفهرس خارج النظاق. يجب ألا يكون قيمته سالبة ويجب ألا يكون أقل من حجم المجموعة اسم المعلمة: index" علماً بأن الفيجوال يعطيني ثلاث رسائل تحذيرية بسبب الممغيرات الفارغة وهي mimeType , fileExtension , warnings
ردحذفأخي جزيت خيراً على الموضوع ولكن لم أجد الإصدار 11 من Microsoft.ReportViewer.WinForms علماً بأن الدوت نت فريم وورك عندي هو .NET Framework 4 أرجو المساعدة
حذف