J'ai une base de données Access pour rendre compte des statistiques d'événements recueillies à partir d'un système mainframe. Le planificateur mainframe (ZEKE) ne dispose pas de fonctionnalités de création de rapports robustes, j'exporte donc les données d'événements quotidiennes sur lesquelles rendre compte.
Une liste principale d'une source distincte (une liste statique qui ne changera pas régulièrement) répertorie l'individu applications, y compris le code de l'application (qui est la norme de dénomination pour les exécutions de production) et le nom du programmeur, du coordinateur, du responsable, de l'unité commerciale, etc. pour cette application.
L'utilisateur peut effectuer une recherche dans n'importe quel champ , code d'application, programmeur, coordinateur, etc.
Choisissez le centre de production dans lequel effectuer la recherche (il y en a 5) ou par défaut, choisissez toutes les dates, une seule date ou une plage de dates.
La requête prend les paramètres de recherche et, en commençant par le code de l'application ou par la personne, recherche dans la table les applications et copie les enregistrements dans une table temporaire à des fins de rapport.
Par exemple, pour voir le nombre d'échecs de l'application Le coordinateur John Doe avait pour la semaine dernière pour toutes les applications dont il est responsable, la requête déplacerait tous les enregistrements d'application répertoriant John Doe comme coordinateur vers la table temporaire.
À partir de là, il parcourt la table temporaire de chaque application et recherche dans les données d'événement les événements sous ce code d'application qui répondent aux critères saisis pour la date, le centre de production et le type d'événement (succès, échec ou les deux).
Ceci est déplacé vers une table temporaire pour le rapport final.
La table des données d'événement compte actuellement 2,5 millions de lignes (soit 15 jours de données) et augmente de jour en jour.
J'ai mis le back-end sur un disque NAS nouvellement créé sur notre réseau.
Un rapport qui prenait deux minutes alors que le back-end et le front-end étaient sur la même machine prend maintenant 29 minutes.
Des suggestions pour rationaliser les requêtes sur un réseau?
Code qui est exécuter à partir du formulaire de sélection des critères du rapport et exécuter le rapport.
'this macro will generate a report based on multiple input criteria. 'this report allows the user to slect: ' date range, single date or all dates ' type of events: Abends, Successes or both ' centers to pull data from: OCC,QCC,BCC,ITS,DAIN, or ALL centers ' The type of data to report on: App code, App Coordinator, Custodian, L3, L4 or L5 'Once the user has selected all of the required data and fields, the report will be generated 'based on the selection criteria. 'we begin by defining the active database as the currently open database Dim db As DAO.Database Set db = DBEngine(0)(0) On Error GoTo ErrorHandler 'Now we designate the variables which will be used in this macro Dim strSQ1 As String Dim strSQ2 As String Dim strSQ3 As String Dim strSQ4 As String Dim appl As String Dim evstatus As String Dim appletype As String Dim fullapp As String Dim length As Long Dim iipmname As String Dim iipmcoor As String Dim fullappnm As String Dim fullappcoor As String Dim kinddate As String Dim coor As String Dim cust As String Dim appL3 As String Dim appL4 As String Dim appL5 As String Dim ctrOCC As String Dim ctrMTL As String Dim ctrBCC As String Dim ctrITS As String Dim ctrDAIN As String 'We will start by setting some default values 'We will ste the default values for center selection. 'We start by searching for terms we know are not there, then change them to 'valid search terms if the center is selected. ctrOCC = "notOCC" ctrMTL = "notMTL" ctrBCC = "notBCC" ctrITS = "notITS" ctrDAIN = "notUSWM" fullapp = "*" 'First we determine which event types the user wants to look for state = Me![opt-status].Value If state = 1 Then evstatus = " [ev-status] = 'AEOJ'" ElseIf state = 2 Then evstatus = " [ev-status] = 'EOJ'" ElseIf state = 3 Then evstatus = " ([ev-status] = 'EOJ' OR [ev-status] = 'AEOJ')" End If 'MsgBox "Event status pulled is:.. " & evstatus & "." ' Next up we will configure the date parameters based on the user input If [grp-datesel] = 1 Then Sdte = "1" Edte = "9999999" kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " " End If If [grp-datesel] = 2 Then 'error handling If IsNull(Me.[sel-onedate]) Then MsgBox "You have not entered a date to search....please try again." Me.[sel-onedate] = Null Me.[sel-onedate].SetFocus Exit Sub End If 'end of error handling Dim currdte As Date currdte = Me![sel-onedate].Value currjul = Format(currdte, "yyyyy") daycurr = CDbl(currjul) Sdte = daycurr Edte = daycurr kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " " End If If [grp-datesel] = 3 Then 'error handling If IsNull(Me.[sel-Sdate]) Or IsNull(Me.[sel-Edate]) Then MsgBox "You Must enter a start and end date for the search....please try again." Me.[sel-Sdate] = Null Me.[sel-Edate] = Null Me.[sel-Sdate].SetFocus Exit Sub End If 'end of error handling Dim startdte As Date Dim enddte As Date startdte = Me.[sel-Sdate].Value enddte = Me.[sel-Edate].Value startjul = Format(startdte, "yyyyy") endjul = Format(enddte, "yyyyy") Sday = CDbl(startjul) Eday = CDbl(endjul) Sdte = Sday Edte = Eday 'MsgBox "start date is " & Sdte & " and end date is " & Edte & "." 'check that dates are in proper chronological order If Sdte > Edte Then MsgBox "The start Date you entered is after the end date....please try again." Me.[sel-Sdate] = Null Me.[sel-Edate] = Null Me.[sel-Sdate].SetFocus Exit Sub End If 'keep going if it's all good kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " " End If MsgBox "Date used is:.. " & kinddate & "." 'Now lets look at center selection If [chk-allctr].Value = True Then ctrOCC = "OCC" ctrMTL = "MTL" ctrBCC = "BCC" ctrITS = "ITS" ctrDAIN = "USWM" End If If [chk-OCC].Value = True Then ctrOCC = "OCC" End If If [chk-MTL].Value = True Then ctrMTL = "MTL" End If If [chk-BCC].Value = True Then ctrBCC = "BCC" End If If [chk-RTF].Value = True Then ctrITS = "ITS" End If If [chk-DAIN].Value = True Then ctrDAIN = "DAIN" End If 'Error handling if no center is selected If [chk-OCC].Value = Flase Then If [chk-MTL].Value = Flase Then If [chk-BCC].Value = Flase Then If [chk-RTF].Value = Flase Then If [chk-DAIN].Value = Flase Then MsgBox "You have not selected a center to search search....please try again." Me.[chk-allctr].SetFocus Exit Sub End If End If End If End If End If 'end of error handling 'MsgBox "centers used are: Chr(10) " & ctrOCC & " Chr(10) " & ctrBCC & " Chr(10) " & ctrMTL & " Chr(10) " & ctrITS & " Chr(10) " & ctrDAIN & " For this run" 'All good so far, now we will parse the application code if an 'application code report is selected appl = "*" If [opt-criteria].Value = 1 Then 'error handling If IsNull(Me.[sel-appcode]) Then MsgBox "You have not entered an application code to search....please try again." Me.[sel-appcode] = Null Me.[sel-appcode].SetFocus Exit Sub End If 'end of error handling End If If [opt-criteria].Value = 1 Then appl = Me![sel-appcode].Value End If 'trust = "no" 'If Mid(appl, 3, 2) = "RT" Then trust = "yes" 'length = Len(appl) 'If length = 2 Then appltype = "short" 'If length = 3 Then appltype = "long" 'If appltype = "short" Then fullapp = "" & appl & "00" 'If appltype = "long" Then fullapp = "" & appl & "0" 'If trust = "yes" Then fullapp = appl 'End If fullapp = appl 'MsgBox "App to use is: " & appl & " fullapp code is " & fullapp & "." 'Now we set values if names are used coor = "*" cust = "*" appL3 = "*" appL4 = "*" appL5 = "*" If [opt-criteria].Value = 2 Then 'error handling If IsNull(Me.[sel-coor]) Then MsgBox "You have not entered a Coordinator to search....please try again." Me.[sel-coor] = Null Me.[sel-coor].SetFocus Exit Sub End If 'end of error handling coor = Me![sel-coor].Value 'MsgBox "Coordinator report selected for: " & coor & "." End If If [opt-criteria].Value = 3 Then 'error handling If IsNull(Me.[sel-custodian]) Then MsgBox "You have not entered a Custodian to search....please try again." Me.[sel-custodian] = Null Me.[sel-custodian].SetFocus Exit Sub End If 'end of error handling cust = Me![sel-custodian].Value 'MsgBox "Custodian report selected for: " & cust & "." End If If [opt-criteria].Value = 4 Then 'error handling If IsNull(Me.[sel-L3]) Then MsgBox "You have not entered an L3 to search....please try again." Me.[sel-L3] = Null Me.[sel-L3].SetFocus Exit Sub End If 'end of error handling appL3 = Me![sel-L3].Value 'MsgBox "L3 report selected for: " & appL3 & "." End If If [opt-criteria].Value = 5 Then 'error handling If IsNull(Me.[sel-L4]) Then MsgBox "You have not entered an L4 to search....please try again." Me.[sel-L4] = Null Me.[sel-L4].SetFocus Exit Sub End If 'end of error handling appL4 = Me![sel-L4].Value 'MsgBox "L4 report selected for: " & appL4 & "." End If If [opt-criteria].Value = 6 Then 'error handling If IsNull(Me.[sel-L5]) Then MsgBox "You have not entered an L5 to search....please try again." Me.[sel-L5] = Null Me.[sel-L5].SetFocus Exit Sub End If 'end of error handling appL5 = Me![sel-L5].Value 'MsgBox "L5 report selected for: " & appL5 & "." End If 'Most of these reports take a while to build with this macro, so to make sure the user 'knows that the macro is still working, we didsplay a splash screen. It's cute and has 'hamsters, cause everyone loves hamsters. DoCmd.OpenForm "PlsWaitFrm", acWindowNormal [Forms]![PlsWaitFrm].Repaint 'All of out criteria values are now selected. We can move on to pulling data from the tables. 'We start by populating the IIPM table with the information that we require for applications. strSQ1 = "DELETE * from [tbl-RPT-IIPM] " db.Execute strSQ1 strSQ2 = "INSERT INTO [tbl-RPT-IIPM] " & _ "SELECT * FROM [tbl-IIPM] " & _ "WHERE (([AppCode] like '" & fullapp & "')" & _ "AND ([AppCoordinator] like '" & coor & "') " & _ "AND ([AppCustodian] like '" & cust & "') " & _ "AND ([L3] like '" & appL3 & "') " & _ "AND ([L4] like '" & appL4 & "') " & _ "AND ([L5] like '" & appL5 & "')) " db.Execute strSQ2 'MsgBox "made it past the populate of rpt-iipm" 'Now we have populated the IIPM report table, it's time to populate the event report table. 'We will loop through all fields in the IIPM report table and pull information for each 'application code. strSQ3 = "DELETE * from [tbl-EVENTREPORT] " db.Execute strSQ3 Dim rs As DAO.Recordset Set db = CurrentDb Set rs = db.OpenRecordset("tbl-RPT-IIPM") 'this opens the IIPM report table just populated 'populate the table rs.MoveLast rs.MoveFirst Do While Not rs.EOF 'we will execute these action against the selected record. 'first step - parse the application code to display the full application code appl = rs![AppCode].Value length = Len(appl) If length = 1 Then appl = "" & appl & "00" rptdelin = Mid(appl, 3, 1) rptcode = Mid(appl, 1, 3) If rptdelin = "0" Then rptcode = Mid(appl, 1, 2) If rptdelin = "R" Then rptcode = "RT" & Mid(appl, 1, 2) & "" 'MsgBox "searching for: " & rptcode & "." applist = applist & "," & appl strSQ4 = "INSERT INTO [tbl-EVENTREPORT] " & _ "SELECT * FROM [tbl-EVENT DATA] " & _ "WHERE (([ev-jobname] LIKE '?" & rptcode & "*') " & _ "AND (([ev-ctr] = '" & ctrOCC & "')" & _ "OR ([ev-ctr] = '" & ctrMTL & "')" & _ "OR ([ev-ctr] = '" & ctrBCC & "')" & _ "OR ([ev-ctr] = '" & ctrITS & "')" & _ "OR ([ev-ctr] = '" & ctrDAIN & "'))" & _ "AND (" & kinddate & ") " & _ "AND " & evstatus & ")" db.Execute strSQ4 'now we're done with this report, we move on to the next rs.MoveNext 'press Ctrl+G to see debuG window beneath Loop 'END OF LOOPING CODE 'MsgBox "made it past the looping" 'Now we have completed populating the table that the report will be based on. 'Next step is to gather master statistics to produce abend and success percentages. totfail = DCount("[ev-status]", "tbl-EVENTREPORT", "[ev-status] = 'AEOJ'") totsucc = DCount("[ev-status]", "tbl-EVENTREPORT", "[ev-status] = 'EOJ'") Dim allabend As Long Dim allsucc As Long allabend = DCount("[ev-status]", "[tbl-EVENT DATA]", "[ev-status] = 'AEOJ' AND ([ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & ")") allsucc = DCount("[ev-status]", "[tbl-EVENT DATA]", "[ev-status] = 'EOJ' AND ([ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & ")") Dim pctabend As Long Dim pctsucc As Long pctabend = (totfail / allabend) * 100 pctsucc = (totsucc / allsucc) * 100 'Now we will generate the reports for display based on what type of report was selected 'by the user in the initial form. 'Before we open the report, we will close the splash screen DoCmd.Close acForm, "PlsWaitFrm", acSaveNo 'Now we open the report If [opt-criteria].Value = 1 Then fullappnm = DLookup("AppName", "tbl-RPT-IIPM", "AppCode = '" & fullapp & "' ") fullappcoor = DLookup("AppCoordinator", "tbl-RPT-IIPM", "AppCode = '" & fullapp & "' ") DoCmd.OpenReport "rpt-APPLREPORT", acViewReport [Reports]![rpt-APPLREPORT]![rpt-appcode].Value = fullapp [Reports]![rpt-APPLREPORT]![rpt-appname].Value = fullappnm [Reports]![rpt-APPLREPORT]![rpt-appcoor].Value = fullappcoor [Reports]![rpt-APPLREPORT]![rpt-abendtot].Value = totfail [Reports]![rpt-APPLREPORT]![rpt-succtot].Value = totsucc [Reports]![rpt-APPLREPORT]![rpt-abdpct].Value = pctabend [Reports]![rpt-APPLREPORT]![rpt-succpct].Value = pctsucc End If If [opt-criteria].Value = 2 Then DoCmd.OpenReport "rpt-COORREPORT", acViewReport [Reports]![rpt-COORREPORT]![rpt-appcode].Value = applist [Reports]![rpt-COORREPORT]![rpt-appcoor].Value = coor [Reports]![rpt-COORREPORT]![rpt-abendtot].Value = totfail [Reports]![rpt-COORREPORT]![rpt-succtot].Value = totsucc [Reports]![rpt-COORREPORT]![rpt-abdpct].Value = pctabend [Reports]![rpt-COORREPORT]![rpt-succpct].Value = pctsucc End If If [opt-criteria].Value = 3 Then DoCmd.OpenReport "rpt-CUSTREPORT", acViewReport [Reports]![rpt-CUSTREPORT]![rpt-appcode].Value = applist [Reports]![rpt-CUSTREPORT]![rpt-appcoor].Value = cust [Reports]![rpt-CUSTREPORT]![rpt-abendtot].Value = totfail [Reports]![rpt-CUSTREPORT]![rpt-succtot].Value = totsucc [Reports]![rpt-CUSTREPORT]![rpt-abdpct].Value = pctabend [Reports]![rpt-CUSTREPORT]![rpt-succpct].Value = pctsucc End If If [opt-criteria].Value = 4 Then DoCmd.OpenReport "rpt-L3REPORT", acViewReport [Reports]![rpt-L3REPORT]![rpt-appcode].Value = applist [Reports]![rpt-L3REPORT]![rpt-appcoor].Value = appL3 [Reports]![rpt-L3REPORT]![rpt-abendtot].Value = totfail [Reports]![rpt-L3REPORT]![rpt-succtot].Value = totsucc [Reports]![rpt-L3REPORT]![rpt-abdpct].Value = pctabend [Reports]![rpt-L3REPORT]![rpt-succpct].Value = pctsucc End If If [opt-criteria].Value = 5 Then DoCmd.OpenReport "rpt-L4REPORT", acViewReport [Reports]![rpt-L4REPORT]![rpt-appcode].Value = applist [Reports]![rpt-L4REPORT]![rpt-appcoor].Value = appL4 [Reports]![rpt-L4REPORT]![rpt-abendtot].Value = totfail [Reports]![rpt-L4REPORT]![rpt-succtot].Value = totsucc [Reports]![rpt-L4REPORT]![rpt-abdpct].Value = pctabend [Reports]![rpt-L4REPORT]![rpt-succpct].Value = pctsucc End If If [opt-criteria].Value = 6 Then DoCmd.OpenReport "rpt-L5REPORT", acViewReport [Reports]![rpt-L5REPORT]![rpt-appcode].Value = applist [Reports]![rpt-L5REPORT]![rpt-appcoor].Value = appL5 [Reports]![rpt-L5REPORT]![rpt-abendtot].Value = totfail [Reports]![rpt-L5REPORT]![rpt-succtot].Value = totsucc [Reports]![rpt-L5REPORT]![rpt-abdpct].Value = pctabend [Reports]![rpt-L5REPORT]![rpt-succpct].Value = pctsucc End If ErrorHandler: If Err.Number = 7874 Then Resume Next 'Tried to delete a non-existing table, resume End If End Sub '''
3 Réponses :
Premièrement, vous devez déterminer où se trouvent les goulots d'étranglement, je vous suggère donc de mettre des instructions Debug.Print Now
dans tout le code pour vous donner une idée de la cause du problème. p>
Je suppose que deux des processus qui prennent le plus de temps sont les instructions DELETE
/ INSERT
que vous faites.
Je suggère qu'au lieu de faire cela, vous envisagiez de normaliser votre base de données, puis de créer une requête qui fournit les informations dont vous avez besoin.
De plus, en exécutant le rapport directement à partir d'une requête plutôt que d'une table temporaire, vous n'avez pas à vous soucier des suppressions / insertions créant une surcharge de base de données.
Si vous insistez vraiment pour conserver ce processus, envisagez de supprimer la table [tbl-RPT-IIPM]
puis de la recréer, plutôt que de supprimer les enregistrements. Et pensez à supprimer les index avant l'insertion, puis à les rajouter par la suite, car les index répartissent les insertions, mais accélèrent évidemment les recherches et les jointures.
De plus, lorsque vous insérez des données dans [tbl-RPT-IIPM]
, vous utilisez ([L3] comme '"& appL3 &"')
, qui est identique à ([L3] = '"& appL3 &"')
, mais plus lent.
Lorsque vous insérez des données dans [tbl-EVENTREPORT]
, vous le faites lorsque vous parcourez un jeu d'enregistrements - il peut être plus rapide d'utiliser une instruction SQL INSERT
.
Cordialement,
Applecore, tout d'abord, permettez-moi de vous remercier pour vos idées. Malheureusement, en raison de la nature du traitement des données, je ne suis pas sûr de pouvoir mettre en œuvre certaines d'entre elles. J'ai utilisé des instructions debug.print pour avoir une meilleure idée du timing.
Vous avez raison, l'instruction INSERT me pose le plus de problèmes, et seulement le second. Les suppressions volent presque instantanément, aucun problème là-bas. C'est la deuxième insertion des données d'événement qui le ralentit.
J'y réfléchis depuis le début pour savoir comment nromaliser plus efficacement et créer de meilleures relations, mais je suis bloqué. Mon problème est que les données entre la table des événements et la table des événements sont liées «dans le monde» mais pas clairement en termes de données. Il n'y a aucun moyen de déterminer la relation sans un calcul complexe. Par exemple, la partie unique des données d'application est le code d'application. Ils sont toujours uniques. Un seul coordinateur d'application peut se voir attribuer des dizaines de codes, tout comme les dépositaires, L3, L4, etc. Chaque événement est lié à une application, cependant, il n'y a pas de champ spécifique qui est exporté qui indique le code de l'application, il est obtenu en analysant le nom de l'événement (Et oui, c'est aussi archaïque que cela puisse paraître). Les normes de dénomination des événements sont des noms de caractères mainframe standard à 8:. Par exemple PGRD1234 - Travail de production, application GRD, 1234 comme désignateur. Donc, pour déterminer à quelle application le travail est lié, je prends le code de l'application et je sélectionne LIKE avec des caractères génériques. Ce n'est pas précis à 100%, je le sais bien, mais pour utiliser des caractères génériques, je semble être bloqué en utilisant LIKE. Je n'ai pas pu faire fonctionner '=' avec des caractères génériques. Peut tu?
Vous avez également mentionné "Lorsque vous insérez des données dans [tbl-EVENTREPORT], vous le faites lorsque vous parcourez un jeu d'enregistrements - il peut être plus rapide d'utiliser une instruction INSERT SQL." dont je ne suis pas sûr de ce que vous dites .. Mes excuses. Je ne pense pas que je le comprends. Je pense que c'est ce que je fais maintenant. J'utilise la table IIPM pour obtenir la liste des codes d'application que je dois extraire, puis je boucle sur ce jeu d'enregistrements pour extraire toutes les données d'événement pour ces applications uniquement. Comme il n'y a pas de corrélation directe entre les données, je ne peux pas penser à une autre façon de le faire.
OK, avec quelques informations supplémentaires, des réponses supplémentaires qui peuvent (ou non !!) aider. Encore une fois, vous devrez exécuter des tests de chronométrage pour voir ce qui fonctionne le mieux pour vous.
Essayez d'ajouter un champ "Oui / Non" à la table [tbl-EVENT DATA]
. Vous pouvez ensuite utiliser une instruction UPDATE
pour indiquer les champs à inclure dans le rapport, plutôt que d'utiliser la requête lente INSERT
.
Autre chose à essayer serait de remplacer l'instruction INSERT
par plusieurs, chacune utilisant une valeur différente pour [ev-ctr]
. Ou bien plutôt que d'utiliser OU
essayez d'utiliser IN
:
Sub sUpdateQuery() Dim objAccess As New Access.Application objAccess.OpenCurrentDatabase "J:\downloads\test.accdb" objAccess.DoCmd.RunSQL "UPDATE test2 SET Field1=UCASE(Field1);" objAccess.CloseCurrentDatabase Set objAccess = Nothing End Sub
Aussi, je remarque que kinddate code> est configuré pour inclure effectivement toutes les dates dans une seule instance, et cet
evstatus
est configuré pour inclure à la fois "EOJ" et "AEOJ" dans une seule instance. Plutôt que d'inclure ces champs comme critères dans ces cas, vous souhaiterez peut-être ne pas les inclure du tout:
If state = 1 Then evstatus = " AND [ev-status] = 'AEOJ'" ElseIf state = 2 Then evstatus = " AND [ev-status] = 'EOJ'" ElseIf state = 3 Then evstatus = " " End If
Et vous réécririez ensuite "AND" & evstatus à
& evstatus
dans l'instruction SQL.
Une dernière chose à regarder est en fait d'exécuter le INSERT
directement dans le backend, plutôt que d'opérer sur des tables liées dans l'interface, car Access fera glisser de grandes quantités de données sur le réseau, puis les renverra. En guise de guide de base, quelque chose comme ceci:
strSQ4 = "INSERT INTO [tbl-EVENTREPORT] " & _ "SELECT * FROM [tbl-EVENT DATA] " & _ "WHERE [ev-jobname] LIKE '?" & rptcode & "*' " & _ "AND [ev-ctr] IN('" & ctrOCC & "','" & ctrMTL & "','" & ctrBCC & "','" & ctrITS & "','" & ctrDAIN & "')" & _ "AND " & kinddate & _ "AND " & evstatus
Cordialement,
Juste ciel!!!! Applecore, MERCI. J'ai mis en œuvre presque toutes vos suggestions et le résultat a été tout simplement spectaculaire. Je pense que ce que cela a fait, c'est d'exécuter les requêtes à distance sur le back-end. J'ai réduit le temps de retour du rapport de 37 minutes à 20,07 secondes. Cela a fonctionné comme un charme. La seule chose que je n'ai pas faite est de passer aux indicateurs OUI / NON, car je pense que cela peut affecter plusieurs rapports exécutés simultanément. Je vais jouer. Encore merci!
C'est bon de l'entendre. Veuillez alors marquer ceci comme réponse.
Au lieu d'écrire des enregistrements dans des tables temporaires, pourquoi ne pas appliquer des critères de filtre au rapport dans la commande OpenReport? Que sont censées accomplir les lignes
.Value
après l'ouverture du rapport?