Espace pile insuffisant : solution ?

Bonjour à tous,

Dans le cadre de mon stage, qui se termine jeudi et qui dure depuis mars, j'ai réalisé un outil de performance en temps réel sur Visual Basic Application de la centrale électrique dans laquelle je travaille.

Qui dit en temps réel, dit utilisation de Application OnTime pour tout rafraîchir tous les x minutes (10 dans mon cas).

Le modèle va chercher les valeurs de capteurs dans une Base de Données grâce à un Add-In, puis effectue un certain nombre de calculs et les affiche dans un Userform.

Le programme fonctionne en plusieurs parties, chacune contenue dans un module différent :

1) Changement des dates de début et de fin pour récupération des données :

Si on le lance à 08h15, il va initialiser le début de récupération des données à 08h04, la fin à 08h14, histoire d'être sûr qu'elles soient dispo

2) Il rafraîchit les données en utilisant la fonction Add-in

3) Il filtre si besoin quand il y a des Valeurs "Null" et les remplace par 0

4) Calcul des performances

5) Il lance un deuxième fichier, en utilisant un Application.Run puis je récupère les résultats

6) Je copie et sauvegarde les résultats dans un fichier journalier et mensuel, un sur le bureau, l'autre dans un dossier serveur commun.

7) L'userform s'affiche grâce aux résultats passés en Variable Publiques dans le calcul des performances

J'ai lu qu'utiliser un End permettait de supprimer les variables à la fin du programme. Je l'utiliser donc ici :

Sub Process()

' INIT

If a > 0 Then
Unload ResultsUserform
End If

' PROCESS

'1st function called (located just below)
'Changing date values in Raw Data sheet before refreshing Raw Data using WonderWare
FunctionData

'2nd function called (in WonderWareRefreshingRawDate module)
'Refreshing raw data using WonderWare function
WonderWareUpdateData

'3rd function called (in FilterModule module)
'It replaces Null cells per 0 if issues in WW data recovery
Filter

'4th function called (in MainCalculation module)
'All efficiency calculations + display in "Results" sheet
AutoRunEfficiency

'+1 at every run
a = a + 1

'Display the current value of a in "Raw data" sheet
Range("Constant") = a

'5th function called (in FDM module)
'If plant ON, run FDM function in FDM module
If PlantOnOff = 1 Then
RunFDM
End If

'6th function called (in SaveFunction module)
'Saving function into a daily and monthly file into desktop
SaveEfficiencyResultsDesktop
'Saving function into a daily and monthly file into shared operation folder
SaveEfficiencyResultsOperationFolder

'7th function called (in ResultsUserform Form)
'Show Userform  with the current values once all the calculations are finished
ResultsUserform.Show

'Delete all variable content before next execution
End

End Sub

Cela fonctionne pour une courte durée ou pendant quelques heures.

Le soucis est qu'à partir de pas mal d'heures de run (généralement 8/9), le programme plante et me renvoie à l'erreur

"Espace pile insuffisant (Erreur 28)".

J'ai tenté de réduire un maximum mon utilisation de mémoire en lisant des réponses de Forumistes sur Internet.

Mais sans doute pas assez.

Je ne peux malheureusement pas vous fournir le fichier en entier, et vous mettriez trop de temps à vous y retrouver.

J'ai environ 10.000 lignes de codes avec pas mal de modules. (j'ai dissocié les module dès que possible par soucis de lisibilité)

Par contre, je vais vous montrer mon module de sauvegarde du fichier car le pointeur lors du débug pointe à ce niveau là. Mais je me dis que c'est peut-être simplement car c'est à cet endroit qu'il n'y a plus mémoire disponible, sans pour autant que ça vienne de cette écriture.

Le pointeur pointe à l'endroit suivant :

'Open the existing file containing the result
Workbooks.Open Filename:="C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateToday & ".xls"

Voyez par vous-même le code :

Sub SaveEfficiencyResultsDesktop()

