Array para leer una tabla con muchos campos

Tengo una tbl con 331 campos y querría recorrerlos para poder extraer la información y operar con ellos. En un primero momento había pensado hacerlo con un bucle anidado. Pero creo que sería más eficiente y rápido con una array, pero aun no me manejo muy bien con ellas.

2 respuestas

Respuesta
2

Carlos: Cuando te iba a contestar he visto la respuesta James (un saludo), que es aplicable a Excel, aunque da una idea.

De otro lado y como cuestíon previa, creo que no puedes tener 331 campos en una Tabla de Access, a no ser que hayan cambiado las especificaciones hace muy poco tiempo.

Independiente de eso, te cito un enlace que pone de manifiesto la captura y visualización de los datos de un Recordset sobre una Tabla.

https://stackoverflow.com/questions/24405409/access-vba-array-by-looping-through-recordset

El Recordset que cita Rs1 no lo de clara explicitamente y tu debes hacerlo sobre tu Tabla.

Un saludo >> Jacinto

Hola Jacinto,

La tabla que tengo es de 231 campos (el max permitido es de 255) rectifico mi error.  La array que busco seria para ACCESS, en el enlace sino me equivoco el ejemplo hace mención a un campo especifico de "rs1!country" y lo que necesitaría sería recorrer todos los campos de la tabla sin indicar el numero que hay ni el numero de registros. Algo así (pero este código solo me encuentra tres campos y un registro y yo quiero que le recorra todos y me devuelva los registros con sus campos):

Dim cnn As Database
Dim rs As Recordset
Dim A As Variant, bytStart As Byte

Set cnn = CurrentDb
Set rs = cnn.OpenRecordset("Plan Calendario")

A = Array(rs.Fields(0).name, rs.Fields(1).name, rs.Fields(2).name, rs.Fields(3))
For bytStart = 0 To 3
Debug.Print A(bytStart)
Next
rs.Close
Set cnn = Nothing

Carlos: Si quieres trasladar "TODOS" los datos de una tabla a una Matriz, la forma sería como ésto, teniendo en cuenta que tu tabla se llame Plan Calendario. Mi sugerencia es que le quites el "espacio" y a lo largo del código que puedas escribir te causará menos problema >> PLanCalendario, y así te lo pongo en lo que te cito a continuación.

Public Sub LlenaMatrizConDatosTabla()
Dim QryDatos As String
Dim RstDatos As DAO.Recordset
Dim StrDatos As String
Dim I As Long
Dim MatrizDatos As Variant
QryDatos = "SELECT * FROM PlanCalendario;"
Set RstDatos = CurrentDb.OpenRecordset(QryDatos, dbOpenSnapshot)
If Not RstDatos.EOF And Not RstDatos.BOF Then
        RstDatos.MoveLast
        RstDatos.MoveFirst
        Do While Not RstDatos.EOF
                 For I = 0 To RstDatos.Fields.Count - 1
                        StrDatos = StrDatos & RstDatos.Fields(I).Value & " | "
                Next I
                RstDatos.MoveNext
                DoEvents
        Loop
Else
End If
'Quito los 3 últimos caraceres a la cadena de datos
StrDatos = Left(StrDatos, Len(StrDatos) - 3)
MsgBox "La cadena resultante es: " & StrDatos  'Es un mensaje de Seguimiento
MatrizDatos = Split(StrDatos, " | ")
End Sub

Para llamar a ese procedimiento desde cualquier parte lo puedes hacer con >>

Call LlenaMatrizConDatosTabla

Se puede simplificar un poco, quizá alguna línea, pero he preferido undesglose paso a paso para una mejor comprensión. Co eso tendrás la Matriz llena, y lo que quieras hacer con ella dependerá de tus necesidades. Un saludo >> Jacinto

