Shordi   21-07-2021, 16:23
#1
A raíz de una consulta en otro hilo del foro, y como tiempo tengo, he hecho un pequeño vídeo sobre cómo hacer eso: pasar los datos que visualizamos en un GridView a un fichero CSV.



Saludos

No podemos regresar
alessandri   24-07-2021, 18:23
#2
Saludos Shordi,
Hay dos características que me parecen interesantes para agregar a tu EXTGRID.

1-Permitir copiar desde una hoja de cálculo y pegar en el grid.
He utilizado un TextArea para pegar los datos ahí, luego los analizo desde el siguiente código y los paso al Grid.

Esto lo he logrado con el siguiente código (en un botón el cual llamo analizar):
Código:
 Dim tm As String
    Dim l As Single
    Dim z As String
    Dim final As String
    Dim d As String
    Dim tupla As New String[17]
    Dim i As Integer

    
    TituloGrid
    
    tm = Len(ta.Text)
    For l = 1 To tm
        z = Mid(ta.Text, l, 1)
        If z = "\t" Then

             tupla[i] = d
             i += 1
             d = ""
             
        Else
            If z = "\n" Then
                tabla2[Fl2, 0].Text = tupla[0]
                tabla2[Fl2, 1].Text = tupla[1]
                tabla2[Fl2, 2].Text = tupla[2]
                tabla2[Fl2, 3].Text = tupla[3]
                tabla2[Fl2, 4].Text = tupla[4]
                tabla2[Fl2, 5].Text = tupla[5]
                tabla2[Fl2, 6].Text = tupla[6]
                tabla2[Fl2, 7].Text = tupla[7]
                tabla2[Fl2, 8].Text = tupla[8]
                tabla2[Fl2, 9].Text = tupla[9]
                tabla2[Fl2, 10].Text = tupla[10]
                
                tabla2[Fl2, 11].Text = tupla[11]
                tabla2[Fl2, 12].Text = tupla[12]
                tabla2[Fl2, 13].Text = tupla[13]
                tabla2[Fl2, 14].Text = tupla[14]
                tabla2[Fl2, 15].Text = tupla[15]
                tabla2[Fl2, 16].Text = tupla[16]
                
                tupla[0] = "" 'nombre
                tupla[1] = "" 'apellido
                tupla[2] = "" 'cedula
                tupla[3] = "" 'codigo
                tupla[4] = "" 'cargo
                tupla[5] = "" 'banco
                tupla[6] = "" 'cuenta
                tupla[7] = "" 'sueldo fijo
                tupla[8] = "" 'sueldo hora
                tupla[9] = "" 'sexo
                tupla[10] = "" 'comunidad
                tupla[11] = "" 'academico
                tupla[12] = "" 'clasificacion
                tupla[13] = "" 'telefono 1 y 2
                tupla[14] = "" 'fecha
                tupla[15] = "" 'contrato
                tupla[16] = "" 'PAD
                
                tupla[i] = d
                d = ""
                
                i = 0
                Fl2 += 1
                Wait
                lblanalizado.Text = Fl2
            Else
                d &= z 'completa un campo carater por caracter
            Endif
        Endif
    Next
Código:
Private Sub TituloGrid()
    tabla2.Clear
    Fl2 = 0
    
    tabla2.Columns.Count = 17  'Cantidad de Columnas de la tabla
    tabla2.Rows.Count = 10000 'Cantidad del Filas
    tabla2.columns.Resizable = True
    
    tabla2.Columns[0].Text = "Nombre"
    tabla2.Columns[0].Width = 110
    tabla2.Columns[1].Text = "Apellidos"
    tabla2.Columns[1].Width = 110
    tabla2.Columns[2].Text = "Cédula"
    tabla2.Columns[2].Width = 90
    tabla2.Columns[3].Text = "Código"
    tabla2.Columns[3].Width = 65
    tabla2.Columns[4].Text = "Cargo"
    tabla2.Columns[4].Width = 70
    tabla2.Columns[5].Text = "Banco"
    tabla2.Columns[5].Width = 70
    tabla2.Columns[6].Text = "Cuenta"
    tabla2.Columns[6].Width = 85
    tabla2.Columns[7].Text = "Suel.Fijo"
    tabla2.Columns[7].Width = 65
    tabla2.Columns[8].Text = "Suel.Hora"
    tabla2.Columns[8].Width = 65

    tabla2.Columns[9].Text = "Sexo"
    tabla2.Columns[9].Width = 40
    tabla2.Columns[10].Text = "Comunidad"
    tabla2.Columns[10].Width = 50
    tabla2.Columns[11].Text = "Academico"
    tabla2.Columns[11].Width = 50
    tabla2.Columns[12].Text = "Clasific."
    tabla2.Columns[12].Width = 50
    tabla2.Columns[13].Text = "telefono1 y 2"
    tabla2.Columns[13].Width = 50
    tabla2.Columns[14].Text = "fecha"
    tabla2.Columns[14].Width = 50
    tabla2.Columns[15].Text = "contrato"
    tabla2.Columns[15].Width = 50
    tabla2.Columns[16].Text = "pad"
    tabla2.Columns[16].Width = 1
