Group: microsoft.public.word.vba.general
From: "Greg Maxey"
Date: Thursday, February 28, 2008 4:30 PM
Subject: Re: Ribbon Customizatin AddIn

As is often the case, if I write out and post my problems I am able to see
things from a different slant and I can find a workable solution.

I am still not sure why the error didn't reoccur when I removed and reloaded
the AddIn, but the subcript out of range error was occuring in the
GetItemCount procedure:

I modified it to add an error handler and changed the AutoExec macro to a
procedure named "LoadArrays"

Sub GetItemCount(ByVal control As IRibbonControl, ByRef count)
On Error GoTo Err_Handler
Select Case control.id
Case "DD1"
count = UBound(myArrayPri)
Case Else
'Do Nothing
End Select
Exit Sub
Err_Handler:
LoadArrays
Resume
End Sub

In changed the AutoOpen procedure to:

Sub AutoOpen()
LoadArrays
End Sub

Apparently the RibbonX tries to build the Ribbon using the callbacks before
the AutoExec event fires but not before the AutoOpen event fires.

I am assuming that since I didn't get the error when I simply opened the
template AddIn directly. In that scnenario the AutoOpen event fired, called
the AutoExec which loaded the arrays and then the Ribbon built the controls
without error. Without the AutoOpen event the RibbonX tries to build the
controls before the AutoExec event fires. I proved this by adding a msgbox
in the AutoExec event. I put the Addin in Word Startup directory, started
Word, the error was generated, I continued, and then the msgbox in the
AutoExec event displayed.

Does anyone have suggestion for a better way? I hate to depend on an error
handler and and an error that I know is going to happen to make this all
work.

I thought about and perhaps foolishly tried:

If IsNull(myArrayPri(0)) Then
LoadArrays
End If

but, again since the array hasn't been created yet that results in the same
error.

Thanks.






--
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Greg Maxey - Word MVP

My web site http://gregmaxey.mvps.org
Word MVP web site http://word.mvps.org
~~~~~~~~~~~~~~~~~~~~~~~~~~~~



Greg Maxey wrote:
> This is a long post with multiple questions. Please don't be
> discouraged and feel free to answer all or part. Thank you.
>
> The other day I became interested in creating an Template AddIn that
> will add a group to the built-in Add-Ins tab. The group holds one
> Dropdown. I wanted the dropdown item count, labels, and OnAction
> events to be dynamic based on information stored in a table contained
> in the AddIn.
> The RibbonX was fairly simple. I just added a new group to the
> Add-Ins tab that contained one dropdown control:
>
> > onLoad="Onload">
>
>
>
>
> > getItemCount="GetItemCount" getItemLabel="GetItemLabel"
> getSelectedItemIndex="GetSelectedItemIndex"
> onAction="MyDDMacro">
>

>

>

>

>

>

