views:

1728

answers:

4

Hi, I'm wondering if there's a simple way for a Word macro to determine which button was just pressed? I have a document template with several button which should all fire a macro. The thing is, I want to create ONE macro which is called in each button. I don't want tons of macros for each button.

Now, this macro, when the button is pressed, it inserts a picture and the size of this picture is selected based on the buttons size. Meaning, this ends up as a picture placeholder. But, I want to write the macro dynamically so that the same code will work on each button without doing more than just calling the macro.

The complete macro is already done, I just need to know this one last thing, if anyone has any info on how to accomplish this? :) Thanx in advance!

UPDATE: This is the code at the moment

Private Sub ImageButton1_Click() PicturePlaceholder ImageButton1 End Sub

Private Sub ImageButton2_Click() PicturePlaceholder ImageButton2 End Sub

Public Sub PicturePlaceholder(ByVal oButton As CommandButton)    
Dim oShape As Word.Shape
Dim Dlg As Office.FileDialog
Dim strFilePath As String
Dim oDoc As Document
Dim rgePlace As Range
Dim buttonHeight As String
Dim buttonWidth As String

Set Dlg = Application.FileDialog(msoFileDialogFilePicker)
Set oDoc = ActiveDocument


Set rgePlace = Selection.Range.Fields(1) _
.Result.Paragraphs(1).Range

Response = MsgBox("Do you want to delete the button/Picture?", vbYesNoCancel, "Do you want an image here?")
If Response = vbYes Then rgePlace.Fields(1).Delete
If Response = vbCancel Then Exit Sub
If Response = vbNo Then

With Dlg
.AllowMultiSelect = False
If .Show() <> 0 Then
strFilePath = .SelectedItems(1)
End If
End With

If strFilePath = "" Then Exit Sub
Set oShape = oDoc.Shapes.AddPicture(FileName:=strFilePath, _
LinkToFile:=False, SaveWithDocument:=True, _
Anchor:=rgePlace)
With oShape
.Height = oButton.Height
.Width = oButton.Width
End With

rgePlace.Fields(1).Delete


End If
End Sub
A: 

You could put your base macro into a separate sub and then just call the macro from each button's click event, passing as a parameter the desired size. Then the only code you would have in the buttons is the call to the base sub.

Dcritelli
+1  A: 

I assume you mean that the button is a Command Bar button (aka toolbar button).

If so, you can use Application.CommandBars.ActionControl to get a reference to the button that was clicked. From there you can examine the caption, tag, or whatever.

Gary McGill
Kenny Bones
Meaning, these aren't toolbar-buttons but CommandButtons inserted through Design Mode.
Kenny Bones
+3  A: 

OK, so they're CommandButtons in the document.

In that case, there's nothing you can do - you need to have handlers called Button1_Click, Button2_Click, etc. (or whatever the button names are).

However, you can do something like this:

Private Sub Button1_Click(...)
    DoStuff Button1
End Sub

Private Sub Button2_Click(...)
    DoStuff Button2
End Sub

Private Sub DoStuff(ByVal oButton As CommandButton)
    ' All your shared code goes here
    MsgBox oButton.Caption
End Sub

See also this tech note for how to create your buttons in code.


EDIT: updated to pass CommandButton reference so that the shared function can access the button properties.


EDIT 2: updated to show complete code using InlineShapes. Note that this no longer passes in the Button object, since the width/height of the button can be obtained directly from the field.

Private Sub CommandButton1_Click()
    PicturePlaceholder
End Sub

Private Sub CommandButton2_Click()
    PicturePlaceholder
End Sub

Public Sub PicturePlaceholder()

    ' Get the selected field, which must be a button field

    Dim oField As Field
    Set oField = Selection.Fields(1)

    Debug.Assert oField.Type = wdFieldOCX


    ' Ask the user what he wants to do

    Select Case MsgBox("Do you want to delete the button/Picture?", vbYesNoCancel, "Do you want an image here?")

        Case vbCancel
            Exit Sub

        Case vbYes
            oField.Delete
            Exit Sub

    End Select


    ' Get the filename of the picture to be inserted

    Dim strFilePath As String

    With Application.FileDialog(msoFileDialogFilePicker)

        .AllowMultiSelect = False

        If .Show() <> 0 Then
            strFilePath = .SelectedItems(1)
        End If

    End With

    If strFilePath = "" Then
        Exit Sub
    End If


    ' Figure out where to insert the picture, and what size to make it

    Dim oRange As Range
    Set oRange = oField.Result

    Dim sglWidth As Single
    sglWidth = oField.InlineShape.Width ' oButton.Width

    Dim sglHeight As Single
    sglHeight = oField.InlineShape.Height ' oButton.Height


    ' Delete the button field

    oField.Delete


    ' Insert and resize the picture

    Dim oInlineShape As Word.InlineShape
    Set oInlineShape = oRange.InlineShapes.AddPicture(FileName:=strFilePath, LinkToFile:=False, SaveWithDocument:=True, Range:=oRange)

    With oInlineShape
        .Width = sglWidth
        .Height = sglHeight
    End With

End Sub


EDIT 3: Updated as requested to use Shapes rather than InlineShapes. (Both the CommandButton and the inserted Picture are now Shapes).


Private Sub CommandButton1_Click()
    PicturePlaceholder
End Sub

Private Sub CommandButton2_Click()
    PicturePlaceholder
End Sub

