Cómo leer un archivo de texto delimitado por comas |
Por Enrique Martínez Montejo |
Última revisión: 25/06/2006 |
Frecuentemente me suelo encontrar en los grupos de noticias, mensajes de programadores que desean leer un archivo de texto delimitado por comas (los famosos archivos con extensión *.csv), utilizando el proveedor de datos OLE DB .NET, en un equipo con una configuración regional de español. Lo mismo se estarán preguntando ¿qué tiene que ver un archivo de texto delimitado por comas, con la configuración regional existente en Windows? Aunque parezca mentira, sí tiene que ver, y bastante, hasta tal punto que seremos incapaces de leerlo, debido a que obtendremos el siguiente mensaje de error:
Como todos ustedes conocerán bien, la configuración regional de español utiliza la coma como símbolo de separador decimal, tanto para los números como para la moneda, por lo que el ISAM instalable de texto del motor Microsoft Jet, es incapaz de leer un archivo de texto delimitado por comas si el símbolo de separador decimal coincide también con la coma, por lo que nos veremos obligados a modificar la configuración regional existente, seleccionando cualquier otra que contemple otro símbolo para el separador decimal (como bien podría ser una configuración de inglés de Estados Unidos), o bien modificar mediante programación dichos separadores decimales.
No soy una persona que anime a cambiar la configuración regional, porque nuestras aplicaciones, en todo momento debe respetar escrupulosamente la configuración regional que tiene establecida el usuario, y es nuestra aplicación la que se debe de adaptar a la misma; nunca al contrario. Pero en ocasiones, no nos queda más remedio que modificarla el tiempo suficiente que nos lleve ejecutar una acción, como es el caso que nos ocupa, restaurándola a sus valores originales, una vez efectuada la acción.
Y en esto consiste el ejemplo que a continuación detallo, el cual utiliza las funciones API GetLocaleInfo y SetLocaleInfo, para obtener y modificar, respectivamente, la configuración regional existente. Para ello, al comienzo de nuestra clase Form, escribiremos las declaraciones de ambas funciones:
Imports System.Data
Imports System.Data.OleDb
Imports
System.Runtime.InteropServices
<DllImport("kernel32",
CharSet:=CharSet.Auto)> _
Private Shared
Function GetLocaleInfo( _
ByVal locale
As Integer, _
ByVal lCType
As Integer, _
ByVal lpLCData
As String, _
ByVal cchData
As Integer)
As Integer
' Sin
código de implementación
End
Function
<DllImport("kernel32", CharSet:=CharSet.Auto)>
_
Private Shared
Function SetLocaleInfo( _
ByVal locale
As Integer, _
ByVal lCType
As Integer, _
ByVal lpLCData
As String)
As Integer
' Sin
código de implementación
End
Function
A continuación, en el evento Click de cualquier botón de comando, llevaríamos a efecto la lectura del archivo de texto de la siguiente manera:
Private Sub Button1_Click(ByVal
sender As Object, _
ByVal e As
EventArgs) Handles Button1.Click
Dim sepDecimal1,
sepDecimal2 As String
Const LOCALE_USER_DEFAULT
As Integer
= &H400
Try
' Guardamos el valor del separador
decimal.
'
Dim
buffer As String =
New String(CChar("
"), 100)
GetLocaleInfo(LOCALE_USER_DEFAULT, &HE, buffer, 99)
sepDecimal1 = buffer.Substring(buffer.IndexOf(" "c) -
2, 1)
' Establecemos el nuevo separador
decimal.
'
SetLocaleInfo(LOCALE_USER_DEFAULT, &HE,
".")
' Guardamos el valor del separador
decimal monetario.
'
buffer = New String(CChar("
"), 100)
GetLocaleInfo(LOCALE_USER_DEFAULT, &H16, buffer, 99)
sepDecimal2 = buffer.Substring(buffer.IndexOf(" "c) -
2, 1)
' Establecemos el nuevo separador
decimal monetario.
'
SetLocaleInfo(LOCALE_USER_DEFAULT, &H16,
".")
'
Configuramos la conexión con el archivo de texto.
'
Using cnn
As New
OleDbConnection( _
"Provider = Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Mis documentos;" & _
"Extended Properties='TEXT;HDR=Yes;'")
' Creamos
un objeto Command para seleccionar
' el archivo de texto que deseamos
abrir.
'
Dim cmd As
OleDbCommand =
cnn.CreateCommand()
cmd.CommandText = "Select
* From Archivo#csv"
'
Configuramos el adaptador de datos.
'
Dim
da As New
OleDbDataAdapter(cmd)
'
Creamos un nuevo objeto DataTable.
'
Dim dt As New DataTable("ArchivoDeTexto")
'
Rellenamos el objeto DataTable.
'
da.Fill(dt)
' Mostramos
los registros en un control DataGridView.
'
DataGridView1.DataSource = dt
End Using
Catch ex
As OleDbException
MessageBox.Show(ex.Errors(0).Message,
_
"Abrir archivo de texto", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
Catch ex
As Exception
MessageBox.Show(ex.Message, _
"Abrir archivo de texto", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
Finally
'
Restablecemos el separador decimal.
SetLocaleInfo(LOCALE_USER_DEFAULT,
&HE, sepDecimal1)
'
Restablecemos el separador decimal monetario.
SetLocaleInfo(LOCALE_USER_DEFAULT,
&H16, sepDecimal2)
End Try
End Sub
Cómo leer un archivo de texto delimitado por comas
Observarán que he incluido en el bloque Finally, el proceso de restaurar a su valores originales los símboles de separación decimales, de ésta forma nos aseguramos que los mismos se restauren, aunque se produzca cualquier excepción.
Como nuestro archivo de texto utiliza la coma para delimitar los campos, deberemos hacer uso de un archivo de configuración de esquema, que necesariamente se llamará Schema.ini, y que debe residir en la misma carpeta donde se encuentre el archivo de texto que deseamos leer, por tanto, siguiendo el ejemplo, crearemos el archivo Schema.ini, en la carpeta C:\Mis documentos, con la siguiente configuración mínima:
[Archivo.csv]
ColNameHeader=True
CharacterSet=ANSI
Format=CSVDelimited
Otros enlaces de interés:
Trabajar con los datos existentes en un archivo de texto
Cómo crear un archivo de texto delimitado con los datos existentes en un DataSet
Enrique Martínez Montejo - 2006
NOTA: La información contenida en este artículo, así como el código fuente incluido en el mismo, se proporciona COMO ESTÁ, sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo explicado, recomendado o sugerido en el presente artículo.
NOTE: The information contained in this article and source code included therein, is provided AS IS without warranty of any kind, and confers no rights. You assume any risk to implement, use or run it explained, recommended or suggested in this article.