End

2- Exportar los datos del Grid a HTML y de ahí convertirlos en PDF con el programa WKHTMLTOPDF desde usando un shell
lo he conseguido así:
Código:
Procedure eTabla()
  Dim DocHtml As String
  Dim i As Integer

   DocHtml = "<html>"
        DocHtml &= "<head>"
            DocHtml &= "<title > GRID EXPORTADO </title >"
        DocHtml &= "</head >"
        
        DocHtml &= "<body>"
            
        'INICIA TABLA
        DocHtml &= "<table align='center' width= 100% border= '1' cellpadding='0' cellspacing='0'>"
            DocHtml &= "<tr align='center' width='10%'>"
            DocHtml &= "<td>"
 
                  For i = 0 To tabla2.Rows.Count - 1
                     DocHtml &= "<tr> \n"
                     
                     DocHtml &= "<td align='right'><font color=black face='Courier, arial' size=2><b>" & tabla2[i, 0].Text & "</b></font></td>\n"
                     DocHtml &= "<td align='right'><font color=black face='Courier, arial' size=2><b>" & tabla2[i, 1].Text & "</b></font></td>\n"
                     DocHtml &= "<td align='right'><font color=black face='Courier, arial' size=2><b>" & tabla2[i, 2].Text & "</b></font></td>\n"
                     DocHtml &= "<td align='right'><font color=black face='Courier, arial' size=2><b>" & tabla2[i, 3].Text & "</b></font></td>\n"
                     
                     DocHtml &= "</tr>\n"
                  Next

            
            DocHtml &= "</td>"
        DocHtml &= "</table>"
        'FIN DE LA TABLA
        
        DocHtml &= "</body>"
        
    DocHtml &= "</html>"
    
    file.save(User.home & "/mi_Grid.html", DocHtml)
End

El código se puede refinar mucho más, se puede usar poppler en vez de WKHTMLTOPDF, pero no lo he usado nunca. 
Mientras se estan pasando los datos a HTML se pueden hacer muchas cosas como: cambiar color al texto, ancho de celdas, negritas, tipografía,
y hasta una CSS se puede usar.
Saludos.
Última modificación: 24-07-2021, 18:25 por alessandri.
jguardon   24-07-2021, 20:00
#3
Hola, Shordi

Dos cuestiones:

Primera, veo que en el último campo de cada registro se crea un separador ; aún no siendo necesario porque ya tienes el salto de línea al siguiente registro. Esto podría provocar que se creen campos vacíos al final de cada registro dependiendo del programa que importe el fichero.

Segunda, si utilizamos el evento Data para cargar datos en el grid, podría ocurrir que sólo se exportasen los datos visibles en éste, ya que el evento sólo carga datos cuando deben visualizarse y no antes. Lo digo porque si la base de la creación del CSV es la iteración por las celdas del grid, no parece una buena idea.

Normalmente uno exporta y convierte los datos provenientes de la consulta, ya sea SQL o de otro tipo de fuente de datos, que es más fiable (y posiblemente más rápido) que "leer" las celdas una por una.

En cualquier caso, puede ser de mucha utilidad para determinadas tareas pequeñas, gracias por enseñarnos tu trabajo, shordi.

Saludos

Por favor, usa el corrector ortográfico antes de pulsar el botón 'Enviar'
Shordi   24-07-2021, 21:25
#4
Alessandri gracias por tu interés en mi trabajo. Unas puntualizaciones:
Cita:1-Permitir copiar desde una hoja de cálculo y pegar en el grid.
El problema ahí es lo que llamas "copiar y pegar". Las hojas de cálculo tienen todas una opción de "guardar como csv", que creo que es lo correcto. y luego pasas ese csv como fuente de datos del Gridview, como digo en el ejemplo de la segunda mitad del vídeo.
Cita:
Código:
....
...
Dim tm As String
    Dim l As Single
    Dim z As String
    Dim final As String
    Dim d As String
    Dim tupla As New String[17]
    Dim i As Integer
 
    
    TituloGrid
    
    tm = Len(ta.Text)
    For l = 1 To tm
        z = Mid(ta.Text, l, 1)
        If z = "\t" Then
 
             tupla[i] = d
             i += 1
             d = ""
             
        Else
            If z = "\n" Then
                tabla2[Fl2, 0].Text = tupla[0]
                tabla2[Fl2, 1].Text = tupla[1]
                tabla2[Fl2, 2].Text = tupla[2]
                tabla2[Fl2, 3].Text = tupla[3]
                tabla2[Fl2, 4].Text = tupla[4]
                tabla2[Fl2, 5].Text = tupla[5]
                tabla2[Fl2, 6].Text = tupla[6]
                tabla2[Fl2, 7].Text = tupla[7]
                tabla2[Fl2, 8].Text = tupla[8]
                tabla2[Fl2, 9].Text = tupla[9]
                tabla2[Fl2, 10].Text = tupla[10]
