Erreur : Mémoire insuffisante (non compréhensible)

Signaler
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015
-
Messages postés
14737
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
14 novembre 2020
-
Bonjour,
je suis sous excel vba

j'ai créé un type de données

Type UneDonnéeDico
    LeAP As String * 89
    LeAQ As Integer '2 octets
    LeAràAZ(9) As Single '4 octets
    LeBBàCS(44) As Integer '2 oct
    LeDate As Date '8 octets
End Type


j'ai créer un tableau :


Dim LesDonnéesDico() As UneDonnéeDico


pour enregistrer des données,
et comme celles ci sont nombreuses, je redim progressivement le tableau:
dans une sub qui est régulièrement appelée j'ai:

    
If RienLDico Mod 1000 = 0 Then
    ReDim Preserve LesDonnéesDico(RienLDico + 1001)
End If
 RienLDico = RienLDico + 1


et là, je rempli les éléments de LesDonnéesDico(RienLDico)

lorsque RienLDico atteint 874000, j'ai l'erreur "Mémoire insuffisante (erreur 7)" qui se produit à : ReDim Preserve LesDonnéesDico(RienLDico + 1001)

la taille de UneDonnéeDico est de :=89+2+10*4+45*2+8=229 octets

ReDim Preserve LesDonnéesDico(RienLDico + 1001) nécessite donc :

875000 * 229= 200,375 méga octets

j'ai 6 giga octets de mémoire sur mon ordi
merci de votre aide
Très cordialement
Claude

19 réponses

Messages postés
14737
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
14 novembre 2020
148
Arriver à un moment, il faut se rendre compte que VBA n'est plus suffisant (et c'est déjà pas mal qu'il arrive à cela pour un simple tableur)..
http://www.commitstrip.com/fr/2014/07/23/excel-the-poor-mans-ideexcel-lide-du-pauvre/

Si tu as autant de données à gérer (2Go par paquet de 229 octets), il faut se poser la question "est-ce que l'outil que j'utilise est adapté ?".

Donc bien que .NET (gratuit en version Express) regroupe différents langages (VB, C#, ...), il reste facile d'accès, à condition de reprendre des bases en programmations (penser objet, architecture, ...).

Si tu as beaucoup l'habitude de VBA, VB.NET te sera plus facile d'accès (même si les langages se ressemblent, ils sont assez différents).

http://openclassrooms.com/courses/apprenez-a-programmer-en-vb-net
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

avec ce code plus simple:


Option Explicit
Option Base 1
'=89+2+10*4+45*2+8

Type UneDonnéeDico
LeAP As String * 89
LeAQ As Integer '2 octets
LeAràAZ(9) As Single '4 octets
LeBBàCS(44) As Integer '2 oct
LeDate As Date '8 octets
End Type
Dim rienldico As Long

Dim LesDonnéesDico() As UneDonnéeDico

Sub MettreDansFeuille_B5()
For rienldico = 1 To 1000000
    If rienldico Mod 1000 = 0 Then
    ReDim Preserve LesDonnéesDico(rienldico + 1001)
   
    End If
Next rienldico
End Sub

j'ai la même erreur au meme endroit pour la meme valeur de rienldico (874000 qui donnera 875000)

merci de votre aide
Claude
Messages postés
30277
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
23 novembre 2020
338
Bonjour,

'=89+2+10*4+45*2+8

en fait c'est
'=(89+10)+2+10*4+45*2+8
car une String c'est 10 + le nombre de caractères....

Concernant le souci en lui même je ne sais pas trop.
Déjà... il faudrait que nous sachions sur quelle version d'Excel tu es. (car les limites ne sont pas les mêmes d'une versions à une autre).
Ensuite... 6Giga de ram ok.. mais il ne faut pas oublier que tu as ton OS qui tourne ainsi que d'autres logiciels (dont Excel lui même).


Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

