Author Topic: Using DropMany in a VSTO add-in (VB.NET)  (Read 386 times)

0 Members and 1 Guest are viewing this topic.

Visisthebest

  • Sr. Member
  • ****
  • Posts: 328
Using DropMany in a VSTO add-in (VB.NET)
« on: December 21, 2020, 10:26:16 AM »
In the Microsoft Visio dev documentation, there is this helpful VBA example for using DropMany:
https://docs.microsoft.com/en-us/office/vba/api/visio.page.dropmany

I am trying to convert this to an altered VB.NET example in a VSTO Add-in, but obviously VB.NET does not allow Variants. Trying to create an Array of Objects (references) also raises an error.

I understand the first argument of the DropMany function:
ObjectsToInstance() should be a one-dimensional array of n >= 1 variants

Is a variant containing an array of variants, I guess this is the key issue why this generates an error. Marshaling this back and forth across the .net interop doesn’t just work automatically it seems.

How can I use DropMany from a VB.NET addin?

Did some performance testing and just using Drop for 2000 shapes is MUCH slower than from VBA, so DropMany can certainly help reduce calls across the .NET interop hopefully improving performance. Thank you for your help!

Code
Public Sub DropMany_Example() 
 
 On Error GoTo HandleError
 
 Dim vsoMasters As Visio.Masters
 Dim intMasterCount As Integer
 Set vsoMasters = ThisDocument.Masters
 intMasterCount = vsoMasters.Count
 
 ReDim varObjectsToInstance(1 To intMasterCount) As Variant
 ReDim adblXYArray(1 To intMasterCount * 2) As Double
 Dim intCounter As Integer
 For intCounter = 1 To intMasterCount
 
 'Pass name of object to drop to DropMany.
 varObjectsToInstance(intCounter) = vsoMasters.Item(intCounter).Name
 
 'Set x components of where to drop to 2,4,6,2,4,6,2,4,6,...
 adblXYArray (intCounter * 2 - 1) = (((intCounter - 1) Mod 3) + 1) * 2
 
 'Set y components to 2,2,2,4,4,4,6,6,6,...
 adblXYArray (intCounter * 2) = Int((intCounter + 2) / 3) * 2
 
 Next intCounter
 
 Dim aintIDArray() As Integer
 Dim intProcessed As Integer
 
 intProcessed = ThisDocument.Pages(1).DropMany(varObjectsToInstance, _
 adblXYArray, aintIDArray)
 Debug.Print intProcessed
 
 For intCounter = LBound(aintIDArray) To UBound(aintIDArray)
 Debug.Print intCounter; aintIDArray(intCounter)
 Next intCounter
 
 Exit Sub
 
 HandleError:
 MsgBox "Error"
 
 Exit Sub
 
End Sub


Should I pass a VariantWrapper object as an argument in VB.NET as a replacement for the Variant in VBA?

https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.variantwrapper?view=net-5.0
« Last Edit: December 21, 2020, 01:12:29 PM by Visisthebest »
Visio 2021 Professional

Nikolay

  • Hero Member
  • *****
  • Posts: 1035
    • UnmanagedVisio
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #1 on: December 21, 2020, 01:13:18 PM »
Replace the word "Variant" with "Object". You probably should be able to see this in the error message you get, just read it  :)
Other than that, make sure you use 0-based arrays and not 1-based in VB.NET.

Your example rewritten for VB.NET:

Code
Public Sub DropMany_Example() 

        Dim vsoMasters As Visio.Masters
        Dim intMasterCount As Integer

        Dim ThisDocument As Visio.Document
        ThisDocument = Globals.ThisAddIn.Application.ActiveDocument

        vsoMasters = ThisDocument.Masters
        intMasterCount = vsoMasters.Count

        Dim varObjectsToInstance(intMasterCount - 1) As Object
        Dim adblXYArray(intMasterCount * 2 - 1) As Double
        Dim intCounter As Integer
        For intCounter = 0 To intMasterCount - 1

            'Pass name of object to drop to DropMany.
            varObjectsToInstance(intCounter) = vsoMasters.Item(intCounter + 1).Name

            'Set x components of where to drop to 2,4,6,2,4,6,2,4,6,...
            adblXYArray(intCounter * 2) = (((intCounter - 1) Mod 3) + 1) * 2

            'Set y components to 2,2,2,4,4,4,6,6,6,...
            adblXYArray(intCounter * 2 + 1) = Int((intCounter + 2) / 3) * 2

        Next intCounter

        Dim aintIDArray() As Short
        Dim intProcessed As Integer

        intProcessed = ThisDocument.Pages(1).DropMany(varObjectsToInstance, adblXYArray, aintIDArray)
        Debug.WriteLine(intProcessed)

    End Sub
