Visio VBA Toggle Buttons and better ways - vba

second question here, and I'll start with the obvious, I'm not a coder, just and enthusiastic ammateur! Thanks for your patience with my incorrect terminology etc!
I have a grid of Layers on a Visio document that I make visible/invisible using ToggleButtons. Imagine an 8 x 8 grid, with each square a box on it's own layer that becomes "highlighted" when the equivalent button is pressed. A-H, 1-8.
At the moment this means creating 64 individual subs:
Private Sub A4_Click()
Dim LyrNum As Integer
LyrNum = A4.Data1
If A4 Then
Call ToggleLayer3(LyrNum, 1)
A4.BackColor = RGB(243, 226, 160)
Else
Call ToggleLayer3(LyrNum, 0)
A4.BackColor = RGB(129, 133, 219)
Where the Data1 Property field contains the Layer Number for the grid reference.
I guess my first question is, is this really the best way of doing this? Seems a but clunky, but perhaps anything more elegant might be beyond me!
...
Second question, When horizontally adjacent layers are selected, I'd like to "mask" the join - essentially hide the lines between the boxes (they're a bit more complicated that straight squares). I have something that's starting to work, but again seems clunky and pretty labour intensive to set up.
I've made the Data2 Property Field the Layer numbers for the boxes to the left and right of the clicked layer (split by delimiter), and the Data3 Property Field the layer number for the "Masking". I can then split Data2 call a sub with (ClickedLayer, LayerBefore, LayerAfter, MaskingLayer, OnOff) and use If loops to see if the layer to the left is visible, and if so add the masking etc.
Means manually entering all the layer info into the property fields of each button etc, but works I guess.
I'm 100% sure there's a better way - I tried making the masking a object in the layer with a ShapeData of visible: True/False that could be changed from VBA, but that boggled my brain a bit. I guess I could have an Array of values in the VBA with the info I'm putting into Property Data# fields.
Thanks in advance for your help
Steve

Related

PowerPoint VBA add shape event/ add shape with tag value

i'am currently trying to add a small function to PowerPoint using VBA, my goal is to create a gadget that works kind of like Photoshop graphics layer.
My plan is to add a layer name Tag on each shape that is drawn by user, so later I can parse through every item by loop and preform lock/unlock, show/hide shapes based on it's tag value, such as:
Sub add_shape_with_layer_tag()
Set islide = ActivePresentation.Slides(1)
Set ishape = islide.Shapes.AddShape(msoShapeRectangle, 5, 5, 80, 60)
ishape.Tags.Add "Layer", "1"
End Sub
Sub show_hide_layer_one_shapes()
Dim active_slide As Slide
Set active_slide = ActiveWindow.View.Slide
For Each ishape In active_slide.Shapes
If ishape.Tags("Layer") = "1" Then
ishape.Visible = Not (ishape.Visible)
End If
Next ishape
End Sub
However, I couldn't found a way to achieve this, so I would like to ask whether there's a method that provides following functions?
override add shape function so I can sneak tag value in to shape every time user drawn a shape
catch add shape event (if this thing did exist) so i can add tag to the last added item
a way to set a default tag value to shape, just like setting default shape color/line width
or is there any better options that is also viable?
thanks.
20200728
To John, thanks for the advice, I did found some interesting event that might be helpful for some of my other projects, however I couldn't found events that able to trigger after custom function while shape is added.
To Steve, my plan is to add a modeless userform with list UI that manage layers, the shape tag and shape fill texture/color will be determined based on what list item that currently selected.
As to saving settings, I'll use VBComponents.CodeModule to dump existing settings in userforms to a VBA module and store as text, so in theory I should able to make this function self contained in one file.
Not totally an answer, sorry SO, but comments don't allow enough scope for this. So ...
To Steve, my plan is to add a modeless userform with list UI that manage layers, the shape tag and shape fill texture/color will be determined based on what list item that currently selected.
Ah, so you're creating your own "pseudo-layers". That wasn't clear. Thanks for the add'l info. As it happens, I have a selection manager add-in that works very similarly to what you're proposing.
To John, thanks for the advice, I did found some interesting event that might be helpful for some of my other projects, however I couldn't found events that able to trigger after custom function while shape is added.
The SelectionChange event should get you there. When it fires, you'll need to check first to see if the current selection is a shape or something else. If a shape, check to see if its .Index = current slide's .Shapes.Count and also to see if you've already tagged it. If no tag AND if it's the correct index, it'll be a newly added shape. If you're tagging ALL shapes, you may only need to check to see if the .Tag(name) is blank.
As to saving settings, I'll use VBComponents.CodeModule to dump existing settings in userforms to a VBA module and store as text, so in theory I should able to make this function self contained in one file.
Why not save any needed slide or presentation level info as further slide- or presentation-level tags? PPT can absorb quite a lot of info as tags w/o getting cranky.

Visio - Button to Show layer