'Sub which is copying and pasting into 2 different files the results from EfficiencyCalculation file in Results sheet :

'1)Creation of a daily file the 1st time containing the results
'After that we open it and add each result until the end of the day

'2)Creation of a monthly file the 1st time containing the results
'After that we open it and add each result until the end of the month

Dim CopyRangeDay  As Range
Dim FirstEmptyLineDay As Long
Dim CopyRangeMonth  As Range
Dim FirstEmptyLineMonth As Long

StartTime = Range("StartTime").Value

'-------------DAILY FILE--------------------------------

'This is today's date with day + Month + year
DateToday = Day(StartTime) & "-" & MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'Location of the file
PathDay = Dir("C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateToday & ".xls")

'File already exists
If PathDay <> "" Then

'Open the existing file containing the result
Workbooks.Open Filename:="C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateToday & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineDay = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy

'Selection of the first cell for paste purpose, using First EmptyLineDay calculating here before
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineDay).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Columns.AutoFit

'Non Existing file
Else

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a folder on the desktop
ActiveWorkbook.SaveAs Filename:= _
    "C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" _
    & DateToday & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeDay = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateToday).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)

'-------------MONTHLY FILE--------------------------------

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'This is the date with only month + year
DateMonth = MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Location of the file
PathMonth = Dir("C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateMonth & ".xls")

'File already exists
If PathMonth <> "" Then

'Open the existing file containng the result
Workbooks.Open Filename:="C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateMonth & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineMonth = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy

'Selection of the first cell for paste purpose, using First EmptyLineMonth calculating here before
Workbooks(DateMonth & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineMonth).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
ActiveSheet.Columns.AutoFit

'Non Existing file
Else

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")

'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a folder on the desktop
ActiveWorkbook.SaveAs Filename:= _
    "C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" _
    & DateMonth & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeMonth = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateMonth).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)
End Sub

Sub SaveEfficiencyResultsOperationFolder()

'Sub which is copying and pasting into 2 different files the results from EfficiencyCalculation file in Results sheet :

'1)Creation of a daily file the 1st time containing the results
'After that we open it and add each result until the end of the day

'2)Creation of a monthly file the 1st time containing the results
'After that we open it and add each result until the end of the month

Dim CopyRangeDay  As Range
Dim FirstEmptyLineDay As Long
Dim CopyRangeMonth  As Range
Dim FirstEmptyLineMonth As Long

StartTime = Range("StartTime").Value

'-------------DAILY FILE--------------------------------

'This is today's date with day + Month + year
DateToday = Day(StartTime) & "-" & MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'Location of the file
PathDay = Dir("Y:\" & DateToday & ".xls")

'File already exists
If PathDay <> "" Then

'Open the existing file containing the result
Workbooks.Open Filename:="Y:\" & DateToday & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineDay = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy

'Selection of the first cell for paste purpose, using First EmptyLineDay calculating here before
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineDay).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Columns.AutoFit

'Non Existing file
Else

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a shared folder
'\\192.168.3.1\sohar-1\OPERATIONS\WONDERWARE-REPORTS
ActiveWorkbook.SaveAs Filename:= _
    "Y:\" _
    & DateToday & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeDay = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateToday).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)

'-------------MONTHLY FILE--------------------------------

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'This is the date with only month + year
DateMonth = MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Location of the file
PathMonth = Dir("Y:\" & DateMonth & ".xls")

'File already exists
If PathMonth <> "" Then

'Open the existing file containng the result
Workbooks.Open Filename:="Y:\" & DateMonth & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineMonth = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy

'Selection of the first cell for paste purpose, using First EmptyLineMonth calculating here before
Workbooks(DateMonth & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineMonth).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
ActiveSheet.Columns.AutoFit

'Non Existing file
Else

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")

'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a shared folder
'\\192.168.3.1\sohar-1\OPERATIONS\WONDERWARE-REPORTS
ActiveWorkbook.SaveAs Filename:= _
    "Y:\" _
    & DateMonth & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeMonth = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateMonth).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)
