Automatically Show ShapeSheet of Current Shape - vba

I do a lot of Visio ShapeSheet editing and it would save me a tremendous amount of time to automatically switch to the current shape's sheet when I select a new shape. Let's assume I only have 1 ShapeSheet open, only select 1 Shape, and have all the windows docked on the Visio app (I don't have RegEdit powers to change this).
So far, I've got the following VBA code in ThisDocument:
Private WithEvents vsoWin as Visio.Window
Private Sub ThisDocument_RunModeEntered(ByRef doc as IVDocument)
'Just assume this is the correct window
Set vsoWin = ActiveWindow
End Sub
Private Sub vsoWin_SelectionChanged(ByRef win as IVWindow)
'If nothing is selected, leave
If vsoWin.Selection.Count < 1 Then Exit Sub
'Look for a ShapeSheet (Window.SubType = 3)
For each oWin in Application.Windows
If oWin.Subtype = 3 Then
Application.ScreenUpdating = False 'Pause screen to prevent jitter
oWin.Close 'Delete old ShapeSheet
vsoWin.Selection(1).OpenSheetWindow 'Make new ShapeSheet
Application.ScreenUpdating = True 'Update visuals
Exit For 'Stop looking for ShapeSheets
End If
Next
Exit Sub
(The above code is written from memory since I don't have access to Visio at the moment. Please forgive any minor errors)
This code works, but I'm hoping for a less jittery result. Application.ScreenUpdating = False doesn't seem to do anything in this case: I still briefly witness the old ShapeSheet closing, the drawing window resizing, then the new ShapeSheet opening. Swapping the order (open new window > close old window) is a little less chaotic, but not great. Using Application.Minimize to hide the swap instead is slightly better on the eyes, but still not a smooth transition.
My question: Is there a smoother way to display the active shape's ShapeSheet?

This code works at my side! I just add variable which related with Visio Application - vsoApp.
Private WithEvents vsoWin As Visio.Window
Private WithEvents vsoApp As Visio.Application
Sub st()
Set vsoWin = ActiveWindow ' initialize Window variable
Set vsoApp = Application ' initialize Application variable
End Sub
Private Sub ThisDocument_RunModeEntered(ByRef doc As IVDocument)
'Just assume this is the correct window
Set vsoWin = ActiveWindow
End Sub
Private Sub vsoApp_SelectionChanged(ByVal Window As IVWindow)
'If nothing is selected, leave
If vsoWin.Selection.Count < 1 Then Exit Sub
'Look for a ShapeSheet (Window.SubType = 3)
For Each oWin In Application.Windows
If oWin.SubType = 3 Then
Application.ScreenUpdating = False 'Pause screen to prevent jitter
oWin.Close 'Delete old ShapeSheet
vsoWin.Selection(1).OpenSheetWindow 'Make new ShapeSheet
Application.ScreenUpdating = True 'Update visuals
Exit For 'Stop looking for ShapeSheets
End If
Next
End Sub
My workaround:
Press Alt+F8 keys and run St sub-routine.
Open ShapeSheet window for selected shape.
Select another shapes and so on...
Update with your code i get error like this.

Related

In Word 2010 use VBA to make first document to fit page

When Word 2010 starts I would to automatically execute the VBA code
ActiveWindow.ActivePane.View.Zoom.PageFit = wdPageFitFullPage
to make the document fit the page.
Many thanks for a tip
You can put your command(s) in the AutoExec macro.
Sub AutoExec()
ActiveWindow.ActivePane.View.Zoom.PageFit = wdPageFitFullPage
End Sub
You could add a macro like the following to the 'ThisDocument' code module of a global template (e.g. Normal.dotm):
Private Sub Document_Open()
With ActiveWindow
'Reduce flickering while changing settings
.Visible = False
'Switch to a single view pane
.View.SplitSpecial = wdPaneNone
.View.Type = wdPrintView
.ActivePane.View.Zoom.PageFit = wdPageFitFullPage
'Restore the window now that we're finished
.Visible = True
End With
End Sub

VBA: Disable button in Excel after first click

I am trying to disable a button placed on my sheet1 once the user click on it.
I went through few old Stackoverflow answers but dosent work as my expectation.
The code:
Sub Button2_Click()
Call FindADate
Dim myshape As Shape: Set myshape = ThisWorkbook.Worksheets("Sheet1").Shapes("Button 2")
With myshape
.ControlFormat.Enabled = False '---> Disable the button
.TextFrame.Characters.Font.ColorIndex = 15 '---> Grey out button label
End With
End Sub
It actually grayed out the button which give a feel that the button is disabled but User can click again and again and it run my code.
Kindly let me know a solution to get the button disabled after 1 click, the button will be active again only once I close and re open the excel. (I am using MS Office professional Plus 2013)
Thanks in advance.
You need to record somehow not to process the click. You could examine the button's text colour and if grey then ignore the click. Alternatively, you could set a variable either a global, module or static local variable. I chose the static local variable in the code below, called vDisable.
Option Explicit
Sub Button2_Click()
Static vDisable As Variant
If IsEmpty(vDisable) Then
Call FindADate
Dim myshape As Shape: Set myshape = ThisWorkbook.Worksheets("Sheet1").Shapes("Button 2")
With myshape
.ControlFormat.Enabled = False '---> Disable the button
.TextFrame.Characters.Font.ColorIndex = 15 '---> Grey out button label
End With
vDisable = True
End If
End Sub
after Dim line just write:
if myshape.TextFrame.Characters.Font.ColorIndex = 15 then exit sub
that should be enough
I know this is an old question, but I had the same situation and solved it by the following:
With myshape
.OnAction = "" '---> Removes any macro from the button
.TextFrame.Characters.Font.ColorIndex = 15 '---> Grey out button label
End With
This removes the need for a global/static variable.

Is there a way to have a scrollable list that is editable?

Following this video I have a spreadsheet that has a "Edit History" box on it that scrolls up and down. It uses a forms control scroll box and a list on a secondary sheet to create a scrollable list. The problem with this is that you cannot then edit the information in the scroll box (you must edit it on the secondary sheet).
I have VBA that automatically enters the person's name into the scrollbox when they edit any part of the sheet, and then enters "Note:" below that. I want the person to be able to edit the "Note:" box so that they can enter the reason they are editing the sheet:
John Smith and James Appleseed are previous users of this sheet. When Wayne Smith comes in to edit the sheet, as soon as he makes a change, it adds "Wayne Smith" and "Note:" to the sheet. (I already have this part working using VBA).
Because of the way that the scroll able list is implemented, it is actually all just formulas within this edit history box. If I double click "Note:" to try and edit it, this is what appears:
But what I want to happen is the ability to edit the "Note:" box (without having to switch to the secondary sheet where the list is actually stored). Essentially I want to make a scroll able text box that is also directly editable, and works with VBA.
Is there any way to do this?
I put together a working example of how to do this.
You can download the workbook here.
This method uses two sheets in a workbook... Sheet1 for the listbox and listboxdata for the data. Sheet1 can be called anything you like.
It would probably be wise to hide the listboxdata sheet.
On Sheet1 you need a Forms Control scrollbar. Use the Name Box to rename it: ScrollBar1. Assign to it the Scroll() procedure.
All of the code for this app should be placed in the Sheet1 code module:
Option Explicit
Private Const LISTBOX_SCROLLBAR = "scrollbar1"
Private Const LISTBOX_DATASHEET = "listboxdata"
Private Const LISTBOX_DATAHEADR = "a1"
Private Const LISTBOX_SCROLLMAX = 50
Private Const LISTBOX_SCROLLMIN = 1
Private Sub Scroll()
Dim ListBoxRows&, n&, ndx&, v
On Error Resume Next
With Shapes(LISTBOX_SCROLLBAR)
SetProps ndx
ListBoxRows = .BottomRightCell.Row - .TopLeftCell.Row
v = ThisWorkbook.Sheets(LISTBOX_DATASHEET).Range(LISTBOX_DATAHEADR).Resize(ListBoxRows).Offset(ndx)
Application.EnableEvents = False
.TopLeftCell(, 0).Resize(ListBoxRows) = v
End With
Application.EnableEvents = True
End Sub
Private Sub Update(Target As Range)
With Shapes(LISTBOX_SCROLLBAR)
If Target.Column = .TopLeftCell(, 0).Column Then
If Target.Row >= .TopLeftCell.Row And Target.Row <= .BottomRightCell.Row Then
If Target.Count = 1 Then
ThisWorkbook.Sheets(LISTBOX_DATASHEET).Range(LISTBOX_DATAHEADR).Offset(.ControlFormat.Value + Target.Row - .TopLeftCell.Row) = Target
Else
Scroll
End If
End If
End If
End With
End Sub
Private Sub SetProps(Optional ndx&)
With Shapes(LISTBOX_SCROLLBAR).ControlFormat
.Min = LISTBOX_SCROLLMIN
.Max = LISTBOX_SCROLLMAX
ndx = .Value
End With
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Update Target
End Sub
Private Sub Worksheet_Activate()
SetProps
End Sub
That's it.
No formulas required in the listbox and any changes made to the cells in the listbox will be written to the source data and kept.

VBA Grey Checkboxes

I would like to grey out my checkboxes in Excel VBA. When using Checkbox.Enabled = False, the checkbox is not editable, but it is also not grey. How do I get the greyed out effect?
Using form controls with Excel 2010. Inserted via developer tab directly into excel worksheet. Not used in a VBA userform.
Thanks!
Whenever anyone says "it is impossible", it hits my stubborn streak. So may I present to you: "The Impossible".
"Visible" and enabled checkbox:
"Disabled" checkbox (you can tweak the degree of visibility by changing values in the code for both color and transparency of the cover shape):
Basic idea: you place a semi transparent shape over the checkbox, and assign a dummy macro to it. Now you can't change the value of the checkbox. The "toggle" button is there to change the state - either place the shapes, or remove them. It uses a global variable to track the current state.
Finally - note that you can't use For Each when you delete (or add) shapes as you should not modify the collection you are iterating over. I circumvented that with a simple "count shapes, then iterate backwards by numerical index".
Is it a hack? You bet! Does it do what you asked? Yes!
Dim checkBoxesVisible As Boolean
Option Explicit
Sub toggleIt()
' macro assigned to "Toggle visibility" button
checkBoxesVisible = Not checkBoxesVisible
toggleCheckboxes checkBoxesVisible
End Sub
Sub grayOut(cb)
' put a "cover" shape over a checkbox
' change the color and transparency to adjust the appearance
Dim cover As Shape
Set cover = ActiveSheet.Shapes.AddShape(msoShapeRectangle, cb.Left, cb.Top, cb.Width, cb.Height)
With cover
.Line.Visible = msoFalse
With .Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 255, 255)
.Transparency = 0.4
.Solid
End With
End With
cover.Name = "cover"
cover.OnAction = "doNothing"
End Sub
Sub doNothing()
' dummy macro to assign to cover shapes
End Sub
Sub unGray(cb)
' find the cover shape for the checkbox passed as the argument
' and delete it
' "correct shape" has the name "cover" and is properly aligned with top left
Dim sh As Shape
For Each sh In ActiveSheet.Shapes
If sh.Name = "cover" And sh.Left = cb.Left And sh.Top = cb.Top Then
sh.Delete
Exit For
End If
Next sh
End Sub
Sub toggleCheckboxes(onOff)
Dim s As Shape
Dim n As Integer, ii As Integer
n = ActiveSheet.Shapes.Count
' loop backwards over shapes: if you do a "For Each" you get in trouble
' when you delete things!
For ii = n To 1 Step -1
Set s = ActiveSheet.Shapes(ii)
If s.Type = msoFormControl Then
If s.FormControlType = xlCheckBox Then
If onOff Then
unGray s
Else
grayOut s
End If
End If
End If
Next ii
End Sub
A slight hack - but the following does work. I created a simple userform with two controls - a regular checkbox (CheckBox1), and a button I called "DisableButton" with the following code:
Private Sub DisableButton_Click()
CheckBox1.Enabled = Not (CheckBox1.Enabled)
If CheckBox1.Enabled Then
CheckBox1.ForeColor = RGB(0, 0, 0)
Else
CheckBox1.ForeColor = RGB(128, 128, 128)
End If
End Sub
When I clicked the button, the checkbox was grayed out and unavailable. Clicking it again "brought it back to life". I think this is the effect you were looking for. If it's not - that's what comments are for.
Here is what it looks like:
I am afraid it is impossible what you are trying to do within a worksheet. You can refer to the Floris' answer if you are using an UserForm.
For more details on the properties of (Form/worksheet) check boxes see MSDN
Maybe this is what you want.
Private Sub CheckBox1_Click()
If CheckBox1.Value = True Then
CheckBox2.Value = False
CheckBox2.Enabled = False
CheckBox2.ForeColor = rgbBlue
Else
CheckBox2.Visible = True
CheckBox2.ForeColor = rgbAntiqueWhite
CheckBox2.Enabled = True
End If
Code tels that when checkbox1 is checked, checkbox2 is disabled; unchecked and the forecollor changes. the colors can be what you want.
Did this with the checkboxes directly in the excel worksheet.
Based on Floris' idea.
The code assumes all the controls are on ActiveSheet and they are called CheckBox1 and CheckBox2, if not, change it accordingly.
You can call this when you click on CheckBox1 or you can call it from another sub, with an optional ticked status (True/False) to check or uncheck CheckBox1.
Draw an object on top of CheckBox2 and name it "mask" (you can name it anything else but then you have to change the code accordingly)
Give mask the same fill color as your background color and opacity of around 50%.
Public Sub CheckBox1_Click(Optional ticked As Variant)
Application.ScreenUpdating = False
ActiveSheet.Unprotect
If Not IsMissing(ticked) Then
If ticked = True Then ActiveSheet.Shapes("CheckBox1").OLEFormat.Object.Value = 1 Else ActiveSheet.Shapes("CheckBox1").OLEFormat.Object.Value = -4146
End If
If ActiveSheet.Shapes("CheckBox1").OLEFormat.Object.Value > 0 Then
ActiveSheet.Shapes("mask").OLEFormat.Object.ShapeRange.ZOrder msoSendToBack
Else
ActiveSheet.Shapes("mask").OLEFormat.Object.ShapeRange.ZOrder msoBringToFront
End If
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
Application.ScreenUpdating = True
End Sub
Now each time you tick CheckBox1, mask comes to front to hide CheckBox2 and when you untick it, mask goes to back to unhide it. Since it is opaque, it gives you the greyed out effect and you don't even have to worry about enable/disable either.
Worksheet should be protected so that user can't accidentally move or edit mask, but should be unprotected for SendToBack/BringToFront to work, so the code does that. Please check the protection settings at the Application.Protect part.

Right click on sheet-tabs disabled in Excel

I used this vba code in the ThisWorkbook module to disable the right click menu in an Excel workbook.
Private Sub Workbook_Activate()
With Application.CommandBars.FindControl(ID:=847)
.Visible = False
End With
End Sub
Private Sub Workbook_Deactivate()
With Application.CommandBars.FindControl(ID:=847)
.Visible = True
End With
End Sub
Works like a charm.
Problem is, I can't access the right click menu on tabs in ANY workbook now.
The second part of the code is supposed to turn it back on, I assumed? Yet it doesn't.
Even when I remove the code entirely, no workbook, not even a new one, has a menu when I click right on one of the tabs.
Is there a general vba codesnippet that "resets" excel maybe? Or a general "enable all menus" thing?
REVISION:
This code posted here doesn't disable the rightclick menu, it removes the "delete" option from that specific menu.
omg
Application.CommandBars("Ply").Enabled = True
-.-
Started googling different keywords after the last edit and BAM.
Late again as usual, but tackled with the same problem today. Here's the solution to get your right-click functionality back:
Option Explicit
'
Sub tester()
'
Dim cBar As CommandBar
'
For Each cBar In CommandBars
Debug.Print cBar.Name
If (cBar.Type = msoBarTypePopup) Then cBar.Enabled = True
Next
End Sub
Also note that the below also exist. Some macro from work had them all disabled in my Excel.
Application.CommandBars("Cell").Enabled = True
Application.CommandBars("Row").Enabled = True
Application.CommandBars("Column").Enabled = True