【问题标题】:Importing variables from TXT files to a Word document将 TXT 文件中的变量导入 Word 文档
【发布时间】:2020-01-20 22:18:58
【问题描述】:

长篇大论,感谢阅读:)

我正在尝试自动分析 AD 导出。我向客户发送 PowerShell 脚本以将 AD 数据导出到 CSV。他们将 CSV 文件发送给我,我将它们导入到一个名为 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。如果你打开 txt 它只显示 10 个,这意味着我们有 10 个禁用用户。

然后我尝试创建一个 VBA 宏来导入 txt 文件并使用包含的值替换 Word 文档中相应的 %...% 文本。

这一切看起来都很顺利,直到我注意到在运行脚本后我得到了20,后面跟着那个框,意思是“我不知道如何显示这个字符”。

在运行脚本之前:

运行脚本后:

我导入的 .txt 内容的图片:

最后但并非最不重要的一点是,我使用来自 word 宏管理器的 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

【问题讨论】:

  • 来自帮助 从 Visual Basic 的第一个版本开始,文件就一直使用 Open 语句和其他相关语句和函数(如下所列)进行处理。这些机制最终将被 FSO 对象模型淘汰,但它们在 Visual Basic 6.0 中得到完全支持。.
  • PS 那条评论是 25 岁。
  • 除此弃用警告外,Open 会在 txt 文件采用意外编码(例如 UTF-8)时弄乱数据。如果您的情况是否正常,您会看到带有重音字符的文本。
  • FWIW,如果您将 .txt 文件的扩展名更改为 .doc,Word 会将其作为 Word 文档打开。

标签: vba ms-word


【解决方案1】:

问题似乎是换行符 (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 绘制框。

如果您确实有多行 txt 文件,但不想要新段落,也不想要框,请在使用之前修改文本文件的内容(摆脱 CR,替换 LF使用垂直制表符,这是 Word 表示“软中断”的方式,即与使用 Shift+Enter 得到的相同):

realValue = ReadFile("\local folderpath\" & variable & ".txt")
realValue = TrimRight(realValue)
realValue = Replace(Replace(realValue, vbCr, ""), vbLf, vbVerticalTab)

【讨论】:

  • 感谢您对 tomalak 的回答,我完全同意您的观点,即粘贴导入 30 次是丑陋且效率较低的,但由于缺乏编码经验,这是我能想到的最好的方法;)目前我没有代码或文件,明天将对此进行测试我是否正确假设我需要将文件路径更改为包含所有 variable.txt 文件的文件夹?然后将所有变量名添加到 split 命令中。还有什么我应该添加或更改的吗?感谢您今天花费大部分时间来让这部分工作,但仍然失败 xD
  • 差不多 - 调整路径,添加变量名。但请确保您在使用它之前了解所有这些是如何工作的。它有助于在 VBA IDE (F9) 中设置断点并逐行执行代码 (F8),同时查看变量值 (View -> Locals Window)。
  • tomalak,我现在正在尝试您的代码,它会从 word 文档中删除所有 %variable% 但不会用其他任何内容替换它们。我在末尾添加了一个 MsgBox(变量),它确实给了我所有变量名称“日期,禁用用户等”的弹出窗口,我还注意到当我打开视图>本地窗口时,我看不到变量的任何值。
  • 使用Debug.Print 而不是MsgBox,这样更不烦人(打开即时窗口以查看Debug.Print 的输出)。我写的代码看不出有什么问题,您确定您没有对其进行任何更改吗?
  • 已修复!必须替换 \local 文件夹路径而不是文件路径;P
猜你喜欢
  • 2015-08-10
  • 2020-12-20
  • 2023-02-14
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 2013-10-03
  • 1970-01-01
  • 2019-10-11
相关资源
最近更新 更多