MS Word VBA - open file with parameters, string longer than 255 chracters - vba

I'm developing a MS Word macro which needs to open a file on a network drive and pass it the calling file's path as a parameter (i can then retrieve the parameters in the opened file using this method http://www.vbaexpress.com/forum/archive/index.php/t-21174.html).
What i am trying to achieve is the following:
1. Document X (any MS word document) calls document Y (macro document)
2. Document Y processes document X (using the Document object)
3. Document Y closes
The reason i am doing step 1 above is do that users don't have to deploy complex vba code (i am dealing with non IT literate users) and the ease of making updates and enhancements to the code if required.
The following code snippet opens the file with parameters:
Dim currentFilePath As String
currentFilePath = ThisDocument.Path & ThisDocument.Name
Dim MacroFilePath As String
MacroFilePath = ThisDocument.Path & "\Test.docm"
MacroFilePath = """" & MacroFilePath & """" & currentFilePath
Documents.Open (MacroFilePath)
The value of 'MacroFilePath' is gets setup like this (263 chars):
“\\XXXXXXXXXXXX\XX_XX\XXX_XXX XXXX procedural documentation\XX Design Support\Macros - DO NOT MOVE\Work in progress\Calling Document.docm” \\XXXXXXXXXXXX\XX_XX\XXX_XXX XXXX procedural documentation\XX Design Support\Macros - DO NOT MOVE\Work in progress\Test.docm
When I run the above code the error Run-Time '9105': String is longer than 255 characters occurs. I have tested the code where i moved the files to a shorter directory and it works. Is there a way to get around this or another way of achieving what i am trying to do?
Shorting the file paths by saving the documents elsewhere, changing the language i am programming in, or creating any kind of executable is not an option as i am in an enterprise environment.

X can open Y, then call a procedure in Y and pass in it's own path as a parameter.
You can use Application.Run to do this.
See:
https://msdn.microsoft.com/en-us/library/office/ff838935.aspx
Here's the example from that link:
Dim strTemplate As String
Dim strModule As String
Dim strMacro As String
Dim strParameter As String
strTemplate = InputBox("Enter the template name")
strModule = InputBox("Enter the module name")
strMacro = InputBox("Enter the macro name")
strParameter = InputBox("Enter a parameter value")
Application.Run MacroName:=strTemplate & "." _
& strModule & "." & strMacro, _
varg1:=strParameter

Related

VBA runtime error 3625 The text file specification Export_Spec does not exist

I am running Access 2016. I am trying to export the results of a query into a text file, I keep on getting an error 3625 no spec is found. I created the spec and if I run the spec it works as expected. I tried putting quotes instead of the export spec, but there was no formatting on the file. The solutions I found on the web were saying to use the advanced tab to define formatting, On my version of Access 2016 there is no advanced tab in the spec creation process. I have stepped through the process and all the directories and the file name is created properly.
The error occurs on the line :
DoCmd.TransferText TransferType:=acExportDelim, SpecificationName:=strExportSpec, TableName:=strQueryName, FileName:=strFullName, HasFieldNames:=True
Any help is appreciated.
Private Sub Export_Click()
Dim strFileName As String
Dim lFileName As Long
Dim strCurrentDate As String
Dim strFormattedDate As String
Dim dtCurrentDate As Date
Dim strDir As String
Dim strFullName As String
Dim strExportSpec As String
Dim strQueryName As String
Dim strYear As String
Dim strMonth As String
Dim strPath1 As String
Dim strPath2 As String
strYear = Format(Date, "yyyy")
strMonth = Format(Date, "mm")
'Check if Directory Year exists
strPath1 = "C:\Users\Owner\Google Drive\Employment\Mass Unemployment\" & strYear
'Check if year exists
If Dir(strPath1, vbDirectory) = "" Then
MkDir strPath1
End If
'Create
strPath2 = "C:\Users\Owner\Google Drive\Employment\Mass Unemployment\" & strYear & "\" & strMonth & "\"
If Dir(strPath2, vbDirectory) = "" Then
MkDir strPath2
End If
strCurrentDate = Date
strFormattedDate = Format(strCurrentDate, "mmddyyyy")
lFileName = InputBox("Enter Week Number", "Enter Week Number")
strFileName = strFormattedDate
strFullName = strPath2 & strFileName & ".txt"
strExportSpec = "Export_Spec" ' error 3625 export spec does not exist
strQueryName = "qryUnEmployment"
DoCmd.TransferText TransferType:=acExportDelim, SpecificationName:=strExportSpec, TableName:=strQueryName, FileName:=strFullName, HasFieldNames:=True
End Sub
I believe what Parfait is telling you is that the Saved Import/Saved Exports are far different than an Import/Export Specification. You are trying to put a Saved Export into the TransferText parameter where a Specification is called for. You likely did an export at some point and saved the steps as a Saved Export.
If you're truly interested in using a specification for this export then you will want to create one by walking through the import of an already existing text file in the format you would like. See Parfait answer above.
Otherwise, just leave the specification parameter blank and the query will be exported.
The Save Import/Export GUI frontend feature and the backend method, DoCmd.TransferText refer to different specification types. The former is more a saved routine as a convenience method to retrieve the same named text, spreadsheet, or XML file and all the steps to import or export the external data and avoid the walk through of wizard in future runs.
However, the latter is specific to formatting of any text file and it is usually created during the text file wizard under Advanced button. See screenshot below. In this dialog you can specify formats for each field, delimiters, etc. and then either run the specification one time or Save As... for future uses on any text file. In fact, Specs... shows a current list of all saved named specifications. It is here where you can find the name to use in DoCmd.TransferText.
Import Text Wizard
Export Text Wizard
To date, there may not be any other GUI way to adjust these saved specifications. They are stored in system tables, MSysIMEXspecs and MSysIMEXColumns. Again, do not confuse above text file specific method for the generalized external data methods: ImportExportSpecifications and DoCmd.RunSavedImportExport.

Add a path to a code VB.net / visual basic

how do I add a path to a code where "HERE_HAS_TO_BE_A_PATH" is. When I do, Im getting an error message. The goal is to be able to specific the path where is the final text file saved.
Thanks!
Here is a code:
Dim newFile As IO.StreamWriter = IO.File.CreateText("HERE_HAS_TO_BE_A_PATH")
Dim fix As String
fix = My.Computer.FileSystem.ReadAllText("C:\test.txt")
fix = Replace(fix, ",", ".")
My.Computer.FileSystem.WriteAllText("C:\test.txt", fix, False)
Dim query = From data In IO.File.ReadAllLines("C:\test.txt")
Let name As String = data.Split(" ")(0)
Let x As Decimal = data.Split(" ")(1)
Let y As Decimal = data.Split(" ")(2)
Let z As Decimal = data.Split(" ")(3)
Select name & " " & x & "," & y & "," & z
For i As Integer = 0 To query.Count - 1
newFile.WriteLine(query(i))
Next
newFile.Close()
1) Use a literal string:
The easiest way is replacing "HERE_HAS_TO_BE_A_PATH" with the literal path to desired output target, so overwriting it with "C:\output.txt":
Dim newFile As IO.StreamWriter = IO.File.CreateText("C:\output.txt")
2) Check permissions and read/write file references are correct:
There's a few reasons why you might be having difficulties, if you're trying to read and write into the root C:\ directory you might be having permissions issues.
Also, go line by line to make sure that the input and output files are correct every time you are using one or the other.
3) Make sure the implicit path is correct for non-fully qualified paths:
Next, when you test run the program, it's not actually in the same folder as the project folder, in case you're using a relative path, it's in a subfolder "\bin\debug", so for a project named [ProjectName], it compiles into this folder by default:
C:\path\to\[ProjectName]\bin\Debug\Program.exe
In other words, if you are trying to type in a path name as a string to save the file to and you don't specify the full path name starting from the C:\ drive, like "output.txt" instead of "C:\output.txt", it's saving it here:
C:\path\to\[ProjectName]\bin\Debug\output.txt
To find out exactly what paths it's defaulting to, in .Net Framework you can check against these:
Application.ExecutablePath
Application.StartupPath
4) Get user input via SaveFileDialogue
In addition to a literal string ("C:\output.txt") if you want the user to provide input, since it looks like you're using .Net Framework (as opposed to .Net Core, etc.), the easiest way to set a file name to use in your program is using the built-in SaveFileDialogue object in System.Windows.Forms (like you see whenever you try to save a file with most programs), you can do so really quickly like so:
Dim SFD As New SaveFileDialog
SFD.Filter = "Text Files|*.txt"
SFD.ShowDialog()
' For reuse, storing file path to string
Dim myFilePath As String = SFD.FileName
Dim newFile As IO.StreamWriter = IO.File.CreateText(myFilePath) ' path var
' Do the rest of your code here
newFile.Close()
5) Get user input via console
In case you ever want to get a path in .Net Core, i.e. with a console, the Main process by default accepts a String array called args(), here's a different version that lets the user add a path as the first parameter when running the program, or if one is not provided it asks the user for input:
Console.WriteLine("Hello World!")
Dim myFilePath = ""
If args.Length > 0 Then
myFilePath = args(0)
End If
If myFilePath = "" Then
Console.WriteLine("No file name provided, please input file name:")
While (myFilePath = "")
Console.Write("File and Path: ")
myFilePath = Console.ReadLine()
End While
End If
Dim newFile As IO.StreamWriter = IO.File.CreateText(myFilePath) ' path var
' Do the rest of your code here
newFile.Close()
6) Best practices: Close & Dispose vs. Using Blocks
In order to keep the code as similar to yours as possible, I tried to change only the pieces that needed changing. Vikyath Rao and Mary respectively pointed out a simplified way to declare it as well as a common best practice.
For more information, check out these helpful explanations:
Can any one explain why StreamWriter is an Unmanaged Resource. and
Should I call Close() or Dispose() for stream objects?
In summary, although streams are managed and should garbage collect automatically, due to working with the file system unmanaged resources get involved, which is the primary reason why it's a good idea to manually dispose of the object. Your ".close()" does this. Overrides for both the StreamReader and StreamWriter classes call the ".dispose()" method, however it is still common practice to use a Using .. End Using block to avoid "running with scissors" as Enigmativity puts it in his post, in other words it makes sure that you don't go off somewhere else in the program and forget to dispose of the open filestream.
Within your program, you could simply replace the "Dim newFile As IO.StreamWriter = IO.File.CreateText("C:\output.txt")" and "newFile.close()" lines with the opening and closing statements for the Using block while using the simplified syntax, like so:
'Dim newFile As IO.StreamWriter = IO.File.CreateText(myFilePath) ' old
Using newFile As New IO.StreamWriter(myFilePath) ' new
Dim fix As String = "Text from somewhere!"
newFile.WriteLine(fix)
' other similar operations here
End Using ' new -- ensures disposal
'newFile.Close() ' old
You can write that in this way. The stream writer automatically creates the file.
Dim newFile As New StreamWriter(HERE_HAS_TO_BE_A_PATH)
PS: I cannot mention all these in the comment section as I have reputations less than 50, so I wrote my answer. Please feel free to tell me if its wrong
regards,
vikyath