bonjour,
je suis sous excel 2007
je n'ai que windows et excel qui tournent
Messages postés
14737
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
14 novembre 2020
148
LeBBàCS
LeBBàCS
On évite les noms avec des accents.

Il me semble que VBA est bloqué en 32 bits, donc même avec 6Go de RAM, ton VBA ne peut dépasser 1.5Go (et en visant large).
Redim Preserve, fait une réallocation de la mémoire (ancienne -> nouvelle plus grande), donc, 2* la conso en RAM durant l'opération.
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
232
Bonjour,
C'est un peu plus compliqué que ce que l'on pense.
Il y a déjà d'énormes différences entre une version de Excel et l'autre. Il est par exemple important de savoir que le gestionnaire de mémoire des versions 95, 97, 2000, 2002 et 2003 n'utilise ni la ram disponible, ni la mémoire virtuelle (et ce : quel que soit le système d'exploitation). Qu'il est donc totalement vain, avec ces versions, de tentger d'améliorer les choses (pour ces versions) en ajoutant des barrettes de mémoire ou en augmentant la taille allouée au "swapp".
Excel connaît ses limites, y compris pour les versions ultérieures. Il serait long de tenter de toutes les exposer ici. Contentons-nous de parler de certaines gourmandises (couleurs, polices, bordures, etc ...) assez importantes.
Ajoutons à tout cela le fait que le redimensionnement (avec Preserve) d'un tableau dynamique semble (je dis bien semble) se faire via le "doublement" du tableau (un nouveau redimensionné et la copie de l'ancien vers le nouveau, puis remplacement de l'ancien par le nouveau)...
Tout cela finit par faire beaucoup beaucoup beaucoup !
Je ne vois pas comment résoudre facilement ton problème, ClaudeDordogne, si tu as besoin de toutes les données présentes à chaque instant.
J'y réfléchirai nonobstant demain matin, à tout hasard.

Au fait : ton calcul d'octets est bon, mais le corse que je suis à demi, aurait évité cet effort.
Regarde :
Dim coucou As UneDonnéeDico
MsgBox Len(coucou) ' =====>> 229, bien sûr

Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

Bonsoir,
merci de tes conseils

dans l'aide d'excel il est noté :
Mémoire insuffisante (erreur 7)
Particularités

La mémoire disponible est insuffisante, ou une limite de segment de 64 Ko a été rencontrée. Causes et solutions de cette erreur :

Vous exécutez Microsoft Windows en mode standard.
Relancez Microsoft Windows en mode étendu.

Vous exécutez Microsoft Windows en mode étendu, mais vous avez épuisé toute la mémoire virtuelle.
Pour augmenter la capacité de mémoire virtuelle, libérez de l'espace disque, ou vérifiez qu'un espace minimal est disponible.

Des programmes résidents sont chargés.
Retirez les programmes résidents.

Trop de pilotes de périphérique sont chargés.
Retirez les pilotes de périphérique inutiles.

Vous n'avez plus de place pour des variables Public.
Réduisez le nombre de variables Public.

Un point me semble pas clair :
Vous exécutez Microsoft Windows en mode standard.
Relancez Microsoft Windows en mode étendu.

mais comment relancer windows en mode étendu???
merci d'avance
claude
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
232
laisse tomber cette possibilité de relancer en mode étendu. D'autant que cette possibilité ne dépend par que de Windows, mais également de ce qu'a prévu le constructeur de ta machine.
A demain.
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
232
Avant de me mettre au dodo : regarde déjà cet article :
http://smallbusiness.support.microsoft.com/fr-fr/kb/455768
Ned tente pas ce genre de manoeuvre.
Bonne nuit
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

Salut :)
229 ok
effectivement il y a un espèce de doublement avec préserve
car on a :
Option Explicit
Option Base 1