« Last Edit: December 21, 2020, 01:19:21 PM by Nikolay »

Visisthebest

  • Sr. Member
  • ****
  • Posts: 328
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #2 on: December 21, 2020, 01:17:22 PM »
Thank you Nikolay then I obviously did something else wrong as well, as the .NET COM interop does take care of this.

Will try it right away, still getting used to VB in .NET!
Visio 2021 Professional

Visisthebest

  • Sr. Member
  • ****
  • Posts: 328
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #3 on: December 21, 2020, 01:24:18 PM »
Tried it works really well thank you Nikolay!
Visio 2021 Professional

Nikolay

  • Hero Member
  • *****
  • Posts: 1035
    • UnmanagedVisio
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #4 on: December 21, 2020, 01:32:18 PM »
Regarding performance, I think Visio 2003  + VBA is unbeatable, this combination could be 10x times faster than Visio 2019 + VB.NET :)

When I was really thinking about performance in one project, was considering pure XML generation as well (i.e. without Visio).
It does not seem to be impossible, just hard, considering there is no Open Xml SDK for Visio and no examples, just schema reference.
But packaging is still there, it's shared between all office document formats.
« Last Edit: December 21, 2020, 01:34:54 PM by Nikolay »

Visisthebest

  • Sr. Member
  • ****
  • Posts: 328
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #5 on: December 21, 2020, 01:44:30 PM »
Yes that is an interesting option no doubt would be much faster.

Just tested Manydropping 3000+ shapes with DropMany over the interop and it is a lot faster for sure!

I will benchmark the difference with Drop but now it was just a few seconds (on a 5+ year old laptop) versus Drop and thinking Visio crashed because it takes so long.

Thank you!

Visio 2021 Professional

Nikolay

  • Hero Member
  • *****
  • Posts: 1035
    • UnmanagedVisio
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #6 on: December 21, 2020, 02:12:47 PM »
Just out of curiosity, checked GitHub. There is a recent project popped up regarding this! And it does not look like someone else's clone or anything. The guy seems to actually trying to break through it  ;D
https://github.com/ihordeyneka/json2visio

Visisthebest

  • Sr. Member
  • ****
  • Posts: 328
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #7 on: December 21, 2020, 02:27:10 PM »
Wow amazing! Still plenty of projects going on with Visio!

Microsoft also published some impressive case studies like with Swiss rail.
Visio 2021 Professional

Visisthebest

  • Sr. Member
  • ****
  • Posts: 328
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #8 on: December 21, 2020, 02:51:24 PM »
Unofficial benchmark (timing with the stopwatch app on iPad) but for a 3000+ shape drop DropMany is at least 3 times as fast as using Drop!

If I also set:
Application.ShowChanges = False
Application.DeferRecalc = True
Application.Settings.UndoLevels = 0
(and restore settings afterwards)

another 2x speedup. (I don't know which of the three settings helps most though)

turning off page autosize (did it via the UI) is also essential (I turn it off in all drop tests) for speed.

I think with 500 shape drops DropMany is much faster than 3x because you see that Visio itself slows down with 3000+ shapes on the page.

Great thank you Nikolay!
Visio 2021 Professional

Visisthebest

  • Sr. Member
  • ****
  • Posts: 328
Re: Using DropMany in a VSTO add-in (VB.NET)
« Reply #9 on: December 21, 2020, 03:04:53 PM »
For connecting up the shapes from an add-in in bulk, I got the advice on the forum earlier to use Page.SetFormulas:
https://docs.microsoft.com/en-us/office/vba/api/visio.page.setformulas

I guess the way to use it is:
1. Drop all the connectors with DropMany from the add-in
2. Wire up all the 1D connectors to the shapes by using Page.SetFormulas and setting in the 1-D Endpoints Section: the BeginX/BeginY and EndX/EndY to the specific shapes and connection points to be wired up.

Visio 2021 Professional