Search code examples
c#visual-studiovisio

Setting x,y position of Visio shape to a graph from a template file C#


I have a template file (.vsdx) which contains a graph with a fixed x and y axis that I load into a new Visio document. I've managed to insert a shape onto the Visio document but it doesn't position according to the the x and y axis of the graph. Example: Setting the vshape with co-ords 0,0 positions to the bottom left corner edge of the document.

I have the following code so far:

 //decalre and initialize Visio objects
        var vApp = new Visio.Application();
        Visio.Document vDoc, vStencil;
        Visio.Page vPage;
        Visio.Shape vToShape, vFromShape, vConnector;
        Visio.Master vConnectorMaster, vFlowChartMaster;
        double dblXLocation;
        double dblYLocation;
        Visio.Cell vBeginCell, vEndCell;
        int iCount;
        string TEMPLATEPATH = @"C:\temp\TestProject\testTemplate.vsdx";

        //Change this constant to match your choice of location and file name.
        string SAVENEWFILE = @"C:\temp\TestProject\testFile.vsdx";
vFlowChartMaster = vStencil.Masters[aryValues[0, 0]];
        dblXLocation = 1;
        dblYLocation = 1;
        vToShape = vPage.Drop(vFlowChartMaster,
           dblXLocation, dblYLocation);
        vToShape.Text = "Test";

 vDoc.Pages[1].Name = "Flowchart Example";
        try
        {
            //Delete the previous version of the file.
            //Kill(SAVENEWFILE);
            File.Delete(SAVENEWFILE);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }


        vDoc.SaveAs(SAVENEWFILE);
        vDoc.Close();
        vApp.Quit();
        vDoc = null;
        vApp = null;
        GC.Collect();

The graph that gets loaded onto the Visio doc is here


Solution

  • Ok, thanks for the update comment. In that case, here's a quick sample. I've created a drawing with a basic 'Graph' master shape, which defines an origin, and a 'Dot' master which is simply a small circle to drop as a dta marker.

    The code (using LINQPad) looks for the first instance of the Graph master and then looks for 'known' cells (which it's up to you to define) to get hold of the origin. It then drops two 'Dot' shapes relative to the Graph origin.

    Here's what the Graph shape looks like:

    enter image description here

    [Note - that you can reference a PNT type in an X or Y cell and Visio will extract the corresponding X or Y coordinate]

    void Main()
    {
        var vApp = MyExtensions.GetRunningVisio();
        var vPag = vApp.ActivePage;
    
        var graphShp = vPag.Shapes.Cast<Visio.Shape>()
                       .FirstOrDefault(s => s.Master?.Name == "Graph");
        if (graphShp != null)
        {
            var dotMst = vPag.Document.Masters["Dot"];
    
            //Get x / y back as a named tuple
            var origin = GetGraphOrigin(graphShp);
    
            //Green fill is the default defined in the master
            var greenDotShp = vPag.Drop(dotMst, origin.x, origin.y);
    
            //Use offest based on graph origin
            var redDotOffsetX = -0.5;
            var redDotOffsetY = 0.25;
            var redDotShp = vPag.Drop(dotMst, origin.x + redDotOffsetX, origin.y + redDotOffsetY);
            redDotShp.CellsU["FillForegnd"].FormulaU = "RGB(200,40,40)";
        }
    }
    
    private (double x, double y) GetGraphOrigin(Visio.Shape targetShp) 
    {
        const string originX = "User.OriginOnPageX";
        const string originY = "User.OriginOnPageY";
    
        if (targetShp == null)
        {
            throw new ArgumentNullException();
        }
        if (targetShp.CellExistsU[originX, (short)Visio.VisExistsFlags.visExistsAnywhere] != 0
            && targetShp.CellExistsU[originY, (short)Visio.VisExistsFlags.visExistsAnywhere] != 0)
        {
            return (x: targetShp.CellsU[originX].ResultIU, 
                    y: targetShp.CellsU[originY].ResultIU);
        }
        return default;
    }
    

    So if you run this code, you should end up with something like this (assuming you started off with the a drawing as described above):

    enter image description here

    So there are lots of ways you could approach this, but probably you need some method or reading where in your Graph shape the origin is and then use that in positioning your 'dot' shapes.