VBA not specific user name when exporting PDF - vba

I have a working code below opening and saving a PDF file for 1 specific user to documents folder.
The issue I do not know is how to replace specific user name like SmithJoe with any other user. The code should be used by more users. Now it doesn´t work when for example TaylorRog tries to use the code. It is working for SmithJoe only.
Is there any possibility to replace specific user "SmithJoe" with all users?
Sheets("ABC").Range("G8:j18").ExportAsFixedFormat Type:=xlTypePDF, Filename:= _ "C:\Users\SmithJoe\Documents\fileA.pdf", Quality:= _ xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, _ OpenAfterPublish:=True
Thank you in advance

To get the content of an Windows environment variable, use the function Environ.
To get the username, use Environ("USERNAME").
But note that there are cases where the name of the folder is not equal to the name of the user or the location of the folder is different from C:\Users. It's better to use Environ("USERPROFILE") - in your case that should return C:\Users\SmithJoe.
But of course that's not the full story. The documents-folder could have a different name or it could be in a different place. To be on the save side, you need to query the folder. There are several ways to do so, I found the following method the easiest:
Function GetSystemFolder(folderID) As String
On Error Resume Next
Dim f
Set f = CreateObject("Shell.Application").namespace(folderID)
On Error GoTo 0
If Not f Is Nothing Then GetSystemFolder2 = f.Self.path
End Function
The parameter folderID tells the function which folder you want, the document folder has the value 5. A list of all ids can be found at Microsoft.
You code could look like this
Const ssfPERSONAL = &H5
...
Dim pdfFilename as String
pdfFilename = GetSystemFolder(ssfPERSONAL) & "\fileA.pdf"
Sheets("ABC").Range("G8:j18").ExportAsFixedFormat Type:=xlTypePDF,
Filename:= pdfFilename , Quality:= xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, _
OpenAfterPublish:=True

thanks a lot.
May I have another question? To make the code work, I need to:
create this function:
Function GetSystemFolder(folderID) As String
create the Sub macro with the code
Const ssfPERSONAL = &H5
...
Dim pdfFilename as String
pdfFilename = GetSystemFolder(ssfPERSONAL) & "\fileA.pdf" etc.
What content should be instead of the three dots? Const ssfPERSONAL = &H5 ... Dim pdfFilename as String
I am trying to solve it myself but did not succeed.
Thank you.

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.

Search and Match Partial Folder Name in Access VBA

I've looked at the top results when typing in the Title of this question, and I hit a dead end...
I have a list of customers, and each customer gets a Job Number [Job_Ref__]. In conjunction with this, each customer gets a folder in SharePoint for all of their documents. The naming convention is Job Number - Last Name, First Name. I want to be able to click a button on my Access form that opens the customer's specific folder, but it keeps opening "My Documents" on my local disk instead.
I've tried the below code without the customer's folder details, and it opens the root of the SharePoint 'drive' with no issue...
Below is what works when I click my OPEN FOLDER button on the form:
Private Sub Command232_Click()
Dim folderName As String
Dim folderfullPath As String
folderName = Me.FilePath
folderfullPath = "C:\Users\" & Environ("Username") & "\SharePoint Site\Customers 2020\"
Call Shell("explorer.exe " & folderfullPath, vbNormalFocus)
End Sub
When I use folderName is when I hit the issue; I've tried to wildcard the folder name, but to no avail:
Private Sub Command232_Click()
Dim folderName As String
Dim folderfullPath As String
folderName = Me.FilePath
folderfullPath = "C:\Users\" & Environ("Username") & "\SharePoint Site\Customers 2020\"
Call Shell("explorer.exe " & folderfullPath & folderName & "*", vbNormalFocus)
End Sub
Any help would be GREATLY appreciated, as I've hit a pretty big brick wall.
Of note: I tried to define folderName = Job_Ref__, but I figured that was too vague, so I added a FilePath field with macros in the Access Form that builds the customer's folder name Job_Ref__ - Last Name, First Name
None of this has worked - am I doing too much with this? XD
Windows allows comma in file name but Shell() function does not like. Options:
don't use comma in file name and use Replace() function in VBA to eliminate comma from field value to match file name
use FollowHyperlink to open folder - it does accept comma
FollowHyperlink(folderfullPath & folderName)