I'm trying to get the next layer to show when the user double clicks a shape.
I've never touched VBA within Visio so I tried the below code, I know its not much but I honestly do not have a clue unfortunately
Visio.layer.*Layername* visible = "1"
End Sub
Any help at all will be greatly appreciated.
what you mean as "Next layer" ?
In visio in Layer Properties Window layers are shown in order by name. In shapesheet layers are shown in order of creation !
VisioApp.ActivePage.Layers.Item("layername").CellsC(visLayerVisible).FormulaU = "1"
try this code
This can actually be done via simple shapesheet functions.
SetF(Getref(ThePage!=Layers.Visible[2]),true) - if you want to set Layer 2 to visible.
Switching from one layer to the next could be done be incrementing a counter on double-click + reset when max layers is reached.
=setf(getref(user.counter), if(user.counter>=user.MaxLayers, 1, user.counter+1)

How to detect Updated textbox with Linq

-->VB.Net VS2010
If this is a stupid question, then let me know. I can't just figure it out.
First of all, this is my question. How do I detect the changed value on those text boxes?
I have an idea that I create a another string values that have the original values and compare them right before saving or form closing event. This sample just have 3 text boxes, but I have 50 + text boxes on my one form. I can do it that way, but that is not really smart idea.
Can I use abcDB.SubmitChanges() to detect any data changes on text boxes?
Dim sqlQuery = (From obj in abcDB.HelloWorld
Select obj.Fname, obj.Lname, obj.PhoneNumber).FirstOrDefault()
me.textboxFname.text = sqlQuery.Fname
me.textboxLname.text = sqlQuery.Lname
me.textboxPhoneNumber.text = sqlQuery.PhoneNumber
What you really want to do is called 'data binding'. Lots of tutorials about that aroud the web and any book about VB.NET will have at least 1 chapter dedicated to it.

How can I center the heading in a column on a DataGridView?

I have a strange problem and it's probably a simple fix, but after much research, I cannot seem to find a solution.
I have a DataGridView on which I'm trying to center the column headings, but the result is a left bias in the centering—almost like an indenting problem. I've seen a few posts on this issue on a site or two, but never a solution. Any thoughts?
Here's the statement I'm currently trying to use:
DataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
The code you've posted is on the right track: you need to set the ColumnHeadersDefaultCellStyle property of your DataGridView control.
However, you need to create a new DataGridViewCellStyle class and assign that to the ColumnHeadersDefaultCellStyle property. You can't modify the Alignment property as your code sample shows unless you have assigned a DataGridViewCellStyle class to this property.
So, for example, the following code achieves perfectly centered column headings in a blank project:
Dim dgvColumnHeaderStyle As New DataGridViewCellStyle()
dgvColumnHeaderStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
myDataGridView.ColumnHeadersDefaultCellStyle = dgvColumnHeaderStyle
In the future, you may find it easier to do these types of things from the Designer. If you still need to do it yourself through code, you can check the *.Designer.vb file that is created to see how it was done.
EDIT: I just now noticed the slight offset you're referring to in the columns—it does indeed create a little extra padding to the right of each header. It's not a bug, though. There's a much simpler explanation.
Like a ListView, the DataGridView supports sorting by columns. Therefore, each column header reserves enough space to display the sort glyph (usually an arrow) when calculating center justification.
If you want the column headers to be perfectly centered, you'll need to disable sorting. Set the SortMode property for the column to "NonSortable". This should prevent space from being reserved for the sort glyph whenever the column text is center or right justified.
If you want to center or use any other alignment style of the Column Header text you can use this
dgvResults.Columns("ColumnName").HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter

MS Access Draw line around detail section that can grow

This really shouldn't be hard, I just can't figure out how to do it.
I am making a proposal report that needs to have a border around it. The problem is to get the vertical lines on the side. I can't figure out how to get a line to grow and shrink based on the height of the detail section.
I have used Crystal reports and sure wish Microsoft would learn a few things in regards to MS Access report writing!
I am very comfortable with VBA so have no fears there.
You were right, this isn't so hard. The trick is to use 2 variables, top and bottom. In the PageHeader_Format event you set top to Me.Height, and in the PageFooter_Format event you set the bottom to Me.Top - correction, where correction is a fixed amound you use to fix the right length. I´m not sure where this amount comes from, you just have to try a little bit.
In the Report_Page event you can then draw your line from top to bottom.
Another method that nobody has mentioned is the one using the Line method of the report, outlined in Knowledge Base article 210321. I've used this one for years, and it can be used to draw both lines and rectangles. It's quite handy for invoices that have variable height subreports for the invoice details, but need the vertical lines to change according to the height of the main report detail.
No VBA needed.
Make a dummy grouping that is unique to each detail. For that grouping, set footer to yes.
In your new group footer section that you just created, add your line.
In your detail section, select all the relevant fields that can grow and set Can Grow = Yes
Done!
Edit
Off-topic, I agree that Access Reports could learn a lesson or two from Crystal. But Crystal isn't perfect either. [/flamewar]
Try this one.
Right click on the detail bar and select properties. Set the special effect to “Sunken”. This will put kind of a border around the detail section that resizes with the detail section.
I have tried to get a line to dynamically resize but its catch 22, by the time you know the height of the section (In the On Print event) you cant make any changes!
use the page event coupled with me.line and scaleheight / scalewidth.
I draw a box around the whole page with the following. Play with it and see where you end up. It is very handy for making professional reports. If you want a line in a certain place on a report you can use the controls coordinates. like
me.line(Mycontrol.left,mycontrol.top) - (myothercontrol.left+myothercontrol.width, myother control.top + myothercontrol.height)
Private Sub Report_Page()
Me.Line (0, 0)-(scalewidth -30, scaleheight-30), 0, B
End Sub