J'utilise Excel sur MacOS. Les informations "À propos de" me disent qu'il s'agit de la version 16.16.5, qui correspond apparemment à Office 2016. Si vous regardez le code ici et pensez "hé, ça marche pour moi", ce serait formidable si vous pouviez laisser un commentaire qui inclut la version d'Excel que vous utilisez.
J'ai une feuille de calcul dans laquelle je voudrais copier des graphiques d'une feuille de calcul "modèle" dans env. 80 autres feuilles de calcul, puis modifiez-les pour faire référence aux données de la feuille de destination plutôt qu'à la feuille d'origine (via une simple recherche et remplacement sur la série).
Cela ne semble pas à première vue tout cela est difficile, et il y a beaucoup de solutions potentielles à la fois ici sur Stack Overflow et ailleurs, mais je semble continuer à rencontrer un comportement inattendu.
Pour les exemples ci-dessous, le code copie simplement les graphiques d'une feuille de calcul vers un autre, plutôt que d'itérer sur toutes les feuilles de calcul disponibles, car cela facilite le nettoyage en cas d'échec. Ce qui, jusqu'à présent, l'est toujours.
Ma première tentative ressemblait à ceci:
For Each chSeries In newChartObj.Chart.SeriesCollection
Cela fonctionne presque : il copie en fait les graphiques dans la feuille de calcul de destination. Cependant, il échoue à cette ligne:
Sub Copy_Charts()
Dim DataSheetName1 As String, DataSheetName2 As String
Dim sourceChartSheet As Worksheet, destChartSheet As Worksheet
Dim chartObj As ChartObject, newChartObj As ChartObject
Dim chartObjCopy As ChartObject
Dim chSeries As Series
Dim chartIndex As Integer
DataSheetName1 = "CU-2"
DataSheetName2 = "CU-8"
Set sourceChartSheet = Sheets("CU-2")
Set destChartSheet = Sheets("CU-8")
For Each chartObj In sourceChartSheet.ChartObjects
' No idea why chartObj.Duplicate returns something other
' than a ChartObject.
Set newChartObj = chartObj.Duplicate.Chart.Parent
newChartObj.Top = chartObj.Top
newChartObj.Left = chartObj.Left
newChartObj.Chart.Location xlLocationAsObject, destChartSheet.Name
For Each chSeries In newChartObj.Chart.SeriesCollection
chSeries.FormulaR1C1 = Replace(chSeries.FormulaR1C1, DataSheetName1, DataSheetName2)
Next
Next chartObj
End Sub
L'erreur est "Erreur d'exécution '1004': Erreur définie par l'application ou définie par l'objet".
Et en fait, si vous regardez destChartSheet.ChartObjects.Count à ce stade, il s'affiche toujours comme 0 . De plus, si vous essayez de supprimer les graphiques en utilisant un code comme celui-ci:
Sub Delete_Charts()
Dim sht As Worksheet
For Each sht In ActiveWorkbook.Worksheets
If sht.Name <> "CU-2" Then
If sht.ChartObjects.Count >= 1 Then
sht.ChartObjects.Delete
End If
End If
Next sht
End Sub
Cela ne supprimera pas réellement les graphiques. Le même code de suppression fonctionne très bien si vous copiez et collez les graphiques à la main.
En résumé: ce code copie les graphiques, mais je ne peux pas obtenir de référence à la copie afin de le modifier , je ne peux pas non plus le supprimer.
J'ai décidé de lancer le copier-coller hors de la fenêtre et d'essayer la méthode Duplicate à la place. Je me suis retrouvé avec ce qui suit:
Set chartObjCopy = destChartSheet.ChartObjects(chartIndex)
Cela fonctionne (et échoue) différemment de la première solution: il copie aussi les graphiques dans la feuille de calcul cible , et contrairement à l'exemple précédent, il est possible de supprimer ces graphiques en utilisant cette sous-routine Delete_Charts .
Malheureusement, ce code échoue à:
Sub Copy_Charts()
Dim DataSheetName1 As String, DataSheetName2 As String
Dim chartObj as ChartObject, chartObjCopy as ChartObject
Dim sourceChartSheet as Worksheet, destChartSheet as Worksheet
DataSheetName1 = "CU-2"
DataSheetName2 = "CU-8"
Set sourceChartSheet = Sheets(DataSheetName1)
Set destChartSheet = Sheets(DataSheetName2)
For Each chartObj In sourceChartSheet.ChartObjects
chartObj.Copy
destChartSheet.Range(chartObj.TopLeftCell.Address).PasteSpecial xlPasteAll
chartIndex = chartIndex + 1
Set chartObjCopy = destChartSheet.ChartObjects(chartIndex)
chartObjCopy.Left = chartObj.Left
chartObjCopy.Top = chartObj.Top
Next chartObj
End Sub
4 Réponses :
Je pense que lorsque l'emplacement du graphique est déplacé, cela change la référence à l'objet graphique, ce qui entraîne l'échec de la collection de séries.
J'ai pu reproduire le problème, et le code ci-dessous fonctionne, mais je suis sur PC, donc je ne suis pas à 100% si des modifications supplémentaires seraient nécessaires pour être opérationnel sur Mac. Si vous déplacez cette ligne:
newChartObj.Chart.Location xlLocationAsObject, destChartSheet.Name
après la boucle SeriesCollection cela fonctionne , mais pas avant.
Option Explicit
Sub Copy_Charts()
Dim DataSheetName1 As String, DataSheetName2 As String
Dim sourceChartSheet As Worksheet, destChartSheet As Worksheet
Dim chartObj As ChartObject, newChartObj As ChartObject
Dim chartObjCopy As ChartObject
Dim chSeries As Series
DataSheetName1 = "CU-2"
DataSheetName2 = "CU-8"
Set sourceChartSheet = ThisWorkbook.Sheets(DataSheetName1)
Set destChartSheet = ThisWorkbook.Sheets(DataSheetName2)
For Each chartObj In sourceChartSheet.ChartObjects
Set newChartObj = chartObj.Duplicate.Chart.Parent
'Set newChartObj = chartObj 'Reference the sheet, good if you are cut/pasting the chart
For Each chSeries In newChartObj.Chart.SeriesCollection
chSeries.FormulaR1C1 = Replace(chSeries.FormulaR1C1, DataSheetName1, DataSheetName2)
Next
newChartObj.Top = chartObj.Top
newChartObj.Left = chartObj.Left
'Move this after the SeriesCollection loop
newChartObj.Chart.Location xlLocationAsObject, destChartSheet.Name
Next
End Sub
Merci! J'ai une question: vous définissez newChartObj = chartObj . Il me semble que vous obtenez juste une deuxième référence au graphique d'origine, de sorte que dans les lignes suivantes, vous modifiez simplement le graphique d'origine et ne faites jamais de copie. Suis-je mal interprété cela?
Oui c'est vrai. J'ai mal compris votre demande, voyez la modification si vous voulez une copie.
La réponse de @ z32a7ul ( stackoverflow.com/a/54221244/147356 ) explique pourquoi les choses ne fonctionnent pas après la mise à jour du Propriété de localisation .
Sub Copy_Charts()
Dim DataSheetName1 As String, DataSheetName2 As String
Dim sourceChartSheet As Worksheet, destChartSheet As Worksheet
Dim chartObj As ChartObject, newChartObj As ChartObject
Dim chartObjCopy As ChartObject
Dim chSeries As Series
Dim chartIndex As Integer
DataSheetName1 = "CU-2"
DataSheetName2 = "CU-8"
Set sourceChartSheet = Sheets("CU-2")
Set destChartSheet = Sheets("CU-8")
For Each chartObj In sourceChartSheet.ChartObjects
' No idea why chartObj.Duplicate returns something other
' than a ChartObject.
Set newChartObj = chartObj.Duplicate.Chart.Parent
newChartObj.Top = chartObj.Top
newChartObj.Left = chartObj.Left
newChartObj.Chart.Location xlLocationAsObject, destChartSheet.Name
'For Each chSeries In newChartObj.Chart.SeriesCollection
' chSeries.FormulaR1C1 = Replace(chSeries.FormulaR1C1, DataSheetName1, DataSheetName2)
'Next
Next chartObj
For Each chartObj In destChartSheet.ChartObjects
For Each chSeries In chartObj.Chart.SeriesCollection:
chSeries.FormulaR1C1 = Replace(chSeries.FormulaR1C1, DataSheetName1, DataSheetName2)
Next
Next chartObj
End Sub
I tested it on my Mac, Excel: 16.20 and it works. It's just a slight change on your original code.
Je n'ai pas accès à un Mac, j'ai donc dû le tester sur Windows 10, Office 2016 mais j'ai pu reproduire l'erreur. Concernant votre tentative n ° 2, j'ai constaté que le problème est causé par la ligne ci-dessous:
Set newChartObj = newChartObj.Chart.Location(xlLocationAsObject, destChartSheet.Name).Parent
Cela a un effet secondaire: un nouveau graphique sera créé tandis que votre objet d'origine (référence) deviendra invalide, vous obtiendrez donc une erreur lorsque vous tenterez d'accéder à sa propriété SeriesCollection. Cependant, la fonction Location renvoie une référence au nouveau graphique, il vous suffit donc de mettre à jour votre newChartObj pour faire référence au nouveau graphique (au lieu de la ligne ci-dessus, mettez ceci dans votre code):
newChartObj.Chart.Location xlLocationAsObject, destChartSheet.Name
Merci pour l'explication! Je ne m'attendais pas à ce que la modification de l'emplacement crée un nouvel objet; ce comportement ne semble pas être dans la documentation < / a>.
Essayez
Sub Copy_Charts()
Dim DataSheetName1 As String, DataSheetName2 As String
Dim chartObj As ChartObject, chartObjCopy As ChartObject
Dim sourceChartSheet As Worksheet, destChartSheet As Worksheet
DataSheetName1 = "CU-2"
DataSheetName2 = "CU-8"
Set sourceChartSheet = Sheets(DataSheetName1)
Set destChartSheet = Sheets(DataSheetName2)
For Each chartObj In sourceChartSheet.ChartObjects
chartObj.Copy
destChartSheet.Paste
'destChartSheet.Range(chartObj.TopLeftCell.Address).PasteSpecial xlPasteAll
chartIndex = chartIndex + 1
Set chartObjCopy = destChartSheet.ChartObjects(chartIndex)
chartObjCopy.Left = chartObj.Left
chartObjCopy.Top = chartObj.Top
Next chartObj
End Sub
La création de nouveaux objets de graphique fonctionnerait-elle pour vous? Il serait plus facile de créer de nouveaux graphiques dans votre feuille de destination en fonction des données de la feuille source.
Vous voulez dire créer de nouveaux graphiques via VBA? Cela pourrait être une meilleure solution à long terme, mais en ce moment, la duplication des graphiques nous donne plus de contrôle sur leur apparence sans avoir à apprendre à faire tout cela via VBA. Mais c'est quelque chose que nous avons envisagé :).