miércoles, 4 de septiembre de 2013

Exportar a Excel un Grid o PivotGrid con valores calculados desde vb.net


Para solucionar el problema de exportar valores calculados en el GridView desde Código Vb.Net se soluciona de la Siguiente manera:

Protected Sub ASPxPivotGridExporter_CustomExportCell(ByVal sender As Object, ByVal e As DevExpress.XtraPivotGrid.Web.WebCustomExportCellEventArgs) Handles ASPxPivotGridExporter.CustomExportCell
        Dim brick As DevExpress.XtraPrinting.TextBrick = e.Brick
        If e.DataField.FieldName = "Budget_Dif" Or e.DataField.FieldName = "LY_Dif" Or e.DataField.FieldName = "SumBudget_Dif" Or e.DataField.FieldName = "SumLY_Dif" Then
            brick.TextValue = ConvertToDouble(brick.Text)
        End If
    End Sub

Pivote Dinámico para Ejemplo Anterior


CREATE PROCEDURE [Tutorial].[UspPivoteDinamicoEjemplo]
@IdValorParametro INT
AS
DECLARE @Pivotiar VARCHAR(MAX) = ''
DECLARE @PivotiarSuma VARCHAR(MAX) = ''

 --DECLARACION DE LA TABLA PARA INSERTAR LOS CAMPOS COLUMNAS
  DECLARE @TblColumnas TABLE 
  (
Id INT IDENTITY(1,1),
Columna VARCHAR(20)
  )

--RELLENANDO LA TABLA 
INSERT INTO @TblColumnas
SELECT [Description] FROM Tutorial.Catalogos
WHERE  IdCatalogo = @IdValorParametro
ORDER BY [Description] DESC

