Leer ficheros csv y de campos de ancho fijo en Visual Basic

En mi vuelta al servicio activo he tenido que procesar dos ficheros en texto plano: uno con campos separados por un carácter y otro con campos de ancho fijo. En su día ya lo hice (concretamente para un csv, valores separados por comas), pero no me acordaba de cómo lo hice (fue al poco de empezar con VB2005) y no tenía a mano ni el código que hice ni el libro que usé de referencia, así que busqué en Internet.

Y fíjese usted por donde, encontré una forma más simple de hacer las cosas que no conocía: usando la clase TextFieldParser.

En la forma más fácil, le pasamos en el constructor la ruta del archivo a tratar. Le indicamos luego qué es, si de ancho fijo (FixedWith) o separado por carácter (Delimited) con la propiedad TextFieldType. Si es el segundo caso, con el método SetDelimiters indicamos el delimitador (por ejemplo, MiTfp.SetDelimiters(vbTab) para indicar campos separados por una tabulación).

En el primero, indicaríamos el ancho de los campos mediante una lista de enteros que le pasamos al método SetFieldWiths: MiTfp.SetFieldWiths(2, 3, 12, 85, 5).

Para leer cada línea tenemos el método ReadFields, que nos devuelve un array de cadenas con cada campo de la línea del fichero en la posición correspondiente del array. Se tarda más en explicar que en hacer.

Hay un pequeño problema adicional: la codificación de caracteres. Por defecto, se usa UTF8. Ahora mismo no recuerdo si Vista y 7 usan UTF8 por defecto, pero XP y versiones anteriores de Windows, no, y podemos encontrarnos con problemas con algunos caracteres, como ñ, tildes, etc. En ese caso, seguramente estemos usando Windows occidental (Windows 1252) o, más raramente, ISO-8859-1. Podemos indicarle esto al TextFieldParser en el constructor, pasándole el código de la página de códigos a emplear:

Dim MiTfp as New TextFieldParser(MiRuta, System.Text.Encoding.GetEncoding(1252))

Lo más largo, como siempre, es el control de errores, o el propio tratamiento de los valores que hayamos leído, pero el hecho de leer en sí más simple no puede ser.

DataRepeater y el evento Enter de sus controles

A la hora de evitar que el usuario manazas edite el valor de algún control, una opción habitual es controlar el evento Enter de ese control o de su contenedor (un GroupBox, un Panel…), mandando el foco a otro control mediante el método OtroControl.Select(). Esto funciona para buena parte de los controles disponibles en Windows Forms, pero no para todos (dtpicker, optionbutton… hay varios que pasarán de nosotros).

Si nosotros queremos usar este sistema con controles que estén dentro de un DataRepeater… En fin, probadlo si queréis, pero ya os digo que la aplicación se quedará muerta si mandáis el foco a un control que esté fuera del DataRepeater. ¿Entonces?

Pues no salgamos. Pasemos el foco al ítem del DataRepeater al que pertenezca el control y listo:

MiDataRepeater.CurrentItem.Select()

El control DataRepeater es más versátil que el habitual DataGridView, pero es caprichoso como él solo.