Création de table à partir d'une requête sélection SQL en vb
RésoluBonjour à 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
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.
-
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 LoopUn énorme merci pour votre aide si précieuse, je n'aurais jamais réussi sans toi!
Bonne journée!! :)
-
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 IfTa solution fonctionne tout aussi bien, bravo!
-