SET @Pivotiar = @Pivotiar +  (SELECT ',['+ Columna + ']'  FROM @TblColumnas FOR XML PATH(''))--PARA CONVERTIR LAS FILAS A UNA SOLA VARIABLE CONCATENANDO CON COMA
SET @Pivotiar = SUBSTRING(@Pivotiar,2,LEN(@Pivotiar)) --PARA QUITAR LA PRIMAR COMA 
SET @PivotiarSuma = REPLACE(@Pivotiar,',','+')--PARA HACER CALCULOS EN EL SELECT CON LAS COLUMNAS

   EXEC('SELECT ROW_NUMBER() OVER(ORDER BY IdCampo DESC) AS Id,*,('+@PivotiarSuma+') AS Total
FROM ( 
SELECT * FROM Tutorial.VwVistaConValores WHERE IdParametro = '+@IdValorParametro +
') Pvt
PIVOT (SUM(Monto) FOR [Description] IN ('+@Pivotiar+')) AS Pivote')

Crear un AspxGridView Dinámico haciendo uso de un Pivot SQL Server

En este ejemplo haremos un gridview la cual las columnas son dinámicas de acuerdo a las columnas de un Pivot Grid. Desde código crearemos las columnas con su tipo de datos.

Primeramete solamente arrastramos el GridView, se verá de esta menera:



Luego creamos las columnas que obtenemos del origen de datos:


 Sub crearControles()

        Try
            grdGridView.Columns.Clear() 'Limpiamos las columnas del grid porque por cada postback se crean las columnas nuevamente.

            agregarCommanColumn() 'Si necesitamos hacer uso del Select,New,Update,Delete

            'Si necesitamos agregar template a nuestras colunas
            'se utiliza para mostrar campos no editables y mostrar un label
            Dim labelTemplate As New GridViewTemplate()

            For Each column As DataColumn In dtOrigenDatos.Columns

                Select Case column.ColumnName
                    
                    Case "Id" 'las columnas que no necesitamos agregar al grid
                     'las columnas con propiedades especificas y para agregar el labeltemplate
                     'para las columnas no editables
                    Case "Columna1"
                        Dim txtColumn As New GridViewDataTextColumn()
                        txtColumn.Name = column.ColumnName
                        txtColumn.FieldName = column.ColumnName
                        txtColumn.Settings.HeaderFilterMode = HeaderFilterMode.CheckedList
                        txtColumn.Settings.AutoFilterCondition = AutoFilterCondition.Contains
                        txtColumn.EditFormSettings.Visible = DevExpress.Utils.DefaultBoolean.False
                        txtColumn.EditItemTemplate = labelTemplate
                        grdMontosLimites.Columns.Add(txtColumn)
                    Case "columna2"
                        Dim cmbColumn As New GridViewDataComboBoxColumn()
                        cmbColumn.Name = column.ColumnName
                        cmbColumn.FieldName = column.ColumnName
                        cmbColumn.Settings.HeaderFilterMode = HeaderFilterMode.CheckedList
                        cmbColumn.CellStyle.HorizontalAlign = HorizontalAlign.Center
                        cmbColumn.Width = 50
                        grdMontosLimites.Columns.Add(cmbColumn)
                    Case "Columna4" 'Para valores numéricos no editables
                        Dim txtColumn As New GridViewDataTextColumn()
                        txtColumn.Name = column.ColumnName
                        txtColumn.FieldName = column.ColumnName
                        txtColumn.Settings.HeaderFilterMode = HeaderFilterMode.CheckedList
                        txtColumn.Settings.AutoFilterCondition = AutoFilterCondition.Contains
                        txtColumn.PropertiesTextEdit.DisplayFormatString = "N2"
                        txtColumn.EditItemTemplate = labelTemplate
                        grdMontosLimites.Columns.Add(txtColumn)
                    Case Else   'Si con el mismo tipo de datos en este caso SpinEdit Editables
                        Dim spnColumn As New GridViewDataSpinEditColumn()
                        spnColumn.Name = column.ColumnName
                        spnColumn.FieldName = column.ColumnName
                        spnColumn.PropertiesSpinEdit.DisplayFormatString = "N2"
                        spnColumn.PropertiesSpinEdit.SpinButtons.ShowIncrementButtons = False
                        spnColumn.Settings.HeaderFilterMode = HeaderFilterMode.CheckedList
                        grdMontosLimites.Columns.Add(spnColumn)

                End Select

            Next

        Catch ex As Exception
             Throw ex
        End Try
    End Sub


Sub agregarCommanColumn()

        If grdGridView.Columns.IndexOf(grdGridView.Columns("CommandColumn")) <> -1 Then
            Return
        End If

        Dim col As New GridViewCommandColumn()
        col.Name = "CommandColumn"
        col.ShowSelectCheckbox = True
        col.Caption = " "
        col.ButtonType = ButtonType.Image
        col.EditButton.Visible = True
        col.EditButton.Image.Url = "~/images/note_edit.png"
        col.CancelButton.Visible = True
        col.CancelButton.Image.Url = "~/images/Cancel_Icon_64.png"
        col.UpdateButton.Visible = True
        col.UpdateButton.Image.Url = "~/images/data_floppy_disk.png"
        col.VisibleIndex = 0
        grdMontosLimites.Columns.Add(col)
    End Sub

Por Ultimo hacemos nuestro llenado del GridView:


 ''' <summary>

    ''' Método para llenar un grid view devexpress
    ''' </summary>
    ''' <param name="grdControl">Control devexpress</param>
    ''' <param name="strCampoLlave">campos llave separado por coma</param>
    ''' <param name="objRecursoDeDato">objeto recurso para llenar el control</param>
    ''' <remarks></remarks>
    Public Sub cargarGridView(ByVal grdControl As ASPxGridView, ByVal strCampoLlave As String, ByVal objRecursoDeDato As Object)

Try

            With grdControl
                .DataSource = objRecursoDeDato
                .KeyFieldName = strCampoLlave
                .DataBind()
            End With
 Catch ex As Exception
       Throw ex
 End Try
End Sub

Clase del GridViewTemplate:

Imports DevExpress.Web.ASPxGridView
Imports DevExpress.Web.ASPxEditors
Imports System.Web.UI
Imports System.Web.UI.WebControls

Public Class GridViewTemplate

    Implements ITemplate

    ''' <summary>
    ''' Agrega label para campos no editables
    ''' </summary>
    ''' <remarks></remarks>
    Private Function agregarLabel(ByVal strValor As Object) As ASPxLabel
        Dim lbl As New ASPxLabel
        lbl.Text = If(IsDBNull(strValor), "", strValor)
        Return lbl
    End Function

  Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn

                Dim strNombreColumna = TryCast(container, GridViewDataItemTemplateContainer).Column.FieldName
                container.Controls.Add(agregarLabel(DataBinder.Eval(TryCast(container, GridViewDataItemTemplateContainer).DataItem, strNombreColumna)))

       
    End Sub

End Class

lunes, 17 de junio de 2013

Suma de Totales en el Footer del ASPXGridView DevExpress por Pagina y por Todos los registros.

El GridView de DevExpress solo nos ofrece la suma de todos los registros del grid, pero si queremos los totales por pagina lo hacemos de la siguiente manera:

1- Creamos nuestros Total Summary: 
Aqui seleccionamos la columna donde se mostrará  y el nombre del campo del origen de dato (FieldName) a sumar. 

En el SummaryType establecemos Custom para que el GridView llame el evento CustomSummaryCalculate. 

En Tag una etiqueta que representa la suma por pagina y la suma del Total, esta propidad nos sirve para poner varias valores en la misma columna(SUM,AVERAGE,COUNT,ETC).


2- Creamos el evento CustomSummaryCalculate:

 Dim _dblTotal As Double
 Dim _dblPagina As Double
 Protected Sub grdResumen_CustomSummaryCalculate(ByVal sender As Object, ByVal e As DevExpress.Data.CustomSummaryEventArgs) Handles grdResumen.CustomSummaryCalculate

        Dim item As ASPxSummaryItem = TryCast(e.Item, ASPxSummaryItem)

        ' Initialization.
        If e.SummaryProcess = DevExpress.Data.CustomSummaryProcess.Start Then

            _dblTotal = 0
            _dblPagina = 0

        End If
        ' Calculation.
        If e.SummaryProcess = DevExpress.Data.CustomSummaryProcess.Calculate Then
        ' Validacion si el registro no esta revertido cuando se maneja esta acción.
            If Not e.GetValue("Revertido") Then
                _dblTotal += e.GetValue("Monto")
            End If

            'Valores de la pagina actual
            If grdResumen.GetCurrentPageRowValues("IdLlave").Contains(e.GetValue("IdLlave")) Then
                _dblPagina += e.GetValue("Monto")
            End If

        End If

        ' Finalization.
        If e.SummaryProcess = DevExpress.Data.CustomSummaryProcess.Finalize Then
            If item.Tag = "MontoTotal" Then
                e.TotalValue = String.Format("∑ {0:N2}", _dblTotal)
            End If
            If item.Tag = "MontoPagina" Then
              ' Verificamos si la suma de los montos son distinto que nos indica que hay mas de
                  una página para ocultarlo cuando solo hay una página.
                If _dblTotal <> _dblPagina Then
                    e.TotalValue = String.Format("∑ {0:N2}", _dblPagina)
                End If
            End If
        End If


    End Sub

' Este metodo tiene un la debilidad que al paginar pone la suma de la pagina que se estaba 
viendo por lo que muestra la suma de la pagina anteror. Mas adelante publicaré la solución 
de este bug.

Lo prometido es deuda y aquí les dejo la solución:

Creamos los eventos al cambiar al cambiar el tamaño de la página o al cambiar de página.
Asignamos una propiedad de JSProperties para luego leerla en el EndCallback de los Client-Side-Event del GridView para ejecutar el PerformCallback del GridView y refrescar los valores.

Protected Sub grdResumen_PageIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles grdResumen.PageIndexChanged
        grdResumen.JSProperties("cpPaginacion") = True
    End Sub

Protected Sub grdResumen_PageSizeChanged(ByVal sender As Object, ByVal e As EventArgs) Handles grdResumen.PageSizeChanged
        grdResumen.JSProperties("cpPaginacion") = True
    End Sub



miércoles, 8 de mayo de 2013

Obtener Primer y Ultimo Dia del Mes VB


  If Not IsPostBack Then
            Dim firstDay = New Date(Now.Year, Now.Month, 1)
            Dim lastDay = firstDay.AddMonths(1).AddDays(-1)
            deFecha1.Value = firstDay
            deFecha2.Value = lastDay
  End If