Saltar al contenido

RECORDSET


Recommended Posts

publicado

Buenos compañer@s, a ver si me podéis ayudar con esta macro. En esencia se conecta al AS400 de mi empresa (previa vista generada) y me trae datos a través de una consulta SQL. La macro funciona bien y no tengo problemas. El tema es que no sé trabajar recorriendo el  RECORDSET y me toca ingeniármelas con un bucle Do Loop para que me vaya generando los datos que quiero. Os detallo la macro y las celdas donde me trae los datos. Lo que me gustaría es poder establecer el rango("C5:C18") de alguna forma en el RECORDSET para que lo hiciese de golpe y no recorriendo celda a celda. Asimismo, si por ejemplo, quisiese ampliar el rango de la matriz de datos y meter, por ejemplo, en D3 el mes 11, en D4 el mes 12, que me trajese los datos.

Muchas gracias

imagen.png.862e9b48a63faa8dc696fbc7e2ab43dd.png

 

Option Explicit
Option Base 1

Public Sub VENTAS_SECCION_MES()

Dim sql As String, SheetName As String
Dim AÑO, CENTRO, SECCION, MES As String

Sheets("Ventas").Select
Range("C5").Select

Do Until ActiveCell.Offset(0, -1) = ""

AÑO = Range("C2").Value
CENTRO = Range("A3").Value
MES = Range("C3").Value
SECCION = ActiveCell.Offset(0, -2).Value

Application.Cursor = xlWait
Dim wb As Workbook, ws As Worksheet

'Venta de un año, un mes, una tienda y una sección
sql = _
"SELECT SUM(TOT_VENTAS) AS TOTAL_VENTAS " & _
  "FROM PRESUPUESTO_VENTAS " & _
 "WHERE ANYO = " & AÑO & " AND COD_CC = " & CENTRO & " AND SECCION= " & SECCION & " AND MES= " & MES & " "

SheetName = "Ventas"

Set wb = ActiveWorkbook

Set ws = wb.ActiveSheet
ws.Name = SheetName


' Poner los datos particulares de la conexión

Dim Con As New ADODB.Connection
Con.Open "provider=IBMDA400;data source=172.16.1.1;Default Collection=-------;USER ID=-----;PASSWORD=-------;"


DownloadQuery Con, sql, SheetName

ActiveCell.Offset(1, 0).Select

Con.Close

Loop

Set Con = Nothing
Set wb = Nothing
Set ws = Nothing

Application.Cursor = xlDefault

End Sub


Private Sub DownloadQuery(Con As ADODB.Connection, sql As String, SheetName As String)

Dim Cmd As ADODB.Command
Dim Rs As ADODB.Recordset

Set Cmd = New ADODB.Command
Set Cmd.ActiveConnection = Con
Cmd.CommandText = sql

Dim ws As Worksheet, fld As ADODB.Field

Set ws = Worksheets(SheetName)

Set Rs = Cmd.Execute()


' Me trae el dato de la Consulta SQL

ActiveCell.CopyFromRecordset Rs

Set fld = Nothing
Set Rs = Nothing

End Sub

 

imagen.png

publicado

Armando, sube el archivo de ejemplo.

No creo que nadie te quiera ayudar si le haces introducir a mano todos esos datos...

Gracias.

publicado

Hola

Es complicado terminar de entenderte sin tener acceso a tu base de datos. Sugiero colocar en una hoja de Excel una copia fiel de una parte de los registros de la tabla "PRESUPUESTO_VENTAS" para poder entender tu bucle y lo de los parámetros usados en la sentencia SQL. No olvidar una mejor y detallada explicación. OJO, repito, parte de los datos de la tabal, tal cual, no de los datos extraídos como has adjuntado.

publicado
'Option Explicit
Option Base 1

Public Sub VENTAS_SECCION_MES()