In vb.net, how do I use directory info with specific files name in the query

Lets say I have a list of files separated by a comma.
Dim listOfFiles As String() = filesPosted.Split(",")
And I use DirectoryInfo to grab that list of files and send it to another array.
Dim files = New DirectoryInfo(StorageRoot) _
.GetFiles("*", SearchOption.TopDirectoryOnly) _
.Where(Function(f) Not f.Attributes.HasFlag(FileAttributes.Hidden)) _
.Where(Function(f) filesPosted.Contains(f.Name)) _
.[Select](Function(f) New FilesStatus(f)).ToArray()
The problem I'm facing is, I need my condition to be more strict. I'll explain:
If my listOfFiles contains ( abc.txt, xyz.txt ) and there's a filename of aabc.txt in the directory that is being searched, it'll return both abc.txt and aabc.txt. I know this is because of this part of the clause:
.Where(Function(f) filesPosted.Contains(f.Name))
As the contains attribute is finding this other file... But I don't want it. I want the files to match exactly based on the string().
Is there a better way to do this without cycling through each file? A tighter way to make it a strict condition on "Contains" ?
Thank you for your help!
Try:
Dim listOfFiles As String() = filesPosted.Split(",").Select(function(f) f.ToLower())
' then
Dim files = New DirectoryInfo(StorageRoot) _
.GetFiles("*", SearchOption.TopDirectoryOnly) _
.Where(Function(f) Not f.Attributes.HasFlag(FileAttributes.Hidden)) _
.Where(Function(f) listOfFiles.Any(function(l) l = f.Name.ToLower())) _
.[Select](Function(f) New FilesStatus(f)).ToArray()
Sorry, poor C# to VB.Net conversion

Moving Multiple Files of Same Type

