** NORMAS DEL FORO **
Inicio del foro Inicio del foro > Access y VBA > Access y VBA
  Mensajes nuevos Mensajes nuevos RSS - Concatenar registros de un campo
  Preguntas frecuentes Preguntas frecuentes  Buscar en el foro   Eventos   Registro Registro  Iniciar sesion Iniciar sesion

Tema cerradoConcatenar registros de un campo

 Responder Responder
Autor
Mensaje
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Tema: Concatenar registros de un campo
    Enviado: 01/Junio/2016 a las 11:52

Hola:

Tengo una aplicación con dos tablas principales: Alumnos (Clave primaria Clave alumno) y Cursos (Clave primaria Código Curso) y luego una relación entre ellas que es la tabla Acciones formativas cuya clave primaria la forman las dos claves primarias de Alumnos y de Cursos y que refleja la asistencia a un determinado curso por un determinado alumno y en la que guardo, entre otras cosas las valoraciones que ese alumno ha hecho de ese curso (cuatro notas numéricas y un campo de Observaciones)

He preparado una consulta (y un informe) que me hacen el resumen anual de todos los cursos con sus datos fundamentales y sus notas medias, número de asistentes, coste, etc. La consulta que he utilizado es:

SELECT Curso.[Título del curso], Curso.Duración, Curso.Organismo, Curso.Emplazamiento, Curso.[Importe abonado], Avg([Acciones formativas].[Organización General]) AS [PromedioDeOrganización General], Avg([Acciones formativas].Formadores) AS PromedioDeFormadores, Avg([Acciones formativas].[Materiales, medios e instalaciones]) AS [PromedioDeMateriales, medios e instalaciones], Avg([Acciones formativas].Satisfacción) AS PromedioDeSatisfacción, Count([Acciones formativas].[Clave alumno]) AS [CuentaDeClave alumno]

FROM Curso INNER JOIN [Acciones formativas] ON Curso.[Código Curso] = [Acciones formativas].[Clave curso]

GROUP BY Curso.[Título del curso], Curso.Duración, Curso.Organismo, Curso.Emplazamiento, Curso.[Importe abonado], [Acciones formativas].[Clave curso], Curso.Realizado, [Acciones formativas].Valorada

HAVING (((Curso.Realizado)=Yes) AND (([Acciones formativas].Valorada)=Yes))

ORDER BY [Acciones formativas].[Clave curso];

Pero me gustaría que, para cada curso, además me concatenara los campos Observaciones de todos los alumnos que han hecho ese curso….Y no sé cómo atacar este problema.

¿Alguna ayuda?

Josss

Arriba
OmniPresente Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 10/Febrero/2009
Localización: España
Estado: Sin conexión
Puntos: 1870
Enlace directo a este mensaje Enviado: 01/Junio/2016 a las 13:05
Yo lo haría con una función a la que se le pasase un identificador de curso y devolviese una "ristra" con  los campos observaciones concatenados... ¿controlas VBA?

Un saludo.


Editado por OmniPresente - 01/Junio/2016 a las 13:05
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 01/Junio/2016 a las 13:16
Mmmmm ....  pues me temo que no....

Josss
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 01/Junio/2016 a las 17:45
He probado algo parecido a lo que he sacado de esta antigua consulta de raipon: http://microsoft.public.es.access.narkive.com/81sUTswA/agrupar-valores-de-varios-registros-en-un-campo

Con lo que he escrito la función como:

Option Compare Database

Public Function Observar(Curso As String) As String
    Dim rsp As New ADODB.Recordset
    rst.Open "Select Observaciones From [Acciones formativas] where [Clave curso]=" & Curso, CurrentProject.Connection, adOpenStatic, adLockReadOnly
    Do Until rst.EOF
     If Observar = "" Then
         Observar = rst.Fields(0)
         Else
         Observar = Observar & ";" & rst.Fields(0)
     End If
     rst.MoveNext
    Loop
    rst.Close
End Function

Y la consulta como:

SELECT Curso.[Título del curso], Curso.Duración, Curso.Organismo, Curso.Emplazamiento, Curso.[Importe abonado], Avg([Acciones formativas].[Organización General]) AS [PromedioDeOrganización General], Avg([Acciones formativas].Formadores) AS PromedioDeFormadores, Avg([Acciones formativas].[Materiales, medios e instalaciones]) AS [PromedioDeMateriales, medios e instalaciones], Avg([Acciones formativas].Satisfacción) AS PromedioDeSatisfacción, Count([Acciones formativas].[Clave alumno]) AS [CuentaDeClave alumno],Observar([Acciones formativas]![Clave curso]) AS OBS
FROM Curso INNER JOIN [Acciones formativas] ON Curso.[Código Curso] = [Acciones formativas].[Clave curso]
GROUP BY Curso.[Título del curso], Curso.Duración, Curso.Organismo, Curso.Emplazamiento, Curso.[Importe abonado], [Acciones formativas].[Clave curso], Curso.Realizado, [Acciones formativas].Valorada
HAVING (((Curso.Realizado)=Yes) AND (([Acciones formativas].Valorada)=Yes))
ORDER BY [Acciones formativas].[Clave curso];

