Задача оказалась не так тривиальна как кажется Прошу помощи
В вопросе определения текущего номера страницы все зависит от цели:
1. Если нужно определить номер станицы чисто для «себя», то есть для использования внутри своей программы, чтобы просто ориентироваться по тексту, то это да
Visual Basic | ||
|
2. Если нужно же определить номер страницы текущего текста в окончательном документе, например в распечатанном документе (или например в сохраненным в pdf), то это уже совершенно другая задача.
Хитрость здесь в том, что предыдущий макрос возвращает номер страницы в текущем режиме просмотра документа (обычно это «разметка») и это номер может не совпасть с реальным номером страницы уже распечатанного документа, потому что включены просмотры кодов полей или в документе установлен предметный указатель и по всему документу идет разметка этих слов, которые занимают место на экране и сдвигают текст вниз.
Таким образом следующий макрос для некоторых строк вернет другие значения:
Visual Basic | ||
|
Вопрос: Как получить реальный номер страницы?
То есть у меня стоит задача найти по тексту абзацы с некоторыми словами и сохранить в отдельном файле со ссылками на страницы. В документе есть предметный указатель со множеством слов и коды отображаются по всему тексту типа «опасные грузы { XE «опасные грузы»} -это вещества…» из-за которых и происходит смещение страниц.
Есть ли другое решение? нежели переключать режим на предпросмотр — это же будет моргать окна при выполнении.
во вложении пример документа — попробуйте определить номер станицы последней строки этими двумя макросами
Документ предоставлен КонсультантПлюс2.docx
Алексей задал вопрос:
Как программно определить номер текущей страницы? Единственное, до чего я додумался — по проценту скробара. Но правильно ли это?
В VBA есть две константы, по которым можно определить номер текущей страницы:
- wdActiveEndPageNumber
- wdActiveEndAdjustedPageNumber
Первая константа wdActiveEndPageNumber используется тогда, когда в документе нумерация начинается с первого номера (нормальная нумерация), а вторая — wdActiveEndAdjustedPageNumber — если пользователь использует свою нумерацию документа (не с первого по порядку листа документа).
Как я полагаю, в случае Алексея нужно узнать номер текущей страницы, на которой находится курсор ввода и нумерация страниц правильная. Вот примерный код:
Sub currentPage() Dim pn As String pn = Selection.Information(wdActiveEndPageNumber) MsgBox pn End Sub
(Note: See below for solution.)
I have been trying to retrieve the page numbers from pages that various headings reside on in a word document using VBA. My current code returns either 2 or 3, and not the correctly associated page numbers, depending on where and how I use it in my main Sub.
astrHeadings = docSource.GetCrossReferenceItems(wdRefTypeHeading)
For Each hds In astrHeadings
docSource.Activate
With Selection.Find
.Text = Trim$(hds)
.Forward = True
MsgBox hds & ":" & Selection.Information(wdActiveEndPageNumber), vbOKOnly
End With
Selection.Find.Execute
Next
docSource
is a test document I have set up with 10 headings over 3 pages. I have the headings retrieved from the getCrossReferenceItems
method in use later in my code.
What I am attempting is to loop through the results from the getCrossReferenceItems
method and use each them in a Find object on docSource
and from this ascertain what page the result is on. The page numbers will then be used in a string later in my code. This string plus page number will be added to another document which is created at the beginning of my main sub, everything else works a treat but this code segment.
Ideally what I need this segment to do is fill a second array with the associated page numbers from each Find result.
Problems Solved
Thanks Kevin you have been a great help here, I now have exactly what I need from the output of this Sub
.
docSource is a test document I have set up with 10 headings over 3 pages.
docOutline is a new document which will act as a Table of Contents document.
I have had to use this Sub
over Word’s built-in TOC features because:
-
I have multiple documents to include, I could use the
RD
field to include these but -
I have another
Sub
which generates custom decimal page numbering in each document 0.0.0 (chapter.section.page representative) that, for the whole document package to make sense, need to be included in the TOC as page numbers. There probably is another way of doing this but I came up blank with Word’s built-in features.
This will become a Function to be included in my page numbering Sub
. I am currently 3/4 of the way to completing this little project, the last quarter should be straightforward.
Revised and cleaned final Code
Public Sub CreateOutline()
' from http://stackoverflow.com/questions/274814/getting-the-headings-from-a-word-document
Dim docOutline As Word.Document
Dim docSource As Word.Document
Dim rng As Word.Range
Dim strFootNum() As Integer
Dim astrHeadings As Variant
Dim strText As String
Dim intLevel As Integer
Dim intItem As Integer
Dim minLevel As Integer
Dim tabStops As Variant
Set docSource = ActiveDocument
Set docOutline = Documents.Add
minLevel = 5 'levels above this value won't be copied.
' Content returns only the
' main body of the document, not
' the headers and footer.
Set rng = docOutline.Content
astrHeadings = docSource.GetCrossReferenceItems(wdRefTypeHeading)
docSource.Select
ReDim strFootNum(0 To UBound(astrHeadings))
For i = 1 To UBound(astrHeadings)
With Selection.Find
.Text = Trim(astrHeadings(i))
.Wrap = wdFindContinue
End With
If Selection.Find.Execute = True Then
strFootNum(i) = Selection.Information(wdActiveEndPageNumber)
Else
MsgBox "No selection found", vbOKOnly
End If
Selection.Move
Next
docOutline.Select
With Selection.Paragraphs.tabStops
'.Add Position:=InchesToPoints(2), Alignment:=wdAlignTabLeft
.Add Position:=InchesToPoints(6), Alignment:=wdAlignTabRight, Leader:=wdTabLeaderDots
End With
For intItem = LBound(astrHeadings) To UBound(astrHeadings)
' Get the text and the level.
' strText = Trim$(astrHeadings(intItem))
intLevel = GetLevel(CStr(astrHeadings(intItem)))
' Test which heading is selected and indent accordingly
If intLevel <= minLevel Then
If intLevel = "1" Then
strText = " " & Trim$(astrHeadings(intItem)) & vbTab & "1" & "." & "2" & "." & strFootNum(intItem) & vbCr
End If
If intLevel = "2" Then
strText = " " & Trim$(astrHeadings(intItem)) & vbTab & "1" & "." & "2" & "." & strFootNum(intItem) & vbCr
End If
If intLevel = "3" Then
strText = " " & Trim$(astrHeadings(intItem)) & vbTab & "1" & "." & "2" & "." & strFootNum(intItem) & vbCr
End If
If intLevel = "4" Then
strText = " " & Trim$(astrHeadings(intItem)) & vbTab & "1" & "." & "2" & "." & strFootNum(intItem) & vbCr
End If
If intLevel = "5" Then
strText = " " & Trim$(astrHeadings(intItem)) & vbTab & "1" & "." & "2" & "." & strFootNum(intItem) & vbCr
End If
' Add the text to the document.
rng.InsertAfter strText & vbLf
docOutline.SelectAllEditableRanges
' tab stop to set at 15.24 cm
'With Selection.Paragraphs.tabStops
' .Add Position:=InchesToPoints(6), _
' Leader:=wdTabLeaderDots, Alignment:=wdAlignTabRight
' .Add Position:=InchesToPoints(2), Alignment:=wdAlignTabCenter
'End With
rng.Collapse wdCollapseEnd
End If
Next intItem
End Sub
Private Function GetLevel(strItem As String) As Integer
' from http://stackoverflow.com/questions/274814/getting-the-headings-from-a-word-document
' Return the heading level of a header from the
' array returned by Word.
' The number of leading spaces indicates the
' outline level (2 spaces per level: H1 has
' 0 spaces, H2 has 2 spaces, H3 has 4 spaces.
Dim strTemp As String
Dim strOriginal As String
Dim intDiff As Integer
' Get rid of all trailing spaces.
strOriginal = RTrim$(strItem)
' Trim leading spaces, and then compare with
' the original.
strTemp = LTrim$(strOriginal)
' Subtract to find the number of
' leading spaces in the original string.
intDiff = Len(strOriginal) - Len(strTemp)
GetLevel = (intDiff / 2) + 1
End Function
This code is now producing (What it should be according to my headings specification found in test-doc.docx):
This is heading one 1.2.1
This is heading two 1.2.1
This is heading two.one 1.2.1
This is heading two.three 1.2.1
This is heading one.two 1.2.2
This is heading three 1.2.2
This is heading four 1.2.2
This is heading five 1.2.2
This is heading five.one 1.2.3
This is heading five.two 1.2.3
In Addition to this I have solved the ActiveDocument
switching issue by using docSource.select
and docOutline.Select
statements instead of using.Active
.
Thanks again Kevin, greatly appreciated
Phil
- Talker
- Новичок
- Сообщения: 30
- Зарегистрирован: 07.05.2006 (Вс) 21:17
Номер страницы в Word через VBA
Пишу программку, которая должна обработать построчно (попараграфно) весь документ кроме первой страницы. Как при переборе параграфов узнать на какой странице я нахожусь? Просмотрел все свойства из Document — ничего не нашёл. Но где-то же это должно быть?
- GSerg
- Шаман
- Сообщения: 14286
- Зарегистрирован: 14.12.2002 (Сб) 5:25
- Откуда: Магадан
GSerg » 20.05.2006 (Сб) 15:44
А я сразу нашёл
Что-то я всё-таки сделал неправильно
range.information(wdActiveEndPageNumber)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас
- Talker
- Новичок
- Сообщения: 30
- Зарегистрирован: 07.05.2006 (Вс) 21:17
Talker » 20.05.2006 (Сб) 17:07
Как всё просто Спасибо.
Вернуться в VBA
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2
I am using the QR-Code DISPLAYBARCODE field. I am updating all DISPLAYBARCODE with some information like date and time, additionaly I want to add the page number on which the DISPLAYBARCODE field is.
For tables I would use the range field but this is not available for fields.
Is there a way how to do that?
BigBen
43.9k6 gold badges27 silver badges40 bronze badges
asked Aug 20, 2020 at 16:23
If you want the page number to display as part of the QR Code, you could embed a page field in the text of the code. Something like:
- { DisplayBarCode «{ Date } { Time } Page { Page }» QR s 100 r 0 q 3 }
Note the quotation marks. They are necessary.
The DATE and TIME fields are the date and time when the document is printed or those fields are updated. They are not fixed timestamps.
I am working on the code for you to enter a field like the one shown.
- Is that what you want?
- Do you want to have the page, date, and time appear inside the DisplayBarCode field so that they show up when the bar code is read?
- Do you instead of the current date and time want a time stamp for when the code is run?
- What else goes in the field? The current content? Before or after the date, time and page?
Take a look at the second answer in this thread (from WillWillPower): Setting up a nested field in Word using VBA
It uses the range of the field code.
answered Aug 20, 2020 at 17:30
Charles KenyonCharles Kenyon
8431 gold badge7 silver badges19 bronze badges