Attribute VB_Name = "Doc2Html2Doc" ' =============================== ' Doc2Html2Doc ' ' You are free to do whatever you want with this code except sell it. ' No warranties, etc. etc. ' ' Copyright (C) 2004 Ryan Ginstrom ' ' OVERVIEW ' ' What it handles: ' font face ' font colors ' bold ' italic ' underline ' superscript and subscript ' most special (e.g. Greek) symbols ' ' What it doesn't handle: ' font size ' background color (highlight) ' font colors other than the basic Word 97 text colors ' hyperlinks ' styles/headings (H1, H2...) ' paragraph formatting ' ... and basically anything not mentioned in "What it handles:" ' ' INCLUDED FUNCTIONS/SUBS ' TestGetSelectionAsHtml ' TestHtml2Doc ' - test routines ' WriteSelectionAsDoc ' WriteSelectionAsHtml ' - convert html to and from doc formatting within document ' GetSelectionAsHtml() as String ' Html2Doc( HtmlText as String ) ' - functions/subs for same ' ... And various other helper routines. Concat and ReplaceText may be of interest ' as VBA solutions to general programming problems (both routines lifted from elsewhere) ' ' =============================== Option Explicit Private CurrentBoldState As Boolean Private CurrentItalicState As Boolean Private CurrentUnderlineState As Long Private CurrentFontName As String Private CurrentForeColor As Long Private CurrentSupState As Long Private Const SUP_NONE As Long = 0 Private Const SUP_SUPER As Long = 1 Private Const SUP_SUB As Long = 2 ' for concat Private ccOffset As Long Private Const ccIncrement = 256 ' Test routines Sub TestGetSelectionAsHtml() MsgBox GetSelectionAsHtml End Sub Sub TestHtml2Doc() Html2Doc "HELLO, world" End Sub Sub WriteSelectionAsDoc() Dim html As String html = Selection.Text Selection.Collapse wdCollapseEnd Selection.TypeText vbCrLf Dim CurrentStart As Long CurrentStart = Selection.Start Html2Doc html Selection.Start = CurrentStart End Sub Sub WriteSelectionAsHTml() Dim html As String html = GetSelectionAsHtml Selection.Collapse wdCollapseEnd Selection.TypeText vbCrLf Dim CurrentStart As Long CurrentStart = Selection.Start Selection.TypeText html Selection.Start = CurrentStart End Sub ' ======================== ' | GetSelectionAsHtml ' ======================== Function GetSelectionAsHtml() As String ' offset used for concat function ccOffset = 0 With Selection ' We need this base case, in order to avoid error when selecting character from ' collection, below If .Characters.Count = 0 Then Exit Function End If ' In the majority of the cases, there will be only one font, and no bold, italic, or other ' formatting. We want to avoid all the work of stepping through each word for these guys. If ThereIsNoFormatting = True Then GetSelectionAsHtml = GetSelectionAsHtmlSimplified Exit Function End If ' =========================================== ' OK THEN, LET'S ROLL UP THE OLD SLEEVES!!! ' =========================================== ' Keep the original range, because we may need to select individual characters ' due to Word's %$(@)# handling of symbols Dim oOriginalRange As Range Set oOriginalRange = Selection.Range ' keep a stack of open tags, so we prevent crossover. ' i.e., we want to avoid stuff like this: ' Hello! ' or this: ' Hello, my name is Myron... Dim TagStack As New Collection ' keep track of our current formatting CurrentBoldState = False CurrentItalicState = False CurrentUnderlineState = wdUnderlineNone CurrentForeColor = 0 CurrentSupState = SUP_NONE CurrentFontName = "" ' store this in a variable in order to avoid too many function calls Dim BoldState As Boolean Dim ItalicState As Boolean Dim UnderlineState As Long Dim SupState As Long Dim ForeColor As Long Dim FontName As String Dim c As Object For Each c In .Characters With c.Font ' keep it to 1 function call, boys BoldState = .Bold ItalicState = .Italic UnderlineState = .Underline ForeColor = .ColorIndex FontName = .Name If .Superscript Then SupState = SUP_SUPER ElseIf .Subscript Then SupState = SUP_SUB Else SupState = SUP_NONE End If ' ' ' First, close off any tags ' ' ' ' /sup-sub If SupState <> CurrentSupState Then Select Case CurrentSupState Case SUP_SUPER: Concat GetSelectionAsHtml, UnwindTagStackUntil(TagStack, "") Case SUP_SUB: Concat GetSelectionAsHtml, UnwindTagStackUntil(TagStack, "") End Select End If ' /bold If BoldState = False And CurrentBoldState = True Then Concat GetSelectionAsHtml, UnwindTagStackUntil(TagStack, "") End If ' /italic If ItalicState = False And CurrentItalicState = True Then Concat GetSelectionAsHtml, UnwindTagStackUntil(TagStack, "") End If ' /underline If UnderlineState <> CurrentUnderlineState And CurrentUnderlineState <> wdUnderlineNone Then Concat GetSelectionAsHtml, UnwindTagStackUntil(TagStack, "") End If ' /span If (CurrentForeColor <> ForeColor) And CurrentForeColor > 0 Then Concat GetSelectionAsHtml, UnwindTagStackUntil(TagStack, "") End If ' /font If FontName <> CurrentFontName And CurrentFontName <> "" Then Concat GetSelectionAsHtml, UnwindTagStackUntil(TagStack, "") End If ' ' ' Now, apply any required formatting tags ' ' ' ' font If FontName <> CurrentFontName Then CurrentFontName = FontName ' new format tag If CurrentFontName <> "" Then Concat GetSelectionAsHtml, "" Push TagStack, "" End If End If ' span If (ForeColor <> CurrentForeColor) Then ' new format tag Concat GetSelectionAsHtml, "" Push TagStack, "" CurrentForeColor = ForeColor End If ' underline If UnderlineState <> CurrentUnderlineState Then CurrentUnderlineState = UnderlineState Concat GetSelectionAsHtml, "" Push TagStack, "" End If ' italic If ItalicState <> CurrentItalicState Then CurrentItalicState = ItalicState Concat GetSelectionAsHtml, "" Push TagStack, "" End If ' bold If BoldState <> CurrentBoldState Then Concat GetSelectionAsHtml, "" Push TagStack, "" CurrentBoldState = BoldState End If If SupState <> CurrentSupState Then Select Case SupState Case SUP_SUPER: Concat GetSelectionAsHtml, "" Push TagStack, "" Case SUP_SUB: Concat GetSelectionAsHtml, "" Push TagStack, "" End Select CurrentSupState = SupState End If End With With c Select Case .Text Case "(" .Select Concat GetSelectionAsHtml, Symbol2Unicode(Dialogs(wdDialogInsertSymbol).charnum) oOriginalRange.Select Case "<" Concat GetSelectionAsHtml, "<" Case "&" Concat GetSelectionAsHtml, "&" Case Else Concat GetSelectionAsHtml, .Text End Select End With ' with c Next c End With ' with selection ' Close off any open tags While TagStack.Count > 0 Concat GetSelectionAsHtml, Pop(TagStack) Wend ' release any memory still reserved GetSelectionAsHtml = Left$(GetSelectionAsHtml, ccOffset) ' clean up oOriginalRange.Select Set oOriginalRange = Nothing Set TagStack = Nothing End Function '================================================ ' Html2Doc + '================================================ Sub Html2Doc(HtmlString As String) On Error GoTo HandleError Selection.Text = "" With Selection.Font ' set up font state CurrentBoldState = .Bold CurrentItalicState = .Italic CurrentUnderlineState = .Underline CurrentForeColor = .ColorIndex CurrentFontName = .Name If .Superscript = True Then CurrentSupState = SUP_SUPER ElseIf .Subscript = True Then CurrentSupState = SUP_SUB Else CurrentSupState = SUP_NONE End If End With ' keep track of our formatting tags ' do formatting like this: ' "bold:false" Dim FormattingStateStack As New Collection ' the text Dim sText As String Dim sTag As String ' find the first tag marker sText = GetLine(HtmlString, "<") While HtmlString <> "" ReplaceHtmlTagsAndWrite sText sTag = GetLine(HtmlString, ">") If Left(sTag, 1) = "/" Then ' end tag ' POP STATE FontInfoGoingOutOfScope Pop(FormattingStateStack) Else ' start tag ' PUSH STATE Push FormattingStateStack, ParseHtmlTag(sTag) End If sText = GetLine(HtmlString, "<") Wend ReplaceHtmlTagsAndWrite sText Set FormattingStateStack = Nothing With Selection.Font .Bold = CurrentBoldState .Italic = CurrentItalicState .Underline = CurrentUnderlineState .ColorIndex = CurrentForeColor .Name = CurrentFontName If CurrentSupState <> SUP_NONE Then If CurrentSupState = SUP_SUPER Then Selection.Font.Superscript = True Else Selection.Font.Subscript = True End If End If End With Exit Sub HandleError: With Selection.Font .Bold = CurrentBoldState .Italic = CurrentItalicState .Underline = CurrentUnderlineState .ColorIndex = CurrentForeColor .Name = CurrentFontName If CurrentSupState <> SUP_NONE Then If CurrentSupState = SUP_SUPER Then Selection.Font.Superscript = True Else Selection.Font.Subscript = True End If End If End With Set FormattingStateStack = Nothing ' pass up the error Err.Raise Err.Number End Sub ' ====================================== ' stack stuff ' ====================================== ' Push Private Sub Push(ByRef stack As Collection, ByRef element As Variant) If stack.Count = 0 Then stack.Add element Exit Sub End If stack.Add Item:=element, Before:=1 End Sub ' Pop Private Function Pop(ByRef stack As Collection) As Variant Pop = stack.Item(1) stack.Remove 1 End Function ' ====================================== ' Various helper routines below here ' ====================================== Function UnwindTagStackUntil(ByRef TagStack As Collection, StopTag As Variant) As String Dim Tag As String While Tag <> StopTag Tag = Pop(TagStack) Select Case Tag Case "", "" CurrentItalicState = False Case "", "" CurrentBoldState = False Case "" CurrentUnderlineState = wdUnderlineNone Case "" CurrentFontName = "" Case "" CurrentForeColor = 0 Case "", "" CurrentSupState = SUP_NONE End Select UnwindTagStackUntil = UnwindTagStackUntil & Tag Wend End Function Function Symbol2Unicode(charcode As Long) As String ' base case If charcode = 40 Then Symbol2Unicode = "(" Exit Function End If Select Case charcode + 4096 Case &H22 ' # FOR ALL Symbol2Unicode = ChrW(&H2200) Case &H24 ' # THERE EXISTS Symbol2Unicode = ChrW(&H2203) Case &H27 ' # CONTAINS AS MEMBER Symbol2Unicode = ChrW(&H220B) Case &H2A ' # ASTERISK OPERATOR Symbol2Unicode = ChrW(&H2217) Case &H2D ' # MINUS SIGN Symbol2Unicode = ChrW(&H2212) Case &H40 ' # APPROXIMATELY EQUAL TO Symbol2Unicode = ChrW(&H2245) Case &H41 ' # GREEK CAPITAL LETTER ALPHA Symbol2Unicode = ChrW(&H391) Case &H42 ' # GREEK CAPITAL LETTER BETA Symbol2Unicode = ChrW(&H392) Case &H43 ' # GREEK CAPITAL LETTER CHI Symbol2Unicode = ChrW(&H3A7) Case &H44 ' # GREEK CAPITAL LETTER DELTA Symbol2Unicode = ChrW(&H394) Case &H44 ' # INCREMENT Symbol2Unicode = ChrW(&H2206) Case &H45 ' # GREEK CAPITAL LETTER EPSILON Symbol2Unicode = ChrW(&H395) Case &H46 ' # GREEK CAPITAL LETTER PHI Symbol2Unicode = ChrW(&H3A6) Case &H47 ' # GREEK CAPITAL LETTER GAMMA Symbol2Unicode = ChrW(&H393) Case &H48 ' # GREEK CAPITAL LETTER ETA Symbol2Unicode = ChrW(&H397) Case &H49 ' # GREEK CAPITAL LETTER IOTA Symbol2Unicode = ChrW(&H399) Case &H4A ' # GREEK THETA SYMBOL Symbol2Unicode = ChrW(&H3D1) Case &H4B ' # GREEK CAPITAL LETTER KAPPA Symbol2Unicode = ChrW(&H39A) Case &H4C ' # GREEK CAPITAL LETTER LAMDA Symbol2Unicode = ChrW(&H39B) Case &H4D ' # GREEK CAPITAL LETTER MU Symbol2Unicode = ChrW(&H39C) Case &H4E ' # GREEK CAPITAL LETTER NU Symbol2Unicode = ChrW(&H39D) Case &H4F ' # GREEK CAPITAL LETTER OMICRON Symbol2Unicode = ChrW(&H39F) Case &H50 ' # GREEK CAPITAL LETTER PI Symbol2Unicode = ChrW(&H3A0) Case &H51 ' # GREEK CAPITAL LETTER THETA Symbol2Unicode = ChrW(&H398) Case &H52 ' # GREEK CAPITAL LETTER RHO Symbol2Unicode = ChrW(&H3A1) Case &H53 ' # GREEK CAPITAL LETTER SIGMA Symbol2Unicode = ChrW(&H3A3) Case &H54 ' # GREEK CAPITAL LETTER TAU Symbol2Unicode = ChrW(&H3A4) Case &H55 ' # GREEK CAPITAL LETTER UPSILON Symbol2Unicode = ChrW(&H3A5) Case &H56 ' # GREEK SMALL LETTER FINAL SIGMA Symbol2Unicode = ChrW(&H3C2) Case &H57 ' # GREEK CAPITAL LETTER OMEGA Symbol2Unicode = ChrW(&H3A9) Case &H57 ' # OHM SIGN Symbol2Unicode = ChrW(&H2126) Case &H58 ' # GREEK CAPITAL LETTER XI Symbol2Unicode = ChrW(&H39E) Case &H59 ' # GREEK CAPITAL LETTER PSI Symbol2Unicode = ChrW(&H3A8) Case &H5A ' # GREEK CAPITAL LETTER ZETA Symbol2Unicode = ChrW(&H396) Case &H5C ' # THEREFORE Symbol2Unicode = ChrW(&H2234) Case &H5E ' # UP TACK Symbol2Unicode = ChrW(&H22A5) Case &H60 ' # RADICAL EXTENDER Symbol2Unicode = ChrW(&HF8E5) Case &H61 ' # GREEK SMALL LETTER ALPHA Symbol2Unicode = ChrW(&H3B1) Case &H62 ' # GREEK SMALL LETTER BETA Symbol2Unicode = ChrW(&H3B2) Case &H63 ' # GREEK SMALL LETTER CHI Symbol2Unicode = ChrW(&H3C7) Case &H64 ' # GREEK SMALL LETTER DELTA Symbol2Unicode = ChrW(&H3B4) Case &H65 ' # GREEK SMALL LETTER EPSILON Symbol2Unicode = ChrW(&H3B5) Case &H66 ' # GREEK SMALL LETTER PHI Symbol2Unicode = ChrW(&H3C6) Case &H67 ' # GREEK SMALL LETTER GAMMA Symbol2Unicode = ChrW(&H3B3) Case &H68 ' # GREEK SMALL LETTER ETA Symbol2Unicode = ChrW(&H3B7) Case &H69 ' # GREEK SMALL LETTER IOTA Symbol2Unicode = ChrW(&H3B9) Case &H6A ' # GREEK PHI SYMBOL Symbol2Unicode = ChrW(&H3D5) Case &H6B ' # GREEK SMALL LETTER KAPPA Symbol2Unicode = ChrW(&H3BA) Case &H6C ' # GREEK SMALL LETTER LAMDA Symbol2Unicode = ChrW(&H3BB) Case &H6D ' # MICRO SIGN Symbol2Unicode = ChrW(&HB5) Case &H6D ' # GREEK SMALL LETTER MU Symbol2Unicode = ChrW(&H3BC) Case &H6E ' # GREEK SMALL LETTER NU Symbol2Unicode = ChrW(&H3BD) Case &H6F ' # GREEK SMALL LETTER OMICRON Symbol2Unicode = ChrW(&H3BF) Case &H70 ' # GREEK SMALL LETTER PI Symbol2Unicode = ChrW(&H3C0) Case &H71 ' # GREEK SMALL LETTER THETA Symbol2Unicode = ChrW(&H3B8) Case &H72 ' # GREEK SMALL LETTER RHO Symbol2Unicode = ChrW(&H3C1) Case &H73 ' # GREEK SMALL LETTER SIGMA Symbol2Unicode = ChrW(&H3C3) Case &H74 ' # GREEK SMALL LETTER TAU Symbol2Unicode = ChrW(&H3C4) Case &H75 ' # GREEK SMALL LETTER UPSILON Symbol2Unicode = ChrW(&H3C5) Case &H76 ' # GREEK PI SYMBOL Symbol2Unicode = ChrW(&H3D6) Case &H77 ' # GREEK SMALL LETTER OMEGA Symbol2Unicode = ChrW(&H3C9) Case &H78 ' # GREEK SMALL LETTER XI Symbol2Unicode = ChrW(&H3BE) Case &H79 ' # GREEK SMALL LETTER PSI Symbol2Unicode = ChrW(&H3C8) Case &H7A ' # GREEK SMALL LETTER ZETA Symbol2Unicode = ChrW(&H3B6) Case &H7E ' # TILDE OPERATOR Symbol2Unicode = ChrW(&H223C) Case &HA0 ' # EURO SIGN Symbol2Unicode = ChrW(&H20AC) Case &HA1 ' # GREEK UPSILON WITH HOOK SYMBOL Symbol2Unicode = ChrW(&H3D2) Case &HA2 ' # PRIME Symbol2Unicode = ChrW(&H2032) Case &HA3 ' # LESS-THAN OR EQUAL TO Symbol2Unicode = ChrW(&H2264) Case &HA4 ' # FRACTION SLASH Symbol2Unicode = ChrW(&H2044) Case &HA4 ' # DIVISION SLASH Symbol2Unicode = ChrW(&H2215) Case &HA5 ' # INFINITY Symbol2Unicode = ChrW(&H221E) Case &HA6 ' # LATIN SMALL LETTER F WITH HOOK Symbol2Unicode = ChrW(&H192) Case &HA7 ' # BLACK CLUB SUIT Symbol2Unicode = ChrW(&H2663) Case &HA8 ' # BLACK DIAMOND SUIT Symbol2Unicode = ChrW(&H2666) Case &HA9 ' # BLACK HEART SUIT Symbol2Unicode = ChrW(&H2665) Case &HAA ' # BLACK SPADE SUIT Symbol2Unicode = ChrW(&H2660) Case &HAB ' # LEFT RIGHT ARROW Symbol2Unicode = ChrW(&H2194) Case &HAC ' # LEFTWARDS ARROW Symbol2Unicode = ChrW(&H2190) Case &HAD ' # UPWARDS ARROW Symbol2Unicode = ChrW(&H2191) Case &HAE ' # RIGHTWARDS ARROW Symbol2Unicode = ChrW(&H2192) Case &HAF ' # DOWNWARDS ARROW Symbol2Unicode = ChrW(&H2193) Case &HB2 ' # DOUBLE PRIME Symbol2Unicode = ChrW(&H2033) Case &HB3 ' # GREATER-THAN OR EQUAL TO Symbol2Unicode = ChrW(&H2265) Case &HB4 ' # MULTIPLICATION SIGN Symbol2Unicode = ChrW(&HD7) Case &HB5 ' # PROPORTIONAL TO Symbol2Unicode = ChrW(&H221D) Case &HB6 ' # PARTIAL DIFFERENTIAL Symbol2Unicode = ChrW(&H2202) Case &HB7 ' # BULLET Symbol2Unicode = ChrW(&H2022) Case &HB8 ' # DIVISION SIGN Symbol2Unicode = ChrW(&HF7) Case &HB9 ' # NOT EQUAL TO Symbol2Unicode = ChrW(&H2260) Case &HBA ' # IDENTICAL TO Symbol2Unicode = ChrW(&H2261) Case &HBB ' # ALMOST EQUAL TO Symbol2Unicode = ChrW(&H2248) Case &HBC ' # HORIZONTAL ELLIPSIS Symbol2Unicode = ChrW(&H2026) Case &HBD ' # VERTICAL ARROW EXTENDER Symbol2Unicode = ChrW(&HF8E6) Case &HBE ' # HORIZONTAL ARROW EXTENDER Symbol2Unicode = ChrW(&HF8E7) Case &HBF ' # DOWNWARDS ARROW WITH CORNER LEFTWARDS Symbol2Unicode = ChrW(&H21B5) Case &HC0 ' # ALEF SYMBOL Symbol2Unicode = ChrW(&H2135) Case &HC1 ' # BLACK-LETTER CAPITAL I Symbol2Unicode = ChrW(&H2111) Case &HC2 ' # BLACK-LETTER CAPITAL R Symbol2Unicode = ChrW(&H211C) Case &HC3 ' # SCRIPT CAPITAL P Symbol2Unicode = ChrW(&H2118) Case &HC4 ' # CIRCLED TIMES Symbol2Unicode = ChrW(&H2297) Case &HC5 ' # CIRCLED PLUS Symbol2Unicode = ChrW(&H2295) Case &HC6 ' # EMPTY SET Symbol2Unicode = ChrW(&H2205) Case &HC7 ' # INTERSECTION Symbol2Unicode = ChrW(&H2229) Case &HC8 ' # UNION Symbol2Unicode = ChrW(&H222A) Case &HC9 ' # SUPERSET OF Symbol2Unicode = ChrW(&H2283) Case &HCA ' # SUPERSET OF OR EQUAL TO Symbol2Unicode = ChrW(&H2287) Case &HCB ' # NOT A SUBSET OF Symbol2Unicode = ChrW(&H2284) Case &HCC ' # SUBSET OF Symbol2Unicode = ChrW(&H2282) Case &HCD ' # SUBSET OF OR EQUAL TO Symbol2Unicode = ChrW(&H2286) Case &HCE ' # ELEMENT OF Symbol2Unicode = ChrW(&H2208) Case &HCF ' # NOT AN ELEMENT OF Symbol2Unicode = ChrW(&H2209) Case &HD0 ' # ANGLE Symbol2Unicode = ChrW(&H2220) Case &HD1 ' # NABLA Symbol2Unicode = ChrW(&H2207) Case &HD2 ' # REGISTERED SIGN SERIF Symbol2Unicode = ChrW(&HF6DA) Case &HD3 ' # COPYRIGHT SIGN SERIF Symbol2Unicode = ChrW(&HF6D9) Case &HD4 ' # TRADE MARK SIGN SERIF Symbol2Unicode = ChrW(&HF6DB) Case &HD5 ' # N-ARY PRODUCT Symbol2Unicode = ChrW(&H220F) Case &HD6 ' # SQUARE ROOT Symbol2Unicode = ChrW(&H221A) Case &HD7 ' # DOT OPERATOR Symbol2Unicode = ChrW(&H22C5) Case &HD8 ' # NOT SIGN Symbol2Unicode = ChrW(&HAC) Case &HD9 ' # LOGICAL AND Symbol2Unicode = ChrW(&H2227) Case &HDA ' # LOGICAL OR Symbol2Unicode = ChrW(&H2228) Case &HDB ' # LEFT RIGHT DOUBLE ARROW Symbol2Unicode = ChrW(&H21D4) Case &HDC ' # LEFTWARDS DOUBLE ARROW Symbol2Unicode = ChrW(&H21D0) Case &HDD ' # UPWARDS DOUBLE ARROW Symbol2Unicode = ChrW(&H21D1) Case &HDE ' # RIGHTWARDS DOUBLE ARROW Symbol2Unicode = ChrW(&H21D2) Case &HDF ' # DOWNWARDS DOUBLE ARROW Symbol2Unicode = ChrW(&H21D3) Case &HE0 ' # LOZENGE Symbol2Unicode = ChrW(&H25CA) Case &HE1 ' # LEFT-POINTING ANGLE BRACKET Symbol2Unicode = ChrW(&H2329) Case &HE2 ' # REGISTERED SIGN SANS SERIF Symbol2Unicode = ChrW(&HF8E8) Case &HE3 ' # COPYRIGHT SIGN SANS SERIF Symbol2Unicode = ChrW(&HF8E9) Case &HE4 ' # TRADE MARK SIGN SANS SERIF Symbol2Unicode = ChrW(&HF8EA) Case &HE5 ' # N-ARY SUMMATION Symbol2Unicode = ChrW(&H2211) Case &HE6 ' # LEFT PAREN TOP Symbol2Unicode = ChrW(&HF8EB) Case &HE7 ' # LEFT PAREN EXTENDER Symbol2Unicode = ChrW(&HF8EC) Case &HE8 ' # LEFT PAREN BOTTOM Symbol2Unicode = ChrW(&HF8ED) Case &HE9 ' # LEFT SQUARE BRACKET TOP Symbol2Unicode = ChrW(&HF8EE) Case &HEA ' # LEFT SQUARE BRACKET EXTENDER Symbol2Unicode = ChrW(&HF8EF) Case &HEB ' # LEFT SQUARE BRACKET BOTTOM Symbol2Unicode = ChrW(&HF8F0) Case &HEC ' # LEFT CURLY BRACKET TOP Symbol2Unicode = ChrW(&HF8F1) Case &HED ' # LEFT CURLY BRACKET MID Symbol2Unicode = ChrW(&HF8F2) Case &HEE ' # LEFT CURLY BRACKET BOTTOM Symbol2Unicode = ChrW(&HF8F3) Case &HEF ' # CURLY BRACKET EXTENDER Symbol2Unicode = ChrW(&HF8F4) Case &HF1 ' # RIGHT-POINTING ANGLE BRACKET Symbol2Unicode = ChrW(&H232A) Case &HF2 ' # INTEGRAL Symbol2Unicode = ChrW(&H222B) Case &HF3 ' # TOP HALF INTEGRAL Symbol2Unicode = ChrW(&H2320) Case &HF4 ' # INTEGRAL EXTENDER Symbol2Unicode = ChrW(&HF8F5) Case &HF5 ' # BOTTOM HALF INTEGRAL Symbol2Unicode = ChrW(&H2321) Case &HF6 ' # RIGHT PAREN TOP Symbol2Unicode = ChrW(&HF8F6) Case &HF7 ' # RIGHT PAREN EXTENDER Symbol2Unicode = ChrW(&HF8F7) Case &HF8 ' # RIGHT PAREN BOTTOM Symbol2Unicode = ChrW(&HF8F8) Case &HF9 ' # RIGHT SQUARE BRACKET TOP Symbol2Unicode = ChrW(&HF8F9) Case &HFA ' # RIGHT SQUARE BRACKET EXTENDER Symbol2Unicode = ChrW(&HF8FA) Case &HFB ' # RIGHT SQUARE BRACKET BOTTOM Symbol2Unicode = ChrW(&HF8FB) Case &HFC ' # RIGHT CURLY BRACKET TOP Symbol2Unicode = ChrW(&HF8FC) Case &HFD ' # RIGHT CURLY BRACKET MID Symbol2Unicode = ChrW(&HF8FD) Case &HFE ' # RIGHT CURLY BRACKET BOTTOM Symbol2Unicode = ChrW(&HF8FE) Case Else ' punt Symbol2Unicode = ChrW(charcode) End Select End Function Function GetSelectionAsHtmlSimplified() As String ' keep a stack of open tags, so we prevent crossover. ' i.e., we want to avoid stuff like this: ' Hello! ' or this: ' Hello, my name is Myron... Dim TagStack As New Collection ' keep original range Dim oOriginalRange As Range Set oOriginalRange = Selection.Range ' --------> With Selection.Font Concat GetSelectionAsHtmlSimplified, "" Push TagStack, "" ' underline If .Underline <> wdUnderlineNone Then Concat GetSelectionAsHtmlSimplified, "" Push TagStack, "" End If ' italic If .Italic = True Then Concat GetSelectionAsHtmlSimplified, "" Push TagStack, "" End If ' bold If .Bold = True Then Concat GetSelectionAsHtmlSimplified, "" Push TagStack, "" End If ' color If (.ColorIndex > 0) Then Concat GetSelectionAsHtmlSimplified, "" Push TagStack, "" End If If .Subscript = True Then Concat GetSelectionAsHtmlSimplified, "" Push TagStack, "" ElseIf .Superscript = True Then Concat GetSelectionAsHtmlSimplified, "" Push TagStack, "" End If End With ' <---------- with selection.font ' Now, add the text ' --------> With Selection Dim pos As Long Dim ParenPos As Long Dim AngleBracketPos As Long Dim AmpersandPos As Long Dim UnicodeSymbol As String pos = 1 ParenPos = InStr(pos, .Text, "(") AngleBracketPos = InStr(pos, .Text, "<") AmpersandPos = InStr(pos, .Text, "&") While ParenPos > 0 Or AngleBracketPos > 0 Or AmpersandPos > 0 ' ( If ParenPos > 0 And (ParenPos < AngleBracketPos Or AngleBracketPos = 0) And (ParenPos < AmpersandPos Or AmpersandPos = 0) Then .Characters(ParenPos).Select UnicodeSymbol = Symbol2Unicode(Dialogs(wdDialogInsertSymbol).charnum) oOriginalRange.Select Concat GetSelectionAsHtmlSimplified, Mid(.Text, pos, ParenPos - pos) Concat GetSelectionAsHtmlSimplified, UnicodeSymbol pos = ParenPos + 1 ' & ElseIf AmpersandPos > 0 And (AmpersandPos < AngleBracketPos Or AngleBracketPos = 0) Then Concat GetSelectionAsHtmlSimplified, Mid(.Text, pos, AmpersandPos - pos) Concat GetSelectionAsHtmlSimplified, "&" pos = AmpersandPos + 1 ' < Else ' ( and & not found, or < is in front of them Concat GetSelectionAsHtmlSimplified, Mid(.Text, pos, AngleBracketPos - pos) Concat GetSelectionAsHtmlSimplified, "<" pos = AngleBracketPos + 1 End If ParenPos = InStr(pos, .Text, "(") AngleBracketPos = InStr(pos, .Text, "<") AmpersandPos = InStr(pos, .Text, "&") Wend Concat GetSelectionAsHtmlSimplified, Mid(.Text, pos) End With ' selection ' Close off any open tags While TagStack.Count > 0 Concat GetSelectionAsHtmlSimplified, Pop(TagStack) Wend ' release any memory still reserved GetSelectionAsHtmlSimplified = Left$(GetSelectionAsHtmlSimplified, ccOffset) ' clean up Set TagStack = Nothing Set oOriginalRange = Nothing End Function Function ThereIsNoFormatting() As Boolean With Selection.Font If .Name <> "" Then ' It will be an empty string only if there is more than 1 font If .Bold <> wdUndefined Then ' it will be wdUndefined if there is a mixture of bold/plain If .Italic <> wdUndefined Then ' ditto If .Underline <> wdUndefined Then ' ditto 2 If .ColorIndex <> wdUndefined Then ' nope, no formatting! If .Subscript <> wdUndefined And .Superscript <> wdUndefined Then ' no sub or superscript ThereIsNoFormatting = True Exit Function End If End If End If End If End If End If End With ' with selection.font End Function Sub ReplaceHtmlTagsAndWrite(HtmlString As String) Dim pos As Long If HtmlString = "" Then Exit Sub End If pos = InStr(1, HtmlString, "&") With Selection While pos > 0 ' write text up to the & .TypeText Left(HtmlString, pos - 1) ' get rest of HtmlString after & HtmlString = Mid(HtmlString, pos + 1) ' get length from code to ; If Left(HtmlString, 1) = "#" Then ' cool, just convert the char code to a unicode char pos = InStr(1, HtmlString, ";") ' turn the numeric tag into unicode .Text = ChrW(CLng(Mid(HtmlString, 2, pos - 2))) .Collapse wdCollapseEnd Else ' drat, it's an ascii string. We have to look it up pos = InStr(1, HtmlString, ";") .Text = Html2Unicode(Left(HtmlString, pos - 1)) .Collapse wdCollapseEnd End If ' get the rest of the HtmlString after we ate the html tag HtmlString = Mid(HtmlString, pos + 1) ' look for the next & pos = InStr(1, HtmlString, "&") Wend ' write the rest of the HtmlString If HtmlString <> "" Then .TypeText HtmlString .Collapse wdCollapseEnd End If End With End Sub Function Html2Unicode(HtmlTag As String) As String Select Case HtmlTag Case "nbsp" Html2Unicode = " " Case "amp" Html2Unicode = "&" Case "lt" Html2Unicode = "<" Case "forall" ' # FOR ALL Html2Unicode = ChrW(&H2200) Case "exist" ' # THERE EXISTS Html2Unicode = ChrW(&H2203) Case "ni" ' # CONTAINS AS MEMBER Html2Unicode = ChrW(&H220B) Case "lowast" ' # ASTERISK OPERATOR Html2Unicode = ChrW(&H2217) Case "minus" ' # MINUS SIGN Html2Unicode = ChrW(&H2212) Case "cong" ' # APPROXIMATELY EQUAL TO Html2Unicode = ChrW(&H2245) Case "Alpha" ' # GREEK CAPITAL LETTER ALPHA Html2Unicode = ChrW(&H391) Case "Beta" ' # GREEK CAPITAL LETTER BETA Html2Unicode = ChrW(&H392) Case "Chi" ' # GREEK CAPITAL LETTER CHI Html2Unicode = ChrW(&H3A7) Case "Delta" ' # GREEK CAPITAL LETTER DELTA Html2Unicode = ChrW(&H394) Case "x2206" ' # INCREMENT Html2Unicode = ChrW(&H2206) Case "epsilon" ' # GREEK CAPITAL LETTER EPSILON Html2Unicode = ChrW(&H395) Case "Phi" ' # GREEK CAPITAL LETTER PHI Html2Unicode = ChrW(&H3A6) Case "Gamma" ' # GREEK CAPITAL LETTER GAMMA Html2Unicode = ChrW(&H393) Case "Eta" ' # GREEK CAPITAL LETTER ETA Html2Unicode = ChrW(&H397) Case "Iota" ' # GREEK CAPITAL LETTER IOTA Html2Unicode = ChrW(&H399) Case "Theta" ' # GREEK THETA SYMBOL Html2Unicode = ChrW(&H3D1) Case "Kappa" ' # GREEK CAPITAL LETTER KAPPA Html2Unicode = ChrW(&H39A) Case "Lambda" ' # GREEK CAPITAL LETTER LAMDA Html2Unicode = ChrW(&H39B) Case "Mu" ' # GREEK CAPITAL LETTER MU Html2Unicode = ChrW(&H39C) Case "Nu" ' # GREEK CAPITAL LETTER NU Html2Unicode = ChrW(&H39D) Case "Omicron" ' # GREEK CAPITAL LETTER OMICRON Html2Unicode = ChrW(&H39F) Case "Pi" ' # GREEK CAPITAL LETTER PI Html2Unicode = ChrW(&H3A0) Case "Theta" ' # GREEK CAPITAL LETTER THETA Html2Unicode = ChrW(&H398) Case "Rho" ' # GREEK CAPITAL LETTER RHO Html2Unicode = ChrW(&H3A1) Case "Sigma" ' # GREEK CAPITAL LETTER SIGMA Html2Unicode = ChrW(&H3A3) Case "Tau" ' # GREEK CAPITAL LETTER TAU Html2Unicode = ChrW(&H3A4) Case "Upsilon" ' # GREEK CAPITAL LETTER UPSILON Html2Unicode = ChrW(&H3A5) Case "Sigma" ' # GREEK SMALL LETTER FINAL SIGMA Html2Unicode = ChrW(&H3C2) Case "Omega" ' # GREEK CAPITAL LETTER OMEGA Html2Unicode = ChrW(&H3A9) Case "Ohm", "ohm" ' # OHM SIGN Html2Unicode = ChrW(&H2126) Case "Xi" ' # GREEK CAPITAL LETTER XI Html2Unicode = ChrW(&H39E) Case "Psi" ' # GREEK CAPITAL LETTER PSI Html2Unicode = ChrW(&H3A8) Case "Zeta" ' # GREEK CAPITAL LETTER ZETA Html2Unicode = ChrW(&H396) Case "there4", "therefore" ' # THEREFORE Html2Unicode = ChrW(&H2234) Case "bottom" ' # UP TACK Html2Unicode = ChrW(&H22A5) Case "radicalex" ' # RADICAL EXTENDER Html2Unicode = ChrW(&HF8E5) Case "alpha" ' # GREEK SMALL LETTER ALPHA Html2Unicode = ChrW(&H3B1) Case "beta" ' # GREEK SMALL LETTER BETA Html2Unicode = ChrW(&H3B2) Case "chi" ' # GREEK SMALL LETTER CHI Html2Unicode = ChrW(&H3C7) Case "delta" ' # GREEK SMALL LETTER DELTA Html2Unicode = ChrW(&H3B4) Case "epsilon" ' # GREEK SMALL LETTER EPSILON Html2Unicode = ChrW(&H3B5) Case "phi" ' # GREEK SMALL LETTER PHI Html2Unicode = ChrW(&H3C6) Case "gamma" ' # GREEK SMALL LETTER GAMMA Html2Unicode = ChrW(&H3B3) Case "eta" ' # GREEK SMALL LETTER ETA Html2Unicode = ChrW(&H3B7) Case "iota" ' # GREEK SMALL LETTER IOTA Html2Unicode = ChrW(&H3B9) Case "phi" ' # GREEK PHI SYMBOL Html2Unicode = ChrW(&H3D5) Case "kappa" ' # GREEK SMALL LETTER KAPPA Html2Unicode = ChrW(&H3BA) Case "lambda" ' # GREEK SMALL LETTER LAMDA Html2Unicode = ChrW(&H3BB) Case "mu" ' # MICRO SIGN Html2Unicode = ChrW(&HB5) Case "mgr" ' # GREEK SMALL LETTER MU Html2Unicode = ChrW(&H3BC) Case "ngr", "nu" ' # GREEK SMALL LETTER NU Html2Unicode = ChrW(&H3BD) Case "omicron" ' # GREEK SMALL LETTER OMICRON Html2Unicode = ChrW(&H3BF) Case "pi" ' # GREEK SMALL LETTER PI Html2Unicode = ChrW(&H3C0) Case "theta" ' # GREEK SMALL LETTER THETA Html2Unicode = ChrW(&H3B8) Case "rho" ' # GREEK SMALL LETTER RHO Html2Unicode = ChrW(&H3C1) Case "sigma" ' # GREEK SMALL LETTER SIGMA Html2Unicode = ChrW(&H3C3) Case "tau" ' # GREEK SMALL LETTER TAU Html2Unicode = ChrW(&H3C4) Case "upsilon" ' # GREEK SMALL LETTER UPSILON Html2Unicode = ChrW(&H3C5) Case "Pgr" ' # GREEK PI SYMBOL Html2Unicode = ChrW(&H3D6) Case "omega" ' # GREEK SMALL LETTER OMEGA Html2Unicode = ChrW(&H3C9) Case "xi" ' # GREEK SMALL LETTER XI Html2Unicode = ChrW(&H3BE) Case "psi" ' # GREEK SMALL LETTER PSI Html2Unicode = ChrW(&H3C8) Case "zeta" ' # GREEK SMALL LETTER ZETA Html2Unicode = ChrW(&H3B6) Case "thksim", "sim" ' # TILDE OPERATOR" Html2Unicode = ChrW(&H223C) Case "euro" ' # EURO SIGN Html2Unicode = ChrW(&H20AC) Case "upsih" ' # GREEK UPSILON WITH HOOK SYMBOL" Html2Unicode = ChrW(&H3D2) Case "prime" ' # PRIME Html2Unicode = ChrW(&H2032) Case "le" ' # LESS-THAN OR EQUAL TO Html2Unicode = ChrW(&H2264) Case "frasl" ' # FRACTION SLASH Html2Unicode = ChrW(&H2044) Case "fraction" ' # DIVISION SLASH Html2Unicode = ChrW(&H2215) Case "infin" ' # INFINITY Html2Unicode = ChrW(&H221E) Case "fnof" ' # LATIN SMALL LETTER F WITH HOOK Html2Unicode = ChrW(&H192) Case "clubs" ' # BLACK CLUB SUIT" Html2Unicode = ChrW(&H2663) Case "hearts" ' # BLACK DIAMOND SUIT Html2Unicode = ChrW(&H2666) Case "diams" ' # BLACK HEART SUIT Html2Unicode = ChrW(&H2665) Case "spades" ' # BLACK SPADE SUIT Html2Unicode = ChrW(&H2660) Case "harr" ' # LEFT RIGHT ARROW Html2Unicode = ChrW(&H2194) Case "larr" ' # LEFTWARDS ARROW Html2Unicode = ChrW(&H2190) Case "uarr" ' # UPWARDS ARROW Html2Unicode = ChrW(&H2191) Case "rarr" ' # RIGHTWARDS ARROW Html2Unicode = ChrW(&H2192) Case "darr" ' # DOWNWARDS ARROW Html2Unicode = ChrW(&H2193) Case "Prime" ' # DOUBLE PRIME" Html2Unicode = ChrW(&H2033) Case "ge" ' # GREATER-THAN OR EQUAL TO Html2Unicode = ChrW(&H2265) Case "times" ' # MULTIPLICATION SIGN Html2Unicode = ChrW(&HD7) Case "prop" ' # PROPORTIONAL TO Html2Unicode = ChrW(&H221D) Case "part" ' # PARTIAL DIFFERENTIAL Html2Unicode = ChrW(&H2202) Case "bull" ' # BULLET Html2Unicode = ChrW(&H2022) Case "divide" ' # DIVISION SIGN Html2Unicode = ChrW(&HF7) Case "ne" ' # NOT EQUAL TO Html2Unicode = ChrW(&H2260) Case "equiv" ' # IDENTICAL TO Html2Unicode = ChrW(&H2261) Case "asymp" ' # ALMOST EQUAL TO Html2Unicode = ChrW(&H2248) Case "hellip" ' # HORIZONTAL ELLIPSIS Html2Unicode = ChrW(&H2026) Case "arrowvertex" ' # VERTICAL ARROW EXTENDER Html2Unicode = ChrW(&HF8E6) Case "arrowhorizex" ' # HORIZONTAL ARROW EXTENDER Html2Unicode = ChrW(&HF8E7) Case "carriagereturn" ' # DOWNWARDS ARROW WITH CORNER LEFTWARDS Html2Unicode = ChrW(&H21B5) Case "aleph" ' # ALEF SYMBOL Html2Unicode = ChrW(&H2135) Case "Ifractur" ' # BLACK-LETTER CAPITAL I Html2Unicode = ChrW(&H2111) Case "Rfractur" ' # BLACK-LETTER CAPITAL R Html2Unicode = ChrW(&H211C) Case "weierstrass" ' # SCRIPT CAPITAL P Html2Unicode = ChrW(&H2118) Case "circlemultiply" ' # CIRCLED TIMES Html2Unicode = ChrW(&H2297) Case "circleplus" ' # CIRCLED PLUS Html2Unicode = ChrW(&H2295) Case "emptyset" ' # EMPTY SET Html2Unicode = ChrW(&H2205) Case "intersection" ' # INTERSECTION Html2Unicode = ChrW(&H2229) Case "cup" ' # UNION Html2Unicode = ChrW(&H222A) Case "sup" ' # SUPERSET OF Html2Unicode = ChrW(&H2283) Case "supe" ' # SUPERSET OF OR EQUAL TO Html2Unicode = ChrW(&H2287) Case "nsub" ' # NOT A SUBSET OF Html2Unicode = ChrW(&H2284) Case "sub" ' # SUBSET OF Html2Unicode = ChrW(&H2282) Case "sube" ' # SUBSET OF OR EQUAL TO Html2Unicode = ChrW(&H2286) Case "isin" ' # ELEMENT OF Html2Unicode = ChrW(&H2208) Case "notin" ' # NOT AN ELEMENT OF Html2Unicode = ChrW(&H2209) Case "ang" ' # ANGLE Html2Unicode = ChrW(&H2220) Case "nabla" ' # NABLA Html2Unicode = ChrW(&H2207) Case "registerserif" ' # REGISTERED SIGN SERIF Html2Unicode = ChrW(&HF6DA) Case "copyrightserif" ' # COPYRIGHT SIGN SERIF Html2Unicode = ChrW(&HF6D9) Case "trademarkserif" ' # TRADE MARK SIGN SERIF Html2Unicode = ChrW(&HF6DB) Case "product" ' # N-ARY PRODUCT Html2Unicode = ChrW(&H220F) Case "radic" ' # SQUARE ROOT Html2Unicode = ChrW(&H221A) Case "sdot" ' # DOT OPERATOR Html2Unicode = ChrW(&H22C5) Case "not" ' # NOT SIGN Html2Unicode = ChrW(&HAC) Case "and" ' # LOGICAL AND Html2Unicode = ChrW(&H2227) Case "or" ' # LOGICAL OR Html2Unicode = ChrW(&H2228) Case "hArr" ' # LEFT RIGHT DOUBLE ARROW Html2Unicode = ChrW(&H21D4) Case "lArr" ' # LEFTWARDS DOUBLE ARROW Html2Unicode = ChrW(&H21D0) Case "uArr" ' # UPWARDS DOUBLE ARROW Html2Unicode = ChrW(&H21D1) Case "rArr" ' # RIGHTWARDS DOUBLE ARROW Html2Unicode = ChrW(&H21D2) Case "dArr" ' # DOWNWARDS DOUBLE ARROW Html2Unicode = ChrW(&H21D3) Case "loz" ' # LOZENGE Html2Unicode = ChrW(&H25CA) Case "lang" ' # LEFT-POINTING ANGLE BRACKET Html2Unicode = ChrW(&H2329) Case "registersans" ' # REGISTERED SIGN SANS SERIF Html2Unicode = ChrW(&HF8E8) Case "copyrightsans" ' # COPYRIGHT SIGN SANS SERIF Html2Unicode = ChrW(&HF8E9) Case "trademarksans" ' # TRADE MARK SIGN SANS SERIF Html2Unicode = ChrW(&HF8EA) Case "summation" ' # N-ARY SUMMATION Html2Unicode = ChrW(&H2211) Case "parenlefttp" ' # LEFT PAREN TOP Html2Unicode = ChrW(&HF8EB) Case "parenleftex" ' # LEFT PAREN EXTENDER Html2Unicode = ChrW(&HF8EC) Case "parenleftbt" ' # LEFT PAREN BOTTOM Html2Unicode = ChrW(&HF8ED) Case "bracketlefttp" ' # LEFT SQUARE BRACKET TOP Html2Unicode = ChrW(&HF8EE) Case "bracketleftex" ' # LEFT SQUARE BRACKET EXTENDER Html2Unicode = ChrW(&HF8EF) Case "bracketleftbt" ' # LEFT SQUARE BRACKET BOTTOM Html2Unicode = ChrW(&HF8F0) Case "bracelefttp" ' # LEFT CURLY BRACKET TOP Html2Unicode = ChrW(&HF8F1) Case "braceleftmd" ' # LEFT CURLY BRACKET MID Html2Unicode = ChrW(&HF8F2) Case "braceleftbt" ' # LEFT CURLY BRACKET BOTTOM Html2Unicode = ChrW(&HF8F3) Case "braceleftex" ' # CURLY BRACKET EXTENDER Html2Unicode = ChrW(&HF8F4) Case "angleright" ' # RIGHT-POINTING ANGLE BRACKET Html2Unicode = ChrW(&H232A) Case "integral" ' # INTEGRAL Html2Unicode = ChrW(&H222B) Case "integraltp" ' # TOP HALF INTEGRAL Html2Unicode = ChrW(&H2320) Case "integralex" ' # INTEGRAL EXTENDER Html2Unicode = ChrW(&HF8F5) Case "integralbt" ' # BOTTOM HALF INTEGRAL Html2Unicode = ChrW(&H2321) Case "parenrighttp" ' # RIGHT PAREN TOP Html2Unicode = ChrW(&HF8F6) Case "parenrightex" ' # RIGHT PAREN EXTENDER Html2Unicode = ChrW(&HF8F7) Case "parenrightbt" ' # RIGHT PAREN BOTTOM Html2Unicode = ChrW(&HF8F8) Case "bracketrighttp" ' # RIGHT SQUARE BRACKET TOP Html2Unicode = ChrW(&HF8F9) Case "bracketrightex" ' # RIGHT SQUARE BRACKET EXTENDER Html2Unicode = ChrW(&HF8FA) Case "bracketrightbt" ' # RIGHT SQUARE BRACKET BOTTOM Html2Unicode = ChrW(&HF8FB) Case "bracerighttp" ' # RIGHT CURLY BRACKET TOP Html2Unicode = ChrW(&HF8FC) Case "bracerightmd" ' # RIGHT CURLY BRACKET MID Html2Unicode = ChrW(&HF8FD) Case "bracerightbt" ' # RIGHT CURLY BRACKET BOTTOM Html2Unicode = ChrW(&HF8FE) Case Else ' PUNT Html2Unicode = "&" & HtmlTag & ";" End Select End Function Function GetLine(SourceString As String, Delim As String) As String Dim pos As Long pos = InStr(1, SourceString, Delim) If pos = 0 Then GetLine = SourceString SourceString = "" Exit Function End If GetLine = Left(SourceString, pos - 1) SourceString = Mid(SourceString, pos + 1) End Function Sub FontInfoGoingOutOfScope(HtmlTag As String) If HtmlTag = "nochange" Then Exit Sub ElseIf HtmlTag = "p" Then Selection.TypeParagraph Exit Sub End If Select Case GetLine(HtmlTag, ":") Case "bold" Selection.Font.Bold = False Case "underline" Selection.Font.Underline = CLng(HtmlTag) Case "italic" Selection.Font.Italic = False ' possibilities: ' font:face:face_name:color:num ' font:color:num:face:face_name ' font:face:face_name ' font:color:num Case "font" Dim key As String key = GetLine(HtmlTag, ":") If key = "face" Then Selection.Font.Name = GetLine(HtmlTag, ":") If HtmlTag <> "" Then key = GetLine(HtmlTag, ":") Selection.Font.ColorIndex = CLng(HtmlTag) End If ElseIf key = "color" Then Selection.Font.ColorIndex = CLng(GetLine(HtmlTag, ":")) If HtmlTag <> "" Then key = GetLine(HtmlTag, ":") Selection.Font.Name = HtmlTag End If End If Case "sub" Selection.Font.Subscript = False Case "sup" Selection.Font.Superscript = False Case "color" Selection.Font.ColorIndex = CLng(HtmlTag) End Select End Sub Function ParseHtmlTag(HtmlTag As String) As String 'easy stuff first HtmlTag = LCase(HtmlTag) Select Case HtmlTag ' paragraph Case "p" Selection.TypeParagraph ParseHtmlTag = "p" Exit Function ' bold Case "b", "strong" If Selection.Font.Bold = True Then ParseHtmlTag = "nochange" Else ParseHtmlTag = "bold:False" End If Selection.Font.Bold = True Exit Function 'underline Case "u" ParseHtmlTag = "underline:" & CStr(Selection.Font.Underline) Selection.Font.Underline = wdUnderlineSingle Exit Function 'italic Case "i", "em" If Selection.Font.Italic = True Then ParseHtmlTag = "nochange" Else ParseHtmlTag = "italic:False" End If Selection.Font.Italic = True Exit Function ' superscript Case "sup" If Selection.Font.Superscript = True Then ParseHtmlTag = "nochange" Else ParseHtmlTag = "sup:False" End If Selection.Font.Superscript = True Exit Function ' subscript Case "sub" If Selection.Font.Subscript = True Then ParseHtmlTag = "nochange" Else ParseHtmlTag = "sub:False" End If Selection.Font.Subscript = True Exit Function End Select ' ok, the hard stuff then ' font If Left(HtmlTag, 4) = "font" Then ParseHtmlTag = "font:" & ParseFontHtmlTag(Mid(HtmlTag, 6)) Exit Function End If Dim pos As Long ' color ' the tag must look like the following: ' span style="color:blue" If Left(HtmlTag, 4) = "span" Then ' we only handle color for now pos = InStr(1, HtmlTag, "color:") If pos = 0 Then ParseHtmlTag = "nochange" Exit Function End If ' get past the colon pos = InStr(1, HtmlTag, ":") HtmlTag = Mid(HtmlTag, pos + 1) ' get the color ParseHtmlTag = "color:" & CStr(Selection.Font.ColorIndex) Selection.Font.ColorIndex = ColorString2Long(LCase(GetLine(HtmlTag, """"))) Exit Function End If Debug.Print "*** UNKNOWN STYLE FORMAT: " & HtmlTag End Function Private Function ParseFontHtmlTag(Tag As String) As String Dim key As String Dim value As String Dim pos As Integer ' get the key key = GetLine(Tag, "=") ' get the value If Left(Tag, 1) = """" Then ' the value is wrapped in quotes Tag = Mid(Tag, 2) pos = InStr(1, Tag, """") value = Left(Tag, pos - 1) Tag = Mid(Tag, pos + 2) Else ' not wrapped in quotes -- naughty naughty, but we turn a blind eye... pos = InStr(1, Tag, " ") If pos > 0 Then value = Left(Tag, pos - 1) Tag = Mid(Tag, pos + 1) Else value = Tag Tag = "" End If End If Tag = LTrim(Tag) Select Case key ' now find out what our key was... Case "face" ParseFontHtmlTag = "face:" & Selection.Font.Name Selection.Font.Name = value Case "color" ParseFontHtmlTag = "color:" & CStr(Selection.Font.ColorIndex) Selection.Font.ColorIndex = ColorString2Long(LCase(value)) End Select If Tag = "" Then Exit Function End If ' Say it with me -- recursion is our friend! ParseFontHtmlTag = ParseFontHtmlTag & ":" & ParseFontHtmlTag(Tag) End Function '================================================ ' Concat + '================================================ Public Sub Concat(Dest As String, Source As String) Dim l As Long l = Len(Source) If (ccOffset + l) >= Len(Dest) Then If l > ccIncrement Then Dest = Dest & Space$(l) Else Dest = Dest & Space$(ccIncrement) End If End If Mid$(Dest, ccOffset + 1, l) = Source ccOffset = ccOffset + l End Sub '===================================================== ' Replace all occurrances of from_str with to_str. + ' Usage: Ouput = ReplaceText( "ABC", "A", "B" ) + ' Result: Output = "BBC" + '===================================================== Public Function ReplaceText(ByVal txt As String, ByVal _ from_str As String, ByVal to_str As String) As String Dim result As String Dim from_len As Integer Dim pos As Integer from_len = Len(from_str) Do While Len(txt) > 0 ' Find from_str. pos = InStr(txt, from_str) If pos = 0 Then ' No more occurrences. result = result & txt txt = "" Else ' Make the replacement. result = result & Left$(txt, pos - 1) & to_str txt = Mid$(txt, pos + from_len) End If Loop ReplaceText = result End Function ' ======================================================== ' || || ' || WORD 97 SPECIFIC || ' || || ' ======================================================== Function ColorLong2String(Color As Long) As String Select Case Color Case wdAuto ColorLong2String = "#000000" Case wdBlack ColorLong2String = "#000000" Case wdBlue ColorLong2String = "#0000ff" Case wdBrightGreen ColorLong2String = "#66FF66" Case wdDarkBlue ColorLong2String = "#00008b" Case wdDarkRed ColorLong2String = "#8b0000" Case wdDarkYellow ColorLong2String = "darkyellow" Case wdGray25 ColorLong2String = "#CCCCCC" Case wdGray50 ColorLong2String = "#999999" Case wdGreen ColorLong2String = "#008000" Case wdNoHighlight ColorLong2String = "#000000" Case wdPink ColorLong2String = "#ffc0cd" Case wdRed ColorLong2String = "#ff0000" Case wdTeal ColorLong2String = "#008080" Case wdTurquoise ColorLong2String = "#40e0d0" Case wdViolet ColorLong2String = "#ee82ee" Case wdWhite ColorLong2String = "#ffffff" Case wdYellow ColorLong2String = "#ffff00" Case Else ColorLong2String = "#000000" End Select End Function Function ColorString2Long(Color As String) As Long Select Case LCase(Trim(Color)) Case "white", "#ffffff" ColorString2Long = wdWhite Case "black", "#000000" ColorString2Long = wdBlack Case "blue", "#0000ff" ColorString2Long = wdBlue Case "#66ff66", "brightgreen" ColorString2Long = wdBrightGreen Case "#00008b", "darkblue" ColorString2Long = wdDarkBlue Case "#8b0000", "darkred" ColorString2Long = wdDarkRed Case "darkyellow" ColorString2Long = wdDarkYellow Case "#cccccc", "lightgray" ColorString2Long = wdGray25 Case "#999999", "gray", "darkgray" ColorString2Long = wdGray50 Case "#008000", "green" ColorString2Long = wdGreen Case "#ffc0cd", "pink" ColorString2Long = wdPink Case "#ff0000", "red" ColorString2Long = wdRed Case "#008080", "teal" ColorString2Long = wdTeal Case "#40e0d0", "turquoise" ColorString2Long = wdTurquoise Case "#ee82ee", "violet" ColorString2Long = wdViolet Case "#ffff00", "yellow" ColorString2Long = wdYellow Case Else Debug.Print "*** Unknown color code: " & Color ColorString2Long = wdAuto End Select End Function