Descargar el contenido de un DataSet en formato CSV

Como generar un fichero en formato CSV con el contenido de un DataSet y forzar la descarga

Fecha: 09/Sep/2004 (03/09/2004)
Autor: José María del Molino jmdmpolo@hotmail.com
 


Esta ejemplo muestra como crear una clase para convertir del contenido de un DataSet a un fichero, con formato CSV, y automatizar su descarga, de manera que en nuestra aplicación ASP.NET podamos integrar esta funcionalidad mediante un control Button o Linkbutton.

El formato CSV (¿Carácteres Separados por Valor?) es reconocido por todos los programas de hoja de cálculo (como MS Excel) y se puede utilizar como orígenes de datos (utilizando por ejemplo MS Text Driver para ODBC) y por lo tanto importar facilmente en cualquier base de datos.

La implementación de esta funcionalidad la hacemos en una clase, un buen nombre sería DataSet2CSV, de esta manera la podremos utilizar facilmente en varios proyectos, compilar por separado y por ejemplo incluirla facilmente en un Servicio Web a utilizar desde múltiples aplicaciones.

Conversión a CSV

La primera funcionalidad de la clase será convertir el contenido del DataSet a formato CSV. Para ello creamos una función, privada a la clase, que reciba el objeto DataSet y genera el contenido del fichero CSV

'Función de Conversión a CSV
Private Function ConvierteCSV(ByRef pDatos As DataSet, _
	Optional ByVal pDelimitadorColumnas As String = ",", _
	Optional ByVal pDelimitadorRegistros As String = vbNewLine) As String    
	
	'Variables Locales
	Dim mSalida As String
	Dim mRegistro As String
	Dim mContadorRegistros As Integer = 0
	Dim mContadorColumnas As Integer = 0
	Dim mValor As String = ""
	Dim mNombreColumna As String = ""
	
	'Solo si hay datos
	If Not IsNothing(pDatos) Then
		If pDatos.Tables.Count > 0 Then
		
			'fila de titulos de columna
			mContadorColumnas = 0
			mRegistro = ""
			'para cada columna
			While mContadorColumnas < pDatos.Tables(0).Columns.Count
			
				mNombreColumna = pDatos.Tables(0).Columns(mContadorColumnas).ColumnName
				
				If mRegistro <> "" Then
					mRegistro = mRegistro & pDelimitadorColumnas
				End If
				
				mValor = """" & mNombreColumna & """"
				mRegistro = mRegistro & mValor
                   
				mContadorColumnas = mContadorColumnas + 1
				
			End While
			mSalida = mSalida & mRegistro
			
			'procesa los registros del dataset
			While mContadorRegistros < pDatos.Tables(0).Rows.Count
				If mSalida <> "" Then
					mSalida = mSalida & pDelimitadorRegistros
				End If
				mRegistro = ""
				mContadorColumnas = 0
				'para cada columna	
				While mContadorColumnas < pDatos.Tables(0).Columns.Count
					If mRegistro <> "" Then
						mRegistro = mRegistro & pDelimitadorColumnas
					End If
					
					mValor = pDatos.Tables(0).Rows(mContadorRegistros)(mContadorColumnas)
					If InStr(mValor, pDelimitadorColumnas) > 0 Then
						mValor = """" & mValor & """"
					End If
					mRegistro = mRegistro & mValor
						mContadorColumnas = mContadorColumnas + 1
				End While
				'añade el registro
				mSalida = mSalida & mRegistro
				mContadorRegistros = mContadorRegistros + 1
			End While
		End If
	End If
       
	Return mSalida
End Function

Automatizar la descarga

Una vez generado el CSV es necesario implementar la descarga del resultado al PC del usuario final.
La siguiente implementación hace que se fuerze la descarga a disco e impide que se visualize el resultado de la conversión a CSV en el propio explorador.

Private Sub DescargaCSV(ByVal pCSV As String, ByVal pNombreCSV As String)

	'Obtiene la respuesta actual
	Dim response As System.Web.HttpResponse = System.Web.HttpContext.Current.Response
	
	'Borra la respuesta
	response.Clear()
	response.ClearContent()
	response.ClearHeaders()
	
	'Tipo de contenido para forzar la descarga
	response.ContentType = "application/octet-stream"
	response.AddHeader("Content-Disposition", "attachment; filename=" & pNombreCSV)
	
	'Convierte el string a array de bytes
	Dim buffer(Len(pCSV)) As Byte
	Dim mContador As Long = 0
	While mContador <  Len(pCSV)
		buffer(mContador) = Asc(Mid(pCSV, mContador + 1, 1))
		mContador = mContador + 1
	End While
	
	'Envia los bytes
	response.BinaryWrite(buffer)
	response.End()

End Sub

Esta función la podemos utilizar para descargar cualquiero fichero. Si esa fuese nuestra idea sería recomendable hacer una clase propia para esta función con vistas a ampliarla con otras funciones para descargar ficheros existentes en disco, realizar cargas al servidor, etc ..

Interfaz pública de la clase

Para concluir la clase no resta hacer la función publica a través de la cual se va a acceder a las funcionalidades de la clase.

	Public Sub EnviaCSV(ByRef pDatos As DataSet, Optional ByVal pNombreFicheroCSV As String = "datos.csv")

		'Convirte el DataSet a String en CSV
		Dim mSalida As String
		mSalida = ConvierteCSV(pDatos)
		'Envia el String en CSV
		DescargaCSV(mSalida, pNombreFicheroCSV)
	
	End Sub

Utilizando la clase

Una vez creada nuestra clase vamos a ver como utlizarla desde un formulario ASPX. Por ejemplo suponiendo que nuestro formulario tiene un Datagrid con nombre Datagrid1 y una función CargaDataSet que devuelve un DataSet con los datos a mostrar en el DataGrid. El Load de la página podría ser algo así:

	Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
		'Introducir aquí el código de usuario para inicializar la página
		If Not IsPostBack Then
			'carga el dataset
			Dim mDatos as DataSet
			mDatos = CargaDataSet() 

			'carga el dataset en el datagrid
			DataGrid1.DataSource = mDatos
			DataGrid1.DataBind()
		End If
	End Sub

	Private Function CargaDataSet() As DataSet
		'.......	
	End Function

Para habilitar la generación y descarga del fichero CSV añadimos un linkbutton LinkButton1

	Private Sub LinkButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkButton1.Click
		
		'carga el dataset 
		Dim mDatos as DataSet
		mDatos = CargaDataSet() 
		
		'instancia la clase 
		Dim mDescargaCSV as New DataSet2CSV 
		'genera el CSV y lo envia 
		mDescargaCSV.EnviaCSV(mDatos, "NombreFichero.csv")
		
	End Sub 

Al pulsar el Linkbutton se convertirá el dataset a CSV y se mostrará al usuario la típica pantalla de Guardar como ...


ir al índice