Coloreado de Sintaxis en Word

Para cuando documentamos software, es común tener que pegar un trozo de código de nuestros programas a Microsoft Word. Desgraciadamente, no siempre se mantiene el formato y los colores que desearíamos. El coloreado de sintaxis que tenemos en nuestra IDE, se puede perder al copiar y pegar.

Para solucionar este problema, y como no encontré en Word algún estilo con reconocimiento de sintaxis, decidí proponer una solución que no requiere instalar ningún complemento. Basta con crear una sencilla macro en el VBA del Word.

Yo lo he probado en Office 2010, pero debería funcionar para otras versiones. La versión que he escrito, solo reconoce los programas de Object Pascal, pero podría cambiarse para reconocer otro lenguaje, modificando las constantes en el código fuente.

Hay muchas cosas que le faltan mejorar, como mejorar el formato, agregarle reconocimiento de cadenas y comentarios de varias líneas, pero este es un buen punto de partida.

Para los que no estén familiarizados con las macros de «Word», les indico como crearla: En Word pulsar la combinación de teclas «Alt + F11» para acceder al editor de macros. Allí en el editor, seleccionar el menú «Insertar>Módulo» y pegar este código:

Option Explicit

'Escribir las palabras en mayúscula o minúscula, separadas por espacios
Const PALABRAS_RESERVADAS = "absolute abstract alias and array as asm assembler begin break case cdecl class const constructor continue default destructor dispose div do downto else end except exit export exports external false far file finalization finally for forward function goto if implementation in index inherited initialization inline interface is label library mod name near new nil not object of on on operator or override packed pascal popstack private procedure program property protected public published raise read record register repeat saveregisters self set shl shr stdcall string then to true try type unit until uses var virtual while with xor"

Const SIMBOLOS = "()+-*/<>:=;"
Const CARACTER_COMENTARIO = "//"
Const CARACTER_CADENA = "'"

Const COL_SIMBOLO = wdRed   'color de símbolo
Const COL_PAL_RES = wdGreen
Const COL_CADENA = wdViolet

Dim pReser As New Collection    'Palabras reservadas

Sub CodigoPascal()
' "CodigoPascal "
' Macro para aplicar resaltado de xintaxis a un párrafo de texto seleccionado
Dim nlin As Integer 'número de líneas
Dim p As Range
Dim i As Integer
Dim pal As Range
    'verificación
    nlin = Selection.Paragraphs.Count
    If nlin > 100 Then
        If MsgBox("¿Aplicar formato a toda la selección de " & nlin & " líneas?", _
                  vbOKCancel Or vbDefaultButton2) = vbCancel Then Exit Sub
    End If
    Call CargaPalabReservadas   'Carga palabras reservadas
    'Aplica formato a todo el texto
    Set p = Selection.Range
    p.Font.Name = "Courier New"  'Caracter
    p.Font.Size = 10
    p.Font.ColorIndex = wdBlack
    p.Font.Bold = False
    
    p.ParagraphFormat.FirstLineIndent = CentimetersToPoints(0)  'sin márgen izquierdo
    p.ParagraphFormat.SpaceBefore = 0   'espacios antes de líneas
    p.ParagraphFormat.SpaceBeforeAuto = False
    p.ParagraphFormat.SpaceAfter = 1    'espacios después de líneas
    p.ParagraphFormat.SpaceAfterAuto = False
    p.NoProofing = True     'desactiva verificaión de sintaxis
    p.Shading.BackgroundPatternColor = -671023309   'color de fondo

    'busca palabras reservadas y símbolos
    For i = 1 To p.Words.Count   'explora palabras
        Set pal = p.Words(i)
        If EsPalabReserv(pal) Then
            pal.Font.ColorIndex = COL_PAL_RES
            pal.Font.Bold = True
        ElseIf Not (Left$(pal.Text, 1) Like "[a-zA-Z0-9]") Then
            Call VerificarSimbolo(pal)
        End If
    Next
    'busca cadenas y comentarios
    Call BuscarCadenas(p)
    Call BuscarComentarioUnaLinea(p)