End Sub

Merci d'avance pour vos conseils,

J'essaierai d'être le plus réactif possible,

Bien à vous,

Maxime

Bonjour maxrsst,

je n'y connais rien, comme celui qui ne savait pas que c'est impossible...

https://msdn.microsoft.com/fr-fr/library/office/gg264734.aspx

https://forum.excel-pratique.com/search.php?keywords=Espace+pile+insuffisant+%28Erreur+28%29

mais vous avez surement déjà tout lu. Je m'imagine aussi que ça plante quand le fichier à mettre à jour sur le serveur est en cours d'utilisation sur un autre poste de travail, du coup "if file opened" un bon "abort" ou "next" résoudrait peut être le pb...

et une chose me choque dans votre programme :

CreateBackup:=False

, j'aurais mis =True, quitte à effacer les sauvegardes mensuellement

Bonjour,

Avant tout chose, Félicitations pour le superbe projet ...!!! çà a l'air vraiment génial ...!!!

Pour libérer l'espace mémoire ... dasn ton code, dès que tu n'as plus besoin de ta variable ... tu peux utiliser

Set tavariable = Nothing

Par ailleurs, une astuce pourrait t'aider ..

Introduire des Sauvegardes ... car au moment du Save ... Excel purge sa mémoire ...

En espèrant que cela t'aide ...

Bonjour njhub,

Je pense qu'on peut se tutoyer. J'ai "seulement" 23 ans.

Merci de cette intervention.

En effet je l'ai lue, en français et en anglais d'ailleurs.

En fait mon fichier est en période de test, donc personne ne l'utilise.

La 1ère sauvegarde est locale sur mon bureau, et personne ne touche au PC.

Ensuite pour la sauvegarde sur serveur, personne n'y touche non plus car personne n'est au courant qu'elle est là, à part l'ingénieur réseau.

Bien vu, j'avais volontairement désactivé le back-up pendant mes tests, ne trouvant pas où la sauvegarde avait lieu.

J'ai une question :

J'ai un test logique qui crée le fichier journalier ou mensuel s'il n'existe pas et qui ouvre l'existant le cas échéant. En cas de création de back-up, comment va se passer la sauvegarde ?

Bien à vous,

Maxime


Bonjour James007,

James007 a écrit :

Bonjour,

Avant tout chose, Félicitations pour le superbe projet ...!!! çà a l'air vraiment génial ...!!!

Merci ! C'est un stage de fin d'études pendant mon école d'ingénieur à l'étranger, dans le Sultanat d'Oman. C'est vraiment bien en effet.

J'avais déjà fait du Matlab (pas mal d'ailleurs) mais jamais de VBA donc j'ai appris moi-même et c'est très intéressant.

James007 a écrit :

Pour libérer l'espace mémoire ... dasn ton code, dès que tu n'as plus besoin de ta variable ... tu peux utiliser

Set tavariable = Nothing

Le fait que la variable soit locale ne libère pas l'espace mémoire une fois sortie de la sub ou de la fonction en question ?

James007 a écrit :

Par ailleurs, une astuce pourrait t'aider ..

Introduire des Sauvegardes ... car au moment du Save ... Excel purge sa mémoire ...

En espèrant que cela t'aide ...

Là j'ai pas trop compris, tu peux préciser s'il te plaît ?

Maxime

Re,

1. Concernant tes variables, je ne sais pas combien sont partagées ou pas, en Public ou pas, entre tous tes modules ... la nuance se situe entre ne plus disposer de la valeur de la variable et physiquement purger la mémoire de l'objet ...

L'instruction Set Noting fait d'une pierre deux coups ...

2. Si, reprendre tes milliers de lignes de code s'avère trop fastidieux ... insérer périodiquement des 'Save' ... conduit Excel à libérer sa propre mémoire tampon ...

En espèrant que tout cela t'aide ...

Re,

D'accord. Si j'ai bien compris :

