0
votes

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

1
Hello @Barry, I'm not completely clear on what's going wrong here (or what you're expecting to see). In Visio, the coordinate system is bottom / left, so you'd need to find the offset of the origin of your graph shape and add that to your drop coordinates. Also, are you managing to drop the correct master? I can't see what aryValues is, so I'm assuming it's an array of master names or master indices? - JohnGoldsmith
Hi @JohnGoldsmith, the main problem I face is that I don't know how to drop a master shape on the correct area of the graph. Example if I use vToShape = vPage.Drop(vFlowChartMaster, 0, 0); The shape gets displayed in the bottom left corner and not in the 0,0 position on the graph where I would like to place it. I'm able to drop correct master - aryValues contains the master indices. - Barry

1 Answers

0
votes

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.