I need to be able to move all .pbo files from one folder, into another folder. The following is my code:
For Each foundPBO As String In My.Computer.FileSystem.GetFiles( _
downloadDirectory & "\Mod Works\Process\#" & CurrentMod, _
FileIO.SearchOption.SearchAllSubDirectories, "*.pbo")
My.Computer.FileSystem.MoveFile(foundPBO, downloadDirectory & "\Mod Works\Process\#STHUD\Addons")
Next
It doesn't do anything when I run it, and the directory strings are correct (downloadDirectory is set correctly & CurrentMod is set correctly)
Any suggestions?
UPDATE:
Thanks for the help, although, I'm getting an error with conversion? Here's my following code, it doesn't get to the "3" message (debug):
Dim testDir As String = downloadDirectory & "\Mod Works\Process\#STHUD\"
For Each foundPBO As String In My.Computer.FileSystem.GetFiles( _
MsgBox("2"), _
testDir, _
MsgBox("3"), _
FileIO.SearchOption.SearchAllSubDirectories, "*.pbo")
MsgBox("4")
My.Computer.FileSystem.MoveFile(foundPBO, downloadDirectory & "\Mod Works\Process\#STHUD\Addons\" & System.IO.Path.GetFileName(foundPBO))
MsgBox("5")
Next
The destination path is wrong: you are intending to move "dir_source\file_source.pbo" to "dir_dest\"; but you should do: "dir_dest\file_source.pbo". Just replace
My.Computer.FileSystem.MoveFile(foundPBO, downloadDirectory & "\Mod Works\Process\#STHUD\Addons")
with:
My.Computer.FileSystem.MoveFile(foundPBO, downloadDirectory & "\Mod Works\Process\#STHUD\Addons\" & System.IO.Path.GetFileName(foundPBO))
Bear in mind that there are System.IO equivalences for all what you are doing (getting files and moving them). You might prefer to rely on System.IO, rather than on My.Computer.FileSystem, as far as this Namespace contains methods to perform much more I/O-related actions (i.e., dealing with files, directories and paths).

Access / Word 2010 VBA Mail Merge Tries to Open [Foldername].mdb Instead of ACCDB Source

We are attempting to automate a mail merge process from within Access - upon clicking a button, VBA runs that specifies the current database (an accdb) as the data source and runs SQL, per the code below:
'Set up Word
Dim objWord As Object
Set objWord = CreateObject("Word.Application")
'Make visible, open specified doc to merge
With objWord
.Visible = True
.Documents.Open strDocName
End With
'Set the data source path
Dim docPath As String
docPath = CurrentProject.Path & "\" & CurrentProject.Name
'Open the merge data source - simplified
objWord.activedocument.mailmerge.opendatasource _
Name:=docPath, _
SQLStatement:=strSQL
strDocName and strSQL are passed in and contain valid, functional contents.
It succeeds in opening word, making it visible and opening the template to merge into. At that point, however, it comes up asking to confirm data source, and shows a list of possible data sources. Upon clicking the 'show all' checkbox, I can scroll down to MS Access Database via ODBC (.mdb, .accdb) and select it from the list.
It then presents with a box titled 'ODBC Microsoft Access Driver Login Failed', saying 'Could Not Find File: "[path to database folder]/[name of containing folder].mdb"'
So, if my database were located in C:\Temp the error path would read 'C:\Temp.mdb'. Moving the access database to another folder causes the error path to update looking for an accordingly named mdb file based on the containing folder.
I don't know if it's relevant but it also appears to be opening the template in the mode for editing the template itself, rather than generating a new document from that template.
Am I missing something here or does anyone have any ideas?
Cheers
With the assistance of Remou below, we gave up linking directly to Access and used the code from Remou's suggested link to output to a temporary text file, then merge from there.
We modified the code to remove CurrentBackendPath() and changed the only reference to this function as follows:
Private Function GetStartDirectory() As String
'GetStartDirectory = CurrentBackendPath() & "mm\"
GetStartDirectory = CurrentProject.Path & "\mm\"
End Function
The only other modifications we used were to change the code to be specific to our purpose. Thanks once again to everyone for your replies. I would upvote Remou for their response if I had enough reputation to do so!
I would strongly advise you not to link to an MS Access file. Output the data required to a text file and link to that. Linking to Access is all very well for manually controlled mailmerges, but it becomes tedious in the extreme when you wish to automate. You may wish to read http://www.tek-tips.com/faqs.cfm?fid=5088
That being said, recording a macro, I get the following:
ActiveDocument.MailMerge.OpenDataSource Name:="Z:\Docs\Test.accdb", _
ConfirmConversions:=False, ReadOnly:=False, LinkToSource:=True, _
AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:="", _
WritePasswordDocument:="", WritePasswordTemplate:="", Revert:=False, _
Format:=wdOpenFormatAuto, Connection:= _
"Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=Z:\Docs\Test.accdb;Mode=Read;Extended Properties="""";Jet OLEDB:System database="""";Jet OLEDB:Registry Path="""";Jet OLEDB:Engine Type=6;Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk" _
, SQLStatement:="SELECT * FROM `Table1`", SQLStatement1:="", SubType:= _
wdMergeSubTypeAccess
Most of the above is unnecessary, but you will see that it includes a connection string. This was not the case in earlier versions. You can get by with:
With objWord.ActiveDocument.MailMerge
.OpenDataSource Name:="Z:\Docs\Test.accdb", _
ConfirmConversions:=False, LinkToSource:=True, _
Connection:= _
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Z:\Docs\Test.accdb;" _
, SQLStatement:="SELECT * FROM `Table1`"
End With