Exportando datos de un GridView a un CSV - Shordi - 21-07-2021
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
RE: Exportando datos de un GridView a un CSV - alessandri - 24-07-2021
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.
RE: Exportando datos de un GridView a un CSV - jguardon - 24-07-2021
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
RE: Exportando datos de un GridView a un CSV - Shordi - 24-07-2021
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
RE: Exportando datos de un GridView a un CSV - alessandri - 25-07-2021
Muy bien. gracias.
RE: Exportando datos de un GridView a un CSV - Shordi - 25-07-2021
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.
RE: Exportando datos de un GridView a un CSV - jguardon - 25-07-2021
(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!
Saludos
|