Bonjour,
J'ai de gros problèmes de performance dans Access 2002 (Office XP avec SP3)
en environnement TSE (Terminal Services) sous Windows Server 2003 SP1:
Les utilisateurs travaillent sur des tables d'environ 50 000 enregistrements
et font des filtres , des tris, des remplacements de valeurs dans les champs.
Au bout de quelques manipulations sur une même table, les performances se
dégradent fortement et il ne faut pas moins de 3 à 4 minutes pour trier une
table de 38 000 enregistrements (en temps normal la même opération prend
moins de 1 seconde).
Ce qu'il y a de suprenant c'est que coté système, il n'y a presque pas de
charge CPU (utilisation à 3 ou 4 % au maximum) et pas d'entrées/sorties
disques non plus. A priori, il ne s'agit donc pas d'un problème de
dimmentionnement de la machine.
Après un compactage de la base tout rentre dans l'ordre ... mais cela ne
dure pas très longtemps : dès que l'on recommence à manipuler la base, les
performances chuttent rapidement !
Les même opérations effectuées avec la même base sur un PC personnel ne
posent aucun problème de ce genre.
Je suis preneur de toute information ou piste de recherche.
Une piste pour cela, mais que je n'ai pas vérifiée :
Récupérer l'objet Screen.ActiveDatasheet (qui est une classe Form) Et voir dans la propriété Filter indique bien le filtre en cours...
Je rappelle que si la fenêtre active est la fenêtre Base de données, l'objet courant et chargé peut être la table sélectionnée dans la liste des tables même si en réalité elle n'est pas la fenêtre active. Dans ce cas, tenter d'accéder à Screen.ActiveDatasheet génère soit une erreur soit une Form qui ne correspond pas à la table en cours.
J'espère que ça fonctionnera pour le filtre...
C'est une idée effectivement et je pense que je vais m'orienter vers cette solution. Il faudrait juste que je puisse récupérer dynamiquement dans le code VBA du formulaire les éventuels filtres que l'utilisateur a préalablement positionné sur la table.
Merci en tout cas pour votre aide et pour les procédures indiquées.
Alors dans ce cas pourquoi pas créer un formulaire rechercher/Remplacer.
Cela nécessite 3 opérations :
1. Créer un bouton de barre d'outil personnalisé "Rechercher/Remplacer" 2. Créer un fonction MonRechercherRemplacer() dans un module standard, qui sera appelée par le bouton 3. Créer un Formulaire "FSearchReplace" de recherche/remplacement qui sera affiché par cette procédure
Procédure 2 : ----------------
La fonction doit être comme suit :
Public Function MonRechercherRemplacer()
Const FRM_CHERCHE_REPLACE As String = "FSearchReplace"
Dim frm As Access.Form Dim acObject As Access.AccessObject Dim sObjName As String Dim sTable As String
' Vérifie que l'objet en cours est une table ' Dans ce cas, vérifie que la table est ouverte en mode feuille de données ' et non en mode création, par exemple
sObjName = CurrentObjectName
Select Case CurrentObjectType
Case acTable
Set acObject = CurrentData.AllTables(sObjName)
If acObject.IsLoaded Then If acObject.CurrentView = acCurViewDatasheet Then sTable = sObjName End If End If
End Select
' Si l'Obet actif est bien une Table ouverte en mode feuille de données, ' Affiche le formulaire
' If Len(sTable) Then '(Test pas indispensable) DoCmd.OpenForm FRM_CHERCHE_REPLACE, acNormal Set frm = Forms(FRM_CHERCHE_REPLACE) frm.ShowReplace sTable ' End If
End Function
Procédure 1 bis : -------------------
Mettre la propriété "sur action" du bouton à :
=MonRechercherRemplacer()
Procédure 3 : -----------------
Placer la Procédure suivante dans le Formulaire :
Public Sub ShowReplace(ByVal sTable As String) Me.Caption = "Rechercher/Remplacer : " & sTable cmbFields.RowSource = sTable End Sub
Le formulaire comporte une zone de liste déroulante cmbFields dont le type de source ("Origine Source") est "Liste des champs".
Afin d'optimiser l'interface, le formulaire devra également avoir la propriété "fenêtre indépendante" à "oui" pour s'afficher au-dessus de la table.
Reste l'Etape 4 : Mettre en place le code SQL et son exécution pour effectuer le remplacement à partir du champ sélectionné par l'utilisateur, le texte cherché et le texte de remplacement indiqués dans le formulaire.
A noter enfin que l'idéal aurait été de fermer le formulaire de recherche lorsque la table est fermée, mais je n'ai pas trouvé comment pour le moment (même en ayant recours au formulaire renvoyé par Screen.ActiveDatasheet).
A noter également : Si la fenêtre active est la fenêtre Base de données, l'objet courant et chargé peut être la table sélectionnée dans la liste des tables même si en réalité elle n'est pas la fenêtre active).
En espérant que cela t'inspirera... (ca peut paraitre complexe, mais en réalité c'est très simple).
Effectivement, ça complique un petit peu.
Une piste pour cela, mais que je n'ai pas vérifiée :
Récupérer l'objet Screen.ActiveDatasheet (qui est une classe Form)
Et voir dans la propriété Filter indique bien le filtre en cours...
Je rappelle que si la fenêtre active est la fenêtre Base de données,
l'objet courant et chargé peut être la table sélectionnée dans la liste des
tables même si en réalité elle n'est pas la fenêtre active.
Dans ce cas, tenter d'accéder à Screen.ActiveDatasheet génère soit une
erreur soit une Form qui ne correspond pas à la table en cours.
J'espère que ça fonctionnera pour le filtre...
C'est une idée effectivement et je pense que je vais m'orienter vers cette
solution. Il faudrait juste que je puisse récupérer dynamiquement dans le
code VBA du formulaire les éventuels filtres que l'utilisateur a
préalablement positionné sur la table.
Merci en tout cas pour votre aide et pour les procédures indiquées.
Alors dans ce cas pourquoi pas créer un formulaire rechercher/Remplacer.
Cela nécessite 3 opérations :
1. Créer un bouton de barre d'outil personnalisé "Rechercher/Remplacer"
2. Créer un fonction MonRechercherRemplacer() dans un module standard, qui
sera appelée par le bouton
3. Créer un Formulaire "FSearchReplace" de recherche/remplacement qui sera
affiché par cette procédure
Procédure 2 :
----------------
La fonction doit être comme suit :
Public Function MonRechercherRemplacer()
Const FRM_CHERCHE_REPLACE As String = "FSearchReplace"
Dim frm As Access.Form
Dim acObject As Access.AccessObject
Dim sObjName As String
Dim sTable As String
' Vérifie que l'objet en cours est une table
' Dans ce cas, vérifie que la table est ouverte en mode feuille de données
' et non en mode création, par exemple
sObjName = CurrentObjectName
Select Case CurrentObjectType
Case acTable
Set acObject = CurrentData.AllTables(sObjName)
If acObject.IsLoaded Then
If acObject.CurrentView = acCurViewDatasheet Then
sTable = sObjName
End If
End If
End Select
' Si l'Obet actif est bien une Table ouverte en mode feuille de données,
' Affiche le formulaire
' If Len(sTable) Then '(Test pas indispensable)
DoCmd.OpenForm FRM_CHERCHE_REPLACE, acNormal
Set frm = Forms(FRM_CHERCHE_REPLACE)
frm.ShowReplace sTable
' End If
End Function
Procédure 1 bis :
-------------------
Mettre la propriété "sur action" du bouton à :
=MonRechercherRemplacer()
Procédure 3 :
-----------------
Placer la Procédure suivante dans le Formulaire :
Public Sub ShowReplace(ByVal sTable As String)
Me.Caption = "Rechercher/Remplacer : " & sTable
cmbFields.RowSource = sTable
End Sub
Le formulaire comporte une zone de liste déroulante cmbFields dont le type
de source ("Origine Source") est "Liste des champs".
Afin d'optimiser l'interface, le formulaire devra également avoir la
propriété "fenêtre indépendante" à "oui" pour s'afficher au-dessus de la
table.
Reste l'Etape 4 : Mettre en place le code SQL et son exécution pour
effectuer le remplacement à partir du champ sélectionné par l'utilisateur, le
texte cherché et le texte de remplacement indiqués dans le formulaire.
A noter enfin que l'idéal aurait été de fermer le formulaire de recherche
lorsque la table est fermée, mais je n'ai pas trouvé comment pour le moment
(même en ayant recours au formulaire renvoyé par Screen.ActiveDatasheet).
A noter également : Si la fenêtre active est la fenêtre Base de données,
l'objet courant et chargé peut être la table sélectionnée dans la liste des
tables même si en réalité elle n'est pas la fenêtre active).
En espérant que cela t'inspirera... (ca peut paraitre complexe, mais en
réalité c'est très simple).
Une piste pour cela, mais que je n'ai pas vérifiée :
Récupérer l'objet Screen.ActiveDatasheet (qui est une classe Form) Et voir dans la propriété Filter indique bien le filtre en cours...
Je rappelle que si la fenêtre active est la fenêtre Base de données, l'objet courant et chargé peut être la table sélectionnée dans la liste des tables même si en réalité elle n'est pas la fenêtre active. Dans ce cas, tenter d'accéder à Screen.ActiveDatasheet génère soit une erreur soit une Form qui ne correspond pas à la table en cours.
J'espère que ça fonctionnera pour le filtre...
C'est une idée effectivement et je pense que je vais m'orienter vers cette solution. Il faudrait juste que je puisse récupérer dynamiquement dans le code VBA du formulaire les éventuels filtres que l'utilisateur a préalablement positionné sur la table.
Merci en tout cas pour votre aide et pour les procédures indiquées.
Alors dans ce cas pourquoi pas créer un formulaire rechercher/Remplacer.
Cela nécessite 3 opérations :
1. Créer un bouton de barre d'outil personnalisé "Rechercher/Remplacer" 2. Créer un fonction MonRechercherRemplacer() dans un module standard, qui sera appelée par le bouton 3. Créer un Formulaire "FSearchReplace" de recherche/remplacement qui sera affiché par cette procédure
Procédure 2 : ----------------
La fonction doit être comme suit :
Public Function MonRechercherRemplacer()
Const FRM_CHERCHE_REPLACE As String = "FSearchReplace"
Dim frm As Access.Form Dim acObject As Access.AccessObject Dim sObjName As String Dim sTable As String
' Vérifie que l'objet en cours est une table ' Dans ce cas, vérifie que la table est ouverte en mode feuille de données ' et non en mode création, par exemple
sObjName = CurrentObjectName
Select Case CurrentObjectType
Case acTable
Set acObject = CurrentData.AllTables(sObjName)
If acObject.IsLoaded Then If acObject.CurrentView = acCurViewDatasheet Then sTable = sObjName End If End If
End Select
' Si l'Obet actif est bien une Table ouverte en mode feuille de données, ' Affiche le formulaire
' If Len(sTable) Then '(Test pas indispensable) DoCmd.OpenForm FRM_CHERCHE_REPLACE, acNormal Set frm = Forms(FRM_CHERCHE_REPLACE) frm.ShowReplace sTable ' End If
End Function
Procédure 1 bis : -------------------
Mettre la propriété "sur action" du bouton à :
=MonRechercherRemplacer()
Procédure 3 : -----------------
Placer la Procédure suivante dans le Formulaire :
Public Sub ShowReplace(ByVal sTable As String) Me.Caption = "Rechercher/Remplacer : " & sTable cmbFields.RowSource = sTable End Sub
Le formulaire comporte une zone de liste déroulante cmbFields dont le type de source ("Origine Source") est "Liste des champs".
Afin d'optimiser l'interface, le formulaire devra également avoir la propriété "fenêtre indépendante" à "oui" pour s'afficher au-dessus de la table.
Reste l'Etape 4 : Mettre en place le code SQL et son exécution pour effectuer le remplacement à partir du champ sélectionné par l'utilisateur, le texte cherché et le texte de remplacement indiqués dans le formulaire.
A noter enfin que l'idéal aurait été de fermer le formulaire de recherche lorsque la table est fermée, mais je n'ai pas trouvé comment pour le moment (même en ayant recours au formulaire renvoyé par Screen.ActiveDatasheet).
A noter également : Si la fenêtre active est la fenêtre Base de données, l'objet courant et chargé peut être la table sélectionnée dans la liste des tables même si en réalité elle n'est pas la fenêtre active).
En espérant que cela t'inspirera... (ca peut paraitre complexe, mais en réalité c'est très simple).