Pero de entrada me dice que "La función 'Observar' no está definida en la expresión"  así que parece que ni siquiera la lee....

Josss
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 02/Junio/2016 a las 17:45
¿Sabéis por qué me dice que la función "Observar" no está definida en la expresión si la he definido como Public?

Josss
Arriba
VIMIPAS Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 06/Enero/2006
Localización: ESPAÑA
Estado: Sin conexión
Puntos: 5419
Enlace directo a este mensaje Enviado: 02/Junio/2016 a las 21:48
Hola Josito, buenas noches.

Yo probaría esto a ver si te lo soluciona:

Public Function Observar(Curso As String) As String
    Dim rsp As New ADODB.Recordset
    rst.Open "Select Observaciones From [Acciones formativas] where [Clave curso]=" & Curso, CurrentProject.Connection, adOpenStatic, adLockReadOnly
    Do Until rst.EOF
'''     If Observar = "" Then
      If Len(nz(Curso,""))=0 Then
         Observar = rst.Fields(0)
         Else
         Observar = Observar & ";" & rst.Fields(0)
     End If
     rst.MoveNext
    Loop
    rst.Close
End Function

Ya nos cuentas.

Saludos
Gracias
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 03/Junio/2016 a las 11:12
Hola: Por lo que entiendo me sugieres cambiar la sentencia If....

Lo he hecho y me sigue diciendo lo mismo "La función 'Observar' no está definida en la expresión.

Sigo sin entender por qué no la reconoce si la he definido como public.....

Josss
Arriba
E. Feijoo Ver desplegable
Moderador
Moderador


Unido: 16/Abril/2004
Localización: España
Estado: Sin conexión
Puntos: 19948
Enlace directo a este mensaje Enviado: 03/Junio/2016 a las 12:14
Porque Access no espera una función en ese punto, has de 'extraerla' del conjunto para que devuelva el resultado:

.... AS [CuentaDeClave alumno],Observar([Acciones formativas]![Clave curso]) AS OBS
FROM Curso INNER JOIN [Acciones formativas ....

.... AS [CuentaDeClave alumno], '" & Observar([Acciones formativas]![Clave curso]) & "' AS OBS
FROM Curso INNER JOIN [Acciones formativas ....

Aprecia que he añadido comillas simples para indicar que 'es un texto' el origen de datos de 'OSB'.
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 03/Junio/2016 a las 14:16
Hola:

Hemos avanzado!!!, pero no acaba de funcionar. No consigo entender qué es lo que me marcas en rojo. Veo tres comillas, un espacio  y el símbolo & pero no acabo de entender qué he de poner (he probado todas las combinaciones que se me han ocurrido...) ni lo que hace, ni qué busco....Lo que hace es escribirme en el campo correspondiente lo que he puesto entre comillas.....

Siento ser tan torpe!!

Josss
Arriba
lbauluz Ver desplegable
Administrador
Administrador
Avatar

Unido: 29/Marzo/2005
Localización: Binghamton Jail
Estado: Sin conexión
Puntos: 3583
Enlace directo a este mensaje Enviado: 03/Junio/2016 a las 14:32
Hola josito:

Supongamos que en Observar([Acciones formativas]![Clave curso] tienes el valor MATEMÁTICAS

Lo que estás haciendo es
AS [CuentaDeClave alumno],Observar([Acciones formativas]![Clave curso]) AS OBS

Se traduce a la query como 

AS [CuentaDeClave alumno], MATEMÁTICAS AS OBS

El cambio que te propone E. Feijoo es convertir la query en 
AS [CuentaDeClave alumno], 'MATEMÁTICAS' AS OBS


Como ves, al ser una cadena y no un valor, tiene que ir entre comillas.

Eso es lo que te indica E. Feijoo.

Un saludo.

Luis



Editado por lbauluz - 03/Junio/2016 a las 14:32
Hay un culto a la ignorancia y siempre lo ha habido y es alimentado por la falsa noción de que democracia significa que "mi ignorancia es tan buena como su conocimiento". (Isaac Asimov)
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 06/Junio/2016 a las 15:49
Hola:

Gracias por la explicación, aunque sigue sin hacer lo que espero....

Como decía antes, no sé qué escribir cuando E Feijoo me pone ''' & observar...... & '''

Lo he probado de todas las formas que se me ha ocurrido (Primero una comilla ' y luego unas dobles "; al revés; tres comillas sencillas '+'+') y en ningún caso hace nada.

Se limita a escribir en el campo OBS lo que hay detrás de la primera comilla.....

Lo que me ha escrito Luis debería ser algo como: Pongo una comilla simple entre ¿dos comillas simples?, que luego concateno (&) con lo de Observar........ y luego vuelvo a concatenar (&) con otra comilla simple entre ¿dos comillas simples?.

Cuando hago eso me escribe en todos los valores del campo OBS: ' & Observar..... & '

Y lo que espero es que, si en el primer curso, Observar..... me ha concatenado, por ejemplo, tres campos que decían "Brillante", "Genial" y "Un poco largo" que me escriba, en el primer registro "Brillante Genial Un poco largo" y en el segundo lo correspondiente del suyo, etc....

Josss

Arriba
E. Feijoo Ver desplegable
Moderador
Moderador


Unido: 16/Abril/2004
Localización: España
Estado: Sin conexión
Puntos: 19948
Enlace directo a este mensaje Enviado: 06/Junio/2016 a las 18:35
Hay unos mínimos que o se respetan o Access 'hará lo que le de la real gana' (y con toda la razón).

Access EXIGE conocer el tipo de dato para tratarlo de forma correcta, los de texto entre comillas (simples o dobles), los de fecha entre almohadillas (#) y los numéricos 'a pelo'.

Sobre comillas dobles o simples ....
Se aplica una regla básica en la comunicación:
.- Lo definido NO PUEDE formar parte de la definición -.

Si a una cadena de texto la definimos con DOBLES COMILLAS, en base a la regla anterior: no puede haber dentro de esa expresión (que se iniciara con una doble comilla y finalizara con otra doble comilla) una doble comilla, por eso se utiliza en sustitución la comilla simple (hay mas métodos, pero 'este es uno de los mas limpios')

La cuestión es: ¿devuelve algún resultado esa función? ... de ella se espera un texto, texto que como ha de 'entrar en una cadena que se define con doble comilla' no puede utilizar la comilla doble para definirla (porque Access EXIGE que se le informe del tipo de dato)

Al evaluarla (porque esa expresión pasa por un analizador de sintaxis, el motor de Access) Access la interpretaría como (y en base al ejemplo):
... AS [CuentaDeClave alumno], '" & Observar([Acciones formativas]![Clave curso]) & "' AS OBS...

La función devuelve : Brillante Genial Un poco largo   (un TEXTO)

Access lo entiende asi:
... AS [CuentaDeClave alumno], 'Brillante Genial Un poco largoAS OBS...


Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 07/Junio/2016 a las 12:51
Ok. Buenísima la explicación. Gracias!!

De todos modos me parece que aún estoy lejos de solucionar mi problema.... Me explico. Voy a dejar de momento la instrucción SELECT (con sus comillas de todo tipo) y me voy a centrar en la función Observar....

Por lo que he leído en el curso VBA de Eduardo Olaz puedo depurar el código hasta que funcione bien mediante la ventana inmediato. El caso es que si en esa ventana escribo "? Observar(12)" no me concatena los campos, por lo que es lógico que luego el SELECT se líe.... Voy a ver si descubro qué es lo que no funciona de la función.

Al hacer esa prueba, me resalta la instrucción "Dim rst As New ADODB.Recordset" y me dice que "No se ha definido el tipo definido por el usuario".

Josss

P.S.: Y sí, ya me he dado cuenta de que el parámetro de Observar ha de ser un Long y no un String como había puesto al principio....
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 07/Junio/2016 a las 17:33
... Y el caso es que he mirado en Herramientas/Referencias y tengo marcadas:

* Visual Basic for Applications
* Microsoft Access 14.0 Object Library
* OLE Automation
* Microsoft Office 14.0 Access database engine Object Library

No sé qué falla...

Josss
Arriba
Josito Ver desplegable
Habitual
Habitual


Unido: 31/Mayo/2016
Localización: Barcelona
Estado: Sin conexión
Puntos: 102
Enlace directo a este mensaje Enviado: 08/Junio/2016 a las 18:10
Ya está solucionado!!!! Tenía activada DAO y no ADO.

Muchas gracias a todos por las aportaciones.

Josss
Arriba
 Responder Responder
  Compartir tema   

Ir al foro Permisos de foro Ver desplegable