Long story, thanks for reading :)
I'm trying to automate analyzing an AD export. I send a customer PowerShell scripts to export AD data to CSV. They send me the CSV files, I import those into an analytic tool called WeGalvanice ACL (ACL for short). Within ACL I am able to filter/match/compare and whatever I need doing.
So far all good. Now I want to use those results and put them in a .docx file, and here comes trouble. ACL cant export to docx, only xlsx/txt/csv/html/json/del.
Ok well we can work around that (or so i thought), I made a template.docx
within that template.docx
I wrote the placeholders like %certainvariable%
.
Within ACL I created a command to write all variables I need to files called %variablename%.txt
and within the txt is the value I need.
For example:
ACL creates disabledusers.txt
. If you open the txt it only shows 10, meaning we got 10 disabled users.
Then I tried to create a VBA macro to import the txt files and use the contained values to replace the according %...%
text within the Word document.
This all looked to go smoothly until I noticed that after running the script I got 20
followed by that box that meanings "I have no clue how to display this char".
Prior to running the script:
After running the script:
picture of .txt content that i import:
And last but not least the VBS code im using from word Macro manager (for convenience I only uploaded 1 import-and-replace job, but in my script I just copied this 30 times for each file and variable):
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
When I open the date.txt
manualy and remove the second line then it all seems to work. But I want it automated. ;)
I tried
split textfile,/n
and split new_date,/n
both with \\n\\r
and \\r
to no avail.I'm open for suggestions on any programming language, (im terrible at them all) ill just queue everything in the right order to make it work ;)
thanks in advance everyone! and of course ask away if you need more info
Update thanks to Tomalak i got the principle working:
' 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
The problem seems to be the newline (CRLF). You have to get rid of it.
And while we are at it, let's also get rid of the "I've copied that code 30 times" bit, that's a horrible way to solve this problem. Loops are better.
Helpers:
' 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
Worker:
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
The TrimRight()
function only strips the final line break from the given input string. Any line breaks that are in the middle of the content are retained. If this is a thing that can happen with your data, Word will create new paragraphs for every LF
it finds. And it will draw boxes for every CR
it finds.
If you do have multi-line txt files, but don't want new paragraphs, and don't want boxes, either, modify the content of the text file before you use it (get rid of CRs, replace the LFs with vertical tabs, which are Word's way to represent "soft breaks", ie the same thing you get with Shift+Enter):
realValue = ReadFile("\local folderpath\" & variable & ".txt")
realValue = TrimRight(realValue)
realValue = Replace(Replace(realValue, vbCr, ""), vbLf, vbVerticalTab)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.