End Sub

Private Function EsPalabReserv(pal As Range) As Boolean
'Indica si una palabra está en la lista de palabras reservadas
Dim i As Integer
Dim txt As String
Dim sig As String
    txt = RTrim(pal)
    sig = pal.Next(wdWord, 1) 'Palabra anterior
    For i = 1 To pReser.Count
        If pReser(i) = LCase(txt) And sig <> "_" Then
            EsPalabReserv = True    'encontró
            Exit Function
        End If
    Next
End Function

Private Sub VerificarSimbolo(pal As Range)
'Identifica un símbolo, o varios símbolos juntos
Dim i As Integer
Dim car As Range
    'verifica si puede ser símbolo
    If Left$(pal.Text, 1) Like "[a-zA-Z0-9']" Then Exit Sub
    If Trim(pal.Text) = "" Then Exit Sub
    If Len(pal.Text) = 1 Then    'un solo caracter
        If InStr(SIMBOLOS, RTrim(pal)) <> 0 Then
            'es símbolo
            pal.Font.ColorIndex = COL_SIMBOLO
            pal.Font.Bold = True
        End If
    ElseIf Len(pal.Text) > 1 Then
        'explora por caracter
        For i = 1 To Len(pal.Text)
            Set car = ActiveDocument.Range(pal.Start + i - 1, _
                                pal.Start + i)
            Call VerificarSimbolo(car)
        Next
    End If
End Sub

Private Sub BuscarCadenas(p As Range)
'Busca y pinta las cadenas
Dim par As Paragraph
Dim i As Integer, j As Integer
Dim cadena As Range
    'busca comentarios de una línea
    For Each par In p.Paragraphs  'explora párrafos
        i = InStr(par.Range, CARACTER_CADENA)
        If i <> 0 Then
            j = InStr(i + 1, par.Range, CARACTER_CADENA)  'busca fin de cadena
            If j = 0 Then Exit Sub
            'hay cadena
            Set cadena = ActiveDocument.Range(par.Range.Start + i - 1, _
                                par.Range.Start + j)
            cadena.Font.ColorIndex = COL_CADENA
        End If
    Next
End Sub

Private Sub BuscarComentarioUnaLinea(p As Range)
'Busca y pinta los comentarios de uan sola línea
Dim par As Paragraph
Dim i As Integer
Dim comen As Range
    'busca comentarios de una línea
    For Each par In p.Paragraphs  'explora párrafos
        i = InStr(par.Range, CARACTER_COMENTARIO)
        If i <> 0 Then
            'hay comentario
            Set comen = ActiveDocument.Range(par.Range.Start + i - 1, _
                                par.Range.End)
            comen.Font.ColorIndex = wdBlue
        End If
    Next
End Sub

Private Sub CargaPalabReservadas()
'Carga palabras reservadas
Dim a() As String
Dim i As Integer
    a = Split(PALABRAS_RESERVADAS)
    For i = 0 To UBound(a)
        pReser.Add LCase(Trim(a(i)))
    Next
End Sub

Pulsar sobre el botón grabar y eso debe ser todo.  Ya tienen una macro para formatear texto con coloreado de sintaxis, al estilo de las IDE de desarrollo.

La forma de trabajo es simple, seleccionar el texto y ejecutar la macro. El texto seleccionado cambiará su formato con un sombreado azul claro, con texto en «Courier New», de tamaño 10, con espaciado simple, y con las palabras reservadas y comentarios, coloreados.

Para ejecutar, se puede usar la combinación Alt+F8 para acceder a las macros creadas y de ahí seleccionar la macro llamada: «CodigoPascal».

Otra forma más elegante, sería crearle un acceso desde un botón desde el mismo Word o una combinación de teclas.


2 comentarios

Dejar una contestacion

Tu dirección de correo electrónico no será publicada.


*