Wiki called WikiDoc: http://sourceforge.net/projects/wikidoc/The following Microsoft Word 97 macros make a single word document into a mini wiki database. Sort of "wiki for one". WHAT?! If you hook the subroutime WikiDoc up to Alt-W (or whatever), whenever you press Alt-W, all wiki names (called "page names" in the code) at the beginning of pages become bookmarks (hyperlink targets) of style "heading 2". All page names not at the beginning of pages become underlined hyperlinks.
If you hook the subroutine WikiUnPage up to Alt-U (or whatever), you can press Alt-U to remove all the page breaks. This is useful if you want to print the document.
The rule used for page names is: start with uppercase and contain at least two uppercase and one lowercase.
[To copy these macros without the ?'s, click on Edit Text, then select text from the edit text box]. -- StanSilver
What a WikiDoc looks like: ---------- TopicOne Blah blah blah TopicTwo ---------- TopicTwo Blah blah TopicThree ---------- TopicThree Blah blah TopicOne and TopicTwo blah blah TopicFour ---------- Sub WikiDoc() '=================================' ' Delete bookmarks and hyperlinks ' '=================================' For i = ActiveDocument.Bookmarks.Count To 1 Step -1 ActiveDocument.Bookmarks(i).Delete Next i For i = ActiveDocument.Hyperlinks.Count To 1 Step -1 ActiveDocument.Hyperlinks(i).Delete Next i '====================================' ' Set target page names as bookmarks ' '====================================' Dim myRange As Range For Each myRange In ActiveDocument.Words If WikiIsPageName(myRange) Then If WikiIsTarget(myRange) Then '=======' ' Taget ' '=======' myName = Trim(myRange.Text) With ActiveDocument.Bookmarks .Add Range:=myRange, Name:=myName .DefaultSorting = wdSortByName .ShowHidden = False End With myRange.Style = wdStyleHeading2 End If End If Next '=================================================' ' Set link page names with targets as hyperlinks ' ' Underline link page names without targets' '=================================================' For Each myRange In ActiveDocument.Words If WikiIsPageName(myRange) Then If Not WikiIsTarget(myRange) Then '======' ' Link ' '======' myRange.Bold = False myRange.Underline = False myName = Trim(myRange.Text) If ActiveDocument.Bookmarks.Exists(myName) = True Then ActiveDocument.Hyperlinks.Add Anchor:=myRange, Address:="", SubAddress:=myName Else myRange.Underline = True myRange.Font.ColorIndex = wdRed End If End If End If Next ActiveDocument.Save MsgBox ("Done") End Sub Function WikiIsPageName(myRange As Range) As Boolean '==============================================================' ' Page name must start with an uppercase, and contain at least ' ' two uppercase and one lowercase characters' '==============================================================' WikiIsPageName = False If (myRange.Characters(1) > "Z") Then Exit Function myUpperCaseCount = 0 myLowerCaseCount = 0 For Each myCharRange In myRange.Characters If ((myCharRange <= "Z") And (myCharRange >= "A")) Then myUpperCaseCount = myUpperCaseCount + 1 End If If ((myCharRange <= "z") And (myCharRange >= "a")) Then myLowerCaseCount = myLowerCaseCount + 1 End If Next If ((myUpperCaseCount > 1) And (myLowerCaseCount > 0)) Then WikiIsPageName = True End If End Function Function WikiIsTarget(myRange As Range) As Boolean '============================================' ' Assume myRange is a page name. Target must ' ' appear directly after a new page character ' '============================================' WikiIsTarget = False myStart = myRange.Start - 1 myEnd = myRange.Start Set myPreviousRange = ActiveDocument.Range(Start:=myStart, End:=myEnd) myPreviousChar = myPreviousRange.Characters(1).Text If Asc(myPreviousChar) = 12 Then WikiIsTarget = True End Function Sub WikiUnPage() '===============================' ' Remove all manual page breaks ' '===============================' Selection.HomeKey Unit:=wdStory Selection.Find.ClearFormatting Selection.Find.Replacement.ClearFormatting With Selection.Find .Text = "^m" .Replacement.Text = "" .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Selection.Find.Execute Replace:=wdReplaceAll End Sub
Suggestion for Speedup:
I removed the lowercase part: If ((myCharRange <= "z") And (myCharRange >= "a")) Then myLowerCaseCount = myLowerCaseCount + 1 End If and replaced the WikiPageName criterion: If ((myUpperCaseCount > 1) And (myLowerCaseCount > 0)) Then WikiIsPageName = True End If By: If (myUpperCaseCount > 1) Then WikiIsPageName = True End IfThe MicrosoftWord interpreter thanks it with greater speed and we have more flexible WikiPageNames. See http://www.data-music.com for useful samples. -- FridemarPache
I found the above code to take greater than 15 seconds to execute even for a small document. The following code is much faster by allowing links to be created on demand, instead of processing the entire document each time. If the macro WikiCreateLink is executed (I have a key bound to this) after typing a Wiki Word, then a link is created to the bookmark with the same name as the Wiki Word. If that bookmark doesn't exist, then the WikiWord is made into a Macro Button field. When this macro button field is double clicked, a page break, along with a page title and a new bookmark is inserted at the end of the current page. I like to set the value of the Field Shading dropdown in the Tools->Options->View Tab to Always so the links to the nonexisting pages stand out. The following code also requires the WikiIsPageName macro from the above code. -- BrianTheado
Sub WikiCreateLink() ' ' Create a Wiki link out of the nearest word to the left ' Selection.MoveLeft Unit:=wdWord, Count:=1, Extend:=wdExtend If WikiIsPageName(Selection.Words.First) Then myName = Trim(Selection.Words.First) If ActiveDocument.Bookmarks.Exists(myName) = True Then ' Page already exists - add a hyperlink ActiveDocument.Hyperlinks.Add Anchor:=Selection.Words.First, Address:="", SubAddress:=myName Else ' ' Page doesn't exist turn the word into a macrobutton ' field that will create a new page when double clicked ' Selection.Words.First.underline = True Selection.Words.First.Font.ColorIndex = wdRed Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldMacroButton, Text:= _ "WikiAddNewPage " + myName, PreserveFormatting:=False End If End If End Sub Sub WikiAddNewPage() ' Remove the macrobutton field Selection.Fields.Unlink ' Hyperlink the word to the about to be created page Selection.MoveLeft Unit:=wdWord, Count:=1, Extend:=wdExtend myName = Selection.Words.First.Text ActiveDocument.Hyperlinks.Add Anchor:=Selection.Words.First, Address:="", SubAddress:=myName If ActiveDocument.Bookmarks.Exists(myName) = False Then ' Move to just beyond the next page break and create the new page FindPageBreak Selection.MoveRight WikiCreatePage (myName) End If End Sub Sub WikiCreatePage(myName As String) Selection.TypeText Text:=myName Selection.Style = wdStyleHeading1 ActiveDocument.Bookmarks.Add Range:=Selection.Words.First, Name:=myName Selection.TypeParagraph Selection.InsertBreak Type:=wdPageBreak Selection.MoveUp End Sub Sub FindPageBreak() Selection.Find.ClearFormatting With Selection.Find .Text = "^m" .Replacement.Text = "" .Forward = True .Wrap = wdFindStop .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Selection.Find.Execute End Sub
on my Word97 SR2 installation, I had to add one line of code:
Sub WikiCreatePage(myName As String)
myName = RTrim(myName) ...-- TimmDanker
This quick linking feature is very helpful. I adapted the WikiDoc routine to also insert macro button fields for unknown Wiki Words, but describing this as changes to the code above would become unreadable, so if anyone is interested, please send me an email. -- RalfHandl
''Alas, I wasn't able to get any of these macros to work on my Word97 setup. Ralf, where is your email address? -- MichaelBrown
Function WikiIsPageName(myRange As Range) As Boolean WikiIsPageName = (myRange.Case = wdToggleCase) End Function... seems to do what we want (and quickly). Now one can inline the function. -- FalkBruegmann
Well, at least on my machine (WinNT, Office97) this is much slower than the original function. -- RalfHandl
Does this work with OfficeXP, too? I tried and it didn't work. Any improvement suggestions? -- PeterHenning?
So, here's my preliminary version based on BrianTheado's. Name restrictions are only given by Word. Why use WikiNames if the Wiki doesn't automatically detect them? I tried to install a routine that converts illegal WikiWords into legal ones (in my sense). Unfortunately, I never used VBA with Word before... -- GüntherLehnert
' WordWiki ' Tested with <a href="http://www.serverlogic3.com/lm/rtl3.asp?si=1&k=office%20xp" onmouseover="window.status='Office XP'; return true;" onmouseout="window.status=''; return true;">Office XP</a> Sub WikiLink() ' Hyperlink the word to the about to be created page Selection.MoveLeft Unit:=wdWord, Count:=1, Extend:=wdExtend myName = Selection.Words.First.Text ' Begin Word with a letter Do While NumberRange(Asc(Left(myName, 1))) < 2 myName = Right(myName, Len(myName) - 1) Loop ' End with the last allowed character Do While NumberRange(Asc(Right(myName, 1))) < 1 myName = Left(myName, Len(myName) - 1) Loop ' Delete characters not allowed in Links i = 1 Do While i < Len(myName) If NumberRange(Asc(Mid(myName, i, 1))) = 0 Then myName = Left(myName, i - 1) & Right(myName, Len(myName) - i) Else i = i + 1 End If Loop ActiveDocument.Hyperlinks.Add Anchor:=Selection.Words.First, Address:="", SubAddress:=myName If ActiveDocument.Bookmarks.Exists(myName) = False Then ' Move to just beyond the next page break and create the new page FindPageBreak Selection.MoveRight WikiCreatePage (myName) End If End Sub ' Checks for allowed characters ' How could you do this easier? Function NumberRange(Number As Byte) As Integer NumberRange = 0 If Number > 47 And Number < 58 Then NumberRange = 1 If Number > 64 And Number < 91 Then NumberRange = 2 If Number > 96 And Number < 123 Then NumberRange = 2 If Number > 191 And Number < 215 Then NumberRange = 2 If Number > 215 And Number < 247 Then NumberRange = 2 If Number > 248 And Number < 256 Then NumberRange = 2 If Number = 95 Then NumberRange = 1 End Function Sub WikiCreatePage(myName As String) Selection.TypeText Text:=myName Selection.Style = wdStyleHeading1 ActiveDocument.Bookmarks.Add Range:=Selection.Words.First, Name:=myName Selection.TypeParagraph Selection.InsertBreak Type:=wdPageBreak Selection.MoveUp End Sub Sub FindPageBreak(Optional joke As Boolean) '<- so it is not displayed as a separate macro Selection.Find.ClearFormatting With Selection.Find .Text = "^m" .Replacement.Text = "" .Forward = True .Wrap = wdFindStop .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With Selection.Find.Execute End Sub
Please see my site at http://www.SuperThinking.com. I have a Word Addin there. Could use some de-klugeing, but addresses many of the aspirations of some of these macros.
--RichVanSchaik?
This link/domain is gone/expired. -- John Godin