Sezoni di stampa con GDI+

martedì 17 febbraio 2009 - 11.55

Teech Profilo | Expert

Ho la necessità di creare delle stampe con GDI+ in quanto vorrei stampare i dati di mie classi e non dati presenti su un DB (attraverso Dataset).
Ho tutto abbastanza chiaro sul funzionamento ma mi trovo a scontrarmi con la gestione delle sezioni di stampa che in GDI+ non sono presenti (o almeno non ho trovato).
Per gestire il la stampa ho deciso di crearmi un sorta di stream personalizzato ereditando dalla classe PrintDocument. Fondamentalmente, estendo la classe PrintDocument con una collection e itero sulla collection per avere i vari oggetti da stampare in ordine: nel metodo PrintPage gestisco un oggetto della collection alla volta.
Per questo motivo ho deciso di spostare tutta la gestione dei dati nel mio streming mentre nel metodo PrintPage gestisco solo il layout di stampa.
Il tutto funziona bene quando mi trovo a stampare dei semplici elenchi "non strutturati", ma non riesco a capire come fare per stampare eventuali "sezioni" (rubando la terminologia a Crystal Report).
Nella fattispecie ho una serie di Commesse che sono formate da una serie di Componenti ciascuna. Praticamente ho una classe Commessa ed una classe Componente. La classe componente contiene una proprietà di tipo Commessa. Ho anche 2 classi collection per Commesse e per Componenti con dei costruttori che permettono di effettuare delle "selezioni" (ad esempio nella collection Componenti ho un costruttore che come parametro accetta una Commessa).

Per stampare un elenco di componenti di una singola commessa uso il seguente "stream":
Imports System.ComponentModel Imports System.Drawing Public Class PrintCommessa Inherits Printing.PrintDocument Private _offSet As Integer Private _list As BindingList(Of Object) Private _pageNumber As Integer Private _hasMore As Boolean = False Public Sub New(ByVal Commessa As Commessa) _offSet = 0 _list = New BindingList(Of Object) Dim cp As New Componenti.Componenti(Commessa) For Each comp As Componenti.Componente In cp _list.Add(comp) Next If _list.Count > 0 Then _hasMore = True End Sub Protected Friend Function GetNextObject() As Object _offSet += 1 If _offSet = _list.Count Then _hasMore = False Return _list(_offSet - 1) End Function Protected Friend Property PageNumber() As Integer Get Return _pageNumber End Get Set(ByVal value As Integer) _pageNumber = value End Set End Property Protected Friend ReadOnly Property HasMore() As Boolean Get Return _hasMore End Get End Property End Class
Questo mi permette di stampare un elenco di Componenti per una singola commessa in quanto nel metodo PrintPage utilizzo il seguente ciclo:
Do Until doc.HasMore = False And AreaP.Y <= e.MarginBounds.Bottom Dim o As Object = doc.GetNextObject If TypeOf o Is Componente Then '... Stampa dati componente... End If Loop
Questo mi permette di avere nel mio stream anche oggetti diversi e riesco ad identificare attraverso l'Offset su quale oggetto sono: inserendo in modo appropriato gli oggetti sullo "stream" posso anche capire quando devo stampare una intestazione di sezione.

Ora finalmente le domande (che sono una serie):
- Se volessi stampare un piede di sezione con i totali come posso fare a capire esattamente dove sono, essendo lo stream un elenco non strutturato?
- Se non volessi usare una List(Of Object) nella classe "Stream" dite che è possibile? (restituirei comunque un oggetto Object al metodo PrintPage ma avrei un maggiore controllo lato "stream").
- Ho pensato anche di far diventare l'OffSet una struttura per memorizzare dati sul posizionamento dello stream, ma non capisco come...
Avete consigli in merito? Anche solo delle indicazioni (ho cercato molto sul Web ma non tovo nulla se non stampe semplici).

Grazie mille, ogni suggerimento è assolutamente ben accetto.
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole

Teech Profilo | Expert

Ho trovato il modo per recuperare i dati ed usare OffSet diversi per ogni sezione: nella classe "stream" uso il seguente codice (solo commesse e relativi componenti):
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
Quello che proprio non capisco è come indicare dinamicamente che voglio stampare un piede per la sezione. Il problema nasce dal fatto che il piede della sezione non è una classe, ma un calcolo... Avete un consiglio?
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5