Dim SheetName As String
Dim strConectar As String
Dim ws As Worksheet
Dim wb As Workbook
Dim Cmd As ADODB.Command
Dim Rs As ADODB.Recordset

Application.ScreenUpdating = False
Sheets("Ventas").Select
'Range("C5").Select



    Application.Cursor = xlWait


    SheetName = "Ventas"

    Set wb = ActiveWorkbook

    Set ws = wb.ActiveSheet
    ws.Name = SheetName


    ' Poner los datos particulares de la conexión

    Dim Con As New ADODB.Connection

    Con.Open "provider=IBMDA400;data source=172.16.1.1;Default Collection=-----;USER ID=---;PASSWORD=------;"
'      Dim Con As New ADODB.Connection
'     strConectar = ThisWorkbook.Path & "\BDVentas.mdb"
'      With Con
'   .ConnectionString = _
'      "Provider=Microsoft.ACE.OLEDB.12.0"
'   .Open "Provider=Microsoft.Jet.OLEDB.4.0; " & _
'     "Data Source=" & strConectar & ";" & _
'     "Jet OLEDB:Database Password=Ventas"
'   End With


 Set ws = Worksheets(SheetName)

 Set Rs = New ADODB.Recordset
    Rs.Open "PRESUPUESTO_VENTAS", Con, adOpenKeyset, adLockOptimistic, adCmdTableDirect

' Me trae el dato de la Consulta SQL
'ActiveCell.CopyFromRecordset Rs

        'LimpiaRango
    ws.Range("C5:C18").ClearContents

    Rs.MoveFirst
    Do While Not Rs.EOF
        dFecha = Rs.Fields(12) 'Año
        wsFecha = Val(ws.Range("C2"))
        dCentro = Rs.Fields(2) 'Centro
        wsCentro = Val(ws.Range("A3"))
        dSeccion = Rs.Fields(5) 'Seccion
        
        dMes = Rs.Fields(15) 'Mes
        wsMes = Val(Range("C3"))
        
        For I = 5 To 18
        wsSeccion = Val(Range("A" & I))
        If dSeccion = wsSeccion And dMes = wsMes Then
            If dFecha = wsFecha And dCentro = wsCentro Then
                If Val(ws.Range("A" & I)) = Rs.Fields(5) Then
                   Valor = Val(ws.Range("C" & I)) + Rs.Fields(9)
                   ws.Range("C" & I) = Valor
                End If
                    
               
            End If
        End If
        Next I
    Rs.MoveNext
    Loop

Con.Close
Set Rs = Nothing
Set Con = Nothing
Set wb = Nothing
Set ws = Nothing




Application.Cursor = xlDefault
Application.ScreenUpdating = True
End Sub

Hola a todos, revisa este código adjunto, lo he corrido en un archivo de access. Tienes que ver como esta su base de datos los campos afectados deben ser números.

publicado

Muchas gracias César.  Me conecto al curro y me pongo con ello.

Da gusto que gente como vosotros (todos los del foro que entendéis a fondo VBA) nos ayudéis al resto a mejorar. Esto no tiene precio. En serio.

publicado

Buenas de nuevo, me da fallo pero entiendo que es porque algo estoy haciendo mal.

imagen.thumb.png.103f8de13773100491af9d3b5b1db9b1.png

 

Creo que para mi sería más fácil trabajarlo sobre la estructura del módulo que tenía inicialmente. Tener en cuenta que me estoy metiendo ahora en este tipo de programación (atacar desde excel bbdd ) y estoy muy verde.

Muchas gracias y disculpar

publicado
'Option Explicit
Option Base 1

Public Sub VENTAS_SECCION_MES()