Les variables ci-dessous gardent leur valeur car j'en ai besoin pour les process suivant (ça je savais)

Public PlantOnOff As Double, GT1OnOff As Double, GT2OnOff As Double, GT3OnOff As Double, HRSG1OnOff As Double
Public HRSG2OnOff As Double, HRSG3OnOff As Double, DB1OnOff As Double, DB2OnOff As Double, DB3OnOff As Double
Public NumberGTOn As Double, NumberHRSGOn As Double, NumberDBOn As Double, STOnOff As Double, NumberSTOn As Double, NumberMSFOn As Double
Public MSF1OnOff As Double, MSF2OnOff As Double, MSF3OnOff As Double, MSF4OnOff As Double, ConfigurationPlant As Variant
Public j As Double

Public OutputLoadMSF1 As Double, OutputLoadMSF2 As Double, OutputLoadMSF3 As Double, OutputLoadMSF4 As Double

Public EvapCoolerGT1OnOff As Byte, EvapCoolerGT2OnOff As Byte, EvapCoolerGT3OnOff As Byte

Mais les variables ci-dessous dans la sub, ne sont pu accessibles une fois sortie de la Sub, mais sont toujours sauvegardées quelque part, c'est ça ?

Sub AutoRunEfficiency()

'This function contains all the efficiency calculations (including error treatment) of the file
'+ input Raw data + display in Results sheet of the results

'i is the variable which change at every column for the display in Results sheet
'k is always equal to 2 but you could change it if you want to display the results value on another line
Dim i As Double, k As Double

'all the variables used only inside the file (no need to declare them as a public variable)

Dim NGMethane As Double, NGNitrogen As Double, NGCarbonDioxide As Double, NGEthane As Double, NGPropane As Double
Dim NGiButane As Double, NGnButane As Double, NGiPentane As Double, NGnPentane As Double, NGnHexane As Double
Dim NGHeptane As Double, NGOctane As Double, NGnNonane As Double, NGNeopentane As Double, NGWobbeIndexSm3 As Double
Dim NGTotalVolFlow As Double, NGSpecificGravity As Double, AmbientPressure As Double
Dim SWTempMSF1 As Double, SWTempMSF2 As Double, SWTempMSF3 As Double, SWTempMSF4 As Double

Dim NGVolFlowGT1 As Double, NGVolFlowGT2 As Double, NGVolFlowGT3 As Double
Dim NGVolFlowDB1 As Double, NGVolFlowDB2 As Double, NGVolFlowDB3 As Double

Je pensais avoir résolu ce problème en utilisant :

End

à la fin de ma sub principale, déjà affiché lors de mon premier message :

Sub Process()

[...]

'7th function called (in ResultsUserform Form)
'Show Userform  with the current values once all the calculations are finished
ResultsUserform.Show

'Delete all variable content before next execution
End

End Sub

Pour le

Save

, j'ai compris merci.

Cependant, à quel moment serait-il plus judicieux de le faire ?

Avant de lancer l'Userform, au début du run après le "réveil" de Application OnTime ? ...

Ou si je le fais à la toute fin, après le "End", je ne sais pas ce qu'il va se passer car mon UserForm est censé rester actif jusqu'au prochain lancement de l'application par Application OnTime

Pour sauvergarde, si mon fichier s'appelle : "Online Efficiency", je dois écrire :

Workbooks("Online Efficiency.xlsm").Save

, n'est ce pas ?

ou plutôt

Active.Workbooks.Save

Edit : J'avais pas pensé à l'enregistreur de macro, je dois utiliser :

ActiveWorkbook.Save

Merci,

Maxime

Re,

En ce qui concerne la sauvegarde :

ActiveWorkbook.Save

Re,

J'avais trouvé (CF edit), mais merci du tuyau en tout cas.

Quand j'arrivais au bureau le matin, Excel était bloqué en fait. J'étais obligé de forcer la fermeture avec le gestionnaire des tâches et je pense que la sauvegarde va vachement aider.

