Crystal 2008 - Modifca report via codice per immagini.

venerdì 05 giugno 2009 - 17.04

crystal Profilo | Newbie

Ciao a tutti, non sono nuovo alla programmazione, ma lo sono a questo forum e a Crystal Reports (2008 ed in genere) via codice.
Ho un problema che mi sta bloccando e cercherò di esporlo il più semplicemente possibile (chiedeno scusa in anticipo per la scarsa riuscita).

Ho una serie di RPT che non devo modificare via Crystal, ma via codice.
In particolare questi hanno (un po' sparsi) degli oggetti Testo con un contenuto prefissato da chi ha "disegnato" il report.

Il programma cui sto mettendo mano compie esattamente questo "ragionamento":
- Nel ReportDocumet corrente, scorri tutte le sezioni e per ogni sezione prendi in considerazione solo i ReportObject di tipo campo di testo.
- Se il campo di testo contiene una particolare contenuto (per esempio "LABEL1"):
. prendi le posizioni di left e di top del campo
. carica l'immagine di dato percorso in quella posizione (left e top)
Per far questo il vecchio programma che ho ereditato (scritto in VB6, usando la libreria CRAXD etc.), sviluppato in funzione di CR 8.5, faceva:

For Each sez In rpt.Sections
...
For Each obj In sez.ReportObjects
Set MyReportObj = obj
Select Case TypeName(obj)
Case "ITextObject"
key = UCase$(obj.Text)
Select Case key
Case "LABEL1"
...
sez.AddPictureObject littleImage, obj.Left, obj.Top
Case "LABEL2"
...
End Select
End Select
Set MyReportObj = Nothing
Next obj
Next sez

Il trucco era "appicicare" un oggetto OLE (in questo caso una immagine da file system, con path = littelImage) "sopra" il campo di testo (che fungeva da "segnaposto"), tramite il metodo AddPictureObject della sezione (sez.AddPictureObject littleImage, obj.Left, obj.Top).

Ora sto "riscrivendo" il tutto in VB.NET, con Visual Studio 2008 (e Crystal Report 2008).
Non uso la "vecchia" libreria CRAXD etc., ma le componenti .NET CrystalDecisions.etc.

Tutto bene fino alle sezioni: il processo è molto simile con il nuovo object model. Ma quando devo "appiccicare" l'immagine scopro che non posso più farlo. Gli OLE sembrano non essere supportati (non esiste un sez.AddPictureObject(...) ).

Allora ho provato a pensare di aggiungere una tabella specifica al mio gestionale (tutti i miei rpt fanno riferimento al medesimo db gestionale): questa tabella contiene una colonna di campi binary (di immagini) mappata opportunamente sul report. Così funzionerebbe, ma...ora l'operazione di aggiungere una campo relativo a quella colonna di quella tabella nei miei report esistenti la devo fare via codice.

Come posso modificare i report via codice?
Sto prendendo una strada sbagliata?

Grazie per avermi sopportato.


>>> SOLUZIONE <<<
15 Giugno 2008.
Mentre aspettavo qualche aiuto (mi rendo conto che il problema è un po' particolare) e mentre ho fatto altro, sono arrivato ad un "aggiramento" del problema per risolvere la questione.
Non so qualitativamente quanto sia buono, ma funziona. Spero di avere suggerimenti per migliorare il workaround...

Semplificando il ragionamento che il prgrm deve fare a run-time: per l'oggetto di testo contenente il testo "LABEL1", prendere le coordinate left e top; su queste coordinate inserire un'immagine di determinato path.

Punto uno. L'immagine di determinato path sarà contenuta in un campo blob (es. IMMAGINE) di una tabella (es. IMMAGINI), riferita ad un determinato campo chiave (es. CODICE). La sarà subito creata e dovrà essere vuota.

Punto due. Si crea un sub-report (es. SUBRPTLABEL1.rpt) con mappata la tabella IMMAGINI e si "mette" sul report stesso il campo BLOB.

Punto tre. Si scrive un programma VB6 (CRAXD etc.) che apre il report dato, scorre le sezioni; per ogni sezione si tiene via le coordinate dell'eventuale TextObject di contenuto LABEL1; se trovato tale TextObject si "importa" nelle coordinate perese il SUBRPTLABEL1.rpt (rpt.Sections.Item(i).ImportSubreport "<dir>\print\SUBRPTLABEL1.rpt ", left, top)).

Punto quattro. Si manipolano i bordi etc. del sub report e si "sopprime" il subreport appena importato.

Punto cinque. Si salva il "nuovo" report (m_Rpt.SaveAs m_RptName & ".new.rpt", cr80FileFormat)

A questo punto posso usare il nuovo report (CR 8.5) con il "vecchio programma VB6" senza che nulla cambi.

Poi passo ad un programma scritto in VB.NET (CrystalDecisions.etc.) dove carico a runtime l'rpt (nel componente Viewer). Prima di visualizzare l'rpt nel viewer carico al volo (tramite un dataset) l'immagine nella tabella IMMAGINI (assegnandole un determinato codice) e setto sul sub-report una RecordSelectionFormula opportuna (rr.RecordSelectionFormula = "{IMMAGINI_RPT.CODICE} = 'MIO_CODICE'). A questo punto sono pronto per la normale procedura di logon del report e di tutti i subreport; infine posso assegnare il report al viewer e visualizzarlo.

Un po' macchinoso, ma così ho risolto la "compatibilità" tra report CR 8.5 e CR 2008, disegnati un unica volta in CR 8.5, con i presupposti di inserimento di immagine in funzione di un segnaposto campo di testo (che erano i presupposti fondamentali che non potevo cambiare).

Spero di essere stato utile oltre che a me anche a qualcuno.

Si accettano suggerimenti, critiche, soluzionei alternative...

freeteo Profilo | Guru

Ciao crystal,
avevi visto per caso questo mio articolo (tral'altro un po' datato)? :
http://www.dotnethell.it/tips/Crystal-Reports-BLOB.aspx

io al tempo in cui usavo spesso i report, avevo risolto facendo un campo BLOB e caricando da codice l'immagine in bytes.
Questo in codice completamente managed quindi C# puro, senza usare la libreria COM "craxdrt" che pur funzionando bene, ti lega ancora a tecnologie vecchie...

Ciao.

Matteo Raumer
[MVP Visual C#]
http://blogs.dotnethell.it/freeteo

crystal Profilo | Newbie

Sì, avevo visto anche il tuo (buon) articolo.
Avevo già fatto sperimenti con DataSet, cambio di datasource e tabelle solo struttura per modificare il report. La cosa più bella è stata la creazione del DataSet (reso "persistente" in struttura e dati con due file, xsd e xml) contenente i Blob delle immagini. Tutto funzionava liscio in CR 2008. Peccato che io dovevo partire da RPT "sviluppati" con designer CR 8.5: i Dataset XML non li potevo "mappare". E poi c'erano tutte quelle pre-condizioni...purtroppo le mie condizioni iniziali (che erano così senza possibilità di cambiarle - soprattutto il fatto di non provocare una rottura fra i report 8.5 e gli stessi CR2008 - noi abbiamo 934 report standard così) mi hanno obbligato a scervellarmi su come mettere insieme tanti ottimi suggerimenti e fantasia. Tutto per "colpa" del mancato supporto in CR .NET si AddPictureObject dell'oggetto Section. Naturalmente "colpa" è di nessuno: è il nostro mestiere, siamo informatici e le cose si evolvono, anche quando le si trascurano.

Tengo il Thread aperto, perché mi sa, che fra poco avrò altre sorpese a riguardo...

freeteo Profilo | Guru

Ok, tieni presente che non serve che i tuoi report abbiano il supporto ai dataset, l'importante è che la struttura dei dati che si aspetta sia la stessa che gli passi tu.
Infatti io che non uso mai i dataset e preferisco Domain-Model e quindi Collection<Entita> varie, mi capita per comodità di farmi i report agganciati ad un mdb (quindi access) con la stessa struttura degli oggetti, quindi stesso tipo/numero/posizione dei campi e poi passargli da codice le collection:
IEnumerable<Cliente> clienti = ClienteManager.GetAll(...); ReportDocument report = new ReportDocument(); report.Load(@"...report.rpt", OpenReportMethod.OpenReportByTempCopy); report.SetDataSource(clienti);

per cui penso sia la stessa cosa se da codice gli passi un datatable (che corrisponde ad una tabella) e non un dataset (se hai il dataset, prendi le varie tabelle dello stesso che corrispondono a quelle del report) e passagli poi quelli con un codice .net.
Tutto resta invariato a livello di file ".rpt" tanto quello viene solo letto dal disco, e visualizzato sul Viewer.

Non ho provato a fare la stessa cosa con report in versione 8.5,ma penso che sia la stessa cosa, tanto appena il runtime lo carica lo rende disponibile nella versione della libreria (di solito crystal è sempre retro-compatibile).

Ciao.

Matteo Raumer
[MVP Visual C#]
http://blogs.dotnethell.it/freeteo
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-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5