Gracias Jacinto por contestar y por la esquematización del código, tiene una presentación muy detallada (Se que no hay que no es recomendable dejar espacios en los nombre de tablas o consultas, pero en la BBDD que llevo 2 años trabajando ya contiene muchos objetos y cada vez cuesta clasificar los objetos al no poder hacerlo por carpetas. Por ello decidí usar espacios para poder clasificar los objetos.

Como podría leer también los nombres de los campos,  para poder usar un if o un Select Case para seleccionar los nombres de los campos que necesite. Hay un campo que es el número de semana y el resto de campos su nombre indica el número de maquina, el día y el turno: "M1_Lun_M", "M1_Lun_T"," M1_Lun_N", "M2_Mar_M", "M2_Mar_T", "M2_Mar_N".................. Todos los campos los cree con una bucle anidado y tienen una ordenación lógica para poder trabajarlos dentro de tu código. 

Voy a intentar explicar hasta donde yo pudo algunas de las partes de tu código que quiero resaltar.

Dim I As Long      'Tipo long para evitar desbordamiento

Dim MatrizDatos As Variant 'Varian para recorrer todo tipo de campos 

If Not RstDatos.EOF And Not RstDatos.BOF Then 'Creo que intentas asegurar que EOF y BOF sean false para asegurar que el RstDatos no de error por falta de datos. Pero no entiendo porque hay que usar los dos EOF y BOF (Falta de experiencia por mi parte)

Do While Not RstDatos.EOF 'Sigue recorriendo Mientras no llegue al final de RstDatos.                                                                    Supongo que nos movemos en la array de forma horizontal.
        For I = 0 To RstDatos.Fields.Count - 1 'Con este bucle For le decimos que recorra el bucle                                                                                  de forma vertical

        Next I  
       RstDatos.MoveNext
       DoEvents   'No comprendo muy bien esta función dentro del bucle. He leído la ayuda de 

                           Microshoft y no termino de asociarlo. 

Loop

MatrizDatos = Split(StrDatos, " | ") ' No termino de entender la utilización de Split. La definición es: Devuelve una matriz de base cero unidimensional que contiene un número especificado de subcadenas. Parece que busque "|" para concatenar el siguiente registro.

Disculpa mis dudas y muchas gracias por tu trabajo 

Carlos: Te comento en primer lugar lo que considero más transcendente para llenar de datos esa Matriz "discriminando" campos. Laidea es que en el Bucle For....Next pongas >>

For I = 0 To RstDatos.Fields.Count – 1
   If RstDatos.Fields(I).Name = "DiaSem" Or Left(RstDatos.Fields(I).Name,1) ="M" Then
       StrDatos = StrDatos & RstDatos.Fields(I).Value & " | "
   End If
Next 

La idea como ves es diciendole  que si el Campo se llama DiaSem (Tu campo) o comienza por M que lo pase a la Cadena de valores y si no es así que salte a otro Campo. Ojo si tienes otros Campos que comiencen por M.

El resto de cuestiones que me citas, como >>

Long >> Para lo que comentas.

Mariz Datos >> En éste caso podría ser String.

El Do While  >> Es una manera >> Otra puede ser

If RstDatos.RecordCount > 0 Then.. o  RstDatos.RecordCount = 0 Then Exit Sub

Y luego >> While ......Wend o Do Until RstDatos.EOF .... Loop o ....

Una explicación más amplia de lo que te comento, lo puedes ver en el Capitulo 4 del curso de VBA de Neckkito.

http://neckkito.xyz/nck/index.php/manuales/47-curso-vba 

Para el Split, mira éste enlace que tiene Ejemplos >>

https://www.techonthenet.com/access/functions/string/split.php 

Dicho todo ésto tu debes saber mejor que nadie como tienes los datos, y si realmente necesitas una Matriz, o es mejor llenar una Tabla temporal o una consulta. No te puedo sugerir una opción u otra porque no tengo los objetos y estructura delante.

Espero te oriente en la solución del problema que tengas. Un Saludo >> Jacinto

Hola Jacinto,

No me quedo claro la utilización de la función DoEvents y la ultima pregunta sería porque usas

RstDatos.MoveLast
RstDatos.MoveFirst

Funciona a la perfección y lo has explicado muy bien. 

Gracias

Carlos: En síntesis DoEvents >> Devuelve el control al sistema operativo y en ocasiones evita que se cuelgue el sistema y permite abortar un proceso si es muy lento.

https://support.office.com/es-es/article/funci%C3%B3n-doevents-7af41eca-88e0-470d-adaf-0b3d4c2575b0 

El hacer >> el MoveLast y MoveFirst, también es una especie de seguro, que obliga ha hacer una prueba de "Recorrido" del Recordset (de Lectura). Aunque solo haya sido en ocasiones puntuales, me he encontrado con el Mensaje >> ... No hay ningún Registro Activo, cuando yo sabía que el Recordset los tenía. Hace años que adopte esa medida, pero soy consciente de su inutilidad en la mayoría de las ocasiones.

Basta con el MoveFirst. Yo conservo ese vicio. Que le vamos a hacer. Un saludo >> Jacinto

Respuesta
1

No das mucho detalle de lo que quieres hacer y es cierto con un array puedes mejorar mucho el desempeño de una macro, en la primera instrucción se crea una matriz de datos llamada datos en esta matriz la instrucción cargara todas las filas y columnas seguidas hasta donde encuentre una fila o columna en blanco, la segunda instrucción es para convertir tus datos a un objeto llamado datos, la diferencia entre ambas instrucciones es que con la segunda le puedes ir asignado todas las propiedades de excel como formateo, colores, sorteo, convertirla a tabla o crear tablas dinámicas, la combinación de ambas da como resultado macros bastante sencillas y poderosas.

Sub crear_array()
datos = Range("a3").CurrentRegion
Set datos = Range("a3").CurrentRegion
End Sub

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas