Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Best way to move one tab one table 1

Status
Not open for further replies.

BrianWen

Programmer
Jun 8, 2009
102
DK
How does one move to next tab in a cell in a table...with VBA of course?
There's no wdTab to use and within tables it all gets a little bit more difficult (for me at least). Even manually you can't use the TAB button, because it skips to the next cell. I know I can use CTRL + TAB, but there must be a correct way to go to next tab with VBA...right? :)
 


Hi,

Is there a reason to actually MOVE to the next cell? Is the user going to do get a visual indication and do something when the program MOVES to the next cell?

You can and ought to REFERENCE the cell that your program is working on, rather than actually moving the selection. I assume that you're in Excel ("There's no wdTab to use..."), so use the sheet, row and column values to reference the proper cell.

Please post the code if you need help.

Skip,

[glasses]Just traded in my old subtlety...
for a NUANCE![tongue]
 
OK, my bad. I should have made my question much more clear:

We're talking Word. I'm in a cell in a table and have a tab defined to indent some text. The whole table and all is created with VBA but I can't seem to figure out how move to that tab.

Code:
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=1, NumColumns:= _
    2, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
    wdAutoFitFixed
    
  With Selection.Tables(1)
    If .Style <> "Table Grid" Then
      .Style = "Table Grid"
    End If
    .ApplyStyleHeadingRows = True
    .ApplyStyleLastRow = False
    .ApplyStyleFirstColumn = True
    .ApplyStyleLastColumn = False
    .ApplyStyleRowBands = True
    .ApplyStyleColumnBands = False
    
    .PreferredWidth = CentimetersToPoints(15)
    
    .Borders(wdBorderLeft).LineStyle = wdLineStyleNone
    .Borders(wdBorderRight).LineStyle = wdLineStyleNone
    .Borders(wdBorderTop).LineStyle = wdLineStyleNone
    .Borders(wdBorderBottom).LineStyle = wdLineStyleNone
    .Borders(wdBorderVertical).LineStyle = wdLineStyleNone
    .Borders(wdBorderDiagonalDown).LineStyle = wdLineStyleNone
    .Borders(wdBorderDiagonalUp).LineStyle = wdLineStyleNone
    .Borders.Shadow = False
    
  End With
  
  With Selection.InlineShapes.AddHorizontalLineStandard
    .Width = CentimetersToPoints(6)
    .Height = 0.8
    .Fill.Solid
    .HorizontalLineFormat.NoShade = True
    .Fill.ForeColor.RGB = RGB(0, 0, 0)
    .Fill.BackColor.RGB = RGB(0, 0, 0)
  End With
  
  Selection.TypeParagraph
  Selection.ParagraphFormat.TabStops.Add position:=CentimetersToPoints(2.4), _
  Alignment:=wdAlignTabLeft, Leader:=wdTabLeaderSpaces


I'm going for a table with two cells, in each cell a horizontal line for a signature and then I need to add some text below (name and such) but indented (with a tab) so it looks better...
 



You want to change the TAB position?

Skip,

[glasses]Just traded in my old subtlety...
for a NUANCE![tongue]
 
No, I specifically make the tab at 2.4 cm (last line). I want to move to the next tab from my selection.
The cursor is at the start of the cell with a tab positioned 2.4 further to the right. I want to jump to that tab. Just as I pressed the TAB manually (CTRL + TAB in a table).
 
And why are you using Selection...at all?

IF the Tab character is already there (in the cell) then...it is a character. Thus:
Code:
Selection.MoveRight Unit:=wdCharacter, Count:=1
moves the Selection one character to the right...and if that character is a Tab....

However, I would reiterate, why are you using Selection?

Gerry
 
Please do explain. I would love to get a better way of doing it. As said in other threads I'm no Word expert (AT ALL) :)

The reason I'm doing it with Selection is that it's creating a whole document including tables, text, lists and more and it's doing it all progressively. In other words, I always know where I am (the script is only going to run once per document created from the template...
 
Hard to say, as I really do not know what you mean by: "The reason I'm doing it with Selection is that it's creating a whole document including tables, text, lists and more and it's doing it all progressively."

Creating a whole document including tables, text, lists etc, does not require Selection.

Selection means one thing....where the visible cursor is (and what it is "selecting").

Nothing more. It is the visible location on-screen.

Say the cursor (Selection) is, oh, let's make it easy, right at the start of the document. Let's make it even easier...it is a brand new, blank, document. So the cursor (Selection) is blinking away at the top of the document.

Now, let's say you have two other documents, SomeText.doc, and SomeOtherText.doc.

SomeText.doc
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.

SomeOtherText.doc
The slender monster barracuda bites hard. The slender monster barracuda bites hard. The slender monster barracuda bites hard.
The slender monster barracuda bites hard. The slender monster barracuda bites hard. The slender monster barracuda bites hard.