>
> I used call backs to set the dropdown list count, the label for each
> list item, and the default displayed list item
>
> As a practical exercise (and prompted by a another post in the
> newsgroups) I decided to use the OnAction callback to insert
> pre-definded comments in the text at the selection. I used a two
> column table in the Addin to define the dropdown labels and default
> comment text. E.g.,
> Column 1 Column2
>
> Select error
> agree. Agreement of subject and verb
> ant. Antecendnet. "the person believed
> that they." The sentence is incorrect because person is singular, and
> they is plural
>
> The code in my VB Project (with comments) is as follows:
>
> Option Explicit
> Public myRibbon As IRibbonUI
> Private myArrayPri() As String
> Private myArraySec() As String
>
> 'This procedure fires when the Add-In is loaded. Its purposes is to
> load the values contained in the template Add-In table into a pair of
> arrays. myArrayPri() holds the data to be used for the dropdown
> labels. myArraySec() holds the data for the predefined comment text. The
> procedure opens a new document based on the template AddIn and
> populates the arrays with data in the tables. The new document is
> then closed without saving changes.
>
> Sub AutoExec()
> Dim aTemplate As Template
> Dim oDoc As Word.Document
> Dim oTbl As Table
> For Each aTemplate In Templates
> If aTemplate.Name = "Proofreading Marks.dotm" Then
> Set oDoc = Documents.Add(aTemplate.FullName, , , False)
> Set oTbl = oDoc.Tables(1)
> myArrayPri() = GetErrorArray(oTbl)
> myArraySec() = GetDescriptiveArray(oTbl)
> oDoc.Close wdDoNotSaveChanges
> Exit For
> End If
> Next
> End Sub
>
> 'This procedure fires when the template AddIn is opened directly for
> editing (i.e., either the VB code or the table data)
>
> Sub AutoOpen()
> AutoExec
> End Sub
>
> 'The next two function actually populate the two arrays.
>
> Function GetErrorArray(ByVal oTbl As Table) As String()
> Dim i As Long
> Dim tempArray() As String
> ReDim tempArray(oTbl.Rows.count)
> For i = 1 To oTbl.Rows.count
> tempArray(i - 1) = Left(oTbl.Cell(i, 1).Range.Text, Len(oTbl.Cell(i,
> 1).Range.Text) - 2)
> Next i
> GetErrorArray = tempArray
> End Function
>
>
> Function GetDescriptiveArray(ByVal oTbl As Table) As String()
> Dim i As Long
> Dim tempArray() As String
> ReDim tempArray(oTbl.Rows.count)
> For i = 1 To oTbl.Rows.count
> tempArray(i - 1) = Left(oTbl.Cell(i, 2).Range.Text, Len(oTbl.Cell(i,
> 2).Range.Text) - 2)
> Next i
> GetDescriptiveArray = tempArray
> End Function
>
> 'This is a RibbonX callback needed to create a ribbon object (I think
> that is what it does???)
>
> Sub Onload(ribbon As IRibbonUI)
> Set myRibbon = ribbon
> End Sub
>
> 'This RibbonX callback establishes the number of items in the
> dropdown. The "id" of the dropdown created by the RibbonX is "DD1." The
> count of items is = to the number of items in myArrayPri()
>
> Sub GetItemCount(ByVal control As IRibbonControl, ByRef count)
> Select Case control.id
> Case "DD1"
> count = UBound(myArrayPri)
> Case Else
> 'Do Nothing
> End Select
> End Sub
>
> 'This RibbonX callback is used to define the labels for each item in
> the dropdown. The procedure is called once for each item in the
> dropdown:
> Sub GetItemLabel(ByVal control As IRibbonControl, Index As Integer,
> ByRef label)
> Select Case control.id
> Case "DD1"
> label = myArrayPri(Index)
> Case Else
> 'Do nothing
> End Select
> End Sub
>
> 'This RibbonX callback sets the default dropdown item to display when
> the Ribbon control is created. In this AddIn, I want "Select error"
> to be displayed intially and after each OnAction event:
>
> Sub GetSelectedItemIndex(ByVal control As IRibbonControl, ByRef Index)
> Select Case control.id
> Case "DD1"
> Index = 0
> Case Else
> 'Do nothing
> End Select
> End Sub
>
> 'This RibbonX callback is fired when the user selects one of the
> items in the dropdown. It does several things:
>
> '1. Determines if there is an open document. If not, the control is
> invalidated (causes the control to be rebuilt with "Select error"
> displayed) '2. Determines if there is text selected to comment on. If not
> the control is invalidated
> '3. Uses the dropdown item selected to insert a custom (customizable)
> comment at the selection
> ' a. Displays a userform containing pre-defined comment text
> ' b. Temporarily sets the Application.UserInitials = the contol
> label text
>
> Sub MyDDMacro(ByVal control As IRibbonControl, selectedId As String,
> selectedIndex As Integer)
> Dim oFrm As UserForm1
> Dim pUserInt As String
> Select Case control.id
> Case "DD1"
> If Documents.count < 1 Then
> myRibbon.InvalidateControl control.id
> Exit Sub
> End If
> If Selection.Type = wdSelectionIP Or wdNoSelection Then
> MsgBox "Please select the proofreading error in the text before
> inserting comments."
> myRibbon.InvalidateControl control.id
> Exit Sub
> End If
> Select Case selectedIndex
> Case Is = 0
> 'Do Nothing
> Case Else
> pUserInt = Application.UserInitials
> Set oFrm = New UserForm1
> oFrm.TextBox1 = myArraySec(selectedIndex)
> oFrm.Show
> Application.UserInitials = myArrayPri(selectedIndex)
> Selection.Comments.Add Selection.Range, oFrm.TextBox1.Text
> Unload oFrm
> Set oFrm = Nothing
> Application.UserInitials = pUserInt
> myRibbon.InvalidateControl control.id
> End Select
> Case Else
> 'Do Nothing
> End Select
> End Sub
>
>
> The UserForm contains one textbox and one command button. The
> textbox is set for multi-line. The command button code is:
>
> Private Sub CommandButton1_Click()
> Me.Hide
> End Sub
>
> Problems/Questions:
>
> 1. I am not very confident of my process for populating the two
> arrays with the data needed for the callbacks. My goals is to find
> the simplest way to make the data customizable to the user and
> accessible to the the callback. By putting the data in a table
> contained in the template. All the user needs to do is open the
> template and edit the table. Once that is done, then when the
> template loads the the compiler has to get to it. AutoExec is the
> only event that I know of that fires when a template is loaded. Is
> this correct and is this the best way?
> 2. a. I have not been able to isolate why, but when I put my Addin
> in the Word Startup Folder and start Word I always get an error
> message "Subscript out of range."
> b. If I remove the AddIn from the Startup folder and attempt to
> load the Add-In manually, I get a get the same message: "Subscript
> out of range."
> c. If I leave Word running, remove the AddIn, and load it a
> second time it loads and works perfectly without error.
> d. The error message never happens when I open the AddIn
> directly. I assume that this problem is caused by some sort of
> timing conflict with the AutoExec procedure and maybe I could
> correct it with a Do Events statement but I am not very familiar with
> those and I don't know how to proceed.
>
> Any thoughts or ideas to fix this?
>
> I'll be happy to share the complete template with anyone that is
> interested in assisting to resolve the issue above. Just contact me
> vai my website feedback at the link below and I will send it as an
> attachment.
>
> Thanks.


Safety Articles | Usenet Groups | Usenet News | Bluegrass