...
...
En este procedimiento estás "destripando" un CSV que utiliza el tabulado como separador. En el control se asume que el separador es un ;. como puedes ver en éste código sacado de la clase extgrid del proyecto adjunto al vídeo (te subrayo en verde la línea donde se asume)
Cita:Private Sub Source_Write(Value As Variant)

    Dim n As Integer
    Dim asLine As String[]
    Dim sValue As String
    Dim v As Variant
    Dim col As Collection
    
    Me.Clear()
    Try sValue = Value 'Intentamos meter el Value en un string
    If Not Error Then
        If Exist(Value) Then ' es un Path
            asLine = Split(File.Load(Value), "\n", "", True)
        Else
            asLine = Split(Value, "\n", "", True) 'es el contenido del csv o un texto
        Endif
        $avSource = New Variant[]
        For n = 0 To asLine.Max
            $avSource.Add(Split(asLine[n], ";")) 'Asumimos el ; como separador. Se podría crear una propiedad, usar un inputbox o un formulario de opciones para afinar esto
        Next

        $asFieldNames = $avSource[0].Copy() 'usamos la primera línea como nombre de campo
        $avSource.Extract(0) 'y la eliminamos del source
        For n = 0 To $avSource[0].Max
            $anFieldTypes.Add(CellType($avSource[0][n])) 'Determinamos el tipo de dato de cada celda según el contenido de la primera fila
        Next
    Else If Value Is String[] Then 'Es un String[] y lo convertimos en un Variant[][]
         $avSource = New Variant[]
....
....
Como ves, el control que paso a los vídeos es una simplificación para no liarla mucho. Sin cambiarle nada, puedes, hacer algo como:
Código:
micsv = File.load(mipath&/nombreficherocsv)
micsv=replace(micsv,"\t",";")
file.save(mipath&/nombreficherocsv,micsv)
miExtGrid.Source=micsv
Esto si el carácter ";" no va a ocasionar conflicto con el contenido del fichero, claro. Si así fuese habría que cambiar el carácter en el código o añadir una propiedad "separator" al control para poder cambiarlo sin problemas.
Pero es mucho más sencillo, si eres tú quien genera el CSV decirle a la hoja de cálculo que utilice ";" como separador.
 
Cita:
Código:
     Private Sub TituloGrid()
        tabla2.Clear
        Fl2 = 0
        
        tabla2.Columns.Count = 17  'Cantidad de Columnas de la tabla
        tabla2.Rows.Count = 10000 'Cantidad del Filas
        tabla2.columns.Resizable = True
        
        tabla2.Columns[0].Text = "Nombre"
        tabla2.Columns[0].Width = 110
        tabla2.Columns[1].Text = "Apellidos"
        tabla2.Columns[1].Width = 110
        tabla2.Columns[2].Text = "Cédula"
        tabla2.Columns[2].Width = 90
        tabla2.Columns[3].Text = "Código"
        tabla2.Columns[3].Width = 65
        tabla2.Columns[4].Text = "Cargo"
        tabla2.Columns[4].Width = 70
        tabla2.Columns[5].Text = "Banco"
        tabla2.Columns[5].Width = 70
        tabla2.Columns[6].Text = "Cuenta"
        tabla2.Columns[6].Width = 85
        tabla2.Columns[7].Text = "Suel.Fijo"
        tabla2.Columns[7].Width = 65
        tabla2.Columns[8].Text = "Suel.Hora"
        tabla2.Columns[8].Width = 65
     
        tabla2.Columns[9].Text = "Sexo"
        tabla2.Columns[9].Width = 40
        tabla2.Columns[10].Text = "Comunidad"
        tabla2.Columns[10].Width = 50
        tabla2.Columns[11].Text = "Academico"
        tabla2.Columns[11].Width = 50
        tabla2.Columns[12].Text = "Clasific."
        tabla2.Columns[12].Width = 50
        tabla2.Columns[13].Text = "telefono1 y 2"
        tabla2.Columns[13].Width = 50
        tabla2.Columns[14].Text = "fecha"
        tabla2.Columns[14].Width = 50
        tabla2.Columns[15].Text = "contrato"
        tabla2.Columns[15].Width = 50
        tabla2.Columns[16].Text = "pad"
        tabla2.Columns[16].Width = 1
    End

