none
Incrementing variables in a macro RRS feed

  • Question

  • I am trying to create a complex form in Word (2007), and one of the things I want to do is to have the facility to add more rows in some sections. I've managed to write a macro that inserts a new row into the table, populates it with the relevant content controls and tag them ... so far, so funky.

    But the problem is that I want each content control to have a unique tag name, and that means I need to be able to append the tag name with an incrementing value ... and I can't work that bit out.

    What I need the macro to do, when it is run, is to:

    - if a variable X already exists, increment it by 1

    - if a variable X does not already exist, create it with value 1

    - keep the variable alive so that it can be re-used by the macro next time it is run.

    This looks like it should be pretty straight-forward but I've scoured the internet and can't find anything that does this and is written in a way that I can understand. (Please note - I am not a programmer. I can cope with recording macros and then going into the macro editor and playing around with them, but that's about my limit - so if it involves anything more complicated, please take it slowly!)

    Any help would be very much appreciated!

    Friday, July 25, 2014 1:46 PM

Answers

All replies

  • Hi Steve

    If you need something that persists over Word sessions then you'll need to store that value somewhere. The most likely candidate for your scenario would be in the document.

    Word documents have a storage area for this purpose called: Document Variables. These aren't to be confused with the variables you use in your code; document Variables allow the developer to store information - data type STRING - within the document in a manner the user cannot access through the UI (unless you were to provide an interface).

    In order to create/populate a document Variable:
       DocumentObject.Variables("NameOfVar") = "string value"

    Note: You probably use ActiveDocument in your code, so you'd use that instead of DocumentObject.

    To read the variable content:
       myStringVar = DocumentObject.Variables("NameOfVar")

    A Variable MUST contain a string with at least one character. If you assign it a zero-length string the variable will be removed:
      DocumentObject.Variables("NameOfVar") = ""

    If the Variable has not yet been created (or has been deleted) you get Runtime error 5825 "Object has been deleted". In order to steer clear of this error you can use one of two approaches:

    1) Use a For...Each loop of the Document.Variables collection to check the name of each Variable and branch accordingly when it's found (or not found)

    2) Use Error Handling (On Error GoTo...)


    Cindy Meister, VSTO/Word MVP, my blog

    Friday, July 25, 2014 3:14 PM
    Moderator
  • There is a demo of adding rows to a table with content controls here: http://www.msofficeforums.com/word-vba/13955-macro-add-row-table-word-form.html#post38461

    Although the demo there doesn't add tags or titles, it replicates any that are already in use on the newly-added last row. Additional code would be required to change either the titles or the tags. For example, assuming the tags are just numeric values you might insert:
    If .Tag = "" Then .Tag = 0
    .Tag = .Tag + 1
    after:
    If .Type = wdContentControlDate Then .Range.Text = ""


    Cheers
    Paul Edstein
    [MS MVP - Word]

    Saturday, July 26, 2014 2:17 AM
  • Thank you Paul - that is much quicker and simpler than what I was doing (a different macro for each table depending on the number of columns and the contents of those columns). I think with a bit of playing around, I should be able to get the tags incrementing with that .. it isn't a straightforward number, but a string appended with a number (eg ID1) but I think I can figure out a way to do that.
    Monday, July 28, 2014 9:40 AM
  • Thanks again ... I've now got it working just as I want it. I've replaced the logic that implements the code so that there is a control with a tag of AddRow on any section where I want it to be able to expand, as that allows before the end of the table, and means that tables that don't need to be expandable aren't. The final code, for anyone who is interested in doing something similar (or who wants to pick holes in what I've done!) is:

    Option Explicit
    Dim bLastCell As Boolean
    _ _ _ _ _
    
    Private Sub Document_ContentControlOnEnter(ByVal ContentControl As ContentControl)
    With ContentControl
    
          If .Tag = "AddRow" Then
              bLastCell = True
    End If
    End With
    End Sub
    _ _ _ _ _
    
    Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
    Dim CCtrl As ContentControl, Prot As Variant, Pwd As String
    
    If bLastCell = True Then
      If MsgBox("Add new row?", vbQuestion + vbYesNo) = vbYes Then
        With ActiveDocument
          Prot = .ProtectionType
          If .ProtectionType <> wdNoProtection Then
            Pwd = "" 'Insert password here
            Prot = .ProtectionType
            .Unprotect Password:=Pwd
          End If
          With Selection.Tables(1).Rows
                Selection.SelectRow
                Selection.Copy
                Selection.MoveDown Unit:=wdLine, Count:=1
                Selection.Paste
                Selection.MoveUp Unit:=wdLine, Count:=1
                Selection.SelectRow
    
            For Each CCtrl In Selection.Range.ContentControls
              With CCtrl
                If .Type = wdContentControlRichText Or .Type = wdContentControlText Then .Range.Text = ""
                If .Type = wdContentControlDropdownList Then .DropdownListEntries(1).Select
                If .Type = wdContentControlComboBox Then .DropdownListEntries(1).Select
                If .Type = wdContentControlDate Then .Range.Text = ""
                
               If .Tag = "" Then
                .Tag = ""
                ElseIf .Tag = "AddRow" Then
                .Tag = "AddRow"
                Else
                Dim RowNumber As Integer
                 RowNumber = Val(Right(.Tag, 2))
                Dim NewRowNumber As Integer
                 NewRowNumber = RowNumber + 1
                 If NewRowNumber < 10 Then
                   .Tag = Left(.Tag, Len(.Tag) - 2) & 0 & NewRowNumber
                   Else
                   .Tag = Left(.Tag, Len(.Tag) - 2) & NewRowNumber
                   End If
                 End If
              End With
            Next
          End With
          .Protect Type:=Prot, Password:=Pwd
        End With
      End If
      bLastCell = False
    End If
    
    End Sub


    Wednesday, July 30, 2014 12:56 PM