Dim sql As String, SheetName As String
Dim AÑO, CENTRO, SECCION, MES As String
Dim strConectar As String
Sheets("Ventas").Select
Range("C5").Select
Application.ScreenUpdating = False

    AÑO = Range("C2").Value
    CENTRO = Range("A3").Value
    MES = Range("C3").Value
    SECCION = ActiveCell.Offset(0, -2).Value
    
    'Application.Cursor = xlWait
    Dim wb As Workbook, ws As Worksheet
    
    'Venta de un año, un mes, una tienda y una sección

    sql = "SUM[TOT_VENTAS]) AS TOTAL_VENTAS FROM PRESUPUESTO_VENTAS WHERE,[ANYO] = 'AÑO'), AND ([COD_CC] = 'CENTRO'), AND ([SECCION] = 

   
    SheetName = "Ventas"
    
    Set wb = ActiveWorkbook
    
    Set ws = wb.ActiveSheet
    ws.Name = SheetName
    
    
    ' Poner los datos particulares de la conexión
    
    Dim Con As New ADODB.Connection
    Con.Open "provider=IBMDA400;data source=172.16.1.1;Default Collection=-----;USER ID=---;PASSWORD=------;"
    
    DownloadQuery Con, sql, SheetName
    

    
    Con.Close



Set Con = Nothing
Set wb = Nothing
Set ws = Nothing

Application.Cursor = xlDefault
Application.ScreenUpdating = False
End Sub


Private Sub DownloadQuery(Con As ADODB.Connection, sql As String, SheetName As String)

Dim Cmd As ADODB.Command
Dim Rs As ADODB.Recordset

Set Cmd = New ADODB.Command
Set Cmd.ActiveConnection = Con
Cmd.CommandText = sql

Dim ws As Worksheet, fld As ADODB.Field

Set ws = Worksheets(SheetName)

'Set Rs = Cmd.Execute()
        
Set Rs = New ADODB.Recordset
    Rs.Open "PRESUPUESTO_VENTAS", Con, adOpenKeyset, adLockOptimistic, adCmdTableDirect

' Me trae el dato de la Consulta SQL

'ActiveCell.CopyFromRecordset Rs
        'LimpiaRango
    ws.Range("C5:C18").ClearContents

    Rs.MoveFirst
    Do While Not Rs.EOF
        dFecha = Rs.Fields(12) 'Año
        wsFecha = Val(ws.Range("C2"))
        dCentro = Rs.Fields(2) 'Centro
        wsCentro = Val(ws.Range("A3"))
        dSeccion = Rs.Fields(5) 'Seccion
        
        dMes = Rs.Fields(15) 'Mes
        wsMes = Val(Range("C3"))
        
        For I = 5 To 18
        wsSeccion = Val(Range("A" & I))
        If dSeccion = wsSeccion And dMes = wsMes Then
            If dFecha = wsFecha And dCentro = wsCentro Then
                If Val(ws.Range("A" & I)) = Rs.Fields(5) Then
                   Valor = Val(ws.Range("C" & I)) + Rs.Fields(9)
                   ws.Range("C" & I) = Valor
                End If
                    
               
            End If
        End If
        Next I
    Rs.MoveNext
    Loop


Set fld = Nothing
Set Rs = Nothing

End Sub

Hola, trata de declarar las variables.

publicado

Saludos @ArmandoR, prueba asi

Option Explicit
Option Base 1

Public Sub VENTAS_SECCION_MES()

    Dim sql As String, SheetName As String
    Dim AÑO, CENTRO, SECCION, MES As String
    
    Sheets("Ventas").Select
    
    AÑO = Range("C2").Value
    CENTRO = Range("A3").Value
    MES = Range("C3").Value
    
    Application.Cursor = xlWait
    Dim wb As Workbook, ws As Worksheet
    
    'Venta de un año, un mes, una tienda y una sección
    sql = _
    "SELECT SECCION, SUM(TOT_VENTAS) AS TOTAL_VENTAS " & _
      "FROM PRESUPUESTO_VENTAS " & _
     "WHERE ANYO = " & AÑO & " AND COD_CC = " & CENTRO & " AND MES = " & MES & " " & _
     "GROUP BY SECCION"
    
    SheetName = "Ventas"
    
    Set wb = ActiveWorkbook
    
    Set ws = wb.ActiveSheet
    ws.Name = SheetName
    
    
    ' Poner los datos particulares de la conexión
    
    Dim Con As New ADODB.Connection
    Con.Open "provider=IBMDA400;data source=172.16.1.1;Default Collection=-------;USER ID=-----;PASSWORD=-------;"
    
    
    DownloadQuery Con, sql, SheetName
    
    Con.Close

    Set Con = Nothing
    Set wb = Nothing
    Set ws = Nothing
    
    Application.Cursor = xlDefault

