Testing row type, before their are any rows (ConnectionPts)

Started by dbramblett, May 15, 2024, 02:10:17 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

dbramblett

How does one test whether you should add a named row (VisTagCnnctNamed)or just a row (VisTagCnnctPt), if there are not any rows to test?

Shape.RowType(Section,Row) allows you to test the row type of an existing row. But if all the rows have been deleted or none have been added yet, there appears to be no way to determine what kind of row you then have to add.

You'd think that if there are no rows, you could add either type of row for the first row. But no, the operation is not allowed for this row type unless it matches the row type of the rows that don't exist yet. It must be a property found somewhere else, but I just can't seem to find it.

Surrogate

When you add connection points via User Interface these connection points are unnamed! If you make one of them as named point, it make all points as named...

dbramblett

Quote from: Surrogate on May 15, 2024, 02:45:38 PMWhen you add connection points via User Interface these connection points are unnamed! If you make one of them as named point, it make all points as named...

Correct! But my question was, how do I test for it. I.E. Someone else creates a stencil, names the rows, but deletes them all. Then I get the stencil, and need to add rows. How do I determine via code that I need to add an indexed or named row?

Imagine I have dozens or hundreds of similar stencils which need a standard set of connection points added. Without opening the shape sheet and manually adding a row to see what happens, how can I query the object and test for it?

Shape.RowType(Section,Row) works, but only if there is already a row to check. The row index is not optional.

Surrogate

Quote from: dbramblett on May 15, 2024, 03:02:08 PMWithout opening the shape sheet and manually adding a row to see what happens, how can I query the object and test for it?
IMHO No way! You cant define it without adding rows and check its type

wapperdude

Couple things.
1). You are referring to shapes, not stencils.  Those are not the same.  They are not interchangeable.

2) if something has been deleted, how can you test it?  BTW, that's rhetorical.  The real question, what is the usage context?  That is, are the connection points referred to by a name or merely row position, e.g., referenced in some code?  Is there a report that refers to them?  That would establish the row type.  If all you typically do is drag/glue a connector, the row type is unimportant.

3) if you have a standardized requirement, then you ought to know what the requirement is, and set the row type accordingly.  Standardized may also include placement order, location, and type.  Perhaps whether or not D-cell is used.  Much more than merely row type.

As Surrogate said, from GUI, Visio merely inserts unnamed row type, regardless of what was there before deletion.  That is the default method.
Visio 2019 Pro

dbramblett

@Surrogate @ wapperdude

I appreciate the responses, but I'm beginning to think I'm confused about the nature of this forum. This is a forum for discussing programming and code where visio is concerned, right? I'm not interested in a gui solution. I'm interested in a VBA or API solution.

The use case is, I want the code I've written to be able to explicitly tell me what the problem is if I try to add a VisTagCnnctPt row to a visSectionConnectionPts section that has already been flipped to VisTagCnnctNamed rows. Presently, it just tells me I can't use that row type. But that could mean I'm adding a row to the wrong section, or that I'm adding the wrong row type. I'd like the error to compare the current VisTag type associated with the section to the VisTag I'm trying to use. But I can only do that in all scenarios if I can obtain that information before looking at any rows.

Worst case, I can do something clunkier and simply try the VisTagCnnctNamed add if the VisTagCnnctPt add fails. But that is just an indirect reference, and doesn't scale very well.

Quote from: wapperdude on May 15, 2024, 06:53:18 PM2) if something has been deleted, how can you test it?  BTW, that's rhetorical.

Lol, I'd agree, except for one snag. As described above, I can't add a row of the wrong type even if there are no rows yet "determining that type". This means that the non-existent row, which you state I can't test, is in fact being tested somehow given the fact that I get an error stating that rowtag isn't allowed. I agree there isn't a row to test. I'm not suggesting that I test a non-existent row, I'm postulating that a value exists somewhere else that can be tested.

Nikolay

I have absolutely no idea how to TEST it, but you could add using try-catch:

Sub AddConnectionPointRow(s As Shape)

  On Error GoTo IsNamed
  s.AddRow visSectionConnectionPts, 0, visTagCnnctPt
  GoTo Done

  IsNamed:
  s.AddRow visSectionConnectionPts, 0, visTagCnnctNamed

  Done:
End Sub

If it is C#

void AddConnectionPointRow(Shape s) {
  try {
    s.AddRow(VisSectionIndices.visSectionConnectionPts, 0, VisRowTags.visTagCnnctPt)
  } catch {
    s.AddRow(VisSectionIndices.visSectionConnectionPts, 0, VisRowTags.visTagCnnctNamed)
  }
}