Got it? Now look at this.
Code:
Option Explicit

Sub DoStuff()
Dim r As Range
Dim oTable As Table
Dim oCell As Cell
Dim oHF As HeaderFooter

Set r = ActiveDocument.Range
With r
   .InsertFile FileName:="c:\zzz\SomeText.doc"
   .Collapse 0
End With
Set oTable = _
   ActiveDocument.Tables.Add(Range:=r, _
      NumRows:=3, _
      NumColumns:=3, _
      DefaultTableBehavior:=wdWord9TableBehavior, _
      AutoFitBehavior:=wdAutoFitFixed)

Set r = ActiveDocument.Range
With r
   .Collapse 0
   .InsertParagraphAfter
   .InsertFile FileName:="c:\zzz\SomeOtherText.doc"
   .Collapse 0
   .InsertBreak Type:=wdSectionBreakNextPage
End With
For Each oCell In oTable.Range.Cells
   oCell.Range.Text = "some yadda"
Next
Set oHF = ActiveDocument.Sections(2) _
      .Headers(wdHeaderFooterPrimary)
   With oHF
      .LinkToPrevious = False
      .Range.Text = "This is text for Section 2 Header"
   End With
End Sub
The result?
[Section 1 no Header text]
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.

[table here]
some yadda some yadda some yadda
some yadda some yadda some yadda
some yadda some yadda some yadda

Section break
[Section 2 header text = "This is text for Section 2 Header"
The slender monster barracuda bites hard. The slender monster barracuda bites hard. The slender monster barracuda bites hard.
The slender monster barracuda bites hard. The slender monster barracuda bites hard. The slender monster barracuda bites hard.

All without EVER moving, or using, Selection. The cursor (Selection) is still blinking at the top of the document. Of course, at the end, you COULD move the cursor (Selection) to where ever you want.

Just to walk you through....

1. make a range object of the document (empty for now)

2. insert the file SomeText.doc. The range object is resized.

3. collapse the range object to its end (.Collapse 0)

4. set a 3 x 3 table object

5. RESET the range object for the whole document (to include the table)

6. collapse the range object to its end

7. insert a paragraph

8. insert the file SomeOtherText.doc

9. collapse the range object to its end

10. make a Section break (Next Page)

11. put "some yadda" in every cell of the table - but this could be anything. I did this to be simple. Note that because you are dealing with a table object, and you are NOT using Selection, you can action the table even though you are now "in" another Section.

12. set a HeaderFooter object to be the header of Section 2.

13. make that header unlinked to the previous one (Section 1)

14. put the text "This is text for Section 2 Header" in the headerfooter object. Note that Section 1 remains blank.

This has everything to do with what Skip mentioned (although greatly expanded).

Skip: "You can and ought to REFERENCE the cell that your program is working on"

It is the reference to objects that is the key to really using VBA, be it Word or Excel, or any other VBA compliant application.

By using objects fully, you can avoid using Selection, or Activate. Why? Because both of those use the resources to change things on screen. When you execute the demo code above, the document just becomes the result of the instructions.

Gerry
 
I just noticed something else.

"I'm going for a table with two cells, in each cell a horizontal line for a signature and then I need to add some text below (name and such) but indented (with a tab) so it looks better... "

Regarding the last part, it would be much better (and this is how Word is designed to be used) if you used an explicit Style. You could have a TableTextIndent (or whatever you want to name it) style, and have that indent defined by the style. Therefore...no need for a Tab.

Therefore, you could put whatever text you want in the cell, attach the style...voila! It is indented by however you defined it in thr style.

Gerry
 


When I use tables in MS Word for signatures, and dates and want an UNDERSCORE for each, here's my drill (for the xlCentric me).

How many apparent columns? 2: one for the NAME and one for the DATE. But I don't want the NAME underscore to run into the DATE underscore, so I ADD a column between, totaling 3.

How many apparent rows? 1: for the Name & Date all on the same line. But I want the Words Signature and Date under the UNDERSCORE for each respective item, so I ADD a row.

So my table is 2 rows by 3 columns. If I want the Signature et al indented, then I'd make it 4 columns: the first and third, being spacers.

The I'd format all BORDERS NONE. Then select the cell for the signer's signature and format the lower border to be a solid line, and repeat for the cell for the signer's date


Skip,

[glasses]Just traded in my old subtlety...
for a NUANCE![tongue]
 
fumei: Thank you for the time you put into explaining it all. I'm going to have a look at it right now and I'll get back to you!!

Skipvought: As I understand your post, you're doing it like I am, more or less. But if I can figure out doing it with styles only, I'll do that!
 
Skip: Reread your post and I see what you mean now. Could be a better way. I can see how it could be easier to control.
 


Empty columns act as indents to data in other columns. Pretty simple.

Skip,

[glasses]Just traded in my old subtlety...
for a NUANCE![tongue]
 
Well, you certainly can do what (I think) is being discussed with a table, and in that vein Skip's route is fine. It uses the structure of the table ("Empty columns act as indents to data in other columns") to create the desired visible result. Sometimes this is the simplest and best way to do it. Especially as it avoids any need for going into OverStrike mode.

That being said...

If I understand correctly (and of course I may not), you are looking to do:

^p
Name^p

A blank - but underlined - area, with actual text "Name" underneath. Yes? This would mean that you would need OverStrike mode...or I think you may.

[N.B. ^p means a paragraph mark]

This can be very easily done by using a combination of a Character style, and a Paragraph style.

A character style can have an underline property. So here is what I do, as a variation on Skip's use of a table.

While Skip has: "How many apparent columns? 2: one for the NAME and one for the DATE. But I don't want the NAME underscore to run into the DATE underscore, so I ADD a column between, totaling 3."

I do not. I have 2 columns. Further, I do not use an extra row to separate the input text of the Name/Date text, from the actual text "Name" / "Date"

So, each cell has TWO paragraphs, with both using UnderParaText style. This is defined as centered. The first paragraph is empty. The second paragraph has the actual text "Name" and "Date", thus:

Col 1 Col 2

^p ^p
Name Date


Now the first paragraph is ALSO is set with the UnderChar Character style (basically, just a underline characteristic).

Because the format structure is pre-defined - by using styles - it makes it much easier if you are putting in the data via code. But it is also easier of course just typing as well.
Code:
Option Explicit

Sub Yadda()
Dim oTable As Table
Set oTable = ActiveDocument.Tables(1)
With oTable
   ' the first cell - Name
   .Range.Cells(1) _
      .Range.Paragraphs(1) _
         .Range.Text = "George Clooney" & _
                  vbCrLf
   ' the second cell - Date
   .Range.Cells(2) _
      .Range.Paragraphs(1) _
         .Range.Text = Format(Now, "mmmm, dd, yyyy") _
                  & vbCrLf
End With
End Sub
Result?

Col 1 Col 2

George Clooney July 07, 2009
Name Date

Further, if you do not want to have the paragraphs pre-setup, you can do it dynamically still using the styles:
Code:
Option Explicit

Sub Yadda()
Dim oTable As Table
Set oTable = ActiveDocument.Tables(1)
With oTable
   ' the first cell - Name
   With .Range.Cells(1)
      ' sets WHOLE cell style
      .Range.Style = "UnderParaText"
      ' sets [b]paragraph 1 character style[/b]
      ' and text
      With .Range.Paragraphs(1).Range
         .Style = "UnderChar"
         .Text = "George Clooney" & _
                  vbCrLf
      End With
   End With
   ' the second cell - Date
   With .Range.Cells(2)
      .Range.Style = "UnderParaText"
      With .Range.Paragraphs(1).Range
         .Style = "myUnderChar"
         .Text = Format(Now, "mmmm, dd, yyyy") _
                  & vbCrLf
      End With
   End With
End With
End Sub

Result?

Col 1 Col 2

George Clooney July 07, 2009
Name Date


IMPORTANT!: because you are dealing with the range of paragraph(1) - to put in the name text - you MUST either:

a) resize the range to NOT include the paragraph mark

