MS Office Forum / Word / Programming / March 2005
Adding spaces at the beginning of specific line
|
|
Thread rating:  |
Amir - 07 Mar 2005 18:54 GMT Hi!
I want to build a macro which will replace hanging indent with equivalent number of spaces like " ".
I assume the user is using the Courier New font with the size set to 12.
I've started building it, but I don't know how to add the spaces at the beginning of each line except for the first line in each paragraph.
Here is what i've got by now. The place where I thought about adding the spaces is marked with ***
I would be pleased if you help me.
Kind Regards, Amir.
================================= Sub Macro1()
'Variables declaration and setting Dim dcmMyDocument As Document, prgMyParagraph As Paragraph Dim intNumberOfSpaces As Integer, intNumberOfLines As Integer Dim blnHasHangingIndent As Boolean, blnHasFirstLineIndent As Boolean Dim i As Integer, j As Integer
Set dcmMyDocument = ActiveDocument
For Each prgMyParagraph In dcmMyDocument.Paragraphs 'Each Paragraph variables declaration blnHasHangingIndent = False blnHasFirstLineIndent = False
'Defines the number of spaces that should be added to each line intNumberOfSpaces = Abs(Round((prgMyParagraph.FirstLineIndent / 7.2), 0))
'Defines whether there is a hanging indent or first line indent 'The 7.2 number is the width in points of the Courier New font with the size set to 12 '(Thanks to Helmut Weber and Klaus Linke who helped me to find that one out!!!!!) If (Round((prgMyParagraph.FirstLineIndent / 7.2), 0) < 0) Then blnHasHangingIndent = True End If 'Currently I want to concentrate only on the hanging indent solution so the next 3 lines in the code has no meaning. 'If (Round((prgMyParagraph.FirstLineIndent / 7.2), 0) > 0) Then ' blnHasFirstLineIndent = True 'End If
'Cancels the hanging indent and the first line indent, then replaces the hanging indent with spaces If blnHasHangingIndent Then prgMyParagraph.FirstLineIndent = 0 prgMyParagraph.LeftIndent = 0
'Defines the number of lines in the current paragraph intNumberOfLines = (prgMyParagraph.Next.Range.Information(wdFirstCharacterLineNumber) - prgMyParagraph.Range.Information_ (wdFirstCharacterLineNumber))
'Supposed to loop through all the lines in the current paragraph, starting from the second line '(The i variable represents the current line in the specific paragraph) i = 2 Do While (i <= intNumberOfLines) '***Here I want to add the spaces (intNumberOfSpaces times) at the beginning of each line, except for the first line For j = 1 To (intNumberOfSpaces) '***Add Space at the beginning of the 'i' line Next j i = i + 1 Loop
End If
Next
End Sub
Amir - 08 Mar 2005 10:57 GMT Solved that one with the following sub procedure.
Regards,
Amir.
============= 'Variables declaration and setting Dim dcmMyDocument As Document, prgMyParagraph As Paragraph Dim intNumberOfLines As Integer Dim blnHasHangingIndent As Boolean, blnHasFirstLineIndent As Boolean Dim i As Integer, j As Integer, k As Integer Dim lngCurrentParagraph As Long, lngParagraphsCount As Long, arNumberOfLinesAndSpaces(1 To 10000, 1 To 3) As Integer Dim blnWasOvertype As Boolean
'Changes mouse pointer to hourglass System.Cursor = wdCursorWait
'Determines if the user is in Insert or Overwrite mode and changes to Insert mode blnWasOvertype = Options.Overtype Options.Overtype = False
'Adding extra paragraph at the end of the document SendKeys "^" & "{END}", True SendKeys "{ENTER}", True
Set dcmMyDocument = ActiveDocument
'Determines How many paragraphs there are in the active document lngParagraphsCount = dcmMyDocument.Paragraphs.Count
lngCurrentParagraph = 1 For Each prgMyParagraph In dcmMyDocument.Paragraphs
'Each Paragraph variables setting blnHasHangingIndent = False blnHasFirstLineIndent = False
'Determines How many lines there are in each paragraph Except for the last one (which was added by the script) If lngCurrentParagraph < lngParagraphsCount Then arNumberOfLinesAndSpaces(lngCurrentParagraph, 1) = prgMyParagraph.Next.Range.Information(wdFirstCharacterLineNumber) - prgMyParagraph.Range.Information(wdFirstCharacterLineNumber) End If
'Defines whether there is a hanging indent or first line indent If (Round((prgMyParagraph.FirstLineIndent / 7.2), 0) < 0) Then blnHasHangingIndent = True End If If (Round((prgMyParagraph.FirstLineIndent / 7.2), 0) > 0) Then blnHasFirstLineIndent = True End If
'Defines the number of spaces that should be added to each line arNumberOfLinesAndSpaces(lngCurrentParagraph, 2) = Abs(Round((prgMyParagraph.FirstLineIndent / 7.2), 0))
'Cancels the indents in the current paragraph If blnHasHangingIndent Then arNumberOfLinesAndSpaces(lngCurrentParagraph, 3) = 1 'Has only hanging indent prgMyParagraph.FirstLineIndent = 0 prgMyParagraph.LeftIndent = 0 End If If blnHasFirstLineIndent Then If Not (blnHasHangingIndent) Then arNumberOfLinesAndSpaces(lngCurrentParagraph, 3) = 2 'Has only first line indent Else arNumberOfLinesAndSpaces(lngCurrentParagraph, 3) = 3 'Has both indents End If prgMyParagraph.FirstLineIndent = 0 End If
lngCurrentParagraph = lngCurrentParagraph + 1
Next
'Removes all list numbers and paragraph numbers dcmMyDocument.RemoveNumbers
'Loops thruogh each one of the paragraphs and adds the \number of spaces needed SendKeys "^" & "{HOME}", True
For i = 1 To lngParagraphsCount 'i represents the paragraph For j = 1 To arNumberOfLinesAndSpaces(i, 1) 'j represents the line in each paragraph Select Case arNumberOfLinesAndSpaces(i, 3) Case 1 'Has only hanging indent If (j <> 1) Then SendKeys "{DOWN}", True SendKeys "{HOME}", True SendKeys "{ENTER}", True For k = 1 To arNumberOfLinesAndSpaces(i, 2) 'k represents the number of spaces that should be added SendKeys " ", True Next k End If Case 2 'Has only first line indent Case 3 'Has both indents End Select Next j SendKeys "^" & "{DOWN}", True Next i
'Removes the extra paragraph at the end of the document SendKeys "^" & "{END}", True SendKeys "{BACKSPACE}", True
'Restores the Overtype mode to be as before the script started running Options.Overtype = blnWasOvertype
System.Cursor = wdCursorNormal
> Hi! > [quoted text clipped - 79 lines] > > End Sub Helmut Weber - 08 Mar 2005 11:49 GMT Hi Amir,
have you thought about paragraphs reaching from one page to next one ?
And all that sendkeys commands may cause trouble in the long run.
Greetings from Bavaria, Germany
Helmut Weber, MVP "red.sys" & chr(64) & "t-online.de" Word XP, Win 98 http://word.mvps.org/
Amir - 08 Mar 2005 12:53 GMT Hi!
I haven't thought about the pages problem, but is there any problem with paragraphs reaching more than one page? There are no 'pages' in my emulation program (just a series of many 'lines').
I agree that sendkeys are bad, but I couldn't think of any better solution to cut the paragraphs in every line except for putting an 'Enter' there.. I will be happy to hear of any idea about that..
Kind Regards, Amir.
> Hi Amir, > [quoted text clipped - 10 lines] > Word XP, Win 98 > http://word.mvps.org/ Helmut Weber - 08 Mar 2005 13:26 GMT Hi Amir, wdFirstCharacterLineNumber is relative to the page. But if you got no pages, though I hardly can imagine how to achieve that, it might work.
For the sendkeys issue, I'd suggest to ask in detail, what you want to do.
I think all those sendkeys could and should be replaced.
Greetings from Bavaria, Germany
Helmut Weber, MVP "red.sys" & chr(64) & "t-online.de" Word XP, Win 98 http://word.mvps.org/
Amir - 08 Mar 2005 13:50 GMT Hi,
Now I understand what you mean... That thing with the pages might be a problem. What i'm trying to do is to convert a Word document to a format which does not have indents, and replace the indents (regular and hanging indents) with equivalent number of spaces. Therefore, I use the SendKeys to "break" the indents and then adds the number of spaces needed according to the indent.
I need that in order to paste that text into an emulation program which doesn't read Word's indents but spaces.
Can you think of a more simple way for doing that? I can live with using SendKeys but I'm concerned about that problem you've mentioned with the line counting, and despite my searches all over the help documents and MSDN, couldn't find a way to solve that...
Thank you!, Amir.
> Hi Amir, > wdFirstCharacterLineNumber is relative to the page. [quoted text clipped - 12 lines] > Word XP, Win 98 > http://word.mvps.org/ Helmut Weber - 08 Mar 2005 14:18 GMT Hi Amir,
that is tedious work, but I don't know of a better way, but to check what paragraph the selection is in, and moving it down, until the number of the paragraph changes.
Everything you do with sendkeys can accomplished.
You only have to inform us about what you want to do. Like this:
>'Removes the extra paragraph at the end of the document >SendKeys "^" & "{END}", True >SendKeys "{BACKSPACE}", True activedocument.paragraphs.last.range.delete
Or
GotoStartOfFirstParagraphInTheSelection
Selection.Paragraphs(1).Range.Select Selection.Collapse
A million ways.
HTH
Greetings from Bavaria, Germany
Helmut Weber, MVP "red.sys" & chr(64) & "t-online.de" Word XP, Win 98 http://word.mvps.org/
Amir - 08 Mar 2005 15:20 GMT OK, I'll try to list the tasks that I don't know how to do:
All these tasks are done inside the next loop: For Each prgMyParagraph In dcmMyDocument.Paragraphs Next
1. Determine how many lines there are in each paragraph. (I've tried to use prgMyParagraph.Next.Range.Information_ (wdFirstCharacterLineNumber) - prgMyParagraph.Range_ .Information(wdFirstCharacterLineNumber) But that produces an error when prgMyParagraph is the last paragraph in the document because it can't calculate the .Next.
2. Determine for each paragraph all the values of the indent. I've solved that by using: If (Round((prgMyParagraph.FirstLineIndent / 7.2), 0) < 0) Then blnHasHangingIndent = True End If If (Round((prgMyParagraph.FirstLineIndent / 7.2), 0) > 0) Then blnHasFirstLineIndent = True End If
** - Here I still have a problem with the autonumbering, because I don't know how to determine the indent caused by the autonumbering! How can I know that? I'm using ActiveDocument.ConvertNumbersToText, but I don't know how many spaces to add starting from the second ('hanging') line to each line that was previously autounumbered!
The part which converts the hanging (not caused by autonumbering) indent works fine, because I'm using an array which saves for each paragrph the amount of spaces that should be added to this paragraph instead of the hanging indent (starting from the second line of each paragraph because it's hanging). Here is what I do to calculate that:
'Defines the number of spaces that should be added to each line 'instead of the indent after the indent is canceled arNumberOfLinesAndSpaces(lngCurrentParagraph, 2) = Abs(Round((prgMyParagraph.FirstLineIndent / 7.2), 0))
The first argument in the array saves the number of the paragraph which it's indent values are currently calculated, and the second argument says which information about the paragraph is saved:
arNumberOfLinesAndSpaces(, 1 ) - Tells for each paragraph, How many lines there are in this paragraph?
arNumberOfLinesAndSpaces(, 2 ) - Tells for each paragraph, How many spaces should be added to each line in order to replace the indent?
arNumberOfLinesAndSpaces(, 3 ) - Tells the type of the indent in the specific paragraph: 1 - indicates hanging indent 2 - indicates first line indent 3 - will indicate autonumbering indent? (but I don't know how to identify autonumbering indent, and, in addition, if there is a way to do so, should I use the Paragraph range? or maybe the Sentence Range?
Your help is needed...
Thank you very much!!
Kind Regards, Amir.
> Hi Amir, > [quoted text clipped - 29 lines] > Word XP, Win 98 > http://word.mvps.org/ Helmut Weber - 08 Mar 2005 22:41 GMT Hi Amir,
as far as I see, question number 1 is enough of a challenge.
Such a seemably simple thing like counting the lines in a paragraph turns out to be hell.
And I got a feeling, that the rectangle approach of Jean-Guy won't work if the paragraph reaches over more than one page. Besides that you haven't got Word 2003. And neither have I.
Not to speak of paragraphs that include a manual page break. In that case, selection.paragraphs(1).range.select stops at the page break.
If you can definitely exclude manual page breaks, then hopefully like this, for getting the number of lines in a paragaph:
Helmut Weber - 08 Mar 2005 22:52 GMT Sorry, was hitting the wrong button:
Public Function PrgNum() As Long ' get number of paragraph Dim rTmp As Range Selection.Collapse Set rTmp = Selection.Range rTmp.Start = 0 rTmp.End = Selection.Range.End + 1 PrgNum = rTmp.Paragraphs.Count End Function ' ---- Public Function PrgLines() As Long Dim l As Long Dim p1 As Long ' starting paragraph p1 = PrgNum ' actual paragraph l = 1 Selection.Paragraphs(1).Range.Select Selection.Collapse Selection.MoveDown Selection.Bookmarks("\line").Select Selection.Collapse direction:=wdCollapseStart While p1 = PrgNum ' as long as the selection is in ' the starting paragraph Selection.MoveDown l = l + 1 If IslastLine Then l = l + 1 GoTo weiter End If Wend weiter: PrgLines = l Selection.MoveUp Selection.Paragraphs(1).Range.Select Selection.Collapse End Function ' ---- Public Function IslastLine() As Boolean On Error GoTo ende If Selection.Bookmarks("\line").Range.End = _ ActiveDocument.Range.End - 1 Then IslastLine = True Else IslastLine = False End If Exit Function ende: IslastLine = True End Function ' ------ Sub test12345() MsgBox PrgLines End Sub ' --------- Sub test777() MsgBox IslastLine End Sub
This is endlessly complicated.
You need a function to tell you, what paragraph the selection is in: PrgNum You need a function to count the lines in a paragraph: PrgLines You need a function to tell you, whether a line is the last line in a doc: IslastLine.
Not regarding manual page breaks!
I wish I was paid for this.
Greetings from Bavaria, Germany
Helmut Weber, MVP "red.sys" & chr(64) & "t-online.de" Word XP, Win 98 http://word.mvps.org/
Amir - 11 Mar 2005 02:15 GMT Hi!
This is brilliant!!
unfortunately I have to leave that problem for some days, since I had too many difficulties by now and not much of success. I hope to get back to it in the next few weeks, then this solution will help me very much. I can live without the manual page breaks.
I thank you very much for your help!!
Kind Regards, Amir.
> Sorry, > was hitting the wrong button: [quoted text clipped - 76 lines] > Word XP, Win 98 > http://word.mvps.org/ Jean-Guy Marcil - 08 Mar 2005 15:46 GMT Amir was telling us: Amir nous racontait que :
> Hi, > [quoted text clipped - 16 lines] > you've mentioned with the line counting, and despite my searches all > over the help documents and MSDN, couldn't find a way to solve that... If you are using Word 2003, you can take advantage of the new Page and Line collections:
'_______________________________________ Dim myPane As Pane Dim myPage As Page Dim myRect As Rectangle Dim myLine As Line Dim LineRge As Range Dim i As Long Dim j As Long Dim k As Long
Set myPane = ActiveWindow.ActivePane
With myPane For i = 1 To .Pages.Count Set myPage = .Pages(i) With myPage For j = 1 To .Rectangles.Count Set myRect = .Rectangles(j) With myRect If .RectangleType = wdTextRectangle Then For k = 1 To .Lines.Count Set myLine = .Lines(k) With myLine If .LineType = wdTextLine Then 'Skip lone ? If Not .Range.Text = Chr(13) Then Set LineRge = .Range With LineRge MsgBox .Text 'Do what you have to with this range 'I guess it would be easier to call a function 'and to pass it the line range object End With End If End If End With Next End If End With Next End With
Next End With '_______________________________________
But watch out, the rectangle collection includes header, footers, text boxes, etc... So you may have to account for that in your code. The Line collection also distinguished between a text line and a table row.
HTH.
 Signature Salut! _______________________________________ Jean-Guy Marcil - Word MVP jmarcilREMOVE@CAPSsympatico.caTHISTOO Word MVP site: http://www.word.mvps.org
Amir - 08 Mar 2005 17:30 GMT Hi!,
Thank you very much for the detailed answer, but unfortunatly I can't use Office 2003 at that computer.
Is there a way I can check to see if a specific paragraph is bulleted / numbered, and the properties of the specific paragraph's numbering?
Guess I'm selecting a paragraph using: Selection.Expand Unit:=wdParagraph
As a user (not with VBA) I can go to the Format -> Bullets and Numbering menu, and check to see if there is a blue rectangle on the activate numbering method of the paragraph i've just selected.
Is there any way to do that with VBA? In addition, how can I check the properties of this numbering/bulleting? (the one which is activated on the paragraph I've selected)
At the help documents I saw something like: With ListGalleries(wdNumberGallery).ListTemplates(7).ListLevels(1) intIndentNumberPosition = .NumberPosition intIndentTabPosition = .TabPosition intIndentTextPosition = .TextPosition intIndentStartAt = .StartAt End With
but that doesn't tell me the current selected paragraph's properties!
Any help will be appreciated!
Regards, Amir.
> Amir was telling us: > Amir nous racontait que : [quoted text clipped - 77 lines] > > HTH. Jean-Guy Marcil - 08 Mar 2005 20:50 GMT Amir was telling us: Amir nous racontait que :
> Hi!, > [quoted text clipped - 12 lines] > and check to see if there is a blue rectangle on the > activate numbering method of the paragraph i've just selected. Look up the help in the VBE on ListFormat and its properties, for example:
Selection.Paragraphs(1).Range.ListFormat.ListType
will return the kind of Bullet/numbering (if any) of the currently selected paragraph.
If you are going to go through every paragraph, use the paragraph collations, as in:
'_______________________________________ Dim MyParRge As Range Dim i As Long
With ActiveDocument.Paragraphs For i = 1 To .Count Set MyParRge = .Item(i).Range With MyParRge Select Case .ListFormat.ListType Case wdListBullet MsgBox "Paragraph " & i & " has bullets" Case wdListSimpleNumbering MsgBox "Paragraph " & i & " has simple numbering" Case wdListOutlineNumbering MsgBox "Paragraph " & i & " has outline numbering" Case wdListNoNumbering MsgBox "Paragraph " & i & " has no numbering" End Select End With Next End With '_______________________________________
 Signature Salut! _______________________________________ Jean-Guy Marcil - Word MVP jmarcilREMOVE@CAPSsympatico.caTHISTOO Word MVP site: http://www.word.mvps.org
Amir - 11 Mar 2005 02:24 GMT Hi,
Thank you for the answer!
Is there any way I can get more details about the current paragraph's numbering, e.g. text position and number position?
I know that I can use (MyParagraph).Range.ListFormat.ListString to get the list string, but how can I get the .StartAt, .TextPosition, .TabPosition and .NumberStyle parameters of the CURRENT paragraph? I want to get these parameters about a selected paragraph or about a paragraph which I will define it's number by variable. e.g. intParagraphNumber.
I thought about using ListGalleries(wdNumberGallery).ListTemplates_ (CurrentParagraphNumber).ListLevels.Item (1) but will that give me the parameters about a specific paragraph?
Regards, Amir.
> Amir was telling us: > Amir nous racontait que : [quoted text clipped - 48 lines] > End With > '_______________________________________ Jean-Guy Marcil - 11 Mar 2005 05:02 GMT Amir was telling us: Amir nous racontait que :
> Hi, > [quoted text clipped - 13 lines] > (CurrentParagraphNumber).ListLevels.Item (1) > but will that give me the parameters about a specific paragraph? First, get the current paragraph outline level, if any. if there is one, then use the something like:
'_______________________________________ Dim MyPara As Range Dim MyLevel As Long Dim MyStart As Long Dim MyTextPos As Single Dim MyTabPos As Single Dim MyNumAlign As Long Dim MyNumPos As Single Dim MyNumStyle As Long
Set MyPara = Selection.Paragraphs(1).Range
With MyPara MyLevel = .ListFormat.ListLevelNumber MyStart = .ListFormat.ListTemplate.ListLevels(MyLevel).StartAt MyTextPos = PointsToInches(.ListFormat.ListTemplate.ListLevels(MyLevel).TextPosition) MyTabPos = PointsToInches(.ListFormat.ListTemplate.ListLevels(MyLevel).TabPosition) MyNumPos = PointsToInches(.ListFormat.ListTemplate.ListLevels(MyLevel).NumberPosition) MyNumAlign = .ListFormat.ListTemplate.ListLevels(MyLevel).Alignment MyNumStyle = .ListFormat.ListTemplate.ListLevels(MyLevel).NumberStyle End With '_______________________________________
If you can, avoid working with .ListGallery. This is a can of worm than can only lead to disaster in the long run. It is very unstable and can produce different results depending on the machine where it is used, unless you have very long and complicated code to clean it up (I mean the Bullet and numbering dialog box) Overall, it is not worth it.
 Signature Salut! _______________________________________ Jean-Guy Marcil - Word MVP jmarcilREMOVE@CAPSsympatico.caTHISTOO Word MVP site: http://www.word.mvps.org
Amir - 20 Mar 2005 05:10 GMT Thank you very much, Jean-Guy Marcil!
Kind Regards, Amir.
> Amir was telling us: > Amir nous racontait que : [quoted text clipped - 51 lines] > unless you have very long and complicated code to clean it up (I mean the > Bullet and numbering dialog box) Overall, it is not worth it.
|
|
|