| View previous topic :: View next topic |
| Author |
Message |
rebel General User

Joined: 05 May 2012 Posts: 10
|
Posted: Sat May 05, 2012 4:16 am Post subject: macro for finding all cross references and inserting -solved |
|
|
IF anybody could help me I'd sure appreciate it. I have about a 1000 page document with a very large number of cross-references set. I want to insert fields to all the cross-references at the end of the document to use as an index. It will take a VERY long time to go through and insert each cross-reference one at a time which is the only way I've found to do it. Would anyone have a macro that would iterate through each cross-reference which has been set in the document and insert a reference to it in the document?
Last edited by rebel on Wed May 09, 2012 11:35 am; edited 1 time in total |
|
| Back to top |
|
 |
patel Power User

Joined: 14 Apr 2012 Posts: 54 Location: Italy
|
Posted: Sat May 05, 2012 6:39 am Post subject: |
|
|
can you attach a sample ? _________________ If your problem has been solved please add "[Solved]" to the beginning of your first post title (edit button). |
|
| Back to top |
|
 |
rebel General User

Joined: 05 May 2012 Posts: 10
|
Posted: Sat May 05, 2012 12:34 pm Post subject: |
|
|
| I would but maybe I'm overlooking something. How do I attach a file to a message. I don't see any options for doing it. |
|
| Back to top |
|
 |
JohnV Administrator

Joined: 07 Mar 2003 Posts: 8976 Location: Lexinton, Kentucky, USA
|
Posted: Sat May 05, 2012 12:57 pm Post subject: |
|
|
Please make a copy of your document to try this. A the very end of your document, in a new paragraph type "The end" (without parentheses) and press Enter.
Here's what I did. I inserted 2 bookmark of selected words then inserted 2 cross-references to those bookmarks to show the referenced words.
The macro below puts working copies of the cross-references, in the order they appear in the document, at its end. The macro looks for text portions that are text fields and copies those to the end so if you have other text fields that are not cross-references those may get copied also. I have tried to eliminate this problem for text fields that are variables.
| Code: | Sub TextPortionEnum
oDoc = ThisComponent
oVC = oDoc.CurrentController.getViewCursor
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
Enum = oDoc.Text.createEnumeration 'Paragraph enumeration
While enum.hasMoreElements
ThisP = enum.nextElement
enum1 = ThisP.createEnumeration 'Text portion enumeration
While enum1.hasMoreElements
portion = enum1.nextElement
If portion.string = "The end" then End
If portion.TextPortionType = "TextField" then
If portion.TextField.TextFieldMaster.InstanceName = "" then 'Variables have an instance name while cross-references don't.
oVC.gotoRange(portion,false)
dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())
oVC.gotoEnd(false)
dispatcher.executeDispatch(document, ".uno:InsertPara", "", 0, Array())
dispatcher.executeDispatch(document, ".uno:Paste", "", 0, Array())
EndIf
EndIf
Wend
Wend
End Sub |
|
|
| Back to top |
|
 |
rebel General User

Joined: 05 May 2012 Posts: 10
|
Posted: Sat May 05, 2012 2:55 pm Post subject: |
|
|
Since I didn't see any other way of doing it I put a small sample at
[url]https://docs.google.com/open?id=0Bzwj_TNIBFRISnJ6WDIxYUZ3MzQ
[/url]
One thing I wasn't thinking about in the first message is that the fields should be sorted. When you go to Insert Cross-references, in the selection window they are all sorted already but you can only select one at a time. Maybe what I want isn't possible but it would make things a whole lot easier. I tried the code given earlier but got an error message that it could not create enumeration. |
|
| Back to top |
|
 |
patel Power User