End Sub


Private Sub DownloadQuery(Con As ADODB.Connection, sql As String, SheetName As String)

    Dim Cmd As ADODB.Command
    Dim Rs As ADODB.Recordset
    Dim nFilFin As Double
    Dim rCelda As Range
    Dim nSeccion As Double
    
    Set Cmd = New ADODB.Command
    Set Cmd.ActiveConnection = Con
    Cmd.CommandText = sql
    
    Dim ws As Worksheet, fld As ADODB.Field
    
    Set ws = Worksheets(SheetName)
    
    Set Rs = Cmd.Execute()
    
    nFilFin = ws.Range("A" & Rows.Count).End(xlUp).Row
    
    ' Me trae el dato de la Consulta SQL
    
    Do While Not Rs.EOF
        nSeccion = Rs.Fields("SECCION") 'Seccion
        
        For Each rCelda In ws.Range("A5:A" & nFilFin)
            If CDbl(rCelda.Value) = nSeccion Then
                rCelda.Offset(0, 2).Value = Rs.Fields("TOTAL_VENTAS")
                Exit For
            End If
        Next
        Rs.MoveNext
    Loop
    
    
    Set fld = Nothing
    Set Rs = Nothing

End Sub

el cambio lo realice sobre tu codigo del primer mensaje, recuerda que sin la base de datos es mas complicado, en esencia es lo mismo, realizas la consulta agrupando por SECCION y luego simplemente buscas cada SECCION en la tabla y colocas su total

 

publicado

Me funciona a la perfección

Muchas gracias por vuestro asesoramiento.

Vuelvo a repetirlo, es un placer estar en un foro como este con gente tan profesional y altruista como vosotros

 

 

Archivado

