none
How to determine which TextColumn a Certain Range Is In RRS feed

  • Question

  • If any Word god can answer me, I'd sure appreciate it since I'm pretty much stumped....

    Given a certain Range object which is a line of text in a multi-columned document (such as a newspaper), is there a quick way to determine which column my Range is in?  Right now, I'm kind of calculating it using LeftMargin, TextColumn::Width, TextColumn::SpaceAfter etc.  Does Word Automation offer any functions that would tell me what column my Selection or Range is in?  Unfortunately, calls to the LeftMargin, Width, SpaceAfter etc are veeeerrrrrry slow and cause the screen to flash in Word 2007.


    Fred
    Wednesday, May 11, 2011 12:40 PM

Answers

  • Hi Fred,

    You might try adding Application.ScreenUpdating = False before the first 'With' and re-set to true after the corresponding 'End With', but I'm not sure it'll do much. Without knowing how your DLL works, there's not much more I can suggest.


    Cheers
    Paul Edstein
    [MS MVP - Word]
    Thursday, May 12, 2011 7:34 PM

All replies

  • Hi Fred,

    Here's a selection-based approach, for reporting the first character's column #, with no screen flickering. Easily adapted to work with a range and/or the last character (a bit more work to do both ends):

    Sub Demo()
    Dim SngCol As Single, SngSel As Single, StrCols As String, i As Long, sCol As Single
    SngSel = Selection.Characters.First.Information(wdHorizontalPositionRelativeToPage)
    With Selection.Characters.First.Sections(1).PageSetup
      StrCols = "," & .LeftMargin
      For i = 1 To .TextColumns.Count
        'add the column width to whatever space after after the last column has been captured
        SngCol = SngCol + .TextColumns(i).Width
        'Don't test for a space after after the last column!
        If i < .TextColumns.Count Then
          'Allow for text from either side to encroach 50% into the inter-column space
          SngCol = SngCol + .TextColumns(i).SpaceAfter / 2
          StrCols = StrCols & "," & SngCol
          SngCol = .TextColumns(i).SpaceAfter / 2
        Else
        StrCols = StrCols & "," & SngCol
        End If
      Next
      'Now compare the selection position against the column widths
      For i = 1 To UBound(Split(StrCols, ","))
        SngCol = SngCol + Split(StrCols, ",")(i)
        'If the selection's position is less than the accumulated column widths,
        'we've got enough data
        If SngSel < SngCol Then
          Exit For
        End If
      Next
      'Output the column #
      MsgBox "The selection is in column " & i
    End With
    End Sub

    The code even allows for the text margins to encroach halfway into the inter-column space.


    Cheers
    Paul Edstein
    [MS MVP - Word]
    Thursday, May 12, 2011 8:06 AM
  • Hi Paul,

        Thanks for reproducing your code.  Unfortunately, under Word 2007, your method is as bad as mine in terms of screen flickering.  The following API's cause the screen to flicker:

    PageSetup::get_LeftMargin

    TextColumns::get_Count

    TextColumn::get_Width

    TextColumn::get_SpaceAfter

    Thanks again for your sample though!


    Fred
    Thursday, May 12, 2011 12:35 PM
  • Hi Fred,

    Would a "Application.ScreenUpdating = False" command help?


    Regards, Rich
    Thursday, May 12, 2011 1:06 PM
  • Hi Fred,

    I developed & tested the code under Word 2007 - and I get no screen flickering whatsoever. Even if I run the code in a loop of 100 iterations in a 10-column page, I get no flickering. And, you'll note, I didn't even bother with settings like:
    Application.ScreenUpdating = False
    which in this case makes no difference to either the flickering or the time taken to execute. The latter, I'll agree, is fairly slow - about 0.05 sec/column.

    I should point out that part of the reason for writing the code as I did was to provide for columns and inter-column spaces of different widths. If those weren't considerations, the code could be made much simpler and faster - and probably with less propensity for whatever flickering you're experiencing.

    Perhaps the flickering problem you're having has more to do with the broader scope of whatever you're doing, or the way whatever programming language you're using interacts with Word (I note your code isn't vba).

    Richard: see my comments above about Application.ScreenUpdating.


    Cheers
    Paul Edstein
    [MS MVP - Word]

    Thursday, May 12, 2011 1:10 PM
  • Hi Paul & Rich,

       Thanks for your comment.  One difference I saw in what I'm doing versus what you gave me is the fact that I'm getting the PageSetup object directly from the Range object.  You are deriving your PageSetup object from a "Sections" object that you get from your Selection.  I'm going to try that idea right now.  Word 2007's object model is verrrry weird with regard to this flashing nonesense.  I'll report back and see if getting the PageSetup in a different way helps me.   

    Thanks again for all of your great advice!

     

    Fred in Fort Wayne 


    Fred
    Thursday, May 12, 2011 1:31 PM
  • Hi Paul,

    I tried your code and did not see any flicker either. However, with all my variables ... I'm remoting into a Win 7 64 bit, Office 2010 PC from an OS X 10.6.7  Mac Pro using VM-Ware Fusion ... I couldn't be certain if my observation would be valid.


    Regards, Rich
    Thursday, May 12, 2011 1:32 PM
  • Hi Fred,

    Page setups are always managed at the Section level. If you don't allow for that, I imaging all you'll be working from are the settings for the document's first Section. If your range isn't in that Section, the results might not be worth te electrons they're splattered onto your screen with.


    Cheers
    Paul Edstein
    [MS MVP - Word]
    Thursday, May 12, 2011 1:37 PM
  • Hi again Paul and Rich,

        It might be interesting to try Paul's code when your Selection and/or Range is on a Table of Contents or List (bulletted or numbered).  That's where I see the screen flash on Word 2007 due to the API's that I enumerated above. 

        I'm also confused Paul as to why the Property-Get API Range::get_PageSetup would screw up.  I'm testing this with Sections right now on a Range that is part of a list and/or Table of Contents.

    Thanks!

    Fred E.  


    Fred
    Thursday, May 12, 2011 1:52 PM
  • Hi Fred,

    No flickering with a multi-column TOC either.

    Have you tried the vba code as-is on your system, to see what happens vis-a-vis flickering?


    Cheers
    Paul Edstein
    [MS MVP - Word]
    Thursday, May 12, 2011 2:07 PM
  • Hi again Paul,

    I think that the difference that we're seeing is that you're running your sample as an "out-of-proc" VBA app.  My DLL which has these calls is being installed as an "in-proc" add-on into Word.  Thus, I get the screen flashes and you don't.

     

    Fred


    Fred
    Thursday, May 12, 2011 4:33 PM
  • Hi Fred,

    You might try adding Application.ScreenUpdating = False before the first 'With' and re-set to true after the corresponding 'End With', but I'm not sure it'll do much. Without knowing how your DLL works, there's not much more I can suggest.


    Cheers
    Paul Edstein
    [MS MVP - Word]
    Thursday, May 12, 2011 7:34 PM