Joined: 14 Apr 2012 Posts: 54 Location: Italy
|
Posted: Sun May 06, 2012 2:12 am Post subject: |
|
|
try with this modification
| Code: | Sub ref
oDoc = ThisComponent
oVC = oDoc.CurrentController.getViewCursor
document = ThisComponent.CurrentController.Frame
oText = oDoc.Text
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
Enum = oText.createEnumeration 'Paragraph enumeration
While enum.hasMoreElements
flag=0
ThisP = enum.nextElement
enum1 = ThisP.createEnumeration 'Text portion enumeration
While enum1.hasMoreElements
portion = enum1.nextElement
If portion.string = "The end" then exit sub
if portion.TextPortionType = "ReferenceMark" then flag=flag+1
if flag mod 2 = 1 and len(portion.string) > 0 then
' print portion.string
oVC.gotoRange(portion, false)
dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())
oVC.gotoEnd(false)
dispatcher.executeDispatch(document, ".uno:Paste", "", 0, Array())
oText.insertString(oText.getEnd(), CHR$(13), False)
end if
Wend
Wend
End Sub |
_________________ If your problem has been solved please add "[Solved]" to the beginning of your first post title (edit button). |
|
| Back to top |
|
 |
rebel General User

Joined: 05 May 2012 Posts: 10
|
Posted: Sun May 06, 2012 4:07 am Post subject: |
|
|
| It's closer. Instead of simply copying the set reference text I want to insert the field to the reference. The sample.odt linked to in the prior message shows an example of the finished product. This would be the the same as going to Insert | Reference | Cross-references | Insert Reference and Inserting reference to Reference and selecting them one-by-one from the Selection window in the order they're given there. The end result will be creating a sorted index and exporting the file to a pdf so when the field in the index is clicked it will go right to that reference. |
|
| Back to top |
|
 |
patel Power User

Joined: 14 Apr 2012 Posts: 54 Location: Italy
|
Posted: Sun May 06, 2012 6:28 am Post subject: |
|
|
Can you do it manually ? I don't, maybe it's possible register a macro. _________________ If your problem has been solved please add "[Solved]" to the beginning of your first post title (edit button). |
|
| Back to top |
|
 |
JohnV Administrator

Joined: 07 Mar 2003 Posts: 8976 Location: Lexinton, Kentucky, USA
|
Posted: Sun May 06, 2012 8:48 am Post subject: |
|
|
Alright, instead of using Bookmarks you selected text and did Insert > Cross-reference > Set Reference. Now, at the end of the document, you want to create cross-references to these set references in alphabetic order. Here's the code.
| Code: | Sub CrossRefSortedRefMarks
oDoc = ThisComponent
rm = oDoc.getReferenceMarks
Dim myList(rm.getCount-1)
For x = 0 to ubound(mylist)
mylist(x) = rm.getByIndex(x).Name
Next
ImprovedBubbleSort(myList())
oVC = oDoc.CurrentController.getViewCursor
oVC.gotoEnd(false)
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dim args1(5) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Type" : args1(0).Value = 13
args1(1).Name = "SubType" : args1(1).Value = 0
args1(2).Name = "Name"
args1(3).Name = "Content" : args1(3).Value = ""
args1(4).Name = "Format" : args1(4).Value = 2
args1(5).Name = "Separator" : args1(5).Value = " "
For x = 0 to uBound(myList)
args1(2).Value = myList(x)
dispatcher.executeDispatch(document, ".uno:InsertPara", "", 0, Array())
dispatcher.executeDispatch(document, ".uno:InsertField", "", 0, args1())
Next
End Sub
Sub ImprovedBubbleSort(myList()) 'By B Marcelly - http://www.oooforum.org/forum/viewtopic.phtml?t=20783
Dim k1 As Long, k2 As Long
Dim x1 As Long, x2 As Long
Dim swapping
k1 = LBound(myList())
k2 = UBound(myList())
for x2 = k2 -1 to k1 step -1
for x1 = k1 to x2
if StrComp(myList(x1), myList(x1 +1), 0) = 1 then
swapping = myList(x1)
myList(x1) = myList(x1 +1)
myList(x1 +1) = swapping
x1 = k1
end if
next
next
End Sub |
|
|
| Back to top |
|
 |