Este tema está ahora archivado y está cerrado a más respuestas.

  • 109 ¿Te parecen útiles los tips de las funciones? (ver tema completo)

    1. 1. ¿Te parecen útiles los tips de las funciones?


      • No
      • Ni me he fijado en ellos

  • Ayúdanos a mejorar la comunidad

    • Donaciones recibidas este mes: 0.00 EUR
      Objetivo: 130.00 EUR
  • Archivos

  • Estadísticas de descargas

    • Archivos
      187
    • Comentarios
      97
    • Revisiones
      28

    Más información sobre "Un juego del Rabino en Excel"
    Última descarga
    Por pegones1

    1    1

  • Crear macros Excel

  • Mensajes

    • Hola nuevamente. Por eso la importancia de lo que mencionas tú como "ruta relativa". Tal cual comentas, y aún sin llegar a algunos detalles importantes para ayudarte, en realidad tal cual te comenté le día miércoles, pues sí podías hacer como comentabas, era cosa de obtener los Id de Windows (como tú los llamas) y la ruta de OneDrive en casa usuario y eso sí se puede obtener con VBA y luego pasarlo a PQ, pero medio que te cerraste en que "PQ no puede trabajar con rutas relativas", cosa cierta pero siempre hay formas. Si SAP puede o no guardar en OneDrive o SharePoint, pues si está mapeado en la PC ¡claro que se puede! Pero bueno, creo que si te es útil tu propia propuesta ¡avanza con eso!
    • Perdona @Abraham Valencia pero he estado liado estos días. En realidad todo el problema se reduce a estos dos problemas: Problema 1: El script que "fabrica" SAP y que luego "pego" en la macro, no es capaz de  guardar archivos en SharePoint. He estado buscando, y en realidad muchas personas tienen ese problema (no poder guardar un Excel en SAP a través de VBA). Eso muy probablemente sean problemas de permisos, que no puedo cambiar (no soy administrador de nada). Como no puedo solucionarlo así, paso al plan B, que es guardar en Excel que me genera SAP en el ordenador de cada usuario que ejecute la plantilla (y que sí está guardada en SharePoint), para después con PowerQuery llamar a ese Excel (el export). Para ello, pretendo guardar el export, en la ruta relativa "C:\..\..\..\OneDrive - NombreEmpresa\Documentos\SAP\SAP GUI" donde los \..\..\..\ saltan las rutas personales de cada usuario (tipo C:\users\IDusuario\). Eso lo hace bien, y el archivo se guarda en la ruta de cada usuario que lo usa, pero surge el problema 2 Problema 2: PowerQuery no trabaja con rutas relativas del tipo  "C:\..\..\..\OneDrive - NombreEmpresa\Documentos\SAP\SAP GUI" necesita que sea del tipo fija "C:\users\IDusuario\OneDrive - NombreEmpresa\Documentos\SAP\SAP GUI" pero claro, IDusuario es diferente para cada usuario.   Pero escribiendo todo esto, creo que he dado con una posible solución, no grabar el export en una ruta de usuario, sino en una en la raiz de C:, que siempre será igual para todos los usuarios, del tipo C:\Sap\export.xlsx que seria igual en todos los ordenadores. Asi sí podría decirle a PowerQuery que vaya siempre a la ruta C:\Sap\ que existirá en todos los ordenadores. Mañana intentaré hacer pruebas, aunque mi solución ideal seria que se pudiera guardar en el SharePoint. Saludos.
    • Hola La opción brindada por @torquemada es correcta, funciona, pero hay algunos inconvenientes que (desde mi punto de vista) no la convierten en mi primera elección. Los inconvenientes son: Tendrías que ir columna por columna haciendo los reemplazos, claro que no se harían a mano sino que utilizarías la opción reemplazar o la opción texto en columnas, aun asi demorará un poquito y será trabajoso. Cada vez que descargues otro listado, tendrás que volver a realizar los reemplazos. Me parece una mejor propuesta lo siguiente: Descarga los movimientos a un archivo de Excel Desde tu control de pagos (otro archivo) cargas los movimientos del archivo descargado mediante Power Query Power Query hará los reemplazos y reconocerá todo correctamente (sin que tengas que hacer nada especial) Cuando descargues los movimientos un día posterior, solamente tendrás que hacer clic en "Actualizar" y todo funcionará en automático
    • Hola a todos, Efectivamente, me temo que tal como trabajan las funciones =HOY() y/o =AHORA() (volátiles), sólo con macros puedes obtener soluciones. Un recurso pedestre podría ser, cada vez que quieras que se fije un dato, te sitúes en esa celda y pulses F2, F9 e INTRO.  Pero claro, puede ser un inconveniente si hay que hacerlo repetitivamente en muchas ocasiones,.............. en fin, lo comento sólo como posibilidad. Saludos,
    • Hola nuevamente, mi duda sigue siendo la ruta, o rutas, finales que quedan, esas que llamas "relativas"; igual por si acaso pon 3 o 4 de esas, tal cual son y/o se ven en el explorador de cada PC y, de ser posible, en cualquier otro "lado" en que las veas.
  • Visualizado recientemente

    • No hay usuarios registrado para ver esta página.
×
×
  • Crear nuevo...

Información importante

Echa un vistazo a nuestra política de cookies para ayudarte a tener una mejor experiencia de navegación. Puedes ajustar aquí la configuración. Pulsa el botón Aceptar, si estás de acuerdo.