Shape data, fixed lists, and index values

Started by Daeruin, August 29, 2014, 07:42:27 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Daeruin

Hi there. This is my first post. I've gotten a lot of great info from this site over the past few months.

I have a master shape with some custom shape data, one of which is a fixed list of text items. I use the selected item for a given shape to populate the shape label. The list is constantly growing, and it's a long list, so I need it to be kept in alphabetical order to help find the items I need. I have been adding new items to the list by editing the master shape, going into the Define Shape Data dialog, and adding new items to the Format list. All was well until we started using Visio 2010. When you select an item from the list, Visio used to store the selected value as a text string. Now, with Visio 2010 and 2013, it instead stores an index value that points to the item chosen.

The problem is that when I add new items to the middle of the list in my master shape, Visio doesn't update the index values. So all of the newer shape labels that are stored as index values are now off by one slot. The older values that were stored as text strings are fine.

I tried using a variable list, but the problem still occurs when adding new items in the middle of the list. I could add items to the end of the list, but that defeats half the purpose of the list. Any suggestions or workarounds?

Yacine

Hi Daeruin,
that's a very interesting question.

I didn't find a way to identify whether the change is made in the list or the custom property too.

So one possible solution could be to make a static copy of the list, so as to separate the orginal list that can be modified, from the one used by the shape. Only by clicking a menu, the list is refreshed. The modification of the custom property of the shape is then "undone" by setting it to a temporary value previously saved.
This is solution is not perfect as it does not refresh automatically the list.

At least I added an option to show that there's a difference between the static and the original list.

An automatic refresh could be done with some coding.
Yacine

Yacine

Sleeping over a problem sometimes helps.
Finding whether the change was made in the shape or the list is actually onyl a matter of comparing the local copy and the orginal list.
So it was just thinking a step further to yesterday's solution.
When ever the lists are different, update the local copy and write the old static copy of the value in the current field.

Regards,
Y.
Yacine

Jumpy

Quote from: Daeruin on August 29, 2014, 07:42:27 PM
When you select an item from the list, Visio used to store the selected value as a text string. Now, with Visio 2010 and 2013, it instead stores an index value that points to the item chosen.

Afaik, Visio internally stored the index value already in Visio 2007. At least that's so in my Version.
If I look at the shapesheet cell of a shapedata with a fixed list and look at the formula I see sth. like =INDEX(1,Prop.MyData.Format)

(Have no Visio at the moment, so could be mistaken).

daihashi

Jumpy is correct; that is the syntax for both a fixed and variable list.

If you don't care about VBA, or automation, then the easy answer is to open the shapesheet and then simply copy the current value in prop.format; save it to a text file so you can copy it again later, and then set prop.format = "". Also, copy prop.value to a text file, and then set prop.value="". Edit the prop.format and prop.value; do the editing that you wish, and modify prop.value to be index + 1 if necessary (depending on what the current value is.. and where you inserted new values in prop.format). This is basically creating the list from scratch; which allows Visio to then index in the order that you've built the list.

If you want to do this programmatically, then here is the logic behind what you need to do... taken from something similar I do in one of my own templates. However, this may be far in excess of what you need to accomplish your own goals. If so then stick to my previous suggestion and call it a day  :) :

While I am not editing the masters; in one of my documents I have some code that adds additional items to an existing variable list for a shape on the page. This is because users may need to add values that didn't exist when I initially created the master shape. I feel the same approach could be taken here.

The way this portion of the document works is that in a userform, the end user enters a value in a combobox which does not exist in the fixed/variable list yet. This value is saved to a string variable (we'll call this User_value), and the format column is also saved to a string variable (we'll call this Format_list). The current prop.value is also saved in a variable.

Format_list is then split using the "split" function using ";" as the delimiter. Then for lbound(Format_list) to ubound(Format_list) is used to compare each name against the user value. Once the correct spot is found (either alphabetical order, or numerical), the Format_list variable is redefined as all of the list values that come before User_value, plus User_value, plus the remainder of the list values... we will call this newly defined variable "New_Format_list".

Then the Prop.list.format is set for vbnullstring, followed by then setting Prop.list.format = New_Format_list. Also, if prop.value had an index value that comes before where User_value was inserted, then no need to change prop.value. Otherwise, if Prop.value was in a position that came after where User_value was inserted, then prop.value will need to change to become index +1.

I hope that you can understand what I said here. Unfortunately since I don't have code that does exactly what you're asking for, all I could do was speak about it in a semi-abstract way. However the logic in my post above will do exactly what you want... you simply need to translate it into VBA.

Daeruin

Wow, thanks for the innovative solutions! I didn't mention that previous to using Visio 2010, we were using Visio 2003. I was assuming the index values were introduced in 2010, but it appears they were introduced in 2007.

Anyway, I will have to look into the ideas you suggested in more detail and try them out. I really appreciate the pointers.

daihashi

No problem, to be honest I've never actually experienced the problem you described here in this post; but that may be because of how I use the Prop.Format and Prop.value sections. In my documents, I don't actually use Index() in the value cells. Instead I use userforms, and then dump the prop.format cell into a combobox by using Split() and using ";" as the delimiter. Then upon clicking the command button, the ComboBox.value is saved to Prop.Value cell.

Since I take this approach, the order that appears in the Format section doesn't matter since I don't use Index() to output the value in the prop.value cell. However, I do put everything back in order... but only for aesthetic reasons... it in no way affects my ability to get the correct value into the prop.value cell.

Jumpy

A tip for the fixed list. I would not place it in the shape or mastershape but in the ShapeSheet of the page (or document). Naturally that only works, if your drawings are based on the same template. So if you wan't to update the list, you have only to Update in once in the page/document.

Nevertheless that won't help you with the problem that the index may point to the wrong entry after an update. You could write an VBA macro that iterates through all shapes and updates the index.

daihashi

Jumpy, that's a very good idea.. I'm surprised I didn't think of that for my own templates; but I suppose it's very easy to miss the obvious when you are so close to the project you are working on.

Taking your idea another step further; can you tell me if it's possible for any page you are working with to inherit the pagesheet of the background page that you apply to it? If so then this could be made even simpler than what you described in your post.

Jumpy

In the Page of every sheet you can place a user defined cell with a formula like:

User.MyListOnNormalPage
=Pages[MyBackgroundPage]!PageSheet!User.MyListOnBackgorundPage

that references a user defined cell of the ShapeSheet.

And only to complete this. Instead of in a background page you could place the "master list" in the ShapeSheet of the document, altough i don't know (out of my head) how to reference that:
=TheDoc!User.MyListOnDocument ?? =TheDoc!PageSheet!User.MyListOnDocument ??

But normally the duplication of that list on every page should not be neccessary because you can place such a formula (referencing the backgroundpage or the documenrt) directly in every shape.

daihashi

What I was hoping for was automatic inheritance. My pagesheets and documentsheets have pretty complicated; probably needlessly complicated due to my current skill level, and would require many many references this way. I use the method you described for some of the automation capabilities I've placed in my documents.

What I was hoping for was to simplify my current method of generating a new page (which requires this mass amount of scratch cell definitions) by simply setting it up on a background page and then having the created page inherit that section from the background.

I'll admit that I probably just need to become more intimately aware of all the various functions that can be used in the shapesheet, and also how I can manipulate certain result to act as my trigger for conditional statements in the shapesheet. I do this already, but if you saw this portion of my shapesheet code then you'll realize that my approach is very "brute force" and not "elegant" at all. It works, but it's not pretty.

Thanks for the input Jumpy; it wasn't what I was hoping for, but it's still very useful information. :)