patel Power User

Joined: 14 Apr 2012 Posts: 54 Location: Italy
|
Posted: Sun May 06, 2012 10:37 am Post subject: |
|
|
very good JohnV !! _________________ If your problem has been solved please add "[Solved]" to the beginning of your first post title (edit button). |
|
| Back to top |
|
 |
rebel General User

Joined: 05 May 2012 Posts: 10
|
Posted: Sun May 06, 2012 11:25 am Post subject: |
|
|
| I "think" it is working. It works great on the sample and on a greatly slimmed down copy of the original. But it is taking a very long time to complete on the full 1000+ page document. But I don't really care if it takes a day to just let the computer run as it goes through getting and sorting them as it would still save me weeks or months of manually inserting the fields. I don't know how many there are but it's a lot. I'll let you know how it went whenever it finishes. |
|
| Back to top |
|
 |
rebel General User

Joined: 05 May 2012 Posts: 10
|
Posted: Mon May 07, 2012 5:09 am Post subject: |
|
|
The sort routine given is definitely no good for this scenario. This one taken from the same message as the bubble routine at http://www.oooforum.org/forum/viewtopic.phtml?t=20783 should be used instead:
Sub ShellSort(myList())
Dim k1 As Long, k2 As Long, listSize As Long
Dim x1 As Long, isSorted As Boolean
Dim swapping
listSize = UBound(myList()) +1 -LBound(myList())
k1 = Fix(listSize /2)
do while k1 > 0
k2 = UBound(myList()) - k1
isSorted = true
for x1 = LBound(myList()) to k2
if StrComp(myList(x1), myList(x1 +k1), 0) = 1 then
swapping = myList(x1)
myList(x1) = myList(x1 +k1)
myList(x1 +k1) = swapping
isSorted = false
end if
next
if isSorted then
k1 = Fix(k1 /2)
end if
loop
End Sub
The improvedbubblesort routine was sorting for almost 14 hours and when I checked the value of x2 it still hadn't gotten past the first iteration! At that point I just stopped the macro. Using the shellsort routine, the list array was populated and sorted in less than 45 seconds. Now the slowdown is at the end where it is inserting the fields into the document. I put in a MSGBOX command in the For...Next loop to let me know when every 1000 fields are inserted and each 1000 takes longer and longer to get done. The document has 11220 reference fields. Eventually it should get done though, now that I'm using a new sort routine. |
|
| Back to top |
|
 |
patel Power User

Joined: 14 Apr 2012 Posts: 54 Location: Italy
|
Posted: Mon May 07, 2012 9:18 am Post subject: |
|
|
You are right, the shellsort is very faster than other _________________ If your problem has been solved please add "[Solved]" to the beginning of your first post title (edit button). |
|
| Back to top |
|
 |
rebel General User

Joined: 05 May 2012 Posts: 10
|
Posted: Wed May 09, 2012 11:34 am Post subject: |
|
|
It finally finished! I think it took somewhere around 45 hours. The first 1000 reference fields took about 20 minutes to insert into the document, and the last 1000 took about 7 hours. But that looks to be probably about what it would have taken to insert 11220 references manually. After it finished I tried it manually and it took 28 seconds to insert one field whereas it took about 5 seconds for each one at the beginning. And that's on a quad-core, 3Ghz computer.
What would the change be in the code to insert a cross-reference to the page # instead of to the cross-reference name?
Thank you so much for your help! It was greatly appreciated. |
|
| Back to top |
|
 |
JohnV Administrator

Joined: 07 Mar 2003 Posts: 8976 Location: Lexinton, Kentucky, USA
|
Posted: Wed May 09, 2012 1:35 pm Post subject: |
|
|
| Quote: | | What would the change be in the code to insert a cross-reference to the page # instead of to the cross-reference name? | I don't find an available Page # property although it may be hidden somewhere. |
|
| Back to top |
|
 |
|