J'essaie d'écrire une macro VBA qui construit un diagramme de base à partir de données et de certaines formes de modèle (conservées sur une page séparée). Bien que je puisse couper et coller avec succès, je semble être incapable de référencer la nouvelle forme après avoir fait cela. Je peux déplacer la forme avant de la couper et de la coller, mais si j'essaye de faire quoi que ce soit après coup, je rencontre une erreur d'exécution. Il y a plusieurs raisons pour lesquelles je pourrais avoir besoin de déplacer / mettre à jour les objets plus tard, donc je dois être en mesure de les référencer par la suite.
Mon code est le suivant:
Dim Shape as Visio.Shape Dim ShapeID as Integer  âcopy shape from template page 2, ID 12 Set Shape = Application.ActiveDocument.Pages.ItemU("Page-2").Shapes.ItemFromID(12).Duplicate  ShapeID = Shape.ID MsgBox ("Created shape ID: " & ShapeID)       'Now relocate the shape appropriately currentX = startX + (Count * xSpacing) currentY = startY        Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm" Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"  Shape.Cut     'Now go to page 1 and paste the object  Application.ActiveDocument.Pages.ItemU("Page-1").Paste â*** THE FOLLOWING LINE THAT DOESNâT WORK *** Set Shape = Application.ActiveDocument.Pages.ItemU("Page-1").Shapes.ItemFromID(ShapeID)  Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm" Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
Si j'exécute ce qui précède, j'obtiens l'erreur "Identificateur de feuille non valide" à la ligne en surbrillance (la forme est collée avec succès). Si je coupe cette ligne, j'obtiens "une exception s'est produite" sur la ligne suivante, il semble donc que j'ai perdu ma référence à l'objet.
4 Réponses :
Bien sûr, vous obtenez l'erreur "Identificateur de feuille invalide"! Parce qu'à "Page-1", vous pouvez avoir une forme avec ShapeID , que vous avez défini pour la forme placée à "Page-2".
Vous pouvez coller la forme et après cette étape définir la forme sélectionnée.
Application.ActiveDocument.Pages.ItemU("Page-1").Paste ' You can define this variable as shape which is selected Set Shape = Application.ActiveWindow.Selection.PrimaryItem
Pourquoi utilisez-vous la variable deux fois?
Peut-être que je ne comprends tout simplement pas comment ces méthodes fonctionnent, mais ce que je pensais se produisait ici (et semble fonctionner) est 1. Sélectionnez l'élément (sur la page 2). 2. Dupliquez l'élément (sur la page 2) et stockez l'ID dans ShapeID. 3. Coupez l'article. 4 Collez l'élément sur la page 1. Tout fonctionne dans le code ci-dessus, mais ce que je veux faire est de déplacer la forme que j'ai collée sur la page 1. Si je supprime la ligne de problème, Shape ne contient pas de référence du tout (il semble le perdre à la pâte). Si je le mets, je veux qu'il trouve celui que j'ai collé.
Désolé, je n'ai pas vu que vous aviez également modifié le code. L'élément collé sera donc celui sélectionné? Si c'est le cas, cela a du sens, mais je ne comprends pas très bien pourquoi mon code n'aurait pas fonctionné également. Un ID de forme change-t-il si je le déplace d'une page à l'autre?
Oui, l'ID de la forme a changé lorsque vous le collez dans une autre page. ID en général, est le numéro correspondant à l'ordre d'ajout des formes à la page! Veuillez en savoir plus sur Propriété Shape.ID , regardez Remarques
Droite. C'est la grande chose qui me manquait. Le vote positif en tant qu'explication a maintenant un sens pour moi et vous avez fourni du code pour résoudre le problème. Merci beaucoup!
L'ID d'une forme est uniquement unique à sa page, donc la nouvelle forme que vous collez dans la page 1 recevra un nouvel ID et donc l'erreur que vous recevez. Bien que la méthode Duplicate
renvoie une référence de forme à la nouvelle forme, Paste
ne le fait pas, vous devez donc y faire référence par d'autres moyens - soit en supposant quelque chose à propos de la sélection de la fenêtre (selon la réponse de Surrogate) ou par index:
Private WithEvents vPags As Visio.Pages Private pastedScopeID As Long Public Sub TestCopyAndPaste() Dim vDoc As Visio.Document Set vDoc = Me 'assumes code is in ThisDocument class module, but change as required Dim srcPag As Visio.Page Set srcPag = vDoc.Pages.ItemU("Page-2") Dim targetPag As Visio.Page Set targetPag = vDoc.Pages.ItemU("Page-1") Dim srcShp As Visio.Shape Set srcShp = srcPag.Shapes.ItemFromID(12) Set vPags = vDoc.Pages pastedScopeID = Application.BeginUndoScope("Paste to page") srcShp.Copy targetPag.Paste Application.EndUndoScope pastedScopeID, True End Sub Private Sub vPags_ShapeAdded(ByVal shp As IVShape) If shp.Application.IsInScope(pastedScopeID) Then Debug.Print "Application.CurrentScope " & Application.CurrentScope Debug.Print "ShapeAdded - " & shp.NameID & " on page " & shp.ContainingPage.Name DoSomethingToPastedShape shp Else Debug.Print "Application.CurrentScope " & Application.CurrentScope End If End Sub Private Sub DoSomethingToPastedShape(ByVal shp As Visio.Shape) If Not shp Is Nothing Then shp.CellsU("FillForegnd").FormulaU = "=RGB(200, 30, 30)" End If End Sub
Un flux de travail plus habituel serait de générer des masques (dans un document gabarit) puis de supprimer ces masques plutôt que de copier et coller entre les pages, mais votre scénario peut nécessiter une approche différente.
Je vais ajouter ce lien comme référence utile pour traiter les propriétés d'index et d'ID:
[Update
Le commentaire de @Jon Fournier ci-dessous est tout à fait exact que ce qui précède fait des suppositions. Par exemple, si le DisplayLevel dans la forme source est inférieure à la forme la plus haute, elle sera collée dans la collection de formes de la page à l'index correspondant et donc count ne retournera pas l'ID de forme correct.
Une autre approche pourrait consister à écouter le événement ShapeAdded
sur les pages (ou page). Ce qui suit est une légère adaptation de IsInScope
exemple dans la documentation, avec le code placé ThisDocument. Cela vous permet de compléter et de terminer votre code dans une paire d'ID d'étendue d'événement que vous pouvez inspecter lors de la gestion de l'événement ShapeAdded:
Dim shp As Visio.Shape Dim pag As Visio.Page Set pag = ActivePage 'or some alternative reference to Page-1 Set shp = pag.Shapes.ItemU(pag.Shapes.Count) Debug.Print shp.Index
Je ne me souviens pas quand, mais je me suis brûlé en supposant que la forme collée était la dernière dans la collection de formes
Merci. Le plus important pour moi a été de découvrir que ce n'est pas la même référence sur différentes pages. Cela clarifie vraiment ce qui se passe.
Oui, bon point @Jon. Avoir une réponse mise à jour avec une approche alternative.
Je n'ai pas trouvé de moyen efficace de gérer cela. J'ai une méthode qui va coller le presse-papiers sur une page et renvoyer toutes les nouvelles formes, en listant tous les identifiants de forme avant et après le collage, puis en renvoyant de nouvelles formes.
Si la vitesse est un gros problème pour moi, je vais généralement coller sur une page masquée vide, faire tout ce que je dois sur cette page, puis couper et coller sur la page de destination. Si vous avez besoin de coller avec d'autres formes, cela ne fonctionnera pas vraiment, mais quand cela a du sens, j'utilise cette logique.
Heureux que ce ne soit pas seulement moi qui ai le problème. La vitesse n'est pas un problème car l'idée était d'écrire un script qui prenait une description du flux que je voulais, puis de le créer une fois (j'en ai beaucoup à dessiner et les exigences changent tous les jours, donc c'était une idée qui économisait du travail. ). La solution ci-dessous donne un moyen d'identifier l'élément collé, il semble donc que j'ai une solution, mais votre solution de contournement est également valide pour mes besoins.
Au lieu de Dupliquer et couper et coller, utilisez simplement Drop:
Dim srcShape, dstShape as Shape Set srcShape = ActiveDocument.Pages("Page-2").Shapes("srcShape") Set dstShape = ActiveDocument.Pages("Page-1").Drop(srcShape, 0, 0)
Après ce qui précède, vous pouvez accéder à dstShape
et en faire ce que vous voulez.
p>