Création de table à partir d'une requête sélection SQL en vb

Résolu

Bonjour à vous! :) 

J'ai essayé beaucoup de choses pour y parvenir, mais sans succès.

Ma base de données comprend des tables attachées. Pour arriver à avoir toutes les informations qu'il me faut (notamment le solde à payer du client par année), j'ai créé une requête qui joint plusieurs tables attachées ensemble et qui fait des sommes sur les soldes annuels. Les informations que je récupère à partir des 3 tables attachées sont les suivantes: Numéro de référence du client (Fiche), nom du client, prénom du client, année de la créance, solde annuel et un numéro de l'établissement que je garde caché, car il sert seulement à filtrer mes données.

Donc à partir d'un formulaire, je choisis l'année et l'établissement et je permets aussi des recherches avec le numéro de référence, le nom et le prénom du client. J'appuie sur "Appliquer" et la requête s'exécute avec les critères de recherche. Jusqu'ici tout va bien.

J'ai un besoin particulier qui est le suivant : Je dois pouvoir cocher les clients désirés dans ma requête. Et comme ce n'est pas possible d'ajouter une case à cocher indépendante dans une requête, je dois créer une table temporaire à partir de ma requête. (Si vous avez une autre solution, je suis toute ouïe).

C'est donc ici que ça se complique. Par étape, je crée une nouvelle table temporaire en vba avec dbs.Execute "CREATE TABLE [...]" qui contient toutes les infos nécessaires, sauf le numéro d'établissement que je n'ai plus besoin à ce stade. Et là je dois pouvoir ajouter le résultat de ma requête à cette nouvelle table. Je suis barrée ici. J'ai essayé  avec un OpenRecorset sur ma requête puis dbs.Execute "INSERT INTO" et j'ai toujours une erreur d'exécution 3061 "Trop peu de paramètres. 5 attendus". Est-ce que ça se pourrait qu'on ne puisse pas faire un OpenRecordset avec une requête ? Là j'essaie avec QueryDefs, mais j'ai l'impression de faire n'importe quoi et je ne me comprends plus. Je vous mets ci-dessous mon code vba avec l'OpenRecordset:

'Récupérer les données et remplir la table temporaire
Dim strRechRef As String 'Valeur du numéro de fiche
Dim strRechNom As String 'Valeur du nom
Dim strRechPNom As String 'Valeur du prénom
Dim strRechAnn As String 'Valeur de l'année
Dim MonSolde As String 'Valeur du solde
Dim DecSolde As String 'Valeur du solde avec la virgule replace par un point
Dim strSQL As String

'On Error Resume Next


Dim db As DAO.Database, qdef As DAO.QueryDef, IngRecAff As Long

Dim base As DAO.Database
Dim enr As DAO.Recordset

Set base = CurrentDb
Set enr = base.OpenRecordset("06-01_AVANTGARDE_SOLDE_ANN_DEM_RECH")

enr.MoveFirst

With enr
Do Until .EOF
    
    'Récupérer les valeurs de l'enregistrement
    strRechRef = .Fields("FICHE")
    strRechNom = .Fields("NOM")
    strRechPNom = .Fields("PNOM")
    strRechAnn = .Fields("ANNEE")
    MonSolde = .Fields("SommeDeSOLDE")
    DecSolde = Replace(MonSolde, ",", ".")
MsgBox strRechRef & strRechNom & strRechPNom & strRechAnn & DecSolde
Exit Sub
    'Ajouter l'enregistrement à la table temporaire
    
    Dim dbs2 As Database
    Set dbs2 = CurrentDb
    
    dbs2.Execute "INSERT INTO " & strNTbl & " (SelCreance,RefSyst,NClient,PNClient,Ann,Sold)" _
    & " VALUES (0,'" & strRechRef & "','" & strRechNom & "','" & strRechPNom & "'," & strRechAnn & "," & DecSolde & ");"

    dbs2.Close
    Set dbs2 = Nothing
    Exit Sub
.MoveNext
Loop

End With

enr.Close
base.Close
Set enr = Nothing
Set base = Nothing

J'ai mis un "Exit Sub" dans ma Loop, car il y a beaucoup de données et comme ça ne marche pas, ma Loop s'exécute sans arrêt.

Je ne peux pas faire une requête Ajout manuellement, car mes données sont variables. Mais si je le fais manuellement avec ma requête "06-01_AVANTGARDE_SOLDE_ANN_DEM_RECH", ça fonctionne très bien. Comment faire pour que le résultat soit le même en vba?.. Peut-on faire une requête Ajout en vba faisant en sorte que la création et le remplissage de la table se fasse dans la même étape comme lorsqu'on le fait manuellement?

Merci beaucoup de votre aide, je suis désespérée et j'ai vraiment besoin que ça fonctionne!!! :)  

12 réponses

Résumé de la discussion

La discussion porte sur la gestion des critères de recherche et l’ajout en VBA des résultats d’une requête dans une table temporaire pour obtenir le solde à payer du client par année. La solution efficace consiste à gérer les champs vides en remplaçant les critères par IS NOT NULL ou LIKE et à construire une requête SQL dynamique qui alimente la table temporaire en une seule étape. En pratique, tester la requête directement et utiliser une INSERT INTO pour récupérer les résultats dans la table cible évite l'erreur 3061 et assure la cohérence des données. D'autres ajustements permettent d'éviter les NULL et d'assurer des critères optionnels, par exemple en pré-remplissant les valeurs ou en adaptant dynamiquement les conditions du HAVING.