Maybe the problem now would be clear for others to help.
If a "connection points" section is named, you can add only named rows to it.
If a "connection points" section is unnamed, you can add only unnamed rows to it.

What a weird behavior but anyway.

wapperdude

I wasn't suggesting that you use the GUI, but rather, that is how Visio works.

However, I haven't been able to replicate your issue.  Generally, the code should check to see if a section exists, if not, add the section, and then proceed. Additionally, the code would look for the last row, and add rows from there.

In your use case, the connection points may or maynot have been added, but, the starting point is none.  Therefore no section exists.  That is the case I started with.  Actually, Visio is clever enough not to need the section to pre-exist to add rows.  And, unless otherwise instructed, will default to last row.  Perhaps not the best code form, but such an approach does work.

Sample code below.  This code starts with a selected shape, no Connection Point section.  I tried both cases.  Virgin never having any connection points, and then with connection points deleted.  The code will automatically create the needed section without explicitly telling it to.  It then adds a normal, unnamed row, followed by a named row, followed by another unnamed row.  No errors. Doesn't care if there is a mixture for purposes of adding.  As noted before, once a row is named, all rows are named.  Step thru the code with <F8>, and you will see 1st row is unnamed.  But, when 2nd row is added, both rows become named.  The 3rd row is added as if it is unnamed, but, in fact, gets added as a named row.

If you still experience difficulty, perhaps you can upload a simple case.

Sub ConnPts()
    Dim vsoShp As Visio.Shape
    Dim iRow As Integer
    Dim vsoRow As Visio.Row

    iRow = 0
       
    Set vsoShp = ActiveWindow.Selection(1)
    vsoShp.AddRow visSectionConnectionPts, iRow, 0
    Set vsoRow = vsoShp.Section(visSectionConnectionPts).Row(iRow)
    With vsoRow
        .Cell(visCnnctX).FormulaU = "Width*0"
        .Cell(visCnnctY).FormulaU = "Height*0.5"
    End With
   
    vsoShp.AddNamedRow visSectionConnectionPts, "P" & iRow + 1, visTagCnnctNamedABCD
    Set vsoRow = vsoShp.Section(visSectionConnectionPts).Row(iRow + 1)
    With vsoRow
        .Cell(visCnnctX).FormulaU = "Width*1"
        .Cell(visCnnctY).FormulaU = "Height*0.5"
    End With

    vsoShp.AddRow visSectionConnectionPts, iRow + 2, 0
    Set vsoRow = vsoShp.Section(visSectionConnectionPts).Row(iRow + 2)
    With vsoRow
        .Cell(visCnnctX).FormulaU = "Width*0.5"
        .Cell(visCnnctY).FormulaU = "Height*1"
    End With

End Sub
Visio 2019 Pro

Croc

dbramblett, perhaps your problem is that you are examining not just a shape, but a shape created on the basis of a master shape. In this case, the master-shape does not allow you to delete all rows from the section. Once deleted, rows are marked as deleted. But the row type is saved in the file. This can be clearly seen if we look at the XML.
Here are two pictures.
One shows a comparison of shapes with named and unnamed strings. Everything is the same, only the Row attributes are different.
The second picture shows the attributes of the deleted Row.
You cannot view this attachment.
You cannot view this attachment.

Croc

You need code something like this
Sub ttt()
    Dim shp As Visio.Shape
    Set shp = ActiveWindow.Selection(1)
    Set mShape = shp.MasterShape
    If Not mShape Is Nothing Then
        If mShape.SectionExists(visSectionConnectionPts, 0) Then
            Debug.Print mShape.RowType(visSectionConnectionPts, 0)
        End If
    End If
End Sub

Nikolay

Just to clarify, the FULL CODE to reproduce the issue (as far as I understand it):

Code (vb) Select
Dim s As Shape
Set s = ActivePage.DrawRectangle(0, 0, 1, 1)

s.AddSection visSectionConnectionPts

s.AddRow visSectionConnectionPts, 0, visTagCnnctPt
s.DeleteRow visSectionConnectionPts, 0 ' <<< deleted the last row in the section

s.AddNamedRow visSectionConnectionPts, "HELLO", visTagCnnctNamed ' << BOOOM!! Empty section prohibits adding named rows

Other way around

Code (vb) Select
Dim s As Shape
Set s = ActivePage.DrawRectangle(0, 0, 1, 1)

s.AddSection visSectionConnectionPts

