BENVENUTI  ::  CINEMA E TV  ::  INFORMATICA  ::  LETTERATURA  ::  MUSICA  ::  >  ::  PROFILO

Opinabile

è tutto ciò che scrivo, vedi tu se credermi o rendermi infelice...

mercoledì 4 novembre 2009

La Poetica Delle Immagini Di Kubrick


Questo fu un video realizzato appositamente per una rassegna sui film di Kubrick. Correva l'anno 2008, eravamo in tre: io, PJ e DM... bei ricordi, bella esperienza... a presto posts di resoconto!

Crystal Report 2008: aggiunta a runtime di campi per l'ordinamento.

Abstract
Questo mostra come sopperire ad una mancanza delle API di Crystal Reports 2008, ovvero come fare quando si vuole "comodamente" aggiungere dinamicamente dei campi di ordinamento in un report rpt.

Requisiti
Si assume che si abbiano minime basi di Crystal Reports e .NET.
Il codice riportato negli esempi è in VB.NET.
Il codice dei link di riferimento è in C#.

Esigenza
L'esigenza mi è nata quando ho dovuto fare una migrazione da un programma VB6, scritto per l'engine di Crystal Reports 8.5, ad una versione in VB.NET, per Crystal Reports 2008.

Problema
Sono profondamente cambiate molte cose nell'object model di Crystal Reports 2008 rispetto a quello di versione 8.5, ma non ne parlerò in questa sede: è un discorso troppo vasto; inoltre siti più mirati di questo possono essere più utili (tra gli italiani consiglio un giro su .net hell.it ). Qui mi basterà soltanto accennare al fatto che il modello di Crystal Reports 2008 oltre ad avere un comportamento diverso dal precedente 8.5 (i wrapper in .Net sui "vecchi" oggetti COM "ragionano" in modo differente dall'approcio 8.5) ha anche strane limitazioni: può darsi che sia la nuova filosofia del modello .NET nella reportistica; resta il fatto, comunque, che queste stranezze provochino impedimenti non banali nelle fasi di porting da un progetto per report Crystal pre-.NET ad uno per report Crystal e .NET.

Uno frai tanti casi può essere la non più supportata possibilità di aggiungere campi di ordinamento via programma (a runtime).

Con un minimo di ricerche e scopro che:
  • Prima del supporto .NET il report manipolato dal programma poteva avere o meno i campi d'ordinamento. Con una banale istruzione delle API di Crystal Reports 8.5 ActiveX runtime si scrive (VB6):

    report.RecordSortFields.Add(nome_campo, flag)

    cioè: tramite l'istanza report (l'oggetto "wrapper" del mio rpt) recupero l'insieme dei campi di ordinamento (quelli per l'order by, per intendersi) e aggiungo ad essi la colonna che voglio (naturalmente deve esistere nelle tabelle dell'rpt, pena errore runtime), indicando il tipo di ordinamento (ASC o DESC). Per esempio:

    report.RecordSortFields.Add("clienti.ragione_sociale", crAscendingOrder)

  • Con la libreria per .NET e Crytal Reports 2008 (CrystalDecision.CrystalReports...) non posso fare la stessa cosa.

    Dal Namespace CrystalDecisions.CrystalReports.Engine si ha la classe ReportDocumet, l'oggetto "wrapper" per l'rpt. L'object model prevede che ReportDocumet abbia in sè la definizione dati del report accessibile tramite l'oggetto DataDefinition. Un passo ancora ed è fatta: dalla definizione dei dati è possibile recuperare i campi di ordinamento tramite la collezione di SortField, SortFields appunto. Esempio di accesso alla collezione SortFields:

    reportdoc.DataDefinition.SortFields

    I SortField sono i campi di ordinamento che il progettista rpt ha introdotto nel report via designer: se il questi non ne ha messi, la collezione SortFields che ci ritroveremo a runtime sarà vuota. Quindi, un ciclo di for come il seguente, per esempio, non eseguirebbe nemmeno una istruzione all'interno del suo blocco:

    For Each sf As SortField In reportdoc.DataDefinition.SortFields
        ' istruzioni
    Next

    Questo perché la collezione SortFields è in sola lettura.
    Perché? Non lo so, mi mancano elementi per rispondere a questo quesito.
    Su Internet ho trovato questa nota che forse può aiutare se non altro ad accettare tale realtà.

    Come ovviare senza perdersi nei meandri di fix, articoli e varie? Con la Reflection.
Soluzione
La via più "breve" è quella di fare ciò che il vecchio metodo Add faceva: se il designer 2008 lo fa (di aggiungere i campi di order by) lo posso fare anch'io; ma serve la Reflection (quel meccanismo che permette di recuperare metodi, attributi etc. da un'istanza, a prescindere dalla visibilità, etc.).

Questo articolo (dal sito DECOMPILER-VB .net) mi è stato di fondamentale aiuto. E' scritto da uno che sa "smanettare" ben bene.  Nella spiegazione (in inglese) viene descritto e riportato a passo a passo il codice C#. Manca un passaggio (solo descritto, ma senza relativo codice): l'aggiunta del nostro campo; ma in sostanza è completo.

Quindi ho riscritto del codice VB.NET per crearmi il metodo che mi serviva.
Nel mio progetto ho implementato in un modulo la seguente funzione:

Public Function AddSortFiled(ByRef reportdoc As ReportDocument, ByRef fd As FieldDefinition) As Boolean
    Dim result As Boolean
    Dim sfs As SortFields
    Dim rassort As Object
    Dim rassorts As Object
    Dim rasfield As Object
    Dim getrassorts As MethodInfo
    Dim addsort As MethodInfo
    Dim setsortfield As MethodInfo
    Dim getrasfield As MethodInfo
    Dim cirassort As ConstructorInfo
    Dim rasassembly As Assembly
    result = False
    If Not reportdoc Is Nothing OrElse Not fd Is Nothing Then
        sfs = reportdoc.DataDefinition.SortFields
        getrassorts = sfs.GetType().GetMethod("get_RasSorts", BindingFlags.NonPublic Or BindingFlags.Instance)
        rassorts = getrassorts.Invoke(sfs, System.Type.EmptyTypes)
        addsort = rassorts.GetType().GetMethod("Add")
        rasassembly = getrassorts.ReturnType.Assembly
        cirassort = rasassembly.GetType("CrystalDecisions.ReportAppServer.DataDefModel.SortClass").GetConstructor(BindingFlags.Public Or BindingFlags.Instance, Nothing, System.Type.EmptyTypes, Nothing)
        rassort = cirassort.Invoke(System.Type.EmptyTypes)
        setsortfield = rassort.GetType().GetMethod("set_SortField", BindingFlags.Public Or BindingFlags.Instance)
        getrasfield = fd.GetType().GetMethod("get_RasField", BindingFlags.NonPublic Or BindingFlags.Instance)
        rasfield = getrasfield.Invoke(fd, System.Type.EmptyTypes)              
        setsortfield.Invoke(rassort, New Object() {rasfield})
        addsort.Invoke(rassorts, New Object() {rassort})
        result = True
    End If
    Return result
End Function

In pratica nei parametri passo il campo del report (presente nel report!) che voglio indicare come campo di ordinamento e lo aggiungo alla lista dei campi di ordinamento (SortFields) "wrappandolo" in un un'istanza di SortField (sarà questa ad essere effettivamente aggiunta alla collezione).

Conclusione
Missione compiuta. Ora nel mio programma posso scrivere qualche cosa come:

...
Dim lastindex As Integer
Dim t As String
Dim c As String
Dim f As DatabaseFieldDefinition
Dim sf As SortField
...
' Campo da inserire nell'ordinamento
t = "tabella"
c = "campo"
' Recupero campo dalla tabella
f = reportdoc.Database.Tables.Item(t).Fields.Item(c)
' Tentativo di inserimento nella lista dei campi di ordinamento
If AddSortFiled(reportdoc, f) Then
    ' istruzioni per il setting del nuovo campo:
    ' ora lo posso fare perché è presente in SortFields
    ' (è l'ultimo inserito)
    lastindex = reportdoc.DataDefinition.SortFields.Count - 1
    sf = reportdoc.DataDefinition.SortFields.Item(lastindex)
    ' Per esmpio in ASC
    sf.SortDirection = CrystalDecisions.Shared.SortDirection.AscendingOrder
    sf.Field = f
Else
    ' istruzioni insuccesso
End If
...
For Each sf In reportdoc.DataDefinition.SortFields
    ' istruzioni
Next
...

LR.

La voce della Moffetta Dio-Ragno


Attualmente di loro alla radio passano "Because Of You".
Ritorno annunciato con una raccolta dei loro successi e qualche inedito... ma non voglio parlare di questo: il Web è pieno di articoli, link e varie sul il ritorno degli Skunk Anansie. Links a riguardo? Google, oppure You Tube, con chiave di ricerca Skunk Anansie ... e buona divertimento!

Tuttavia qualche parola (sicuramente di troppo) su Because Of You la voglio sprecare: un po' di Muse e un ripescaggio (anche autoreferenziale) da quella giungla metal sviluppatasi nei '90 (chiamiamola genericamente alternative metal per far prima) per confezionare un prodotto commerciale di sicuro impatto. Mettiamoci anche una vena "dark" (intesa proprio come "colore", non come genere musicale) e l'aggressività di Skin con il supporto energico degli altri "CAM" ed ecco di nuovo in auge gli Skunk Anansie.

Si dica quello che si vuole, ma per me Because Of You è proprio bella. Tuttavia la mia "bella" non è d'accordo... abbiamo grosse divergenze nei nostri gusti musicali.

Skin mi sorprende sempre. Ha una voce straordinaria: sa gridare; sa graffiare; sa "saltellare"; sa accarezzare. Sa cantare. Non apprezzo fino in fondo le sue produzioni (sia come solista sia come Skunk Anansie), tuttavia la cito sempre nella mia classifica delle voci femminili contemporanee. Lei insieme ad Elisa e Alicia Keys.

Puzzola (o varietà di cannabis?) Dio-ragno ed una pantera, ovvero Skunk Anansie con l'inquietante Skin: Because Of You sempre al massimo volume sulla mia autoradio! Avvertiti gli eventuali passeggeri!

LR.

<track>Because Of You</track>

lunedì 2 novembre 2009

Addio Alda (semi-spleen nel giorno dei morti...)

Piove. Leggera e fredda è questa pioggia. La radio mi rallegra un po' questa mattina. Non è un brutto giorno, o meglio: fa freddo e piove! Ma, in fondo, è pur sempre autunno; è pur sempre il due di novembre e non si può pretendere altro. Quindi il cielo grigio e questa voglia di letto e coperte ci stanno.

Il fine settimana - oggi è lunedì - è stato tranquillo. Ieri era persino una splendida giornata. "Week-end piovoso", urlavano le previsioni, eppure... domenica pomeriggio, passeggiando per il centro, ho addirittura tolto il giubbotto! D'accordo, sono stato un po' azzardato,  ma riporto questo fatto per dire che il sole, seppur ormai con poco spazio nella giornata, batteva ancora e si faceva onore. Oggi, invece, sembra autunno. Già, è vero: lo è.

Il lunotto anteriore dell'auto ora è completamente bagnato. Lo speaker, intanto, annuncia l'evento del giorno che riflette un fatto di ieri: Alda Merini è morta. Aumento la velocità dei tergicristalli. Adesso vedo bene, ma avrei tanto voluto non sentire.
Ancora. Il conduttore manda in onda una poesia di Alda recitata da lei stessa, forse un pezzo di repertorio di una sua rappresentazione pubblica: è una poesia d'amore di una donna per un uomo; di quella donna sola, stravagante, che ha saputo tanto amare la luce della vita.

Ho sempre rubato versi alla Merini: in libreria, mentre cercavo altri libri e ne prendevo uno suo in mano, per leggerne una o al massimo due sue poesie; da qualche fotocopia; ascoltando qualche fonte audio. Tuttavia sempre poco, molto poco alla volta, perché la lettura o l'ascolto di ogni sua composizione è la scoperta di un'anima intera... e ti riempie...

La trasmissione continua con qualche aneddoto sulla poetessa, poi via con una canzone. Spengo in tempo la radio. Fra poco comincerò a lavorare e questo spleen d'autunno scemerà tra i tic tac delle tastiere, il caffè con i colleghi e la solita routine.

Accendendo una luce penserò ad un'anima profonda.

LR.

P.S.
Sito di Alda Merini...

sabato 31 ottobre 2009

Primo...

Primo messaggio in assoluto per questo blog!
Che cos'è Blog Ludico O Generico? Rispondo subito: non lo so.
Lo definirei un contenitore di appunti, idee od altro che nascono (e muoiono!) direttamente dalla mie esperienze e che, per qualche a me ignoto motivo (vanità, voglia di condividere o, semplicemente, "metto lì che poi ci penso"), rendo a disposizione (od al massacro!) in un luogo pubblico.
Ci saranno (presto) quindi post di ogni tipo: tempo libero, tecnici, sfoghi, od altro. Mia cura sarà etichettarli in maniera decente in modo da rendere possibile un minimo di navigazione in quello che sarà - presumo - un "Oceano Solaris" di caratteri...

Basta, ho tediato troppo chi legge (forse io il solo)!

Buon Blog Ludico O Generico a tutti!

LR.



ポストの決勝戦!


 

Lettori fissi...
se non funziona fai refresh (baco di Blogger!) altrimenti "segui" in alto a sx!

Seguo anche...

Piccolo spot per un amico...