Bobot (l’IA à votre service)
  1. Bonjour yg_be,

    Ça fonctionne enfinnnnnn!!!

    Je suis extrêmement contente!

    J'ai du adapter le code lorsque les champs de recherche sont vides pour qu'il prenne en considération "IS NOT NULL", mais tout marche à la perfection!

    Voici le code final:

    Dim base As DAO.Database
    Dim enr As DAO.Recordset
    Dim rstemp As DAO.Recordset
    Dim SqlD As String
    
    'Valeurs de recherche
    Dim strRechRef As String 'Valeur du numéro de fiche
    Dim strRechNom As String 'Valeur du nom
    Dim strRechPNom As String 'Valeur du prénom
    
    'Remplacer la valeur recherchée par IS NOT NULL si aucun critère n'est entré dans le champ de recherche
    If IsNull([Forms]![03-B1_Ajout_Creance_AVG].[Texte16]) Then
    strRechRef = "IS NOT NULL"
    Else
    strRechRef = "Like '*" + CStr([Forms]![03-B1_Ajout_Creance_AVG].[Texte16]) + "*'"
    End If
    
    If IsNull([Forms]![03-B1_Ajout_Creance_AVG].[Texte18]) Then
    strRechNom = "IS NOT NULL"
    Else
    strRechNom = "Like '*" + CStr([Forms]![03-B1_Ajout_Creance_AVG].[Texte18]) + "*'"
    End If
    
    If IsNull([Forms]![03-B1_Ajout_Creance_AVG].[Texte58]) Then
    strRechPNom = "IS NOT NULL"
    Else
    strRechPNom = "Like '*" + CStr([Forms]![03-B1_Ajout_Creance_AVG].[Texte58]) + "*'"
    End If
    
    
    
    Set base = CurrentDb
    
    SqlD = "SELECT [dbo_SDG_E_FACT].[FICHE], [dbo_SDG_E_ELE].[NOM], [dbo_SDG_E_ELE].[PNOM], [dbo_SDG_E_FACT].[ANNEE], Sum([dbo_SDG_E_FACT].[SOLDE]) AS [SommeDeSOLDE]" & _
    " FROM ([dbo_SDG_E_FACT] INNER JOIN [04-ETABLISSEMENTS] ON [dbo_SDG_E_FACT].[ID_SDG] = [04-ETABLISSEMENTS].[NoSdgAG]) INNER JOIN [dbo_SDG_E_ELE] ON [dbo_SDG_E_FACT].[FICHE] = [dbo_SDG_E_ELE].[FICHE] " & _
    " GROUP BY [dbo_SDG_E_FACT].[FICHE], [dbo_SDG_E_ELE].[NOM], [dbo_SDG_E_ELE].[PNOM], [dbo_SDG_E_FACT].[ANNEE], [04-ETABLISSEMENTS].[NoEtablissement]" & _
    " HAVING ((([dbo_SDG_E_FACT].[FICHE]) " & strRechRef & ") And (([dbo_SDG_E_ELE].[NOM]) " & strRechNom & ") " & _
    "And (([dbo_SDG_E_ELE].[PNOM]) " & strRechPNom & " ) And (([dbo_SDG_E_FACT].[ANNEE]) = " + CStr([Forms]![03-B1_Ajout_Creance_AVG].[Texte14]) + ") And (" & _
    "(Sum([dbo_SDG_E_FACT].[SOLDE])) > 0) And (([04-ETABLISSEMENTS].[NoEtablissement]) = '" + CStr([Forms]![03-B1_Ajout_Creance_AVG].[Texte33]) + "'))" & _
    " ORDER BY [dbo_SDG_E_ELE.NOM];"
    
    Set enr = base.OpenRecordset(SqlD)
    
    If enr.BOF Then
    MsgBox "Requête vide"
    Exit Sub
    End If
    
    
    base.Execute ("DELETE * FROM " & strNTbl)
    Set rstemp = base.OpenRecordset(strNTbl)
    
    enr.MoveFirst
    
    Do Until enr.EOF
        rstemp.AddNew
        rstemp!SelCreance = 0
        rstemp!RefSyst = enr!FICHE
        rstemp!NClient = enr!NOM
        rstemp!PNClient = enr!PNOM
        rstemp!Ann = enr!ANNEE
        rstemp!Sold = enr!SommeDeSOLDE
        rstemp.Update
        enr.MoveNext
    Loop
    

    Un énorme merci pour votre aide si précieuse, je n'aurais jamais réussi sans toi!

    Bonne journée!! :) 

    0
    1. Contributeur

      Meri pour le retour!

      J'avais anticipé le souci avec NULL.

      Ce qu'on fait souvent, c'est, si la condition (dans le formulaire) est NULL, c'est de ne pas insérer le test correspondant dans la requête.

      Quelque-chose comme:

      If IsNull([Forms]![03-B1_Ajout_Creance_AVG].[Texte16]) Then
          strRechRef = "True"
      Else
          strRechRef = " [dbo_SDG_E_FACT].[FICHE]) Like '*" + CStr([Forms]![03-B1_Ajout_Creance_AVG].[Texte16]) + "*' "
      End If
      

      Ta solution fonctionne tout aussi bien, bravo!

      1