I'm working on Visio (I didn't to the file) and all the shapes are grouped, there is only one shape by group and when I ungroup all the shapes all the names are modified and replaced by random names like "sheet.8331" , do you know if there is a way to ungroup all the shapes without modifying the names of shapes ? Thank you very much in advance
You could read the names prior to ungrouping (VBA), but it is generally a bad idea to use names.
You better rely on fields in the user section to identify shapes.
eg: user.MyIdentificator = "It's me!"
Retrieving the shape is as easy as:
for each shp in activepage.shapes (or in parent_shape)
if shp.cellexists("user.MyIdentificator", visExistsAnywhere) then
if shp.cells("user.MyIdentificator").ResultStr("") = "It's me!" then
'do your stuff
... closing ifs and loops
HTH,
I suspect GG made a "shape" that was a set of shapes, then dragged them onto a stencil.
You may not need to ungroup, as there is a way to "go inside of the group" and make changes. Many users that are destroying things by ungrouping are unaware of "group-editing windows".
Just right-click any group, then choose Group > Open Group, or Group > Open SomeName.
I'll add some more technical mumbo-jumbo that may help other readers who find their way to this thread.
When the newly-created master is dragged back into a drawing, Visio groups the shapes together. This is to preserve the inheritance that Visio establishes between the local master (stored in the Document Stencil of the drawing file) and each instance of the master on the pages of the document.
The inheritance is a way of saving data---shapes on pages aren't all copies of their original masters, then inherit the properties of masters. Only bits that the user changes, such as location, size, text, etc. are overridden. This inheritance can be a powerful tool, can save on file size, but can also be confusing.
When you ungroup the master, you sever it's link to the master, and the shapes become new copies with no inheritance. Visio has to give them names. I'm not sure why your original names are lost. I would think you would end up with a bunch of names that look like "NameOriginal.3", "NameOriginal.46", etc. That's what happens in my tests.
Anyway, names must be unique "at scope" - meaning at the same level of grouping. So for shapes just sitting on the page, there can only be one "Bob". If you make a copy of "Bob", he'll be "Bob.46" or something.
I can have 7000 groups that each have a subshape named "Bob", since each "Bob" exists in its own unique scope--the group shields one Bob from another. But all of those Bobs will have unique "SheetID" indices. Those can be used for doing cross-sheet formula references in the ShapeSheet.
Related
I have a data set containing the following fields:
rack, rack_type, box_number, box_label, row, column
Each rack in the real world is basically a 2D grid with cells, each cell containing an object(a small box in this case). Each box will be associated with a specific position in the rack based on row and column. The size of the grid (number of rows/columns) is different based on rack_type
Is there a way to create a visual representation of these racks from the data supplied above? Specifically, I am looking to create a grid (as if you were looking at it in real life) where each cell shows some text--box_number and box_label in this case. I've been searching for hours on Google to no avail and I don't know if I'm even asking the question correctly. From what I can tell, the normal report/form features in Access do not support such a configuration of data. I'm wondering if there is some VBA solution, since I have some experience with VBA in Excel. Please let me know if this is incomprehensible gibberish.
If your racks has a finite maximum number of boxes in any configuration then you might consider this solution:
Let's say that any of your racks contains at most R boxes
create a form F
open F and add to it R text boxes B (they are not linked to anything)
save the form
now in VBA, on loading a rack you can iterate on each box and use some code to position each each of them on the form, show or hide it, and finally set its size!
Basically you've added to your form more boxes than a typical rack configuration would normally need, and by doing so you can hide some of them when not needed. You have this limit because you cannot create and add at runtime new text boxes to a form in VBA (it should work for reports too).
Note that you could use also other types of objects, text boxes are useful if you want to edit the text inside of them, otherwise you could use a label or anything that suits your needs the most (combo box... for example).
Basic methods that you might want to look at:
cell1.Height = 100
cell1.Visible = Not cell1.Visible
cell1.Move Left:=0, Top:=0, Width:=400, Height:=3000
Anyhow if you get more in details, by giving some examples of your racks we might be able to come with a more detailed solution.
In Outlook 2010 I have a UserForm with a ListBox.
This ListBox has 4 columns where I show a list of attachments (the columns "File-Name", "File-Type", "File-Size" and "Target-Directory".
Unfortunately the ListBox is restricted in layout functionality, the user can not adjust the column width at runtime (so I have to specify the width of the columns by design).
Because the file path can be quiet long, I set the width of the last column to 999 Pt.
So my ListBox has a horizontal scrollbar.
I want to have the following layout changes to my ListBox:
Add column headers
Change the alignment of a column to right-aligned
Optional: allow the user to sort the list by any column
Optional: allow the user to sort change the width of any column
Optional: show a grid in the ListBox
For 1. I found some answers that this is very complicated and I should use static labels above the list instead.
This is not possible, because my ListBox can be scrolled horizontally.
Is the ListBox really so restricted or is #1 and #2 possible somehow?
I know that there are foreign components available, but I am not allowed to buy any component.
And my solution should work at my colleagues too, so they would also have to install these components.
I have been experimenting with possible solutions to your problem. I think I have taken the listbox approach as far as it will go so I will share what I have discovered.
I can find nothing on the web to suggest that anyone believes you can have listbox column headers without using property RowSource. To use RowSource, you set it to an Excel range.
I got Outlook to create an Excel workbook and to write some data to it. Unfortunately, I could not find any way of getting an Outlook user form to access an Excel range. The syntax for setting RowSource is:
ListBox1.RowSource = "Emails!A2:D20"
This is not the standard syntax for a range and I have failed to discover any method of extending it to include a workbook name.
Jonah_Hess describes an interesting approach in https://stackoverflow.com/a/43381634/973283. He has two list boxes. One is a one-line listbox that contains the headings and the other contains the data. The two listboxes are set to the same number of columns with the same widths. This gives an attractive appearance but if you scroll the data listbox, the headings listbox does not scroll with it. This is not really any different from placing labels above a single listbox.
I tried putting the headings and the data list boxes in a frame and scrolling the frame but could not get it to work. I have used frames with VB user forms but the functionality is very different so there are no lessons learnt that I could bring to a VBA user form. Perhaps someone more familiar with VBA frames could get this approach to work.
I gave up trying to get a solution in Outlook. An Excel macro can access Outlook data so I tried that approach.
I created a macro-enabled workbook. Within it, I have two forms both of which fill the screen to conceal the worksheet. The first form just says: “Please wait while I load data from Outlook”. I am not clear about the data on your form so I imported selected details from a folder full of junk emails which I wrote to a worksheet. I sized the columns for the list box to match those for the worksheet. The result was:
The text is a little small but I think it is readable. The listbox at the bottom allows me to select emails for different periods. Long ago I had problems with RowSource which meant I could change the values in the range but I could not change the size of the range. I have either managed to avoid that problem today or it was a bug that has been fixed.
You can see that the headings are displayed. The columns are a little wide but I consider them to be a reasonable first approximation. Options to change the widths would be easy to implement.
The changes you ask for:
Add column headers. Done
Change the alignment of a column to right-aligned. Possible but difficult. You would need to pad the text with an appropriate number of leading spaces.
Optional: allow the user to sort the list by any column. The data is in a worksheet so easy.
Optional: allow the user to change the width of any column. I have set the column widths at runtime to show it is possible.
Optional: show a grid in the ListBox. Not possible.
If the above is interesting, I could show you all my code and instruct you on creating the forms so you could duplicate my experiment. Alternately, I could just explain: how I imported the Outlook data to Excel, how I included the column headings and how I set the column widths.
I cannot find anything to suggest that anything better can be achieved with listboxes.
An alternative approach is to use a grid of labels. This can give an attractive appearance and one or more columns could be right-aligned. Using the Controls property of the user form, you can treat the grid as a two-dimensional array. I have used this technique long ago and found it attractive and not particularly difficult.
In order to set the alignment of a specific column to the right, trying the opposite way might help you:
Set TextAlign attribute of the listbox to "3-fmTextAlignRight".
Add spaces at the END of the each data in the column of sourcearray, which you want to align LEFT. The number of added spaces should be so large as to exceed the width of the column in which the data appears. You don't have to mind whether the number fits to the columnwidth (overflown spaces do no harm). You may prefer to use & String(30, " ") instead (30 is just for example) .
If added spaces seem to be wholly ignored (i.e. data appear right-aligned only), further add any single character (such as "_") at the end of the spaces.
This is a cosmetic solution, but works when seeing left-aligned figures is too annoying.
After doing the above, please be careful when selecting from the list (trimming the added spaces, keeping BoundColumn data intact, etc.).
This trick works for both Excel and Outlook (not sure for other applications).
Test result in Outlook VBA (...trailing 50 spaces are added to data in column 1 and 4.)
Hope this helps.
I got two (or more) same tables on two (or more) different PowerPoint slides, one table per slide.
I need to update the respective cell in all tables whenever I modify this cell on just one of them.
I have been trying to access the cell value and store it as a variable using pptx package.
The only thing I could do is InputBox() but it is not convenient.
Since PowerPoint lacks bookmarks and has only a few fields, you'll have to specify the read and write locations the long way. Keep an eye out for tables with merged or split cells, those can pose an addressing problem.
Sub UpdateTableCell()
Dim CellContent$
CellContent$ = ActivePresentation.Slides(1).Shapes(1).Table.Rows(2).Cells(2).Shape.TextFrame.TextRange.Text
ActivePresentation.Slides(2).Shapes(1).Table.Rows(3).Cells(4).Shape.TextFrame.TextRange.Text = CellContent$
End Sub
You'll probably find this more convenient to use if you add it to the Quick Access Toolbar. If the icon is in the 5th position on the QAT, you can run it with Alt + 5 for a keyboard shortcut.
I have another challenge. Has anyone tried to intercept the copy/paste events? My goal is to prevent someone from cut/copy/paste a shape that is already on a sheet. If they drag it from a stencil, that is fine. I just can't have them duplicate an existing shape. To make this a bit harder, it is only the shape that I need to prevent. If the want to copy text, that is fine.
We have a order type database that contains items that need to be dropped on a Visio sheet. I cannot use the shapeID because I need to be able to update the shape from the database and I can't write the ID back to the database as it is against security policy. The way that I am tying the two together is a property named shapeKey and that value is provided by the database at the time the shape is dropped.
When a use needs to refresh the sheet from the database, I interate through the shapes, comparing the shapeKey in the shape and in the database. if there is a match, I do an update of the other properties. If there is no match, I want to delete the shape. if a user copies a shape, the shapeKey will also be duplicated and that causes problems. Lastly, they can add their own shapes from stencils and those shapes must be excluded from the delete process
I have two options:
Disable shape cut/copy/paste
Intercept the copy/cut and when they paste, change a property so that I know that it was a user pasted shape. This is preferred because it is more user friendly
I just thought if another way I that might work. Is there a way to lock the shapes to prevent the copy? If there is a lock, would that also lock the location? The user needs to be able to most the shapes around.
I thought about capturing the event but I could not find the event codes to look for. I cannot install the Visio SDK which has the Event monitor. The monitor might have shown me the code. Here is some pseudo code as to what I think would be the flow.
option 1
if select item is a shape then
msgbox "shape copying verboten. please us the stencil"
clear selected item
option 2
capture the paste event
if selected item is a shape then
vsoShape.Cells("Prop.ShapeKey").Formula = Chr(34) & "protect" & Chr(34)
Layers might work. All the database controlled shapes can be on one layers and all the user shapes on another but I haven't worked with layers before. would that work? How can I be sure that any shape pasted goes onto the user layer?
Thanks all! I did find a solution and it was really elegant. I found the idea here and changed it to what I needed:
Shape added event: https://msdn.microsoft.com/en-us/library/office/ff767288.aspx
Here is what I came up with:
Private Sub Document_ShapeAdded(ByVal vsoShape As Visio.IVShape)
If vsoShape.CellExistsU("Prop.ShapeName", 0) Then
vsoShape.CellsU("Prop.ShapeName").Formula = Chr(34) & "ShapeName" & Chr(34)
End If
End Sub
The interesting thing is that it doesn't fire if I add the shape via VBA. That is perfect for what I need but I would have thought that dropping a shape is adding a shape. I am only looking for one property because not all shapes on the stencils come from a database and for those objects, I don't need to do anything.
It was not the solution that I expected but it works really well.
I'd like to be able to create a page element which I can feed text and it will form itself into the preferred layout. For instance:
{MACRO DocumentIntro("Introduction to Business Studies", "FP015", "Teachers' Guide")}
with that as a field, the output should be a line, the first two strings a certain size and font, centred, another line and then the third string fonted, sized and centred.
I know that's sort of TeX-like and perhaps beyond the scope of VBA, but if anyone's got any idea how it might be possible, please tell!
EDIT:
Ok, if I put the required information into Keyword, as part of the document properties, with some kind of unique separator, then that gets that info in, and the info will be unique to each document. Next one puts a bookmark where the stuff is going to be displayed. Then one creates an AutoOpen macro that goes to that bookmark, pulls the relevants out of the keywords, and forms the text appropriately into the bookmark's .Selection.
Is that feasible?
You're certainly on the right track here for a coding solution. However, there is a simpler way with no code - this is the type of scenario that Content Controls in Word 2007 were built for and with Fields/Properties, you can bind to content controls (CC). These CC can hold styles (like centered, bold, etc.). No VBA required.
The very easiest thing to do is to pick 3 built-in document properties that you will always want these to be. For example, "Title" could be your first string, "Subject" your second string and "Keywords" your third. Then, just go to the Insert ribbon, Quick Parts, Document Properties and insert, place and format those how you like. Then go to Word's start button (the orb thingy) and then under Prepare choose Properties. Here you can type, for example "Introduction to Business Studies", into the Title box and then just deselect it somehow (like click in another box). The Content Control for Title will be filled in automatically with your text.
If you want to use this for multiple files, just create this file as a .dotx (after CC insertion/placement/formatting and before updating the Document Properties' text). Then every time all you'll have to do is set these three properties with each new file.
Well, yes, it did turn out to be feasible.
Sub autoopen()
Dim sKeywords As String
sKeywords = ActiveDocument.BuiltInDocumentProperties(4)
ActiveDocument.Bookmarks("foo").Select
Selection.Text = sKeywords
End Sub
Okay, I have some filling out to do, but at least the guts of it are there.