Импорт переменных из TXT-файлов в документ Word - PullRequest
0 голосов
/ 16 января 2020

Длинная история, спасибо за чтение:)

Я пытаюсь автоматизировать анализ экспорта AD. Я отправляю клиенту скрипты PowerShell для экспорта данных AD в CSV. Они отправляют мне файлы CSV, я импортирую их в аналитический инструмент c, который называется WeGalvanice ACL (сокращенно ACL). В ACL я могу фильтровать / сопоставлять / сравнивать и все, что мне нужно делать.

Пока все хорошо. Теперь я хочу использовать эти результаты и поместить их в файл .docx, и тут возникает проблема. ACL не может экспортировать в docx, только xlsx / txt / csv / html / json / del.

Хорошо, мы можем обойти это (или так я думал), я сделал template.docx в этом template.docx Я написал заполнители как %certainvariable%.

В ACL я создал команду для записи всех необходимых мне переменных в файлы с именем %variablename%.txt, а внутри txt - нужное мне значение.

Для пример:

ACL создает disabledusers.txt. Если вы откроете текстовый файл, он покажет только 10, что означает, что у нас есть 10 отключенных пользователей.

Затем я попытался создать макрос VBA для импорта текстовых файлов и использовать содержащиеся в нем значения для замены соответствующего текста %...% в документ Word.

Все это выглядело гладко до go, пока я не заметил, что после запуска скрипта я получил 20, за которым следовало это поле, означающее «Я понятия не имею, как отобразить этот символ».

До запуска сценария:

picture prior to running the script

После запуска сценария:

picture after running the script

изображение .txt контента, который я импортирую:

https://i.imgur.com/Aa90Ek4.png

И последний, но не менее важный код VBS, который я использую из слова Диспетчер макросов (для удобства я загрузил только 1 задание импорта и замены, но в своем сценарии я только 30 раз скопировал это для каждого файла и переменной):

Sub ACL()
    ' ACL Macro

    FilePath = "local folderpath\date.txt"
    TextFile = FreeFile
    Open FilePath For Input As TextFile
    new_date = Input(LOF(TextFile), TextFile)
    old_date = "%date%"
    Close TextFile

    With ActiveDocument.Content.Find
        .Forward = True
        .Wrap = wdFindStop
        .Execute findtext:=old_date, replacewith:=new_date, Replace:=wdReplaceAll
    End With    
End Sub

Когда я открываю date.txt вручную и удалите вторую строку, тогда все, кажется, работает. Но я хочу, чтобы это было автоматизировано. ;)

Я попытался

  • , добавив split textfile,/n и split new_date,/n с \n\r и \r безрезультатно.
  • Использовал команды sed для удалить вторую строку. безрезультатно.
  • Нашел множество методов findstr для удаления так называемого возврата каретки (crlf), но либо мои txt-файлы внезапно опустели, либо я все еще получил коробки в моем файле Word.

Я открыт для предложений по любому языку программирования (я ужасен для всех), я просто ставлю все в очередь в правильном порядке, чтобы заставить его работать;)

заранее всем спасибо! и, конечно, спросите, если вам нужна дополнительная информация

Обновление благодаря Tomalak, у меня работает принцип:

    ' removes CR & LF from the end of a string (not pretty but gets the job done)
Function TrimRight(InputStr As String) As String
    While Right(InputStr, 1) = vbCr Or Right(InputStr, 1) = vbLf
        InputStr = Left(InputStr, Len(InputStr) - 1)
    Wend
    TrimRight = Trim(InputStr)
End Function

' reads any text file and returns the content as-is
Function ReadFile(FilePath As String) As String
    Dim filenum As Integer

  If Dir(FilePath) > "" Then
        filenum = FreeFile
        Open FilePath For Input As filenum
        ReadFile = Input(LOF(filenum), filenum)
        Close filenum
    Else
        Debug.Print "File not found: " & FilePath
    End If
End Function

' replaces all instances of a single word in the given document
Sub ReplaceAll(oldValue As String, newValue As String, doc As Document)
    With doc.Content.Find
        .Forward = True
        .Wrap = wdFindStop
        .Execute findtext:=oldValue, replacewith:=newValue, Replace:=wdReplaceAll
    End With
End Sub