Verdict demain matin !

Bonne journée,

Maxime

Re,

Fais nous part de l'avancée de tes périgrinations ...

Re,

J'y manquerai pas. Si jamais ça bug, ça sera pas avant cette nuit donc à demain !

Bonjour,

la pile est un espace particulier où excel empile les adresses de retour entre autres, espace qui est réservé dès le lancement d'excel.

Par exemple sur une fonction récursive tu empiles l'adresse de retour à chaque fois qu'elle s'appelle. Si la taille de la pile n'est que de 4, au 5e tu as ce message d'erreur, même si tu as 16 Go de mémoire disponible.

Le plus souvent tu as cette erreur sur une boucle sans fin, ou dont la fin est mal évaluée ou mal détectée.

Si tu es sûr de la conception de ton programme (c'est la première cause) tu peux changer cette taille. Mais en intervenant sur l'exécutable Excel, ça ne sera valable que pour cette installation.

Pour contrôler ton programme consulte la pile des appels dans VBE au moment du plantage (menu Affichage), ça te confirmera éventuellement cette voie et ça aiguillera tes recherches.

Ceci dit bien nettoyer la mémoire, surtout sur un gros programme qui traite beaucoup de données, est une nécessité.

En plus des set obj=nothing tu peux aussi nettoyer les tableaux à la fin de leur utilisation avec Erase tableau.

eric

Bonjour eriiic,

En fait je tourne sur un PC 32 bits, par contrainte par rapport à l'autre fonction lancée à partir d'un deuxième fichier Excel (Run FDM, cf post 1, qui ne peut tourner que sur un 32 bit par conception. Et c'est une boîte noire, donc on peut rien modifier.)

Je me trouve donc limité à 4 Gb de RAM (dont 3 et des papates utilisable).

Je pense que mon programme est "bon" oui, car il fonctionne durant plusieurs heures, toutes les 10 minutes, avant que la pile ne sature.

Pour nettoyer la mémoire, est ce qu'un End en fin de procédure est suffisant ?

J'ai lu qu'il vidait les variables.

Je reprécise l'avoir déjà écrit en fin de programme (cf post 1)

J'ai seulement quelques sets lors de ma sauvegarde (cf post 1), et le Set = Nothing y apparaît. Donc pour ça c'est OK.

Mis à part End, puis-je nettoyer toutes les variables en une seule commande ou je dois le faire un par un ?

Variable1 = Nothing

[...]

VariableN = Nothing

Est-ce que suivant chaque type, le nettoyage est une instruction différente ? Là tu me parles de Erase Tableau, Set Nothing ... ?

Pour ce qui est de la pile, je ferais ça demain si mes modifications d'aujourd'hui n'ont pas suffit. Les ingé IT vont pas être trop content si je modifie de tels propriétés.

Merci.

Maxime

Bonjour et salut à tous !

Sans essayer de décortiquer ton code car difficile de tout voir à distance et cela prendrait beaucoup trop de temps... si ton programme tourne déjà 8 ou 9 heures avant de déclarer forfait cela laisse penser que rien de dramatique mais une accumulation progressive qui finit par saturer la pile des appels...

Lorsque tu es en mode arrêt, suite à l'erreur d'exécution, il convient de commencer par vérifier la liste des appels de procédure actifs au moment de l'arrêt. Cela te donnera une idée plus précise de ce qui est en cours et voir ce qui pourrait et devrait être achevé à ce moment... Dans le cas d'imbrications d'appels de procédures, certaines peuvent rester ouvertes jusqu'à ce que la procédure appelante soit fermée.

Je ne pense pas qu'il y ait problème de saturation mémoire dû aux variables... Il est vrai que l'instruction End a pour effet de réinitialiser toutes les variables modules et statiques, mais (je ne raffole pas !) c'est fait un peu à la hussarde, sans s'occuper des composants actifs qui éventuellement le demeurent... Les variables locales n'ont en principe pas d'impact, sauf si trop de variables locales dans une procédure, aboutissant à dépasser l'espace qui leur est dévolu, ou si (on y revient) de nombreuses procédures ne sont pas fermées et leur variables sont donc toujours présentes...

C'est pourquoi je pense que la liste des appels fournira des indices sur la source du problème...

Sur ce, je vais terminer mes bagages... Bonne continuation.

Bonjour MFerrand,

Merci pour ces explications,

Comme je l'ai expliqué lors de mon premier post, le moment où ça bug est lors de l'ouverture du fichier déjà existant pour la sauvegarde.

Mon module principal est celui-ci :

'6th function called (in SaveFunction module)
'Saving function into a daily and monthly file into desktop
SaveEfficiencyResultsDesktop
'Saving function into a daily and monthly file into shared operation folder
SaveEfficiencyResultsOperationFolder

'7th function called (in ResultsUserform Form)
'Show Userform  with the current values once all the calculations are finished
ResultsUserform.Show

'Delete all variable content before next execution
End

End Sub

Je n'ai mis que la fin du module

Et la fonction sauvegarde est la suivante :

Sub SaveEfficiencyResultsDesktop()

'Sub which is copying and pasting into 2 different files the results from EfficiencyCalculation file in Results sheet :

'1)Creation of a daily file the 1st time containing the results
'After that we open it and add each result until the end of the day

'2)Creation of a monthly file the 1st time containing the results
'After that we open it and add each result until the end of the month

Dim CopyRangeDay  As Range
Dim FirstEmptyLineDay As Long
Dim CopyRangeMonth  As Range
Dim FirstEmptyLineMonth As Long

StartTime = Range("StartTime").Value

'-------------DAILY FILE--------------------------------

'This is today's date with day + Month + year
DateToday = Day(StartTime) & "-" & MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'Location of the file
PathDay = Dir("C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateToday & ".xls")

'File already exists
If PathDay <> "" Then

'Open the existing file containing the result
Workbooks.Open Filename:="C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateToday & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineDay = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy

'Selection of the first cell for paste purpose, using First EmptyLineDay calculating here before
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineDay).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Columns.AutoFit

'Non Existing file
Else

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a folder on the desktop
ActiveWorkbook.SaveAs Filename:= _
    "C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" _
    & DateToday & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeDay = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateToday).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)

