none
Come scrivere una Query particolare RRS feed

  • Domanda

  • Ciao a tutti.

    Sto cercando di avere un report un poco particolare a partire da una struttura dati ben definita. Nella Figura sottoriportata è riassunto tutto il problema dove viene presentata la struttura dati, l'obiettivo che si vuole raggiungere la query utilizzata e il risultato che si ottiene.

    In particolare faccio rilevare che la Qry utilizzata e riportata nella figura non è l'unica che ho provato, ma il risultato massimo che riesco ad ottenere è sempre quello presentato.

    In pratica chiedo se a partire dalla struttura dati presentata è possibile raggiungere il risultato preposto e, se si, in che modo deve essere scritta la Where condition?, oppure se per ottenere il risultato voluto è necessario cambiare la struttura dati creando tante colonne quante sono quelle che si vogliono sommare?

    Ringrazio anticipatamente per il contributo che, sono certo, mi darete. Io ci stò provando da un paio di giorni ma non sono riuscito ad andare oltre a quanto presentato.

    grazie matylda

    martedì 28 agosto 2012 14:58

Risposte

  • Ciao Matylda,

    Per rendere le discussioni più fluide anche per gli altri membri che leggono il forum, è più facile seguire un topic per thread e, al momento che quel topic sia stato risolto, chiudere il thread corrente marcando la risposta che ha fornito la soluzione. In questo caso, possiamo considerare che hai trovato una soluzione per il query che stavi cercando? Se questo non è il caso, sarebbe gradevole almeno fare il follow-up sullo stesso thread invece di aprirne un altro.

    Grazie in anticipo per la tua comprensione,


    Irina Turcu - Microsoft

    Scusate per il ritardo con cui rispondo, ma prima volevo essere sicuro di aver provato, in modo completo, tutte le strade che vedevo per la soluzione del problema in essere, compreso quello contenuto nel thread "Generalizzazione di un sistema di reportistica."

    Per arrivare alla soluzione, credo generale, per la formalizzazione generale di un report, ho realizzato tre soluzioni avendo risultati equivalenti. L'ultima, che penso definitiva, è stata realizzata utilizzano i consigli/suggerimenti sia di Mario Formosa che di Carmelo La Monica.

    Riepilogando il problema consisteva nel generalizzare la forma visiva del risultato di una query, di volta in volta diversa anche in funzione della/e struttura/e dati che si andavano ad interrogare.

    L'esempio che volevo risolvere è relativo ad un oggetto molto semplice, uno scontrino di cassa con la seguente struttura dati:

    - Data registrazione

    - Nome Cliente

    - Importo

    - Modalità di pagamento  (bancomat, carta di credito, contanti)

    una semplice di quattro colonne.

    Interrogando il DB per un intervallo temporale il risultato avrebbe dovuto essere presentato in una griglia le cui colonne avrebbero dovuto essere le seguenti:

    - Nome Cliente

    - N° visite

    - Totale Incassato

    - Importo Bancomat

    - Importo Carta di Credito

    - Importo Contanti

    e alla fine della tabella i totali per ogni colonna.

    A seguire l'esempio della struttura dati:

    Il codice

    Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
            '
            '----- Dichiaro la Qry
            '
            Qry = "Select NomeCliente As Nome, Count(NomeCliente) As Frequenza, Sum(TotCassa) As Cassa, Carta As Pagam " ', Sum(TotCassa) As Bancomat, Sum(TotCassa) As Contanti, Sum(TotCassa) As Credito " '' ' As Totale "
            Qry = Qry & "From Vendita "
            Qry = Qry & "Where (Data Between @P0 And @P1) And (Carta = @P2 Or Carta = @P3 Or Carta = @P4 Or Carta = @P5) "
            Qry = Qry & "Group By Grouping Sets((NomeCliente), (NomeCliente, Carta)) "
            Qry = Qry & "Order By NomeCliente"
            '
            '----- Risolvo la Qry
            '
            Dim MyGrid As New DataGridView
            Me.Controls.Add(MyGrid)
            MyGrid.Visible = False
            RowSel = True
            Vincoli(0) = CDate(DateTimePicker1.Value)
            Vincoli(1) = CDate(DateTimePicker2.Value)
            Vincoli(2) = "BM"
            Vincoli(3) = "CC"
            Vincoli(4) = "CT"
            Vincoli(5) = "SI"
            MyGrid.DataSource = QrySolver(Qry, Vincoli, RowSel)
            MyGrid.Location = New Point(12, 244)
            'ResizeGrid(MyGrid, 1, 30, 10)
            MyGrid.Visible = True
            '
            '----- Definisco una nuova lista (List(Of T))
            '
            '----- Inizializzo i valori sella struttura
            Dim MyList As List(Of NuovaStruttura) = New List(Of NuovaStruttura)
            '----- Inizializzo i valori sella struttura
            Dim ValNM As String = Nothing
            Dim ValVS As String = Nothing
            Dim ValTT As String = Nothing
            Dim ValBM As String = Nothing
            Dim ValCC As String = Nothing
            Dim ValCT As String = Nothing
            '----- Inserisco i valori utilizzando il risultato della query
            For jj As Integer = 0 To MyGrid.Rows.Count - 1
                If IsDBNull(MyGrid(3, jj).Value) Then
                    ValNM = MyGrid(0, jj).Value
                    ValVS = MyGrid(1, jj).Value
                    ValTT = MyGrid(2, jj).Value
                    '----- Aggiungo la riga alla lista
                    MyList.Add(New NuovaStruttura With {.Nome = ValNM, .Visite = ValVS, .Totale = ValTT, _
                                                        .Bancomat = ValBM, .CartaC = ValCC, .Contanti = ValCT})
                    '----- Inizializzo i valoro successivi
                    ValNM = Nothing
                    ValVS = Nothing
                    ValTT = Nothing
                    ValBM = Nothing
                    ValCC = Nothing
                    ValCT = Nothing
                Else
                    If Not IsDBNull(MyGrid(3, jj).Value) Then
                        If MyGrid(3, jj).Value = "BM" Then ValBM = MyGrid(2, jj).Value
                        If MyGrid(3, jj).Value = "CC" Then ValCC = MyGrid(2, jj).Value
                        If MyGrid(3, jj).Value = "CT" Then ValCT = MyGrid(2, jj).Value
                    End If
                End If
            Next
            '
            '----- Al termine della costruzione della lista la inserisco nel DataGridView
            '
            MyGrid.DataSource = MyList
            '
            '----- Formatto le colonne del DataGridView secindo i tipi di campo
            '      e calcolo i totali per colonna
            '
            MyGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
            MyGrid.ScrollBars = ScrollBars.None
            ResizeGrid(MyGrid, 1, 30, 10)
            MyGrid.Columns(1).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
            Dim YPos As Integer = MyGrid.Location.Y + MyGrid.Height
            Dim XPos As Integer = MyGrid.Location.X + MyGrid.RowHeadersWidth
            For jj As Integer = 1 To MyGrid.ColumnCount - 1    'colonne
                If jj > 1 Then MyGrid.Columns(jj).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
                Dim SumCol = 0
                XPos = XPos + MyGrid.Columns(jj - 1).Width
                For kk As Integer = 0 To MyGrid.RowCount - 1    'righe
                    SumCol = SumCol + CDec(MyGrid(jj, kk).Value)
                Next
                Dim TxTBox As New TextBox
                TxTBox.Name = "Totale" & jj
                TxTBox.Location = New Point(XPos, YPos)
                Me.Controls.Add(TxTBox)
                TxTBox.Text = SumCol
                If jj > 1 Then TxTBox.Text = Format(CDec(TxTBox.Text), "#,###.00")
                TxTBox.Width = MyGrid.Columns(jj).Width
                If jj = 1 Then TxTBox.TextAlign = HorizontalAlignment.Center
                If jj > 1 Then TxTBox.TextAlign = HorizontalAlignment.Right
                TxTBox.Visible = True
            Next
            Dim Totale As New Label
            Totale.Text = "Totale Gen."
            Me.Controls.Add(Totale)
            Totale.Location = New Point(MyGrid.Location.X, YPos + 3)
            Totale.ForeColor = Color.Red
            Totale.Visible = True
            '
            '----- Fine
            '
        End Sub
    End Class
    Public Class NuovaStruttura
        Dim GetNome As String
        Dim GetVisite As String
        Dim GetTotale As String
        Dim GetBancomat As String
        Dim GetCartaC As String
        Dim GetContanti As String
        '-----------------------------------
        Public Property Nome() As String
            Get
                Return GetNome
            End Get
            Set(ByVal value As String)
                GetNome = value
            End Set
        End Property
        '-----------------------------------
        Public Property Visite() As String
            Get
                Return GetVisite
            End Get
            Set(ByVal value As String)
                GetVisite = value
            End Set
        End Property
        '-----------------------------------
        Public Property Totale() As String
            Get
                Return GetTotale
            End Get
            Set(ByVal value As String)
                GetTotale = value
            End Set
        End Property
        '-----------------------------------
        Public Property Bancomat() As String
            Get
                Return GetBancomat
            End Get
            Set(ByVal value As String)
                GetBancomat = value
            End Set
        End Property
        '-----------------------------------
        Public Property CartaC() As String
            Get
                Return GetCartaC
            End Get
            Set(ByVal value As String)
                GetCartaC = value
            End Set
        End Property
        '-----------------------------------
        Public Property Contanti() As String
            Get
                Return GetContanti
            End Get
            Set(ByVal value As String)
                GetContanti = value
            End Set
        End Property
    End Class

    Il risultato finale

    Il risultato è stato ottenuto grazie Carmelo La Monica e Mario Formosa che ancora ringrazio

    matylda

    Mi scuso per la confusione con la quale formulo le richieste, ma credete, non è cattiveria ma solo difficoltà.

    Grazie

    Per rispondere a Irina, ritengo che, alla luce di quanto sopra, siano da ritenersi chiusi i thread relativi, salvo suggerimenti da parte vostra. Grazie per il tuo contributo

    matylda

    • Modificato Matylda lunedì 10 settembre 2012 15:11
    • Contrassegnato come risposta Matylda martedì 11 settembre 2012 14:25
    lunedì 10 settembre 2012 15:06