OR

b) add a vbCrLf at the end ("George Clooney" & vbCrLf), to put the paragraph mark back in.

I prefer the second, as I am lazy.

If you do not do this, you end up with:

George ClooneyName

Gerry
 
Just as a point regarding Range in Word.....

Notice the multiple levels of .Range used for ONE thing.
Code:
With oTable
   ' the first cell - Name
   .[b]Range[/b].Cells(1) _ [COLOR=red] ' the Cell property of the table range[/color red]
      [b].Range[/b].Paragraphs(1) _[COLOR=red] ' the paragraph property of the Cell range[/color red]
         .[b]Range[/b].Text = "George Clooney" & _
                  vbCrLf[COLOR=red]  '  the text property of the paragraph range[/color red]
This is different from the Range concept in Excel...I think. I am not good enough to fully know, as I find Excel way beyond my skills.

This may also be applicable to something mentioned earlier in this thread, the use of Selection. While it may seem that:
Code:
Selection.Font.Bold = True
is an instruction actioning the Selection object, this is in fact not quite accurate. What Word VBA is really doing is:
Code:
Selection.[b]Range[/b].Font.Bold = True
In fact, other than actual GUI values of Selection - e.g. Selection.Information(wdWithInTable), it is in a table - ALL Selection instructions are really using Selection.Range.

So:

Selection.TypeText "Yadda"

is REALLY

Selection.Range.TypeText "Yadda"

