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
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
- Compartir respuesta
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
- Compartir respuesta