Tutte le risposte

  • Ciao Matylda,

    ho letto il tuo post  ma non ho capito il tuo scopo , puoi gentilmente specificare l'obbiettivo ?

    Ciao.


    martedì 28 agosto 2012 17:31
  • Ciao Matylda,

    ho letto il tuo post  ma non ho capito il tuo scopo , puoi gentilmente specificare l'obbiettivo ?

    Ciao.

    Ciao Carmelo, ci sono due obiettivi. Prima però diciamo che i dati rappresentano dei valori relativi alle vendite ricavati dagli scontrini.

    Quello che si vuole ottenere è un primo report dal quale far partire un'analisi più approfondita sul cliente (abitudini, gusti, merce, fornitori preferiti....). Questo è l'obiettivo principale, altro obiettivo è quello di riuscire a fare con una query quello che riesco a fare con un foglio excel e con la funzione Somma.se. Capisco che cambiando la struttura della Tabella otterrei facilmente quello che voglio ma questo mi comporterebbe il lavoro di cambiamento dell'acquisizione dei dati, della loro memorizzazione e del recupero di quelli esistenti. Ma al di là di questo l'obiettivo reale è quello di capire, perchè a me sembra di aver scritto la query in modo corretto ma guardando il risultato mi devo ricredere e vorrei capire perchè. Questo secondo obiettivo diventa il principale perchè è capire dove è che sbaglio.

    grazie matylda

    mercoledì 29 agosto 2012 06:14
  • Ciao Matylda, non so se hai visto questo thread !

    Forse fa al caso tuo.

    Ciao.


    mario formosa

    mercoledì 29 agosto 2012 11:55
  • Ciao Matylda, non so se hai visto questo thread !

    Forse fa al caso tuo.

    Ciao.


    mario formosa

    Ciao Mario, felice di rileggerti. Ho guardato il thread da te indicato sono arrivato alla seguente conclusione:

    Per poter utilizzare uno schema sinile dovrei prima arrivare a una simile situazione, cosa peraltro facilmente ottenibile, e poi applicare lo schema indicato, oppure cambiare la struttura dati, anche questa cosa facilmente fattibile, recuperare i dati e modificare l'interfaccia. In pratica quello che volevo, e posso, ottenere sarebbe stato possibile se fisse stato possibile scrivere, come in Excel) nella Select una istruzione simile a questa; SumIf(TotCassa, Carta = P1) ma ciò non è possibile.

    Credo che adotterò la seconda soluzione, perchè per me molto più gestibile, ti ringrazio comunque della segnalazione, una informazione in più non fa mai male.

    Ulteriori suggerimenti sono ben accett.

    Ti ringrazio e colgo l'occasione per farti vedere come ho utilizzato le tue informazioni relative alle query con parametri, allegandoti copia della function appositamente da me sviluppata, nulla di eccezionale, ma per il mio problema (in generale) molto funzionale.

    Public Function QryConParam(Qry, Vincoli(), RowSel) As DataTable
            '
            'FUNCTION GENERALIZZATA PER L'INTERROGAZIONE DEL DataBase
            '
            '---Qry .............Stringa contenente la Query al DB
            '---Vincoli()........Condizioni, Vincoli o Parametri imposti. (Max 100)
            '---RowSel...........Boolean = Falso: nessuna riga selezionata
            '
            Dim DbConn As New SqlClient.SqlConnection("Data Source=MATY-16-02-2008\SQLEXPRESS;Initial Catalog=Maty01Db;Integrated Security=True")
            Dim QryConParamCMD As New SqlClient.SqlCommand
            Dim Tabella As New DataTable
            '---Definisci la parte Command
            QryConParamCMD.Connection = DbConn
            QryConParamCMD.CommandType = CommandType.Text
            QryConParamCMD.CommandText = Qry
            '---Inserisci i vincoli
            For jj As Integer = 0 To 100
                If Vincoli(jj) = Nothing Then Exit For
                QryConParamCMD.Parameters.Add(New SqlClient.SqlParameter("@P" & CStr(jj), Vincoli(jj)))
            Next
            '---Apri la connessione ed esegui la Query
            DbConn.Open()   ' Apri la connessione al Db
            Tabella.Load(QryConParamCMD.ExecuteReader)    ' Esegui la Qry
            '---Chiudi la connessione, controlla il risultato e esci
            DbConn.Close()
            If Tabella.Rows.Count <= 0 Then
                RowSel = False
                MsgBox("Attenzione!" & vbCrLf & vbCrLf & "Nessun record selezionato dal DB per le condizioni poste. !!", MsgBoxStyle.Critical)
            End If
            Return Tabella
        End Function

    Grazie di tutto, matylda

    mercoledì 29 agosto 2012 16:19
  • Ciao Matylda, ti ringrazio per la felicità che hai provato nel rileggermi e mi complimento per l'impegno che stai mettendo nello sviluppo. La tua funzione, sicuramente perfezionabile, ad esempio io passerei anche la tringa di connessione fra gli argomenti e non farei il test di tabella vuota all'interno della funzione, è molto utile in quanto permette un notevole risparmio di scrittura di codice evita la duplicazione di codice e può essere impiegata in applicazioni diverse. Complimenti.

    Tornando al problema da te posto e premettendo che io sono un piccolo studente di Ms SQL Server, vorrei consigliarti di evitare di modificare la struttura dei dati in quanto ritengo sia giusta. Ci sono delle persone che fanno dei movimenti contabili (diciamo così) e i movimenti possono essere di vario tipo. Tu vuoi ottenere per ogni persona il numero totale di movimenti  e il totale degli importi delle varie tipologie di movimenti.

    Per esempio MsSqlServer2008 permette di specificare nell'ambito di un unica query più set di raggruppamenti (Grouping Sets)  e ottenere un unico risultato(tabella). E' in un certo senso come se con una query ne facessi due risparmiando in più sull'impegno del server.

    Ad esempio questa query

    query

    restituisce il seguente risultato

    risultato

    Come puoi notare il risultato mi restituisce tutte le informazioni inerenti ai movimenti fatti dalle varie persone, se poi la mia applicazione le deve 'mostrare' in un modo diverso allora credo che sia un problema che deve essere risolto dal livello di presentazione dell'applicazione.

    Comunque questo è un mio modestissimo punto di vista, quello di uno studente.

    Ciao.


    mario formosa

    giovedì 30 agosto 2012 09:25
  • Ad integrazione dell'esempio precedente allego una funzione diciamo così, del livello di presentazione di un'ipotetica applicazione, che partendo dalla tabella restituita dalla query del post precedente, restituisce un'altra tabella che 'presenta' gli stessi dati in un formato diverso.

    Function Orizzontale() As DataTable
    
            Dim Nomi As New Generic.List(Of String)
            Dim TipiMov As New Generic.List(Of String)
            Dim NumMovDelNomePerIlTipo As New Generic.Dictionary(Of String, Integer)
            Dim ImportoMovDelNomePerIlTipo As New Generic.Dictionary(Of String, Decimal)
            Dim TotNumMovDelNome As New Generic.Dictionary(Of String, Integer)
            Dim TotImportoMovDelNome As New Generic.Dictionary(Of String, Decimal)
    
            Dim k As String = ""
            For Each xr As DataRow In t1.Rows
    
                If Not Nomi.Contains(xr.Item("nome")) Then
                    Nomi.Add(xr.Item("nome"))
                End If
    
                If Not IsDBNull(xr.Item("tipo")) Then
                    k = xr.Item("nome") + xr.Item("tipo")
                    NumMovDelNomePerIlTipo.Add(k, xr.Item("TotMovimenti"))
                    ImportoMovDelNomePerIlTipo.Add(k, xr.Item("totTipo"))
                    If Not TipiMov.Contains(xr.Item("tipo")) Then
                        TipiMov.Add(xr.Item("tipo"))
                    End If
                Else
                    TotNumMovDelNome.Add(xr.Item("nome"), xr.Item("TotMovimenti"))
                    TotImportoMovDelNome.Add(xr.Item("nome"), xr.Item("totTipo"))
    
                End If
    
            Next
    
            Nomi.Sort()
            TipiMov.Sort()
    
            Dim tipiColIndex As New Generic.Dictionary(Of String, Integer)
    
            Dim t2 As New DataTable
    
            t2.Columns.Add("Nome", GetType(String))
            Dim ni As Integer = 1
            For Each x As String In TipiMov
                t2.Columns.Add("Num. Mov. Tipo " + x, GetType(Integer))
                t2.Columns.Add("Importo Mov. Tipo " + x, GetType(Decimal))
                tipiColIndex.Add(x, ni)
                ni = ni + 2
            Next
            t2.Columns.Add("Tot Num. Mov", GetType(Integer))
            t2.Columns.Add("Tot Importi Mov", GetType(Decimal))
    
            For Each x As String In Nomi
                Dim xr As DataRow = t2.NewRow
                xr.Item("nome") = x
                xr.Item("Tot Num. Mov") = TotNumMovDelNome(x)
                xr.Item("Tot Importi Mov") = TotImportoMovDelNome(x)
    
                For Each y As String In TipiMov
                    k = x + y
                    If NumMovDelNomePerIlTipo.ContainsKey(k) Then
                        xr.Item(tipiColIndex(y)) = NumMovDelNomePerIlTipo(k)
                        xr.Item(tipiColIndex(y) + 1) = ImportoMovDelNomePerIlTipo(k)
                    End If
                Next
    
                t2.Rows.Add(xr)
    
            Next
    
            Return t2
    
        End Function

    la tabella restituita viene ad esempio passata alla proprietà DataSource di una DataGridView per ottenere questa visualizzazione

    dgv


    mario formosa

    giovedì 30 agosto 2012 12:17
  • Ad integrazione dell'esempio precedente allego una funzione diciamo così, del livello di presentazione di un'ipotetica applicazione, che partendo dalla tabella restituita dalla query del post precedente, restituisce un'altra tabella che 'presenta' gli stessi dati in un formato diverso.

    Function Orizzontale() As DataTable
    
            Dim Nomi As New Generic.List(Of String)
            Dim TipiMov As New Generic.List(Of String)
            Dim NumMovDelNomePerIlTipo As New Generic.Dictionary(Of String, Integer)
            Dim ImportoMovDelNomePerIlTipo As New Generic.Dictionary(Of String, Decimal)
            Dim TotNumMovDelNome As New Generic.Dictionary(Of String, Integer)
            Dim TotImportoMovDelNome As New Generic.Dictionary(Of String, Decimal)
    
            Dim k As String = ""
            For Each xr As DataRow In t1.Rows
    
                If Not Nomi.Contains(xr.Item("nome")) Then
                    Nomi.Add(xr.Item("nome"))
                End If
    
                If Not IsDBNull(xr.Item("tipo")) Then
                    k = xr.Item("nome") + xr.Item("tipo")
                    NumMovDelNomePerIlTipo.Add(k, xr.Item("TotMovimenti"))
                    ImportoMovDelNomePerIlTipo.Add(k, xr.Item("totTipo"))
                    If Not TipiMov.Contains(xr.Item("tipo")) Then
                        TipiMov.Add(xr.Item("tipo"))
                    End If
                Else
                    TotNumMovDelNome.Add(xr.Item("nome"), xr.Item("TotMovimenti"))
                    TotImportoMovDelNome.Add(xr.Item("nome"), xr.Item("totTipo"))
    
                End If
    
            Next
    
            Nomi.Sort()
            TipiMov.Sort()
    
            Dim tipiColIndex As New Generic.Dictionary(Of String, Integer)
    
            Dim t2 As New DataTable
    
            t2.Columns.Add("Nome", GetType(String))
            Dim ni As Integer = 1
            For Each x As String In TipiMov
                t2.Columns.Add("Num. Mov. Tipo " + x, GetType(Integer))
                t2.Columns.Add("Importo Mov. Tipo " + x, GetType(Decimal))
                tipiColIndex.Add(x, ni)
                ni = ni + 2
            Next
            t2.Columns.Add("Tot Num. Mov", GetType(Integer))
            t2.Columns.Add("Tot Importi Mov", GetType(Decimal))
    
            For Each x As String In Nomi
                Dim xr As DataRow = t2.NewRow
                xr.Item("nome") = x
                xr.Item("Tot Num. Mov") = TotNumMovDelNome(x)
                xr.Item("Tot Importi Mov") = TotImportoMovDelNome(x)
    
                For Each y As String In TipiMov
                    k = x + y
                    If NumMovDelNomePerIlTipo.ContainsKey(k) Then
                        xr.Item(tipiColIndex(y)) = NumMovDelNomePerIlTipo(k)
                        xr.Item(tipiColIndex(y) + 1) = ImportoMovDelNomePerIlTipo(k)
                    End If
                Next
    
                t2.Rows.Add(xr)
    
            Next
    
            Return t2
    
        End Function

    la tabella restituita viene ad esempio passata alla proprietà DataSource di una DataGridView per ottenere questa visualizzazione

    dgv


    mario formosa

    Ciao Mario, ho riflettuto sul quanto mi hai inviato e ho capito che la risposta alla mia domanda è molto semplice in quanto si tratta di fare solo una trasposizione dei dati che sono nel Db e che possono essere estratti per un intervallo temporale. Per poter generalizzare, non solo questo problema ma anche quello risolto con il contributo fondamentale di Carmelo La Monica con l'utilizzo delle Classi (Rif. Thread "Generalizzazione di un sistema di reportistica") avrei pensato ad una soluzione la quale ha un prerequisito che presenterò nel prossimo thread.

    Grazie

    venerdì 31 agosto 2012 17:20
  • Ciao Matylda,

    Per rendere le discussioni più fluide anche per gli altri membri che leggono il forum, è più facile seguire un topic per thread e, al momento che quel topic sia stato risolto, chiudere il thread corrente marcando la risposta che ha fornito la soluzione. In questo caso, possiamo considerare che hai trovato una soluzione per il query che stavi cercando? Se questo non è il caso, sarebbe gradevole almeno fare il follow-up sullo stesso thread invece di aprirne un altro.

    Grazie in anticipo per la tua comprensione,


    Irina Turcu - Microsoft

    [Manifesto] Regole e Aspetti generali all'uso dei forum MSDN

    Questo contenuto è distribuito “as is” e non implica alcuna responsabilità da parte di Microsoft. L'azienda offre questo servizio gratuitamente, allo scopo di aiutare gli utenti e approfondire la loro conoscenza dei prodotti e tecnologie Microsoft.

    LinkedIn

    lunedì 3 settembre 2012 15:13
  • Ciao Matylda,

    Per rendere le discussioni più fluide anche per gli altri membri che leggono il forum, è più facile seguire un topic per thread e, al momento che quel topic sia stato risolto, chiudere il thread corrente marcando la risposta che ha fornito la soluzione. In questo caso, possiamo considerare che hai trovato una soluzione per il query che stavi cercando? Se questo non è il caso, sarebbe gradevole almeno fare il follow-up sullo stesso thread invece di aprirne un altro.

    Grazie in anticipo per la tua comprensione,


    Irina Turcu - Microsoft

    Scusate per il ritardo con cui rispondo, ma prima volevo essere sicuro di aver provato, in modo completo, tutte le strade che vedevo per la soluzione del problema in essere, compreso quello contenuto nel thread "Generalizzazione di un sistema di reportistica."

    Per arrivare alla soluzione, credo generale, per la formalizzazione generale di un report, ho realizzato tre soluzioni avendo risultati equivalenti. L'ultima, che penso definitiva, è stata realizzata utilizzano i consigli/suggerimenti sia di Mario Formosa che di Carmelo La Monica.

    Riepilogando il problema consisteva nel generalizzare la forma visiva del risultato di una query, di volta in volta diversa anche in funzione della/e struttura/e dati che si andavano ad interrogare.

    L'esempio che volevo risolvere è relativo ad un oggetto molto semplice, uno scontrino di cassa con la seguente struttura dati:

    - Data registrazione

    - Nome Cliente

    - Importo

    - Modalità di pagamento  (bancomat, carta di credito, contanti)

    una semplice di quattro colonne.

    Interrogando il DB per un intervallo temporale il risultato avrebbe dovuto essere presentato in una griglia le cui colonne avrebbero dovuto essere le seguenti:

    - Nome Cliente

    - N° visite

    - Totale Incassato

    - Importo Bancomat

    - Importo Carta di Credito

    - Importo Contanti

    e alla fine della tabella i totali per ogni colonna.

    A seguire l'esempio della struttura dati:

    Il codice

    Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
            '
            '----- Dichiaro la Qry
            '
            Qry = "Select NomeCliente As Nome, Count(NomeCliente) As Frequenza, Sum(TotCassa) As Cassa, Carta As Pagam " ', Sum(TotCassa) As Bancomat, Sum(TotCassa) As Contanti, Sum(TotCassa) As Credito " '' ' As Totale "
            Qry = Qry & "From Vendita "
            Qry = Qry & "Where (Data Between @P0 And @P1) And (Carta = @P2 Or Carta = @P3 Or Carta = @P4 Or Carta = @P5) "
            Qry = Qry & "Group By Grouping Sets((NomeCliente), (NomeCliente, Carta)) "
            Qry = Qry & "Order By NomeCliente"
            '
            '----- Risolvo la Qry
            '
            Dim MyGrid As New DataGridView
            Me.Controls.Add(MyGrid)
            MyGrid.Visible = False
            RowSel = True
            Vincoli(0) = CDate(DateTimePicker1.Value)
            Vincoli(1) = CDate(DateTimePicker2.Value)
            Vincoli(2) = "BM"
            Vincoli(3) = "CC"
            Vincoli(4) = "CT"
            Vincoli(5) = "SI"
            MyGrid.DataSource = QrySolver(Qry, Vincoli, RowSel)
            MyGrid.Location = New Point(12, 244)
            'ResizeGrid(MyGrid, 1, 30, 10)
            MyGrid.Visible = True
            '
            '----- Definisco una nuova lista (List(Of T))
            '
            '----- Inizializzo i valori sella struttura
            Dim MyList As List(Of NuovaStruttura) = New List(Of NuovaStruttura)
            '----- Inizializzo i valori sella struttura
            Dim ValNM As String = Nothing
            Dim ValVS As String = Nothing
            Dim ValTT As String = Nothing
            Dim ValBM As String = Nothing
            Dim ValCC As String = Nothing
            Dim ValCT As String = Nothing
            '----- Inserisco i valori utilizzando il risultato della query
            For jj As Integer = 0 To MyGrid.Rows.Count - 1
                If IsDBNull(MyGrid(3, jj).Value) Then
                    ValNM = MyGrid(0, jj).Value
                    ValVS = MyGrid(1, jj).Value
                    ValTT = MyGrid(2, jj).Value
                    '----- Aggiungo la riga alla lista
                    MyList.Add(New NuovaStruttura With {.Nome = ValNM, .Visite = ValVS, .Totale = ValTT, _
                                                        .Bancomat = ValBM, .CartaC = ValCC, .Contanti = ValCT})
                    '----- Inizializzo i valoro successivi
                    ValNM = Nothing
                    ValVS = Nothing
                    ValTT = Nothing
                    ValBM = Nothing
                    ValCC = Nothing
                    ValCT = Nothing
                Else
                    If Not IsDBNull(MyGrid(3, jj).Value) Then
                        If MyGrid(3, jj).Value = "BM" Then ValBM = MyGrid(2, jj).Value
                        If MyGrid(3, jj).Value = "CC" Then ValCC = MyGrid(2, jj).Value
                        If MyGrid(3, jj).Value = "CT" Then ValCT = MyGrid(2, jj).Value
                    End If
                End If
            Next
            '
            '----- Al termine della costruzione della lista la inserisco nel DataGridView
            '
            MyGrid.DataSource = MyList
            '
            '----- Formatto le colonne del DataGridView secindo i tipi di campo
            '      e calcolo i totali per colonna
            '
            MyGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
            MyGrid.ScrollBars = ScrollBars.None
            ResizeGrid(MyGrid, 1, 30, 10)
            MyGrid.Columns(1).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
            Dim YPos As Integer = MyGrid.Location.Y + MyGrid.Height
            Dim XPos As Integer = MyGrid.Location.X + MyGrid.RowHeadersWidth
            For jj As Integer = 1 To MyGrid.ColumnCount - 1    'colonne
                If jj > 1 Then MyGrid.Columns(jj).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
                Dim SumCol = 0
                XPos = XPos + MyGrid.Columns(jj - 1).Width
                For kk As Integer = 0 To MyGrid.RowCount - 1    'righe
                    SumCol = SumCol + CDec(MyGrid(jj, kk).Value)
                Next
                Dim TxTBox As New TextBox
                TxTBox.Name = "Totale" & jj
                TxTBox.Location = New Point(XPos, YPos)
                Me.Controls.Add(TxTBox)
                TxTBox.Text = SumCol
                If jj > 1 Then TxTBox.Text = Format(CDec(TxTBox.Text), "#,###.00")
                TxTBox.Width = MyGrid.Columns(jj).Width
                If jj = 1 Then TxTBox.TextAlign = HorizontalAlignment.Center
                If jj > 1 Then TxTBox.TextAlign = HorizontalAlignment.Right
                TxTBox.Visible = True
            Next
            Dim Totale As New Label
            Totale.Text = "Totale Gen."
            Me.Controls.Add(Totale)
            Totale.Location = New Point(MyGrid.Location.X, YPos + 3)
            Totale.ForeColor = Color.Red
            Totale.Visible = True
            '
            '----- Fine
            '
        End Sub
    End Class
    Public Class NuovaStruttura
        Dim GetNome As String
        Dim GetVisite As String
        Dim GetTotale As String
        Dim GetBancomat As String
        Dim GetCartaC As String
        Dim GetContanti As String
        '-----------------------------------
        Public Property Nome() As String
            Get
                Return GetNome
            End Get
            Set(ByVal value As String)
                GetNome = value
            End Set
        End Property
        '-----------------------------------
        Public Property Visite() As String
            Get
                Return GetVisite
            End Get
            Set(ByVal value As String)
                GetVisite = value
            End Set
        End Property
        '-----------------------------------
        Public Property Totale() As String
            Get
                Return GetTotale
            End Get
            Set(ByVal value As String)
                GetTotale = value
            End Set
        End Property
        '-----------------------------------
        Public Property Bancomat() As String
            Get
                Return GetBancomat
            End Get
            Set(ByVal value As String)
                GetBancomat = value
            End Set
        End Property
        '-----------------------------------
        Public Property CartaC() As String
            Get
                Return GetCartaC
            End Get
            Set(ByVal value As String)
                GetCartaC = value
            End Set
        End Property
        '-----------------------------------
        Public Property Contanti() As String
            Get
                Return GetContanti
            End Get
            Set(ByVal value As String)
                GetContanti = value
            End Set
        End Property
    End Class

    Il risultato finale

    Il risultato è stato ottenuto grazie Carmelo La Monica e Mario Formosa che ancora ringrazio

    matylda

    Mi scuso per la confusione con la quale formulo le richieste, ma credete, non è cattiveria ma solo difficoltà.

    Grazie

    Per rispondere a Irina, ritengo che, alla luce di quanto sopra, siano da ritenersi chiusi i thread relativi, salvo suggerimenti da parte vostra. Grazie per il tuo contributo

    matylda

    • Modificato Matylda lunedì 10 settembre 2012 15:11
    • Contrassegnato come risposta Matylda martedì 11 settembre 2012 14:25
    lunedì 10 settembre 2012 15:06
  • Ciao Matylda,

    Il risultato è stato ottenuto grazie Carmelo La Monica e Mario Formosa che ancora ringrazio

    matylda

    Mi scuso per la confusione con la quale formulo le richieste, ma credete, non è cattiveria ma solo difficoltà.

    Grazie

    Per rispondere a Irina, ritengo che, alla luce di quanto sopra, siano da ritenersi chiusi i thread relativi, salvo suggerimenti da parte vostra. Grazie per il tuo contributo

    matylda

    di nulla , e stato un piacere essere stato di aiuto.

    Ciao, alla prossima.


    lunedì 10 settembre 2012 15:45
  • Grazie, Matylda, adesso è tutto molto più chiaro :)

    Buona giornata,


    Irina Turcu - Microsoft

    [Manifesto] Regole e Aspetti generali all'uso dei forum MSDN

    Questo contenuto è distribuito “as is” e non implica alcuna responsabilità da parte di Microsoft. L'azienda offre questo servizio gratuitamente, allo scopo di aiutare gli utenti e approfondire la loro conoscenza dei prodotti e tecnologie Microsoft.

    LinkedIn

    martedì 11 settembre 2012 14:45