'-------------MONTHLY FILE--------------------------------

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'This is the date with only month + year
DateMonth = MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Location of the file
PathMonth = Dir("C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateMonth & ".xls")

'File already exists
If PathMonth <> "" Then

'Open the existing file containng the result
Workbooks.Open Filename:="C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateMonth & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineMonth = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy

'Selection of the first cell for paste purpose, using First EmptyLineMonth calculating here before
Workbooks(DateMonth & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineMonth).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
ActiveSheet.Columns.AutoFit

'Non Existing file
Else

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")

'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a folder on the desktop
ActiveWorkbook.SaveAs Filename:= _
    "C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" _
    & DateMonth & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeMonth = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateMonth).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)
End Sub

Sub SaveEfficiencyResultsOperationFolder()

'Sub which is copying and pasting into 2 different files the results from EfficiencyCalculation file in Results sheet :

'1)Creation of a daily file the 1st time containing the results
'After that we open it and add each result until the end of the day

'2)Creation of a monthly file the 1st time containing the results
'After that we open it and add each result until the end of the month

Dim CopyRangeDay  As Range
Dim FirstEmptyLineDay As Long
Dim CopyRangeMonth  As Range
Dim FirstEmptyLineMonth As Long

StartTime = Range("StartTime").Value

'-------------DAILY FILE--------------------------------

'This is today's date with day + Month + year
DateToday = Day(StartTime) & "-" & MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'Location of the file
PathDay = Dir("Y:\" & DateToday & ".xls")

'File already exists
If PathDay <> "" Then

'Open the existing file containing the result
Workbooks.Open Filename:="Y:\" & DateToday & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineDay = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy

'Selection of the first cell for paste purpose, using First EmptyLineDay calculating here before
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineDay).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
Workbooks(DateToday & ".xls").Worksheets("Efficiency Results").Columns.AutoFit