Si cuando generas el csv en la hoja de cálculo le dices que utilice las cabeceras como primera línea te ahorrarás todo esto. Si tu hoja de cálculo no tiene las cabeceras adecuadas y quieres cambiarlas no es necesario este código. Para eso está la propiedad Titles del gridview. y los anchos de columna, si no te valen con ancho automático sólo tienes que introducirlos en la propiedad Widths. Con lo que se quedaría así:
Cita:
Código:
micsv = File.load(mipath&/nombreficherocsv)
micsv=replace(micsv,"\t",";")
file.save(mipath&/nombreficherocsv,micsv)
miExtgrid.Source=micsv
miExtgrid.Titles=["Nombre","Apellidos","Cédula","Código","Cargo","Banco","Cuenta",...etc, etc.]
miExtgrid.Widths=[110,110,90,65,70,70,85...etc.etc]

De todas formas la generación de CSV no es tarea del control. El sólo los carga no los procesa. Eso queda para la Hoja de Cálculo... o para el programa del vídeo, donde puedes añadir todas las opciones y tejemanejes que quieras.

Un saludo.

(24-07-2021, 20:00)jguardon escribió: Hola, Shordi

Dos cuestiones:

Primera, veo que en el último campo de cada registro se crea un separador ; aún no siendo necesario porque ya tienes el salto de línea al siguiente registro. Esto podría provocar que se creen campos vacíos al final de cada registro dependiendo del programa que importe el fichero. Totalmente cierto. Se me pasó el detalle. Lo corrijo y actualizo el control adjunto al vídeo.

Segunda, si utilizamos el evento Data para cargar datos en el grid, podría ocurrir que sólo se exportasen los datos visibles en éste, ya que el evento sólo carga datos cuando deben visualizarse y no antes. Lo digo porque si la base de la creación del CSV es la iteración por las celdas del grid, no parece una buena idea.

Normalmente uno exporta y convierte los datos provenientes de la consulta, ya sea SQL o de otro tipo de fuente de datos, que es más fiable (y posiblemente más rápido) que "leer" las celdas una por una.
No se miran las celdas. los valores se extraen a través de la propiedad Value del array Source del control. Eso hace que sea más rápido que recurrir a la base de datos (al menos si la base de datos no es local de la máquina). La fiabilidad del tipo de datos devuelto (de caracter o numérico) es 100% si se cargó desde una base de datos y, digamos, al 90 por cien si se hizo desde un CSV. El código es éste tomado de la función Values_read() del control:

Código:
     col = New Collection
            For i = 0 To Me.Columns.Count - 1
                Select Case $anFieldtypes[i]
                    Case gb.String                
                        v = $avSource[anSelection[n]][i] 'donde $avSource es el array bidimensional fuente del Control.
                    Case gb.Integer
                        v = Val($avSource[anSelection[n]][i])
                    Case gb.Float
                        v = Val($avSource[anSelection[n]][i])
                End Select
                col.Add(v, $asFieldNames[i])
            Next


En cualquier caso, puede ser de mucha utilidad para determinadas tareas pequeñas, gracias por enseñarnos tu trabajo, shordi.

Saludos

y gracias por tu interés.


Saludos
Última modificación: 24-07-2021, 21:43 por Shordi.

No podemos regresar
alessandri   25-07-2021, 00:22
#5
Muy bien. gracias.
Shordi   25-07-2021, 09:59
#6
De todas formas eso a lo que apuntas también lo tengo hecho por ahí. Me refiero al mecanismo de impresión en html y pdf a partir de un gridview, con CSS por medio y demás. Dame unos días para que lo adecúe a los nuevos controles (ahora están imbricados en el software de mi antigua empresa) y los presentaré en sociedad.

No podemos regresar
jguardon   25-07-2021, 11:01
#7
(24-07-2021, 21:25)Shordi escribió: No se miran las celdas. los valores se extraen a través de la propiedad Value del array Source del control.

Pues se me pasó ese detalle. Efectivamente esa es la manera más rápida y fiable, pero por un momento pensé que estabas tomando los valores desde las celdas. Fantástico! Tongue

Saludos

Por favor, usa el corrector ortográfico antes de pulsar el botón 'Enviar'
  
Usuarios navegando en este tema: 2 invitado(s)
Powered By MyBB, © 2002-2024 MyBB Group.
Made with by Curves UI.