Copy file with progress bar bypass file replacement confirmation

This is a follow up to this question and great answer:
Copy files with progress bar
So I added the code from Siddharth Rout's answer and it does exactly what I want to happen with a minor exception. When I copy the files, I am looping through each file in the directory and copying it up as long as it is not *List.xml. Because I am replacing an existing library the 97% of the documents are pre-existing and I get prompted to replace existing documents each time.
Is there a way to get it to prompt me to choose to replace for all files? Do I need to reformat/structure the sequence of my code?
Function UploadToSharepoint(Folderpath As String, Foldername As String, Filenames() As String, SharepointLinks() As String) As Boolean
'upload file to sharepoint library based on the folder name
Dim SharePointLib As String
Dim LocalAddress As String
Dim DestinationAddress As String
Dim xCounter As Long
On Error GoTo loadFailed
Pickafolder:
Folderpath = FolderPick
Foldername = Left(Folderpath, Len(Folderpath) - 1)
Foldername = RIght(Foldername, Len(Foldername) - InStrRev(Foldername, "\"))
Select Case Foldername
Case "OPSS", "SSP", "OPSD", "MTOD", "SSD"
SharePointLib = "\\my.company.com\Subsite\" & Foldername & "\"
Case "West", "Eastern", "Northeastern", "Northwestern", "Head Office"
SharePointLib = "\\my.company.com\Subsite\NSP\" & Foldername & "\"
Case "NSP", "NSSP"
MsgBox "Pick the NSP regional sub folder: West, Eastern, Northeastern, Northwestern, Head Office"
GoTo Pickafolder
Case Else
MsgBox "Inappropriate directory to upload from. Please select one of the CPS download directories"
GoTo Pickafolder
End Select
Filenames = GetFilesDir(Folderpath)
ReDim SharepointLinks(LBound(Filenames) To UBound(Filenames))
For xCounter = LBound(Filenames) To UBound(Filenames)
LocalAddress = Folderpath & Filenames(xCounter)
DestinationAddress = SharePointLib & Filenames(xCounter)
'**********************************************************
Call VBCopyFolder(LocalAddress, DestinationAddress)
'**********************************************************
SharepointLinks(xCounter) = "#http:" & Replace(DestinationAddress, "\", "/") & "#"
Next xCounter
UploadToSharepoint = True
Exit Function
loadFailed:
UploadToSharepoint = False
End Function
And by the looks of things I am not excluding the file I was referring to earlier...must be doing that else where.
Update
Based on comment received at the linked question, the solution is to declare a public constant at the start:
Public Const FOF_NOCONFIRMATION As Long = &H10
and then in the copy procedure change the line of code to:
.fFlags = FOF_SIMPLEPROGRESS Or FOF_NOCONFIRMATION
Now, this does solve the problem of being constantly asked to confirm the replacement. I am very happy about this. The problem now is the progress window displays for the first file to be copied then disappears but fails to reappear for subsequent files. The remaining files still get copied and the prg carries on like it's supposed to. The whole point of the progress bar though was to let people know that "THINGS" were still happening in the background and now that is not happening. Is there something I need to adjust?
Update 2
After running my code and choosing a source directory on the network drive instead of the local computer, the copy window is popping up for every single file like I was expecting. I notice that sometimes the progress bar closes before reaching 100%. This leads me to believe that since the file sizes are so small that when it is copying from my local drive to sharepoint, the operation completes so fast that it does not have time to draw and update the progress window before its time to close it.

How do I fix my VBA renaming program's 0 return?

I am open to completely changing this code. The link to the original is in the code itself. I'm sure there's an easier way to do it and the actual renaming part is NOT my own code, so I will redo it so it isn't plagiarizing. I can't use a batch file renamer to do it; I need to make it myself to stay out of trouble with legal :) No grey area!
Anyways, after a few dozen attempts on my own, I finally caved and grabbed this code online that is supposed to rename the files I specify. I edited it to fit my parameters and assigned variables/directories. When I run it, however, I always get a return of zero and the files are not being renamed. The one thing I could think of is that this directory is going to the full path name of the folder instead of the part after the last "\". But I'm not sure how to fix this either. I thought about trying to tell it to only tell it to pull, say the last 8 characters of the string, but that won't work either as these string lengths will vary anywhere from one character to 20 or so characters.
Here is my code:
Private Sub Apply_Click()
'This will initiate Module 1 to do a batch rename to find and replace all
'Module 1 will then initiate the resolving links process
Dim intResponse As Integer 'Alerts user to wait until renaming is complete
intResponse = MsgBox("Your folders are being updated. Please wait while your files are renamed and your links are resolved.")
If intResponse = vbOK Then 'Tests to see if msgbox_click can start a new process
Dim i As Integer
Dim from_str As String
Dim to_str As String
Dim dir_path As String
from_str = Old_Name_Display.Text
to_str = New_Name.Text
dir_path = New_Name.Text
If Right$(dir_path, 1) <> "\" Then dir_path = dir_path _
& "\"
Old_Name_Display = dir$(dir_path & "*.*", vbNormal)
Do While Len(Old_Name_Display) > 0
' Rename this file.
New_Name = Replace$(Old_Name_Display, from_str, to_str)
If New_Name <> Old_Name_Display Then
Name Old_Name_Display.Text As New_Name.Text
i = i + 1
End If
' Get the next file.
Old_Name_Display = dir$()
Loop
MsgBox "Renamed " & Format$(i) & " files. Resolving links now."
If intResponse = vbOK Then
MsgBox "You selected okay. Good luck coding THIS." 'Filler line to test that next step will be ready to initialize
Else: End
End If
Exit Sub
'Most of batch renaming process used from VB Helper, sponsored by Rocky Mountain Computer Consulting, Inc. Copyright 1997-2010; original code available at http://www.vb-helper.com/howto_rename_files.html
End Sub
Does anyone have another theory on why I get a 0 return/how to fix that potential above problem?
It doesn't look like the directory is getting referenced in the rename.
Change
Name Old_Name_Display.Text As New_Name.Text
to
Name Dir_Path & Old_Name_Display.Text As Dir_Path & New_Name.Text

Issue with an LPR Command in VB

I am creating a VB app which will "move" xls reports from a directory to a ReportSafe app. I am also working in an existing VB app which does just that, so I am using it for reference.
It isn't as simple as moving files from one directory to another, because ReportSafe requires an lpr command to tell it (ReportSafe) which file to pick up.
Here is what I have so far:
Imports System.IO
Module Module1
Sub Main()
''Declarations
Dim Files As ArrayList = New ArrayList()
Dim FileName As String
''Write All Files in *directory* to ReportSafe
Files.Clear()
Files.AddRange(Directory.GetFiles(*directory*))
For Each FileName In Files
Dim RPname As String
Dim RealName As String
RPname = FileName.ToString
RealName = "/"
RealName = RealName & RPname.Remove(0, 34)
Dim a As New Process
a.StartInfo.FileName = "C:\Windows\system32\lpr.exe"
a.StartInfo.Arguments = "-S*ServerName* -Plp -J" & Chr(34) & RealName & Chr(34) & " " & Chr(34) & RPname & Chr(34)
a.StartInfo.UseShellExecute = False
Next
End Sub
End Module
The whole lpr command/arguments are throwing me for a loop. I'm not sure if my question is specific to ReportSafe, and if that's the case, I may be out of luck here. I have pulled this code from the already existing app which moves reports to ReportSafe, and adjusted for my own use, but no luck so far.
FYI, I had to turn on LPR Monitor services to obtain to the lpr.exe
Questions:
What are the proper arguments to pass through to this lpr command?
Is there a problem with the logic that is causing the issue?
I continued to tinker and look at my reference code and discovered some flaws in logic:
For one, the report name I was passing did not include the complete file path.
Another thing is that I never started the process with a.Start(). Rookie mistakes for sure... haha