Déconnecter un graphique (même gros) de sa source (VBA)
Il y a plusieurs méthodes pour obtenir un graphique qui ne soit pas lié à une page Excel contenant
les données source chiffrées.
- La plus simple consiste à copier le graphique sous forme d'image. Pour ce faire, il suffit de sélectionner le graphique, de maintenir appuyée la touche MAJ en cliquant sur Edition, puis de cliquer sur "copier une image", avant de coller le graphique à l'endroit souhaité.
- Par macro, on peut également copier le graphique sous forme d'image .gif (cliquez ici).
Inconvénient de ces deux techniques, le graphique est complètement figé et ne peut même plus être mis en forme.
- On peut aussi inscrire directement les données sous forme de matrice dans les "données source" du graphique :
Graphique / Données source / valeur ={5\7\9.5\8\4\3\7\5.2}
- A partir d'un graphique existant, il suffit de sélectionner une série, de placer le curseur dans la barre de formule, puis de taper la touche F9 pour remplacer les références à une plage de cellule par la matrice correspondante.
- La même opération est réalisée aisément par macro en utilisant
SeriesCollection(1).Name = SeriesCollection(1).Name
SeriesCollection(1).Values = SeriesCollection(1).Values
SeriesCollection(1).XValues = SeriesCollection(1).XValues
Les dernières méthodes se heurtent à une difficulté liée au fait que l'espace dans lequel sont stockées les données sous forme de matrice est limité.
Au delà d'un certain volume de données, Excel cale et ne peut afficher le graphique.
Le problème est amplifié quand les données proviennent d'un calcul et contiennent beaucoup de décimales.
Une solution, certes un peu laborieuse permet de contourner ce problème : l'utilisation de l'espace de stockage disponible dans les "names" que peut contenir tout classeur Excel.
Ces names peuvent également contenir un volume limité de données, mais on peut utiliser un grand nombre de names (matrices de données coupées en morceaux).
Le fichier Excel proposé au téléchargement contient une macro VBA qui réalise cette opération.
Il ne comprend qu'une page ("datas") contenant une seule plage de données ("plagx"). Dans l'exemple retenu, plagx contient 1000 points d'une fonction conduisant à des chiffres comprenant un grand nombre de décimales (15 chiffres par valeur).
La macro va couper la matrice contenant les données de plagx en sous-macros plus petites (200 caractères maxi par macro) et placer ces sous-macros dans des names.
Ensuite, la macro opère un travail de reconsolidation de la matrice dans un nouveau name (matx),
puis crée un nouveau classeur contenant le graphique... sans page de données.
Attention, l'opération de création du graphique peut être un peu longue
Ne fonctionne que si la série ne contient que des données chiffrées (pas de texte, pas de #N/A...).
cliquez ici pour télécharger le fichier excel (zippé)
Texte de la macro :
Sub graph()
lenmax = 200
Set nouv = Workbooks.Add(xlWBATWorksheet) 'nouveau fichier
Set gr = Charts.Add
gr.ChartType = xlLineMarkers
nouv.Worksheets(1).Visible = xlVeryHidden
'balayer la plage de données
Set plagx = ThisWorkbook.Sheets("datas").Range("plagx")
num = 1
nummat = 0
décal = 0
nouvmat:
nummat = nummat + 1 'numérote la matrice
matx = ""
matxnew = ""
nouvpt:
matx = matxnew
matxnew = matx & ";" & plagx.Cells(num)
num = num + 1
'nouveau point si on n'est pas au bout de matx
'ou si la longueur de matnew ne dépasse pas la limite
If num <= plagx.Count + 1 And Len(matxnew) < lenmax Then GoTo nouvpt
matx = Right(matx, Len(matx) - 1)
matx = "={" & matx & "}"
nouv.Names.Add Name:="matix" & nummat, RefersToR1C1:=matx
matprec = "=matx" & (nummat - 1) & "+"
If nummat = 1 Then matprec = "="
nouv.Names.Add Name:="matx" & nummat, RefersToR1C1:= _
matprec & "MMULT(1*(ROW(OFFSET(Feuil1!R1C1,0,0," & _
plagx.Cells.Count & ",COUNT(matix" & _
nummat & ")))=COLUMN(OFFSET(Feuil1!R1C1,0,0," & _
plagx.Cells.Count & ",COUNT(matix" & nummat & ")))+" _
& décal & "),matix" & nummat & ")"
num = num - 1
décal = num - 1
'nouvelle matrice si on n'est pas au bout de la plage
If num <= plagx.Count Then GoTo nouvmat
nouv.Names.Add Name:="matx", RefersToR1C1:="=matx" & nummat
'tracer le graphe
gr.SeriesCollection.NewSeries
gr.SeriesCollection(1).Values = "=" & nouv.Name & "!matx"
gr.SeriesCollection(1).MarkerStyle = xlNone
gr.Deselect
End Sub
cliquez ici pour télécharger le fichier excel (zippé)
Remarque
Pour le cas précis de l'exemple mentionné dans le fichier à télécharger, qui utilise une série de chiffres calculés par une simple fonction, on peut obtenir le même résultat très simplement en se contentant d'entrer la fonction dans une zone de noms.
La fonction est y=x^2*SIN(x/20).
Il suffit donc d'entrer =LIGNE(Feuil1!$A$1:$A$1000)^2*SIN(LIGNE(Feuil1!$A$1:$A$1000)/20) dans la zone de noms "mat", puis de créer un graphique avec mat comme valeurs pour obtenir le graphique avec 1000 points (x variant de 1 à 1000).