'Non Existing file
Else

'CopyRangeDay will selected all the designated area of the sheet
Set CopyRangeDay = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")
'Copy the selected area with CopyRangeDay
CopyRangeDay.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a shared folder
'\\192.168.3.1\sohar-1\OPERATIONS\WONDERWARE-REPORTS
ActiveWorkbook.SaveAs Filename:= _
    "Y:\" _
    & DateToday & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeDay = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateToday).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)

'-------------MONTHLY FILE--------------------------------

'Test to check if the file is already existing
'If so, we just have to open it and add the line of calculation
'If not, we have to create it

'This is the date with only month + year
DateMonth = MonthName(Month(StartTime)) & "-" & Year(StartTime)

'Location of the file
PathMonth = Dir("Y:\" & DateMonth & ".xls")

'File already exists
If PathMonth <> "" Then

'Open the existing file containng the result
Workbooks.Open Filename:="Y:\" & DateMonth & ".xls"

'Find the first empty line to know where starting the results paste
FirstEmptyLineMonth = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row + 1

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A2:DU2")
'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy

'Selection of the first cell for paste purpose, using First EmptyLineMonth calculating here before
Workbooks(DateMonth & ".xls").Worksheets("Efficiency Results").Range("A" & FirstEmptyLineMonth).Select
'Paste of the results into the cells
ActiveSheet.Paste

'Autofit of columns
ActiveSheet.Columns.AutoFit

'Non Existing file
Else

'CopyRangeMonth will selected all the designated area of the sheet
Set CopyRangeMonth = Workbooks("Online Efficiency.xlsm").Sheets("Results").Range("A1:DU2")

'Copy the selected area with CopyRangeMonth
CopyRangeMonth.Copy
'Open a new Excel file
Workbooks.Add

'Rename the current sheet Efficiency Results
ActiveSheet.Name = "Efficiency Results"

'Paste the selected area content into the new sheet
ActiveSheet.Paste

'Delete Sheet 2/3
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Sheet2").Delete
ActiveWorkbook.Sheets("Sheet3").Delete
Application.DisplayAlerts = True

'Save it as a new file whose name is the current date in a shared folder
'\\192.168.3.1\sohar-1\OPERATIONS\WONDERWARE-REPORTS
ActiveWorkbook.SaveAs Filename:= _
    "Y:\" _
    & DateMonth & ".xls", _
    FileFormat:=xlNormal, Password:="", WriteResPassword:="", _
    ReadOnlyRecommended:=False, CreateBackup:=False

'Autofit of columns
ActiveSheet.Columns.AutoFit

End If

'Release memory
Set CopyRangeMonth = Nothing

'Unselect the coppied cells
Application.CutCopyMode = False

'Close the results workbook at the end of the process
Workbooks(DateMonth).Close True
'True if you want to save it while it closes (required otherwise a pop-up will appear asking you to save it or not)
End Sub

Comme indiqué, l'élément en surbrillance lors du débuguage est le suivant :

'Open the existing file containing the result
Workbooks.Open Filename:="C:\Users\maxime\Desktop\ResultsOnlineEfficiency\" & DateToday & ".xls"

Si jamais le problème apparaît toujours demain, je tâcherai de regarder au niveau des appels.

Merci et bonnes vacances !

Maxime

Je pense que tu as mal lu ma réponse

la pile est un espace particulier où excel empile les adresses de retour entre autres, espace qui est réservé dès le lancement d'excel.

et les pointeurs des variables en cours d'utilisation etc.

Ce n'est pas un problème de taille mémoire (même s'il peut exister en parallèle) mais de pile saturée.

Comme je te l'ai dit tu peux avoir cette erreur même avec 16 Go disponible suite à une mauvaise conception du code (ou trop de variables ou que sais-je encore, mais leur nombre en tant que tel, pas leur occupation mémoire où tu aurais un autre message d'erreur)