The point being - other than NOT using up resources you do not need to use up - is that you may as well use the object that VBA actually uses for carrying out instructions.

Range.

Gerry
 
Thynaks for the extensive (and very informative) posts.
I'm in the process of rewriting my whole script after your instructions.
I have one problem though and as usual, it might just be me not understanding it all fully:
THIS IS A TEXT <b>THIS IS A</b> TEXT THIS IS A TEXT.

How would one do this whole operating with ranges? - I mean make a part of a sentence in bold. Before I used boldrun, which I guess it's exactly the same as pressing CTRL + B and typing.
However on a range you only have .bold and font.bold. I guess it's font.bold to use, but in conjunction with something else, as it would otherwise just activate it and then deactivate it for the whole range. .Collapse 0 doesn't seem to be the answer and that also be a bit strange to me if it did.

How is it done?
 
Regarding the signature; it's not exactly as I want it.

The document is in the end supposed to the printed and then signed, meaning no text above the line...

-------------------
The signer's name
his telephone number
his email


And the right of this, in the same height and all I want

----------------------
"Date"

Meaning the three lines under the signature line is aligned left (starts where the line starts) and the "Date" text is centered under the second line.

I have done it as wanted by a table with only one row and two cells, so I might just keep that...But no matter what I will look even more into you guys' posts about it, just to learn some more!!
 
It always help to be very clear and explicit.

"The document is in the end supposed to the printed and then signed, meaning no text above the line...

-------------------
The signer's name
his telephone number
his email
"

Ummm, what has the telephone number and email have to do with anything? Is this text YOU are putting in? Text the user as to put it? Is it even relevant (I mean to the question of this thread)?

In any case, if it is to be printed and signed, then this whole thing seems rather overblown.

Make a line. A paragraph of a bunch of spaces, and a character style of underlined. Done.

Now your question regarding using range and:

THIS IS A TEXT <b>THIS IS A</b> TEXT THIS IS A TEXT.

is much more interesting. You have hit on the one weakness of Range v.s. Selection. It can not be done (at least not easily, intuitively...or as some Excel people would say, even remotely sanely). Font.Bold = True applies across the entire range, not part of it. Even using a bold character style will not work.

This is the difference between typing text, and inserting text. Or the fact that you CAN bold highlighted (Selected) non-contiguous areas in the GUI (by hitting the Bold button) but you can NOT - EVER - do that with VBA. VBA can not action non-contiguous ranges. They do not exist in VBA.

However, having part of inserted text bold CAN be done via VBA.

Assumptions:

1. a Paragraph style (myMaintext) - formatted however you need

2. a Character style (in this case, essentially just a Bold)
Code:
Option Explicit

Sub RangeBolding()
Dim r As Range
Dim j As Long
Dim lngDiff As Long
[COLOR=red] ' set range object for current paragraph[/color red]
Set r = Selection.Paragraphs(1).Range

With r
[COLOR=red]'  set [b]paragraph[/b] style[/color red]
   .Style = "myMainText"
[COLOR=red]'  insert the first part of the text[/color red]
   .InsertAfter "This is a text "
[COLOR=red]'  get CURRENT new range values[/color red]
   lngDiff = r.End - r.Start
   .Collapse 0
[COLOR=red]'  put next text INTO the range[/color red]
   .Text = "This is a "
[COLOR=red]'  get CURRENT new .End[/color red]
   j = r.End
[COLOR=red]'  insert remaining text[/color red]
   .InsertAfter " Text This is a text"
End With
Set r = Nothing
[COLOR=red]'  RESET range for the values of the text
'  to get the character style applied[/color red]
Set r = ActiveDocument.Range( _
   Start:=lngDiff, _
   End:=j)
[COLOR=red]'  and apply the style[/color red]
   r.Style = "MainTextBold"
Set r = Nothing
End Sub

"This is a text This is a Text This is a text"

Gerry
 
fumei, again thanks for the answer.

Somehow I'm glad it's wasn't just me being stupid, since I couldn't figure out how to apply bold :)

I've tried your solution and it works, except this line:
lngDiff = r.End - r.Start
had to be
lngDiff = r.End

Guess I'm going to use that solution, even though it's a cumbersome way to do such a simple thing (looking at it from a end user perspective)...Thanks again!
 
I think I'm down to just one small problem now:

In a table cell I need some text (Style="Normal") and directly following that (same line, not even seperated by a space) a character with the font Wingdings (some speciel symbol). I can't figure out how to do that. I can't collapse the range, because I'm using ....cells(1)....meaning when I .collapse 0, it collapses the whole cell and goes on at the next cell.
Adn since collapse isn't really useful here, I can't use the trick described above either, because I can't 'save' the start and end of that smaller range. Does all of that make sense?

But I see what you wanted with range instead in selection. The speed is like quadrupled. :D
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top