Sub ReplaceAllVariables()
    Dim variables As Variant, variable As Variant
    Dim placeholder As String, realValue As String

    variables = Split("customer,c_adgroup,c_adgroup_Cannot_change_PW,c_adgroup_disabled,c_adgroup_enabled,c_adgroup_expire_and_disabled,c_adgroup_LockedOut,c_adgroup_Locked_and_disabled,c_adgroup_loginx,c_adgroup_loginx_disabled,c_adgroup_nolastpasswordset,c_adgroup_nologondate,c_adgroup_PWRQ_and_disabled,c_adgroup_PWx,c_adgroup_PWx_and_disabled,c_adgroup_PW_and_disabled,c_adgroup_PW_and_enabled,c_adgroup_PWRQ_and_enabled ,c_adgroup_PW_not_required,c_adgroup_PW_no_expire,c_adgroup_loginx_and_enabled,c_adusers_f_Cannot_change_PW,c_adusers_f_disabled,c_adusers_f_enabled,c_adusers_f_expire_and_disabled,c_adusers_f_LockedOut,c_adusers_f_Locked_and_disabled,c_adusers_f_loginx,c_adusers_f_loginx_disabled,c_adusers_f_nolastpasswordset,c_adusers_f_nologondate,c_adusers_f_PWRQ_and_disabled,c_adusers_f_PWx,c_adusers_f_PWx_and_disabled,c_adusers_f_PW_and_disabled,c_adusers_f_PW_not_required,c_adusers_f_PW_no_expire,c_adusers_f_loginx_and_enabled,date,c_adusers_f_PW_and_enabled,lastlogon", ",")

    For Each variable In variables
        placeholder = "%" & variable & "%"
        realValue = ReadFile("C:\Users\jerryw\Documents\Klanten\ACL\AD analyse\var\" & variable & ".txt")
        realValue = TrimRight(realValue)
        ReplaceAll placeholder, realValue, ActiveDocument
    Next
End Sub

1 Ответ

0 голосов
/ 16 января 2020

Кажется, проблема в переводе строки (CRLF). Вы должны избавиться от этого.

И пока мы на этом, давайте также избавимся от "Я скопировал этот код 30 раз" бит, это ужасный способ решить эту проблему. Циклы лучше.

Помощники:

' removes CR & LF from the end of a string (not pretty but gets the job done)
Function TrimRight(InputStr As String) As String
    While Right(InputStr, 1) = vbCr Or Right(InputStr, 1) = vbLf
        InputStr = Left(InputStr, Len(InputStr) - 1)
    Wend
    TrimRight = Trim(InputStr)
End Function

' reads any text file and returns the content as-is
Function ReadFile(FilePath As String) As String
    Dim filenum As Integer

    If Dir(FilePath) > "" Then
        filenum = FreeFile
        Open FilePath For Input As filenum
        ReadFile = Input(LOF(filenum), filenum)
        Close filenum
    Else
        Debug.Print "File not found: " & FilePath
    End If
End Function

' replaces all instances of a single word in the given document
Sub ReplaceAll(oldValue As String, newValue As String, doc As Document)
    With doc.content.Find
        .Forward = True
        .Wrap = wdFindStop
        .Execute findtext:=oldValue, replacewith:=newValue, Replace:=wdReplaceAll
    End With
End Sub

Работник:

Sub ReplaceAllVariables()
    Dim variables As Variant, variable As Variant
    Dim placeholder As String, realValue As String

    variables = Split("date,disabledusers,and,any,other,variable,you,have", ",")

    For Each variable In variables
        placeholder = "%" & variable & "%"
        realValue = ReadFile("\local folderpath\" & variable & ".txt")
        realValue = TrimRight(realValue)
        ReplaceAll placeholder, realValue, ActiveDocument
    Next
End Sub

Функция TrimRight() убирает только окончание строки final с заданная входная строка. Любые разрывы строк, которые находятся в середине содержимого, сохраняются. Если это может произойти с вашими данными, Word создаст новые абзацы для каждого найденного LF. И он будет рисовать блоки для каждого найденного CR.

Если у вас есть многострочные текстовые файлы, но вы не хотите новых абзацев и не хотите, чтобы блоки также изменяли содержимое текстовый файл перед его использованием (избавьтесь от CR, замените LF вертикальными вкладками, которые являются способом Word представлять «мягкие разрывы», то есть то же самое, что вы получаете с помощью Shift + Enter):

realValue = ReadFile("\local folderpath\" & variable & ".txt")
realValue = TrimRight(realValue)
realValue = Replace(Replace(realValue, vbCr, ""), vbLf, vbVerticalTab)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...