Public Sub PicturePlaceholder()

    ' Get the selected shape, which must be a button shape

    Debug.Assert Selection.Type = wdSelectionShape

    Dim oButtonShape As Shape
    Set oButtonShape = Selection.ShapeRange(1)


    ' Ask the user what he wants to do

    Select Case MsgBox("Do you want to delete the button/Picture?", vbYesNoCancel, "Do you want an image here?")

        Case vbCancel
            Exit Sub

        Case vbYes
            oButtonShape.Delete
            Exit Sub

    End Select


    ' Get the filename of the picture to be inserted

    Dim strFilePath As String

    With Application.FileDialog(msoFileDialogFilePicker)

        .AllowMultiSelect = False

        If .Show() <> 0 Then
            strFilePath = .SelectedItems(1)
        End If

    End With

    If strFilePath = "" Then
        Exit Sub
    End If


    ' Insert the picture at the same size/position

    Dim oPictureShape As Shape
    Set oPictureShape = ActiveDocument.Shapes.AddPicture _
        ( _
        FileName:=strFilePath, _
        LinkToFile:=False, _
        SaveWithDocument:=True, _
        Left:=oButtonShape.Left, _
        Top:=oButtonShape.Top, _
        Width:=oButtonShape.Width, _
        Height:=oButtonShape.Height, _
        Anchor:=oButtonShape.Anchor _
        )


    ' Copy across the button shape formatting

    oButtonShape.PickUp
    oPictureShape.Apply


    ' Copy across other layout details

    oPictureShape.LayoutInCell = oButtonShape.LayoutInCell

    oPictureShape.LockAnchor = oButtonShape.LockAnchor

    oPictureShape.RelativeHorizontalPosition = oButtonShape.RelativeHorizontalPosition
    oPictureShape.RelativeVerticalPosition = oButtonShape.RelativeVerticalPosition

    oPictureShape.WrapFormat.Type = oButtonShape.WrapFormat.Type
    oPictureShape.WrapFormat.Side = oButtonShape.WrapFormat.Side
    oPictureShape.WrapFormat.DistanceTop = oButtonShape.WrapFormat.DistanceTop
    oPictureShape.WrapFormat.DistanceLeft = oButtonShape.WrapFormat.DistanceLeft
    oPictureShape.WrapFormat.DistanceBottom = oButtonShape.WrapFormat.DistanceBottom
    oPictureShape.WrapFormat.DistanceRight = oButtonShape.WrapFormat.DistanceRight
    oPictureShape.WrapFormat.AllowOverlap = oButtonShape.WrapFormat.AllowOverlap


    ' Delete the button shape

    oButtonShape.Delete

End Sub
Gary McGill
Ok thanx! :) But how do I extract the name of the button from the shared code? For example, the only thing I need is extracting the Height and Width of the button clicked
Kenny Bones
I've edited the answer to show how you can pass the button as a parameter to the shared function, and thus access its properties.
Gary McGill
Wow, this works pretty well! :)But could you take a quick look at the code I've updated in the first post?I see that my code inserts pictures as oShapes so they can be moved around alot easier. But the button are actually inLine, so the position the image ends up in is the exact position of the button. Is it possible to alter the code slightly to allow the buttons to be oShapes as well? Try the code out and see for yourself, it works but the picture ends up on top of the text in the document, since it's oShape and not inLine shape, like the button was before it was deleted.
Kenny Bones
I'm not sure I understand what you're trying to do (you talk about making the buttons Shapes, but if you're looking to have the picture inserted exactly where the button was, then I think you actually want the button and the pictures to be InlineShapes). On the assumption that you do want them both to be InlineShapes, I've modified the code above (see Edit 2).
Gary McGill
Yeah, that's the thing. I don't really understand why Microsoft implemented inline shapes and oShapes in the first place. You have alot less freedom with inline shapes than with oShapes. That's why I wanted pictures to be oShapes. But since the buttons are inLine shapes (they can be oShapes too), then the picture inserted (oShape) ends up at the exact location (selection) as the button was in. Meaning the position ends up all screwed up. The best thing would have been to have the button be oShape to begin with. Thanx for the code though, will check it out! :) You're great! :)
Kenny Bones
Kenny, I still don't really understand. I thought the goal WAS to make the button disappear and be replaced by a picture of the same size, which is what the posted code does. It would be easy enough to change the code to use Shapes instead of InlineShapes, but I'm puzzled as to exactly where you want the picture to appear - you seemed to not want it do cover the text, so where DO you want it?
Gary McGill
:)Well, I want the code to do exactly what it does, except I want it to be oShapes instead. The thing is, if the button is an inline shape and the inserted picture is an oShape, that means that the button is in line with the text, and the oShape behaves like a layer ontop of the text. That means that the picture ends up on top of the text. I just want the picture to be an oShape but behave as if it were an inline shape. Perhaps if we just added some code which converts the inserted picture to an oShape at the very end?
Kenny Bones
OK, see edit 3. Hope this helps!
Gary McGill
This helps alot! Thanx! Weird why picture placeholders arent in Word to begin with, only in the 2007 version. But this does the trick! :)
Kenny Bones
A: 

You can have a button in Vba to pass arguments when it calls the macro which takes arguments. For eg: if you have a function called as function test(x as string) then the button which calls the macro will have a syntax as onclick("sheetx!test", "whatever"). So that way you can either have a generic macro to be called. Hope this helps you.

StevenzNPaul