s.AddNamedRow visSectionConnectionPts, "HELLO", visTagCnnctNamed
s.DeleteRow visSectionConnectionPts, 0 ' <<< deleted the last row in the section

s.AddRow visSectionConnectionPts, 0, visTagCnnctPt ' << BOOOM!!! Empty section prohibits adding unnamed rows

Interesting fact: if you delete all connection points in a section, it may disappear on save. Meaning, if you save a file with empty connection point sections (i.e. a connection points section without rows), as VSDX and then open the file again, the section disappears. But if you save the file as VSD, them empty connection points section will stay.

Anyway, the whole thing looks like a mental exercise of little to no practical use.

If you have connection points in the section, check the type of the first one.
If you don't have any, just delete the section and re-add it, a new one will be able to hold any kind of connection points.

wapperdude

@Croc, @Nikolay:  Interesting thoughts.  I tried each of your suggestions thinking that I missed something.  I have not encountered the OP's problem, nor the issue that Nikolay's code produces.

Here is my updated code to mimic Nikolay's code.  It does both cases that he shows.  It would be easy enough to copy my code and run it.

I'm running V2019 Pro on laptop with Win11 64B.

Sub ConnPts()
    Dim vsoShp As Visio.Shape
    Dim iRow As Integer

    iRow = 0
       
    Set vsoShp = ActiveWindow.Selection(1)
    vsoShp.AddRow visSectionConnectionPts, iRow, 0
    vsoShp.DeleteRow visSectionConnectionPts, iRow
    vsoShp.AddNamedRow visSectionConnectionPts, "P" & iRow, visTagCnnctNamedABCD 'Row index starts at "0", but want names to start at "1"
    Set vsoRow = vsoShp.Section(visSectionConnectionPts).Row(iRow)
    With vsoRow
        .Cell(visCnnctX).FormulaU = "Width*0"
        .Cell(visCnnctY).FormulaU = "Height*0.5"
    End With
   
    vsoShp.AddNamedRow visSectionConnectionPts, "P" & iRow + 1, visTagCnnctNamedABCD 'Row index starts at "0", but want names to start at "1"
    vsoShp.DeleteRow visSectionConnectionPts, iRow + 1
    vsoShp.AddRow visSectionConnectionPts, iRow + 1, 0
    Set vsoRow = vsoShp.Section(visSectionConnectionPts).Row(iRow + 1)
    With vsoRow
        .Cell(visCnnctX).FormulaU = "Width*1"
        .Cell(visCnnctY).FormulaU = "Height*0.5"
    End With

    vsoShp.AddRow visSectionConnectionPts, iRow + 2, 0
    Set vsoRow = vsoShp.Section(visSectionConnectionPts).Row(iRow + 2)
    With vsoRow
        .Cell(visCnnctX).FormulaU = "Width*0.5"
        .Cell(visCnnctY).FormulaU = "Height*1"
    End With

End Sub

Visio 2019 Pro

Nikolay

@wapperdude
The issue happens when you try to add an "unnamed" type connection point to a section that already contains "named" connection points.

Your code does not mix them; to hit the issue, it should.

Better example (attached). You have 2 files, they look exactly the same (ShapeSheet is also the same).
They have a single rectangle inside. The "connection points" section is empty (has no rows).

Now try executing this line for each of them (adds one row to connection points section):

ActivePage.Shapes(1).AddRow visSectionConnectionPts, 0, visTagCnnctPt
If you try to execute this for the first file, it succeeds.
If you try to execute the same line for the second file, it fails.


wapperdude

@Nikolay:  Wrong.  It does both. 

First row added as normal, deleted, replaced with "named" row.  Here's the steps:
QuotevsoShp.AddRow visSectionConnectionPts, iRow, 0
        vsoShp.DeleteRow visSectionConnectionPts, iRow
        vsoShp.AddNamedRow visSectionConnectionPts, "P" & iRow, visTagCnnctNamedABCD

Second row, similar, except 1st add is named, then deleted, replaced with normal.  I watched the process as I stepped thru the code using <F8> to verify that is what is going on.

So we're all on same page, at least from Forum perspective, here's my latest test case, attached.

The file has two shapes.  Yellow square that has a master, on Document Stencil.  Master has Connection Pts section.  That section has been deleted from the shape on drawing page.  The green circle has no master and no connection pts.

Code has been modified to step thru both shapes.  No error observed.
Visio 2019 Pro

Nikolay

I've updated the post above with an easier example that should help to understand the issue.

The topicstarter is looking for a code that would work for both CP1 and CP2 file above.