Wednesday, March 30, 2011

Cómo pasar Los datos De un gridview a Un datatable

ASP.NET, VB.NET

Se podría dar el caso de que las celdas de un GridView sean generadas o ingresadas por el usuario en tiempo de ejecución. Es decir, lo que se muestra en el GridView no son datos bindeados.

Para poder recuperar estos datos, no existe un método como tal. Por tanto, hay que programarlo.

Es sencillo, primero hay que crear la estructura del DataTable. Por ejemplo:

Public Sub prcCrearEstructuraDatatable()
        Dim dt As New DataTable
        dt.Columns.Add("inProdNcod")
        dt.Columns.Add("inProdCodg")
        dt.Columns.Add("vtLisDPrec")
        dt.Columns.Add("vtLisDDsct")
        dt.Columns.Add("vtLisDMoni")
        dt.Columns.Add("vtLisDMarg")
        dt.Columns.Add("vtLisMNcod")
        dt.Columns.Add("vtLisDNcod")
        Me.ViewState("dtDetalle") = dt
    End Sub


(Meto el DataTable dentro de un ViewState para luego poder manipular la tabla en cualquier momento)

Luego de haber cargado los datos al Gridview, los cuales se desea guardarlos, le hacemos un For Each y metemos en cada fila del DataTable lo que hay en cada celda del GridView, las celdas que deseemos. Para ello, recuperamos la estructura del DataTable la cual está en el ViewState. Y al final, hacemos el caso inverso, asignamos lo que hay en el DataTable ahora al ViewState (esto es para la manipulación posterior de los datos)

Public Function fncCargarDataTable(ByRef strMensaje As String) As Boolean
    Me.prcCrearEstructuraDatatable()
    Dim dt As DataTable = Me.ViewState("dtDetalle")
    If Me.grvListaDePrecios.Rows.Count > 0 Then
        For Each fila As GridViewRow In Me.grvListaDePrecios.Rows
            Dim f As DataRow = dt.NewRow()
            Dim txtDescuento As TextBox = DirectCast(fila.Cells(6).Controls(1), TextBox)

            f("inProdNcod") = DirectCast(fila.Cells(8).Controls(1), Label).Text
            f("inProdCodg") = fila.Cells(1).Text
            f("vtLisDPrec") = DirectCast(fila.Cells(4).Controls(1), TextBox).Text
            f("vtLisDDsct") = IIf(txtDescuento.Text = "", "0", txtDescuento.Text)
            If txtDescuento.Text = "" Then
                txtDescuento.Text = "0"
            End If
            f("vtLisDMoni") = DirectCast(fila.Cells(4).Controls(7), DropDownList).SelectedValue
            f("vtLisDMarg") = DirectCast(fila.Cells(5).Controls(1), Label).Text
            f("vtLisMNcod") = Me.ViewState("EstadoID")
            f("vtLisDNcod") = DirectCast(fila.Cells(9).Controls(1), Label).Text

            dt.Rows.Add(f)
        Next
        Me.ViewState("dtDetalle") = dt
    Else
        strMensaje = "Debe generar la lista de precios antes de guardarla."
        Return False
    End If
    Return True
End Function

=) HaPPy CoDiNg!

Monday, March 28, 2011

Como quitar Los ceros que genera el AVG de SQL

Me topé con el lio de que cuando ejecuto la siguiente consulta sql, en el resultado del AVERAGE o promedio, me agrega hasta 6 dígito después del punto. Si el resultado no tuviera decimales, le agrega en total 6 molestosos ceros.

SELECT p.inProdCodg, p.inProdDesc, AVG(a.inPxalCuni) AS COSTO
FROM dbo.inProd p INNER JOIN dbo.inPxAl a ON a.inProdNcod=p.inProdNcod
GROUP BY p.inProdCodg, p.inProdDesc

Una solución? Hacerle un CAST
El tipo de dato de la columna de la cual saco el promedio es DECIMAL(14,2)

Por tanto, la consulta sql quedaría así:

SELECT p.inProdCodg, p.inProdDesc, CAST(AVG(a.inPxalCuni) AS DECIMAL(14,2)) AS COSTO
FROM dbo.inProd p INNER JOIN dbo.inPxAl a ON a.inProdNcod=p.inProdNcod
GROUP BY p.inProdCodg, p.inProdDesc


=) Happy Coding!

Monday, March 21, 2011

Cómo obtener los textpath De Los nodos padres


TreeView, ASP.NET, VB.NET Selected Node Text Path

Un TreeNode tiene como propiedad el ValuePath, con esa propiedad se puede obtener la ruta de los valores dado un nodo hasta llegar al nodo raíz. Por ejemplo: ---> 0/1/2/3/4

Si, ahora, estás buscando cómo obtener la ruta del text... buscando un TextPath? No hay, qué raro. Si hay un ValuePath, por qué no hicieron un TextPath. En fin, como no hay, hay que hacerlo :P A mi me tocó hacerlo pues lo necesitaba para obtener algo asi como en la siguiente imágen:



Dado un nodo seleccionado, se obtiene la ruta de los text a partir de ahí hasta el nodo raíz. Tiene el formato: Parent - Child1 - Child11 - Child111 ... Si no le colocas el "-" Usará el separador que por defecto pone el lenguaje "/"

El código:


Protected Sub trvListaDePrecios_SelectedNodeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles trvListaDePrecios.SelectedNodeChanged
        Dim nodo As TreeNode = Me.trvListaDePrecios.SelectedNode
        Dim strTextPath As String = nodo.Text
        Dim strSeparador As String = "-"
        Me.trvListaDePrecios.PathSeparator = CChar(strSeparador)
        While Not nodo.Parent Is Nothing
            strTextPath = nodo.Parent.Text & " " & Me.trvListaDePrecios.PathSeparator & " " & strTextPath
            nodo = nodo.Parent
        End While
        Dim strValuePath As String = Me.trvListaDePrecios.SelectedNode.ValuePath
        Me.prcCargarDatosPopUp(strValuePath, strTextPath.ToUpper())
    End Sub