Ce que te confirme MFerrand.

Donc oui, 1ère chose à faire : consulter la pile des appels qui si elle est pleine te confirmera un éventuel défaut de conception du code. Une proc qui se rappelle elle même par exemple jusqu'à saturation. Ou trop d'appels emboités les uns dans les autres, là ce n'est plus forcément une erreur mais il faut trouver une autre façon de faire.

Et ta ligne en erreur n'a sûrement rien à voir avec le pb. C'est juste qu'arrivé à ce point là il n'a plus de place, place qui peut être occupée à tort pour tout une autre cause.

eric

Re,

En fait j'avais bien compris que la pile est indépendante de la RAM (je l'ai vu en cours d'ailleurs), mais je sais pas pourquoi je l'ai précisé en fait..

Ok pour la ligne d'erreur.

Il faut faire Ctrl + L pour ouvrir la pile en mode débug, n'est ce pas ? (je l'ai lu mais je suis pas sûr, n'ayant jamais eu affaire à la pile)

Je vous tiendrai au courant demain,

Merci.

Maxime

Oui, Ctrl+L ou menu Affichage comme dit précédemment

Bonjour à tous,

Feedback de ce matin :

Toujours le même problème, ça pointe au même endroit mais ça a duré quelques heures de plus avant de bugguer.

Je joins une photo de l'endroit en surbrillance avec la pile en premier plan.

La première fonction dans la pile est la fonction dans laquelle se trouve la ligne de code qui est actuellement en jaune (SaveEfficiencyResultsDesktop)

Après j'ai 232 lignes de plus (donc 233 en tout) qui composent la pile (oui j'ai compté 1 par 1 ), et c'est des cycles de 3 fonctions :

  • Clock.Process (la fonction appelée par Application Ontime)
  • Clock.ReloadRawData (la première fonction appelée par Process)
Après c'est écrit :

- [<Non-Basic Code>]

Ensuite ça revient à Process.

Question : Est-ce qu'il est possible que la pile est changée en 4/5 heures (moment où ça bug et moment où j'arrive au boulot) ? Je pense pas mais vous serez mieux placé que moi.

Je sais pas trop quoi conclure de la pile, à part que je dois sûrement augmenter la taille de la pile car si ça plante à 232, ça fait pas beaucoup de taille pour la pile.

Dans le lien transmis hier pour la modification manuelle, en supposant que la taille maximale de ma pile soit 232, ça fait pas beaucoup comparé au 3175 appels de =JBO= sachant que ça correspond à 1 Mo. Ca voudrait dire que j'ai seulement quelques Ko de pile, c'est que dalle.

D'autres idées (avant que je quitte le débug) ?

Sinon je vais changer le stack manuellement (du moins essayer).

Merci à tous,

Maxime

screen stack

Bonjour,

As-tu introduit des 'Save' périodiques dans ton code ...???

Salut James007,

Oui, il y en a un à chaque fin de processus, juste avant que l'Userform n'apparaisse :

Sub Process()

[...]

'5th function called (in FDM module)
'If plant ON, run FDM function in FDM module
If PlantOnOff = 1 Then
RunFDM
End If

'6th function called (in SaveFunction module)
'Saving function into a daily and monthly file into desktop
SaveEfficiencyResultsDesktop
'Saving function into a daily and monthly file into shared operation folder
SaveEfficiencyResultsOperationFolder

'7th function used
ActiveWorkbook.Save 

'8th function called (in ResultsUserform Form)
'Show Userform  with the current values once all the calculations are finished
ResultsUserform.Show

'Delete all variable content before next execution
End

End Sub

Je sauvegarde aussi le deuxième fichier duquel je lance la fonction "FDM" une fois avoir récupéré ses résultats. (5ème fonction ci-dessus)

Maxime

Rechercher des sujets similaires à "espace pile insuffisant solution"