Acrobat cannot read .FDF written with Excel VBA - vba

I exported a PDF with form fields in FDF and wrote a sub to output another FDF verbatim, with cell values for the form field values. If I edit the FDF in a text editor and change the values, Acrobat can read the file just fine, but the file output with VBA throws an error:
Adobe could not open whatever.fdf because it is either not a supported file type or because the file has been damaged
I've tried two different types of line breaks, I've tried a similar sub with xfdf formatting which is slightly different with the same results.
Sub something()
Dim sht As Worksheet
Set sht = Sheets("owssvr")
Dim lastrow As Integer
lastrow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim Fileout As Object
Dim x As Integer
For x = 2 To lastrow
Set Fileout = fso.CreateTextFile("C:\Users\blabla\" & x & ".fdf", True, True)
Fileout.Write "%FDF-1.2" & vbCrLf & _
"%âãÏÓ" & vbCrLf & _
"1 0 obj" & vbCrLf & _
"<</FDF<</F(MyDocument.pdf)/Fields[<</T(Adobe Form Field)/V(" & sht.Range("U" & x) & ")>>]/ID[<4ED54800AC4A3D41ABE4F4C7B12A3D23><609E705B7532334B8F914CFF4C09F2A0>]/UF(MyDocument.pdf)>>/Type/Catalog>>" & vbCrLf & _
"endobj" & vbCrLf & _
"trailer" & vbCrLf & _
"<</Root 1 0 R>>" & vbCrLf & _
"%%EOF" & vbCrLf
Fileout.Close
Next x
End Sub

Simply leave out the line: "%âãÏÓ" & vbCrLf & _". /ID and /UF keys not really needed.
Something like this should work:
Fileout.Write "%FDF-1.2" & vbCrLf & _
"1 0 obj<</FDF<<" & vbCrLf & _
"/F(MyDocument.pdf)" & vbCrLf & _
"/Fields" & vbCrLf & _
"[<</T(Adobe Form Field)/V(xyValue)>>]" & vbCrLf & _
">>>>" & vbCrLf & _
"endobj" & vbCrLf & _
"trailer" & vbCrLf & _
"<</Root 1 0 R>>" & vbCrLf & _
"%%EOF" & vbCrLf

You will find that in the Acrobat IAC documentation. Here a quick vbs(vba) example. Where you need only 2 lines from that: jso.getField and f.value =... Good luck.
'//-> Set a value for a form field via JSO
'//-> Settings
FileNm = "d:\TestInput.pdf"
FieldNm= "Input1"
FieldValue= "50"
'//-> let's start
Set App = CreateObject("Acroexch.app")
app.show
Set AVDoc = CreateObject("AcroExch.AVDoc")
'//-> open the file and put the value in
If AVDoc.Open(FileNM,"") Then
Set PDDoc = AVDoc.GetPDDoc()
Set jso = PDDoc.GetJSObject
'//-> Get the field and put a value in
set f = jso.getField(FieldNm)
f.value = FieldValue
end if

As much as I want to leave this open in hopes somebody figures out WHY VBA is screwing up the unicode, my problem can be solved without invoking fso at all and just using FreeFile and string replace on an original FDF
Sub blabla()
Dim objAcroApp As Acrobat.AcroApp
Dim objAcroAVDoc As Acrobat.AcroAVDoc
Dim objAcroPDDoc As Acrobat.AcroPDDoc
Dim jsObj As Object
Dim boResult As Boolean
Dim oldPDF As String
Dim NewFilePath As String
Dim sTemp As String
Dim iFileNum As Integer
Dim oldFDF As String
Dim i As Integer
Dim lastRow As Integer
Dim sht As Worksheet
Set sht = Sheets("owssvr")
With sht
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
End With
For i = 2 To lastRow
oldPDF = "\mydoc.pdf"
oldFDF = "\mydoc_data.fdf"
newPDF = "\" & i & ".pdf"
iFileNum = FreeFile
Open oldFDF For Input As iFileNum
Do Until EOF(iFileNum)
Line Input #iFileNum, sBuf
sTemp = sTemp & vbCrLf
Loop
Close iFileNum
sTemp = Replace(sTemp, "<</T(some form field)/V( )>>", "<</T(some form field)/V(" & sht.Range("E" & i) & ")>>")
iFileNum = FreeFile
oldFDF = "\" & i & ".fdf"
Open oldFDF For Output As iFileNum
Print #iFileNum, sTemp
Close iFileNum
Set objAcroApp = CreateObject("AcroExch.App")
Set objAcroAVDoc = CreateObject("AcroExch.AVDoc")
boResult = objAcroAVDoc.Open(oldPDF, "")
Set objAcroPDDoc = objAcroAVDoc.GetPDDoc
Set jsObj = objAcroPDDoc.GetJSObject
jsObj.ImportAnFDF oldFDF
jsObj.SaveAs newPDF
boResult = objAcroAVDoc.Close(True)
boResult = objAcroApp.Exit
Next i
End Sub

Related

HOW TO USE SHELL COMMAND COPY IN VBA

I was trying to copy and paste files from a source folder to a destination folder in VBA using the fyle system object, but noticed that it is kind of slow, so I decided to use a shell command instead, but cannot make it work, it's probably something with text literals, here's the code
Dim sourceFolderName As String, destFolderName As String
Dim sourceFolderPath As String, destFolderPath As String
Dim filteredRange As Range, myRange As Range
Dim lastRowNumber As Integer
sourceFolderName = "SOURCE"
destFolderName = "DESTINATION"
sourceFolderPath = Application.ThisWorkbook.Path & _
Application.PathSeparator & sourceFolderName & Application.PathSeparator
destFolderPath = Application.ThisWorkbook.Path & _
Application.PathSeparator & destFolderName
On Error Resume Next
Kill destFolderPath & "\*.*"
lastRowNumber = ThisWorkbook.Sheets(1).Cells(Sheets(1).Rows.Count, 1).End(xlUp).Row
If lastRowNumber = 2 Then
lastRowNumber = 3
End If
Set filteredRange = ThisWorkbook.Sheets(1).Range("A2", "A" & lastRowNumber).SpecialCells(xlCellTypeVisible)
For Each myRange In filteredRange
Shell "cmd /c copy " & sourceFolderPath & myRange.Value & ".pdf " & destFolderPath, vbHide
Next

To move files from multiple source folders to multiple destination folders based on two hour delay

Yesterday we have finalized and tested the code (the first part of the code is VBScript) and the second part of the code is (in Excel VBA) to move file from one source folder to one destination folder successfully based on two hour delay (i.e. each file which will come to source folder will upload 2 hour delay), however the situation is that i have actually 15 source folders and 15 destination folders.
One method is that i should create 15 VBScript files and 15 Excel files that contains the code for each source and destination folder which i believe is not efficient way. I have tried a lot to add multiple source and destination folder options in the below mentioned code(s) but i am not successful, can anyone help me, i will be thankful.
the below mentioned code is VBscript
Dim oExcel, strWB, nameWB, wb
strWB = "E:\Delta\Folder monitor.xlsm"
nameWB = Left(strWB, InStr(StrReverse(strWB), "\") - 1)
nameWB = Right(strWB, Len(nameWB))
Set objExcel = GetObject(,"Excel.Application")
Set wb = objExcel.Workbooks(nameWB)
if wb is nothing then wbscript.quit 'the necessary workbook is not open...
dim strComputer, strDirToMonitor, strTime, objWMIService, colMonitoredEvents, objEventObject, MyFile
strComputer = "."
'# WMI needs two backslashes (\\) as path separator and each of it should be excaped.
'# So, you must use 4 backslashes (\\\\) as path separator!
strDirToMonitor = "E:\\\\Delta\\\\Source" 'use here your path
'# Monitor Above every 10 secs...
strTime = "10"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceOperationEvent WITHIN " & strTime & " WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=" & Chr(34) & strDirToMonitor & Chr(34) & "'")
Do While True
Set objEventObject = colMonitoredEvents.NextEvent()
Select Case objEventObject.Path_.Class
Case "__InstanceCreationEvent"
' msgbox "OK"
'MsgBox "A new file was just created: " & _
MyFile = StrReverse(objEventObject.TargetInstance.PartComponent)
'// Get the string to the left of the first \ and reverse it
MyFile = (StrReverse(Left(MyFile, InStr(MyFile, "\") - 1)))
MyFile = Mid(MyFile, 1, Len(MyFile) - 1)
'send the information to the waiting workbook:
objExcel.Application.Run "'" & strWB & "'!GetMonitorInformation", Array(MyFile,Now)
End Select
Loop
and the second code for this purpose should be copied in a standard module:
Option Explicit
Private Const ourScript As String = "FolderMonitor.vbs"
Private Const fromPath As String = "E:\Delta\Source\"
Sub startMonitoring()
Dim strVBSPath As String
strVBSPath = ThisWorkbook.Path & "\VBScript\" & ourScript
TerminateMonintoringScript 'to terminate monitoring script, if running..
Shell "cmd.exe /c """ & strVBSPath & """", 0
End Sub
Sub TerminateMonintoringScript()
Dim objWMIService As Object, colItems As Object, objItem As Object, Msg
As String
Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", 48)
For Each objItem In colItems
If objItem.Caption = "wscript.exe" Then
'// msg Contains the path of the exercutable script and the script name
On Error Resume Next
Msg = objItem.CommandLine 'for the case of null
On Error GoTo 0
'// If wbscript.exe runs the monitoring script:
If InStr(1, Msg, ourScript) > 0 Then
Debug.Print "Terminate Wscript process..."
objItem.Terminate 'terminate process
End If
End If
Next
Set objWMIService = Nothing: Set colItems = Nothing
End Sub
Sub GetMonitorInformation(arr As Variant)
'call DoSomething Sub after 2 hours (now IT WILL RUN AFTER 1 MINUTE, for testing reasons...)
'for running after 2 hours you should change "00:01:00" in "02:00:00":
arr(0) = Replace(arr(0), "'", "''") 'escape simple quote (') character'
Application.OnTime CDate(arr(1)) + TimeValue("00:01:00"), "'DoSomething """ & CStr(arr(0)) & """'"
Debug.Print "start " & Now 'just for testing (wait a minute...)
'finaly, this line should be commented.
End Sub
Sub DoSomething(strFileName As String)
Const toPath As String = "E:\Delta\Destination\"
If Dir(toPath & strFileName) = "" Then
Name fromPath & strFileName As toPath & strFileName
Debug.Print strFileName & " moved from " & fromPath & " to " & toPath 'just for testing...
Else
MsgBox "File """ & toPath & strFileName & """ already exists in this location..."
End If
End Sub
you can see the previous query here on the link Previous Query
Please, use the next scenario. It assumes that you will fill the necessary path in an existing Excel sheet. Since, it will take the necessary paths based on a cell selection, it is necessary to name the sheet in discussion as "Folders". In Column A:A you should fill the 'Source' folder path (ending in backslash "") and in B:B, the 'Destination' folder path (also ending in backslash).
The proposed solution takes the necessary paths based on your selection in A:A column. The 'Destination' path is extracted based on the selection row.
Please, replace the existing string with the next one, adapting the two necessary paths:
Dim oExcel, strWB, nameWB, wb
strWB = "C:\Teste VBA Excel\Folder monitor.xlsm" 'use here your workbook path!!!
nameWB = Left(strWB, InStr(StrReverse(strWB), "\") - 1)
nameWB = Right(strWB, Len(nameWB))
Set objExcel = GetObject(,"Excel.Application")
Set wb = objExcel.Workbooks(nameWB)
if wb is nothing then wbscript.quit 'the necessary workbook is not open...
dim strComputer, strDirToMonitor, strTime, objWMIService, colMonitoredEvents, objEventObject, MyFile
strComputer = "."
'# WMI needs two backslashes (\\) as path separator and each of it should be excaped.
'# So, you must use 4 backslashes (\\\\) as path separator!
strDirToMonitor = "C:\\\\test\\\\test" 'use here your path !!!
'# Monitor Above every 10 secs...
strTime = "10"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceOperationEvent WITHIN " & strTime & " WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=" & Chr(34) & strDirToMonitor & Chr(34) & "'")' and " _
' & "'Win32_Directory.Name=" & Chr(34) & strDirToMonitor & Chr(34) & "'")
Do While True
Set objEventObject = colMonitoredEvents.NextEvent()
Select Case objEventObject.Path_.Class
Case "__InstanceCreationEvent"
MyFile = StrReverse(objEventObject.TargetInstance.PartComponent)
' Get the string to the left of the first \ and reverse it
MyFile = (StrReverse(Left(MyFile, InStr(MyFile, "\") - 1)))
MyFile = Mid(MyFile, 1, Len(MyFile) - 1)
'send the information to the waiting workbook:
objExcel.Application.Run "'" & strWB & "'!GetMonitorInformation", Array(MyFile, Now, strDirToMonitor)
End Select
Loop
The adapted script sends also the source path to the waiting workbook...
TerminateMonintoringScript Sub remains exactly as it is.
Please, copy the next adapted code instead of existing one, in the used standard module (TerminateMonintoringScript included, even not modified):
Option Explicit
Private Const ourScript As String = "FolderMonitor.vbs"
Private fromPath As String, toPath As String
Sub startMonitoring()
Dim strVBSPath As String, actCell As Range, strTxt As String, pos As Long, endP As Long, oldPath As String
Set actCell = ActiveCell
If actCell.Parent.Name <> "Folders" Then MsgBox "Wrong activated sheet...": Exit Sub
fromPath = actCell.Value
If actCell.Column <> 1 Or Dir(fromPath, vbDirectory) = "" Then Exit Sub 'not a valid path in the selected cell
strVBSPath = ThisWorkbook.Path & "\VBScript\" & ourScript
'change the script necessary "strDirToMonitor" variable path, if the case:__________________________
strTxt = ReadFile(strVBSPath)
pos = InStr(strTxt, Replace(fromPath, "\", "\\\\"))
If pos = 0 Then 'if not the correct path already exists
pos = InStr(strTxt, "strDirToMonitor = """) 'start position of the existing path
endP = InStr(strTxt, """ 'use here your path") 'end position of the existing path
'extract existing path:
oldPath = Mid(strTxt, pos + Len("strDirToMonitor = """), endP - (pos + Len("strDirToMonitor = """)))
strTxt = Replace(strTxt, oldPath, _
Replace(Left(fromPath, Len(fromPath) - 1), "\", "\\\\")) 'replacing existing with the new one
'drop back the updated string in the vbs file:
Dim iFileNum As Long: iFileNum = FreeFile
Open strVBSPath For Output As iFileNum
Print #iFileNum, strTxt
Close iFileNum
End If
'__________________________________________________________________________________________________
TerminateMonintoringScript 'to terminate monitoring script, if running...
Application.Wait Now + TimeValue("00:00:02") 'to be sure that the next line will load the updated file...
Shell "cmd.exe /c """ & strVBSPath & """", 0 'run the VBScript
End Sub
Function ReadFile(strFile As String) As String 'function to read the vbscript string content
Dim iTxtFile As Integer
iTxtFile = FreeFile
Open strFile For Input As iTxtFile
ReadFile = Input(LOF(iTxtFile), iTxtFile)
Close iTxtFile
End Function
Sub TerminateMonintoringScript()
Dim objWMIService As Object, colItems As Object, objItem As Object, Msg As String
Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", 48)
For Each objItem In colItems
If objItem.Caption = "wscript.exe" Then
'// msg Contains the path of the exercutable script and the script name
On Error Resume Next
Msg = objItem.CommandLine 'for the case of null
On Error GoTo 0
'// If wbscript.exe runs the monitoring script:
If InStr(1, Msg, ourScript) > 0 Then
Debug.Print "Terminate Wscript process..."
objItem.Terminate 'terminate process
End If
End If
Next
Set objWMIService = Nothing: Set colItems = Nothing
End Sub
Sub GetMonitorInformation(arr As Variant)
'call DoSomething Sub after 2 hours (now IT WILL RUN AFTER 1 MINUTE, for testing reasons...)
'for running after 2 hours you should change "00:01:00" in "02:00:00":
arr(0) = Replace(arr(0), "'", "''") 'escape simple quote (') character'
fromPath = Replace(arr(2), "\\\\", "\")
Dim rngFrom As Range: Set rngFrom = ThisWorkbook.Sheets("Folders").Range("A:A").Find(what:=fromPath)
toPath = rngFrom.Offset(, 1).Value
Application.OnTime CDate(arr(1)) + TimeValue("00:00:30"), "'DoSomething """ & fromPath & "\" & CStr(arr(0)) & """, """ & toPath & CStr(arr(0)) & """'"
Debug.Print Now; " start " & arr(0) & fromPath & "\" & CStr(arr(0)) 'just for testing (wait a minute...)
'finaly, this line should be commented.
End Sub
Sub DoSomething(sourceFileName As String, destFilename As String)
If Dir(destFilename) = "" Then
Name sourceFileName As destFilename
Debug.Print sourceFileName & " moved to " & destFilename 'just for testing...
Else
Debug.Print "File """ & destFilename & """ already exists in this location..."
End If
End Sub
Sub DoSomething_(strFileName As String) 'cancelled
If Dir(toPath & strFileName) = "" Then
Name fromPath & strFileName As toPath & strFileName
Debug.Print strFileName & " moved from " & fromPath & " to " & toPath 'just for testing...
Else
MsgBox "File """ & toPath & strFileName & """ already exists in this location..."
End If
End Sub
So, you only need to replace the existing VBA code with the above adapted one, to place the 'source'/'destination' paths in columns A:B of one of Excel sheets, which to be named "Folders".
Select in column A:A a 'Source' cell and run startMonitoring.
Play with files creation and check their moving from the new 'source' to the new 'destination'...
But you have to understand that only a session of the WMI class can run at a specific moment. This means that you cannot simultaneously monitor more than one folder...
I am still documenting regarding the possibility to use a query able to be common for multiple folders. But I never could see such an approach till now and it may not be possible...

VBA Excel Ignores PrintArea Pdf

I have 250 excel documents where I try to print a sheet for pdf. If I do it manually, it will be 4 pages, but if I use my code, it will be 7 pages long.
It's like it ignores the print area, and makes several blank pages.
Can any of you figure out the mistake?
Dim wb As Workbook
Dim xExtension As String: xExtension = "*.xls*"
Dim xFolder As String: xFolder = [MailFolder]
Dim xFile As String: xFile = Dir(xFolder & xExtension) 'DIR gets the first file of the folder
Dim Rng As Range: Set Rng = Range("A1")
Dim s As String
Do While xFile <> "" 'Loop through all files in a folder until DIR cannot find anymore
Set wb = Workbooks.Open(xFolder & xFile): wb.Activate
Call WorksheetsToPDF(wb, "F:\VBA\PDF\Udlejning\" & CleanFileName("Police - " & "2021 -" & [KompletPoliceNr] & " - " & [Forsikringstager]) & ".pdf", "Certifikat")
'Call WorksheetsToPDF(wb, "F:\VBA\KF Begæringer\" & CleanFileName("KF Begæring-2021-" & [KompletPoliceNr] & "-" & [Forsikringstager]) & ".pdf", "Police")
wb.Close savechanges:=False
xFile = Dir()
Loop
End Sub
Private Sub WorksheetsToPDF(wb As Workbook, DistinationPath As String, ParamArray Arr() As Variant)
wb.Sheets(Arr()).Select
Debug.Print EFDK.GetNextavailablefilename(DistinationPath)
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, FileName:=EFDK.GetNextavailablefilename(DistinationPath), Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False
End Sub
Private Function GetNextAvailableFilename(ByVal xPath As String) As String
With CreateObject("Scripting.FileSystemObject")
Dim strFolder As String, strBaseName As String, strExt As String, i As Long
strFolder = .GetParentFolderName(xPath)
strBaseName = .GetBaseName(xPath)
strExt = .GetExtensionName(xPath)
Do While .FileExists(xPath)
i = i + 1
xPath = .BuildPath(strFolder, strBaseName & " - " & i & "." & strExt)
Loop
End With
GetNextAvailableFilename = xPath
End Function
You did not answer my clarification questions...
Just for the sake of testing, please try the next adapted function:
Private Sub WorksheetsToPDF(wb As Workbook, DistinationPath As String, ParamArray arr() As Variant)
Dim El
wb.Sheets(arr()).Select
For Each El In arr()
wb.Sheets(El).PageSetup.FitToPagesWide = 1
wb.Sheets(El).PageSetup.PaperSize = xlPaperA4 ' xlPaperLetter
wb.Sheets(El).PageSetup.Orientation = xlLandscape
Next
'Debug.Print EFDK.GetNextavailablefilename(DistinationPath)
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, FileName:=EFDK.GetNextavailablefilename(DistinationPath), Quality:=xlQualityStandard, IncludeDocProperties:=True
End Sub

Correct Excel Macro to Save A Copy Excel File as TXT or CSV

So I have this home-made Excel Macro Template.
The task of the macro code that I inserted in my xlsm file is to Save a copy in the same folder with a different format. That format is .txt (see image below)
The expected result of the macro (after saving) should be the same with the excel file (visually) but this time it is in a .txt format.
Unfortunately, that didn't happened. It generates a different txt file and it contains unreadable alpha numeric characters, here's an example of the generated txt file.
¬TËNÃ0 ¼#ñ ‘¯(vဠjÚ # °µ· ©c[^SÚ¿g“–
P ö '±wfvìq 8o\1ÃD6øJœËž(Ðë`¬ŸTâõå¾¼ eð \ðX‰ ’ NOú/‹ˆTpµ§JÔ9Çk¥H×Ø É ÑóÌ8¤ 2 ¦‰Š §0AuÑë]* |FŸËÜbˆAÿ Çðîrq7çßK%#ëEq³\×RU btVCf¡jæ l¨ã±Õ(g#xJá
u j#XBG{Ð~J.Wr%WvŒTÛHgÜÓ †vf»ÜUÝ#ûœ¬Áâ R~€†›Rs§>BšŽB˜ÊÝ «žq®ÑIª ³l#§pçaä ý ë¿ î`ê*IuÃù ( ³´Ü ýÞð JŠ Át` “m'Ýû ™ ªîy¸„ f !å…C:r·KÐ}Ì5$4Ï9q Ž.à;ö. ¼] H ¼„ÿwá+mu S¶¸ŽÃ¦Ã¶fäÔ l;¶×‚A³ [u×Ðà ÿÿ PK ! µU0#ô L _rels/.rels ¢ (
Here's my macro code:
Sub SaveMe()
Dim FName As Range
Dim firstDate As String
Dim firstTime As String
Dim answer As Integer
firstDate = Format(Date, "mmddyyyy")
firstTime = Format(Now, "hhmmssAM/PM")
Set FName = Range("H5")
ActiveWorkbook.SaveCopyAs FileName:=ActiveWorkbook.Path & "\" & "QB JE " & FName & " " & firstDate & " " & firstTime & ".txt", FileFormat:=xlText, CreateBackup:=False
End Sub
I was wondering if anyone could take a look at my code and help to point out whats wrong.
It looks like you want the SaveAs Not the SaveCopyAs.
Fileformat xlText or xlTextMSDOS
You can two step the process. Save a copy, then open it, and save it as a text file.
ActiveWorkbook.SaveCopyAs FileName:=ActiveWorkbook.Path & "\" & "QB JE " & FName & " " & firstDate & " " & firstTime & ".xlsx"
Workbooks.Open (ActiveWorkbook.Path & "\" & "QB JE " & FName & " " & firstDate & " " & firstTime & ".xlsx")
ActiveWorkbook.SaveAs FileName:=ActiveWorkbook.Path & "\" & "QB JE " & FName & " " & firstDate & " " & firstTime & ".txt", FileFormat:=xlText, CreateBackup:=False
https://msdn.microsoft.com/en-us/library/office/ff841185.aspx
https://msdn.microsoft.com/en-us/library/office/ff198017.aspx
See from my post here. Excel VBA Export To Text File with Fixed Column Width + Specified Row and Columns Only + Transpose
Loop all rows and all cells. Send each value to a padspace function. Build the string from for each cells value with spaces padded after the cell value.
You will have to add a reference to you workbook. In the VBA IDE go to the tools pull down menu and select references. Then scroll down and select "Microsoft Scripting Runtime". Then hit OK.
Adjust the pad space function call argument to a number that fits the data that you have in your spreadsheet. So you will change the 20 in the line with the padspace call. PadSpace(20, len(cellValue))
This will do all rows and columns.
Public Sub MyMacro()
Dim lRow As Long
Dim lCol As Long
Dim strRow As String
Dim ws As Excel.Worksheet
Dim ts As TextStream
Dim fs As FileSystemObject
'Create the text file to write to
Set fs = New FileSystemObject
Set ts = fs.CreateTextFile("C:\Temp\test.txt", True, False)
Set ws = Application.ActiveSheet
'Loop through all the rows.
lRow = 1
Do While lRow <= ws.UsedRange.Rows.count
'Clear the string we are building
strRow = ""
'Loop through all the columns for the current row.
lCol = 1
Do While lCol <= ws.UsedRange.Columns.count
'Build a string to write out.
strRow = strRow & ws.Cells(lRow, lCol) & PadSpace(20, Len(ws.Cells(lRow, lCol)))
lCol = lCol + 1
Loop
'Write the line to the text file
ts.WriteLine strRow
lRow = lRow + 1
ws.Range("A" & lRow).Activate
Loop
ts.Close: Set ts = Nothing
Set fs = Nothing
End Sub
'This function will take the max number of spaces you want and the length of the string in the cell and return you the string of spaces to pad.
Public Function PadSpace(nMaxSpace As Integer, nNumSpace As Integer) As String
If nMaxSpace < nNumSpace Then
PadSpace = ""
Else
PadSpace = Space(nMaxSpace - nNumSpace)
End If
End Function

How to use arrays to access files in folder in vba?

had some troubles with this code. It actually is intended to allocate values to the dir1array(ctr1) and dir2array(ctr2) by looping thru all the files in the directory/folder; Is there a way to make this array work ?
Option Explicit
'*********************************************************************
'* Verify if files have the same name before proceeding to compare *
'* their length *
'* DYNAMIC ARRAYs *
'*********************************************************************
Sub findMatchFilenames()
'Dim fso As fileSystemObject
Dim objMapinfo
Dim fso As New Scripting.FileSystemObject
Dim dir1 As Folder
Dim dir2 As Folder
Dim file1 As File
Dim file2 As File
Dim dir1array() As String
Dim dir2array() As String
ReDim dir1array(0 To 100) As String
ReDim dir2array(0 To 100) As String
Dim ctr1 As Integer
Dim ctr2 As Integer
Dim lLen1 As Long, lLen2 As Long
Dim myFile As String, text As String, textline As String
Set fso = New FileSystemObject
Set dir1 = fso.GetFolder("c:\Temp\")
Set dir2 = fso.GetFolder("c:\Tempo\")
ctr1 = 0
For Each file1 In dir1.Files
ctr2 = 0
For Each file2 In dir2.Files
dir1array(ctr1) = file1.Name
dir2array(ctr2) = file2.Name
If dir1array(ctr1) = dir2array(ctr2) Then
MsgBox "" & dir1array(ctr1) & "" & dir2array(ctr2)
Debug.Print file1.Name & " matches " & file2.Name
lLen1 = FileLen(file1)
lLen2 = FileLen(file2)
If lLen1 <> lLen2 Then
Exit Sub
Else
MsgBox "The files have the same length"
End If
End If
ctr2 = ctr2 + 1
Next file2
ctr1 = ctr1 + 1
Next file1
Close #1
End Sub
The following is a variation of your code, but does not use arrays.
Option Explicit
Sub findMatchFilenames()
Dim lLen1 As Long
Dim lLen2 As Long
Dim oFSO As New Scripting.FileSystemObject
Dim dir1 As Folder
Dim dir2 As Folder
Dim oFile1 As File
Dim oFile2 As File
Dim strFolder1 As String
Dim strFolder2 As String
Close #1 ' I always close first when testing (in case I don't get to normal close)
Close #2
Open "C:\Temp\" & Format(Now(), "_SAME_yyyy-mm-dd_hh-mm") & ".txt" For Output As #1
Open "C:\Temp\" & Format(Now(), "_Different_yyyy-mm-dd_hh-mm") & ".txt" For Output As #2
Set oFSO = New FileSystemObject
strFolder1 = "c:\Temp\"
strFolder2 = "c:\Tempo\"
Set dir1 = oFSO.GetFolder(strFolder1)
Set dir2 = oFSO.GetFolder(strFolder2)
For Each oFile1 In dir1.Files
If oFSO.FileExists(strFolder2 & oFile1.Name) Then ' If it matches same name
Set oFile2 = oFSO.GetFile(strFolder2 & oFile1.Name)
If oFile1.Size = oFile2.Size Then
Print #1, oFile1.Name & vbTab & "File found in both folders; Size is the same;"
Debug.Print oFile1.Name & vbTab & "File found in both folders; Size is the same;"
Else
Print #1, oFile1.Name & vbTab & "Found in both folders; Size is DIFFERENT; " & oFile1.Size & " vs: " & oFile2.Size
Debug.Print oFile1.Name & vbTab & "Found in both folders; Size is DIFFERENT; " & oFile1.Size & " vs: " & oFile2.Size
End If
Else ' Same file not found.
Debug.Print "File not present in 2nd folder: " & oFile1.Name
Print #1, oFile1.Name & vbTab & "File NOT found in second folder;"
End If
Next oFile1
Set oFile1 = Nothing
Set oFile2 = Nothing
Set oFSO = Nothing
Close #1
Close #2
End Sub