HaPPy CoDiNg =)

Tuesday, March 15, 2011

Convert.ToInt32 vs CInt

Ambas sentencias devuelven el mismo valor:




Dim d1 As Double = 5.5
Dim i1 As Integer = Convert.ToInt32(d1)

Dim d2 As Double = 5.5
Dim i2 As Integer = CInt(d2)




Si estás usando Visual Basic .NET tal vez te has preguntado cuál es la diferencia de usar Convert.ToInt32 o CInt, o si es indiferente o cuándo usar lo uno y cuándo lo otro.

Microsoft recomienda usar CInt a utilizar el método de Convert.ToInt32 de .NET Framework ¿Por qué? Porque esta función se compila en línea, es decir, el código de conversión forma parte del código que evalúa la expresión. A veces no se produce una llamada a un procedimiento para realizar la conversión, lo que mejora el rendimiento.

Good Coding! =)

Monday, March 14, 2011

Como insertar registros De Una tabla a otra tabla

SQL SERVER

El caso más sencillo es cuando ambas tablas se encuentran dentro de la misma base de datos que pertenece a un mismo servidor.

INSERT INTO tabla_destino SELECT * FROM tabla_origen

La cantidad y tipo de datos de columnas deben coincidir tanto para la tabla origen como en la de destino (asímismo para los otros dos casos)

Ej:

INSERT INTO dbo.cfPrfl (cfEmprNcod,cfPrflNmbr) SELECT cfEmprNcod, dcPrsnNmbr FROM dcPrsn

Este es el caso medio, cuando se quiere insertar datos de una tabla a otra pero estas pertecenen a diferentes base de datos en un mismo servidor. En este caso, el usuario debe tener acceso a las dos base de datos.

INSERT INTO base_de_datos.dbo.tabla_destino SELECT * FROM base_de_datos.dbo.tabla_origen

Ej:


INSERT INTO UponERP.dbo.cfPais SELECT cfPaisNmbr FROM UponErpTestLizzy.dbo.cfPais

Y por último, este es el caso final. Cuando se desea insertar datos de una tabla a otra pero que ambas tablas están en diferentes base de datos y las cuales a su vez pertenecen a distintos servidor.

Para este caso, es necesario que el usuario tenga acceso a los dos servidores y a las dos base de datos

INSERT INTO servidor.base_de_datos.esquema.tabla_destino SELECT * FROM servidor.base_de_datos.esquema.tabla_origen

Ej:


INSERT INTO [DESARROLLO02\SQL2005].UponErpTestLizzy.dbo.cfBsAu SELECT * FROM [SRV-DB\SQL2005].UponErpTest.dbo.cfBsAu

Good Coding =)

Wednesday, March 9, 2011

String.Empty vs EnTre ComiLLas VaCiAs

Cuando necesito crear/reiniciar o limpiar variables de string o cajas de texto, solía hacerlo de ambas formas:

Me.txtNombre.text = String.Empty()
Me.txtNombre.text = ""

Las usaba de la misma manera pero luego me pregunté cuál es la diferencia y si alguna forma es mejor que la otra.

Cuando usamos las comillas, se crea un nuevo objeto en la memoria. Mientras que cuando se utiliza String.Empty(), no se crea nada. Por tanto, para la buena administración de memoria, es preferible usar String.Empty()

A utilizar String.Empty() !!!

Good Coding...

Thursday, March 3, 2011

Datatable y DataKeyNames

DataKeyNames permite agregarle un array de campos llaves que se usarán para seleccionar un registro dentro del datatable. Al menos yo lo utilizo para hacer un select con esa llave o conjunto de llaves. Solía usar siempre solo un item para el array. Pero cuando me tocó usar más de uno, no supe hacerlo. Pero ya lo hice, jajaja :p Es sencillo, es com sigue:

Por ejemplo, cuando sólo era uno, por código yo lo llenaba así:
Me.grvResultado.DataKeyNames = New String() {Me.pNombrePrimaryKey}

Pero cuando me tocó llenar con más de uno, fue asi:

Me.grvResultado.DataKeyNames = New String() {Me.strNombrePrimaryKey, Me.strKeySecundaria}

(Sin embargo, si lo querés hacer por diseño, podes seleecionar tu gridview, ir a sus propiedades y en donde dice: "DataKeyNames", agregar los campos llaves separados por coma.)

En el evento de tu gridview RowDataBound, hay que llenar el CommandArgument

If e.Row.RowType = DataControlRowType.DataRow Then
Dim lnkSeleccionar As LinkButton = CType(e.Row.Cells(0).Controls(0), LinkButton)
lnkSeleccionar.CommandArgument = Me.grvResultado.DataKeys(e.Row.RowIndex).Values(0) & "," & Me.grvResultado.DataKeys(e.Row.RowIndex).Values(1)
End If

El Values(0) es el primer campo llave, el Values(1) es segundo, y así sucesivamente. Fijate que están separados por coma.

Luego en el evento de tu gridview RowCommand, desglosas tu array de llaves.

Dim valores() As String = e.CommandArgument.ToString().Split(",")
Dim valor1 As String = valores(0)
Dim valor2 As String = valores(1)

Y mi Select sería así:

dt.Select(Me.strNombrePrimaryKey & "=" & valor1 & " AND " & Me.strKeySecundaria & "=" & valor2)

Happy Codding =)