Type UneDonnéeDico
LeAP As String * 89
LeAQ As Integer '2 octets
LeAràAZ(9) As Single '4 octets
LeBBàCS(44) As Integer '2 oct
LeDate As Date '8 octets
End Type
Dim LesDonnéesDico(1400000) As UneDonnéeDico

Sub un()
MsgBox Len(LesDonnéesDico(1))
LesDonnéesDico(1).LeAQ = 5
End Sub

qui fonctionne : ça passe
mais pas
Dim LesDonnéesDico(1500000) As UneDonnéeDico

qui plante lamentablement excel

que penses tu de relancer Microsoft Windows en mode étendu???
Merci
Claude
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

Pour le mode étendu... Je SUIS tes conseils, pas la peine d'aller chercher les galères ....
merci
bonne nuit :)
Messages postés
14737
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
14 novembre 2020
148
Question bête, as-tu essayé de compter le nombre de case à générer dès le début et ensuite faire un seul redim ?
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
232
Ce problème m'empêche de dormir.
Bon ...
Si je devine tout bien (du fait que tu utilises une structure).
Ton tableau est issu de l'exploitation d'un fichier texte structuré de la même manière.
J'ai bon ?
Si oui, voici ce que je tenterais personnellement :
- à l'ouverture de la session ===>> mon tableau à partir du fichier. Le nombre de lignes de ce tableau étant calculable (filelen/len(enregistrement), on peut d'emblée dimensionner le tableau et donc éviter les redim preserve.
- si, en cours de session, tu as des articles à créer ===>> mets-les donc dans un second tableau de la même structure (en utilisant redim preserve pour ce second tableau uniquement).
- si, toujours en cours de session, tu as à consulter, consulte le premier tableau, puis, si non trouvé, le second et décide en fonction de ce que ainsi trouvé ou totalement absent.
- en fin de session ===>> ajoute à ton fichier texte structuré les données du second tableau. (il sera complet à l'ouverture de la session suivante et ... rebelote ...)
Tu suis l'idée ?
Bonne nuit (en espérant que je parvienne cette fois-ci à dormir).
Messages postés
18038
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
232
Que stockes-tu dans le membre LeAP de ta structure ?
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

Bonjour,

"Ce problème m'empêche de dormir."... il ne faut pas , je suis désolé pour cela.

Ton tableau est issu de l'exploitation d'un fichier texte structuré de la même manière. :

en fait LeAP est un résultat stocké sous forme de code alphabétique d'un calcul de comparaison complexe sur une série de données, il y a 89 résultats de comparaison et donc 89 lettres les résumant.
chaque LeAP entraine une valeur différente pour: LeAQ ,chacun des 9 LeAràAZ et chacun des 44 LeBBàCS

LeDate n'est là que pour repérer le point d'entrée du calcul sur les données

par exemple LeAQ correspond à la fréquence du LeAP retrouvé dans les données (varie de 1 à environ 300)

au début je suis parti d'un tableau sur feuille excel et donc AP,AQ,AR,AZ,BB,CS se réfèrent au nom des colonnes de la feuille excel... que j'ai abandonné vue la lenteur d'affichage des feuilles et la limite à 10^6 lignes.

comme tu le constatera AR à AZ =9 colonnes, idem BB à CS = 44 colonnes.... d'où le à dans le nom de la variable

le nombre de cases à générer dès le début est impossible à connaitre car dépendant du résultat de mon calcul complexe, de plus même en faisant un seul dim "maxi" (1 500 000 environ), cela est insuffisant....

- si, toujours en cours de session, tu as à consulter:

non pas de consultation dans cette partie de construction du tableau mais uniquement de la création.

j'ai bien pensé transférer les LesDonnéesDico sur un fichier structuré sur disque, mais si à chaque fois... beaucoup trop long
et je ne vois pas comment transférer par paquet (par exemple quand j'arrive à 100 000 LesDonnéesDico) en les ajoutant au fichier disque et en réinitialisant ensuite LesDonnéesDico pour repartir à 1.
ceci car il ne s'agit pas d'un fichier texte.
et pour les relire ensuite avec comme clé LeAP?
c'est pour cela que j'avais pensé au dictionnaire :)

amicalement

Merci en tout cas
Claude
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

Salut,
Suite à tes conseils, j'ai sauvegardé par
paquet de" 140 LesDonnéesDico " sur le disque grâce à un put :

Const NbEltàLaFois = 140 
'Est un Max car Len du fichier est un entier et donc 229*140 =32060 ...
Sub OuvreLesFichiersPourEcrire()
'bla bla
intFic3 = FreeFile
Open NomFichier3 For Random As intFic3 Len = CLng(NbEltàLaFois + 1) * Len(LesDonnéesDico(1))
RecordNumber_intFic3 = 0
end sub

Sub MettreDansFeuille_B5()
For RienL = 1 To NbLignesàAfficher 'nb lignes qui existent
    If RienLDico Mod NbEltàLaFois = 0 Then
         If RienLDico > 0 Then
            RecordNumber_intFic3 = RecordNumber_intFic3 + 1
            Put intFic3, RecordNumber_intFic3, LesDonnéesDico
         End If
        ReDim LesDonnéesDico(NbEltàLaFois)
        RienLDico = 0
    End If
     RienLDico = RienLDico + 1

'ici je rempli LesDonnéesDico(RienLDico)
  
Next RienL
End Sub


j'arrive à relire sans problème par une sub avec get

mais pb:
le fichier NomFichier3 plante quand il atteint 2 giga octets ....
(représentant 9311260 LesDonnéesDico de 229 octets chacun....)

cette limite de 2 giga est elle structurelle?
il y a t il un moyen de la contourner???
d'après mes estimation la totalité devrait faire entre 30 et 40 giga !!
Merci pour ton aide PRECIEUSE
Claude
Messages postés
14737
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
14 novembre 2020
148
2Go, ça ressemble beaucoup à la limite d'un 32 bits signé, cela n'est donc pas étonnant.
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

bonsoir
le 32 bit est il une limite structurelle de excel?
mais comment alors créer des fichiers de plus de 2 giga?
merci
Claude
Messages postés
14737
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
14 novembre 2020
148
As Integer '2 octets
L'entier est la base, on peut monter jusqu'au long qui lui est sur 4 octets donc 32 bits signés.

Donc, même si VBA voudrait aller plus loin, il lui faudrait utiliser une structure plus complexe (qui regrouperait 2 long) et les fonctions d'écriture et de lecture de fichiers ne sont pas adaptées à cela.

Par contre, si tu automatise ton ficher en le commandant à partir de .NET (64 bits évidemment) (par exemple), tu pourrais aller largement plus loin.
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

merci
cependant je ne connais pas .NET... qu'est ce que c'est et comment l'utiliser dans ce cas où le reste du programme est écrit en vba excel?
merci de ton aide
Messages postés
47
Date d'inscription
mardi 13 janvier 2015
Statut
Membre
Dernière intervention
7 mars 2015

bonjour,
ce qui me chagrine c'est que le nombre d'enregistrements est limité à 9311260.... je ne vois pas la relation entre excel et la taille du fichier sur disque, puisqu'excel n'écrit qu'un enregistrement un endroit sur le disque...
merci
vb.net : cela m'embête de tout reprogrammer, alors que c'est le dernier point non résolu de mon programme (assez complexe)...
Messages postés
14737
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
14 novembre 2020
148
On ne parle pas d'écrire sur le disque, mais d'occupation mémoire.

Certes, passer à VB.NET t'embête, mais il faut aussi savoir que 9'311'260 enregistrements, c'est déjà énorme. On ne peut pas demander à un langage qui est là "juste pour dépanner" de faire le café non plus.

Soit tu revois la manière de traiter tes enregistrements (càd en charger moins en même temps) soit tu passes à un langage plus adapté.