My macro for Word highlights specific words from a specified list for each document in a folder. At the end of the macro, I would like to append the names of each of these files to include "_Highlight" using the command line. I am not too familiar with using the Command Prompt in VBA, so my code ended up being messy.
I am trying to replicate the following command prompt in VBA.
for %a in (“C:\path\*.docx*”) do ren “%~a” “%~Na_Highlight%~Xa”
For the actual file path, I select a folder in FileDialog and store it in a variable to be used in the command prompt, strShellFldr. I am having some trouble concatenating all pieces of the code, especially with special characters, spaces, and quotation literals.
Here is what I tried:
The code below runs just fine, however it seems quite cumbersome. Is there a more efficient way to write this?
Shell.Run "cmd.exe /c" & "for %a in" & Chr(32) & "(" & Chr(34) & strShellFldr & Chr(34) & ")" & Chr(32) & "do ren" & Chr(32) & Chr(34) & "%~a" & Chr(34) & Chr(32) & Chr(34) & "%~Na_Hilight%~Xa" & Chr(34)
Is there a native VBA function that allows you to append a file name maybe?
Thank you for your help and my apologies for posting some wretched code on here.
This piece of VBA code can loop through a list of files in a given folder as input, and add "_Highlight" at the end of the name, just before the file extension:
example:
MyFile.txt --> MyFile_Hightlight.txt
Public Sub RenameFiles(Folder As String)
Dim oFSO As Scripting.FileSystemObject
Dim oFolder As Scripting.Folder
Dim oFile As Scripting.File
Dim ext As String
Dim Name As String
On Error GoTo ERROR_TRAP
Set oFSO = New Scripting.FileSystemObject
Set oFolder = oFSO.GetFolder(Folder)
For Each oFile In oFolder.Files
ext = Split(oFile.Name, ".")(UBound(Split(oFile.Name, ".")))
Name = Left$(oFile.Path, Len(oFile.Path) - Len(ext) - 1)
oFSO.MoveFile Name & "." & ext, Name & "_Highlight" & "." & ext
Next oFile
Set oFSO = Nothing
Set oFolder = Nothing
Set oFile = Nothing
Exit Sub
ERROR_TRAP:
Debug.Print "ERROR : RenameFiles (" & oFolder.Name & ")"
End Sub
Do not forget to add Microsoft Scripting Runtime reference first in your VB Editor.
Related
I am trying to import multiple .txt files from a directory into an Access table using VBA.
I have code that currently works that imports the data and moves the files to an archive directory.
What I need to do is add the first part of the filename as field in the table, namely the date.
The file format is MMDDYYYY_LbxReport.txt (ex 02082022_LbxReport.txt)
Here is the code that I have working, and I commented out what I tried to add to fix my problem:
Private Sub Command9_Click()
On Error GoTo bImportFiles_Click_Err
Dim objFS As Object, objFolder As Object
Dim objFiles As Object, objF1 As Object
'Dim dteEntry As Variant 'added this variant for use in UPDATE cmd
Dim strFolderPath As String
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFS.GetFolder("\\*****************\upload\SSDTestLBXa\")
Set objFiles = objFolder.files
For Each objF1 In objFiles
If Right(objF1.Name, 11) = "xReport.txt" Then 'LBX level report capture
'dteEntry = Left(objF1.Name, 8)
'dteEntry = Left(dteEntry, 2) & "/" & Mid(dteEntry, 3, 2) & "/" & Right(dteEntry, 4) 'added to reformat into standard date format
DoCmd.TransferText acImportDelim, "lbxlevelspecs", "lbxlevel", strFolderPath & objF1.Name, False
'CurrentDb.Execute "Update lbxlevel" & "Set EntryDate=" & dteEntry & "", [] 'getting syntax errors here
Name strFolderPath & objF1.Name As "\\**************\upload\SSDTestLBXa\Archive\" & objF1.Name 'Move the files to the archive folder
End If
Next
Set objF1 = Nothing
Set objFiles = Nothing
Set objFolder = Nothing
Set objFS = Nothing
'Call Site_level
MsgBox ctr & "All volumes imported", , "Volume Import"
bImportFiles_Click_Exit:
Exit Sub
bImportFiles_Click_Err:
MsgBox Err.Number & " " & Err.Description
Resume bImportFiles_Click_Exit
End Sub
I saw a similar thread for this question, but I can't get the syntax right, and the OP's code was very different from what I have that's working so far.
Any help would be greatly appreciated!
This is how you would construct the update statement:
Public Sub doit()
Dim dteEntry As Variant
dteEntry = Left("02142024_SomeName.txt", 8)
dteEntry = Left(dteEntry, 2) & "/" & Mid(dteEntry, 3, 2) & "/" & Right(dteEntry, 4) 'added to reformat into standard date format
CurrentDb.Execute "ALTER TABLE lbxlevel ADD EntryDate DATETIME"
CurrentDb.Execute "Update lbxlevel " & "Set EntryDate='" & dteEntry & "'"
End Sub
Because it needs apace before 'SET', and quotation marks around the date.
EDIT: I added the ALTER TABLE, this tests successfully on my side.
Please go through my code, correct me where I am wrong, files are not moving from folder to folder.
Option Explicit
Sub MoveFiles()
Dim FSO As Object
Dim FromDir As String
Dim ToDir As String
Dim FExtension As String
Dim Fnames As String
FromDir = "C:\Users\B\Source Folder"
ToDir = "C:\Users\B\Destination Folder"
FExtension = "*.*"
Fnames = Dir(FromDir & FExtension)
If Len(Fnames) = 0 Then
MsgBox "No files or Files already moved" & FromDir
Exit Sub
End If
Set FSO = CreateObject("Scripting.FileSystemObject")
FSO.MoveFile Source:=FromDir & FExtension, Destination:=ToDir
End Sub
Problem
You are missing a \ at the end of your FromDir which will separate the path from your filenames.
For your info: & is not really combining path and filename, but just concatenating two strings, so it never adds the \ itself.
Correction possibility 1
You can add it to the definition of FromDir:
FromDir = "C:\Users\B\Source Folder\"
Correction possibility 2
Add it to these lines of code dynamically:
Fnames = Dir(FromDir & "\" & FExtension)
FSO.MoveFile Source:=FromDir & "\" & FExtension, Destination:=ToDir
Another remark
You should also separate FromDir from the error text, like this:
MsgBox "No files or Files already moved: " & FromDir
I would like to create a macro to perform an "Advanced Search" on tasks subject and optionally tasks body. For instance search for "#Cris"
I have copied and modified this code from an example for Excel but it doesnt run. Runtime Error. Appreciate any assistance
Sub AdvancedSearchComplete()
Dim rsts As Outlook.Results
Dim i As Integer
Dim strF As String
Dim strS As String
strS = "Tasks"
StrName = InputBox("Search String?")
strF = InStr(LCase("urn:schemas:tasks:subject"), StrName)
Set sch = Application.AdvancedSearch(strS, strF, , "Search1")
End Sub
You need to specify a valid scope and search criteria. The scope of the search is the folder path of a folder, not a folder name. It is recommended that the folder path is enclosed within single quotes. Otherwise, the search might not return correct results if the folder path contains special characters including Unicode characters. To specify multiple folder paths, enclose each folder path in single quotes and separate the single quoted folder paths with a comma.
The Filter parameter can be any valid DASL query. For additional information on DASL queries, see Filtering Items.
Note, you can use the Chr Function to represent any character in the search criteria.
Sub TestSearchForMultipleFolders()
Dim Scope As String
Dim Filter As String
Dim MySearch As Outlook.Search
Dim MyTable As Outlook.Table
Dim nextRow As Outlook.Row
m_SearchComplete = False
'Establish scope for multiple folders
Scope = "'" & Application.Session.GetDefaultFolder( _
olFolderInbox).FolderPath _
& "','" & Application.Session.GetDefaultFolder( _
olFolderSentMail).FolderPath & "'"
'Establish filter
If Application.Session.DefaultStore.IsInstantSearchEnabled Then
Filter = Chr(34) & "urn:schemas:httpmail:subject" _
& Chr(34) & " ci_phrasematch 'Office'"
Else
Filter = Chr(34) & "urn:schemas:httpmail:subject" _
& Chr(34) & " like '%Office%'"
End If
Set MySearch = Application.AdvancedSearch(Scope, Filter, True, "MySearch")
While m_SearchComplete <> True
DoEvents
Wend
Set MyTable = MySearch.GetTable
Do Until MyTable.EndOfTable
Set nextRow = MyTable.GetNextRow()
Debug.Print nextRow("Subject")
Loop
End Sub
Also you may find the Advanced search in Outlook programmatically: C#, VB.NET article helpful.
Ok, this is what I got to work.
When starting the macro:
It Asks user to enter string
Performs and advance search and search for string in subject (including special characters like #cris)
Creates search folder to display search results
In case it helps anybody else. I don't know how to create an output like when doing a manual search. But this works for me.
Sub AdvSearchForStr()
On Error GoTo Err_SearchFolderForSender
Dim strFrom As String
Dim strTo As String
Dim strSearch As String
strSearch = InputBox("Enter String to AdvSearch", "Advanced Search")
strTo = "Test"
Dim strDASLFilter As String
strDASLFilter = "urn:schemas:httpmail:subject LIKE '%" & strSearch & "%'"
Debug.Print strDASLFilter
Dim strScope As String
strScope = "'Inbox', 'Sent Items', 'Tasks'"
Dim objSearch As Search
Set objSearch = Application.AdvancedSearch(Scope:=strScope, Filter:=strDASLFilter, SearchSubFolders:=True, Tag:="SearchFolder")
'Save the search results to a searchfolder
objSearch.Save (strSearch)
Set objSearch = Nothing
Exit Sub
Err_SearchFolderForSender:
MsgBox "Error # " & Err & " : " & Error(Err)
End Sub
I am reading a list of files and come accross updated versions along the way. In my loop I am checking if the file already exists and trying to remove it, so that I can create the newer version again:
objFs = CreateObject("Scripting.FileSystemObject")
If (objFs.FileExists(location & "\" & fileName & ".xml")) Then
System.IO.File.Delete(location & "\" & fileName & ".xml")
End If
objTextStream = objFs.CreateTextFile(location & "\" & fileName & ".xml", True)
objTextStream.Write(System.Text.Encoding.UTF8.GetString(recordXml))
Ideally I would rather just open the file if it already exists and overwrite the contents, but so far my attempts have been in vein.
location is a user defined path, e.g. c://
recordXML is a retrieved value from the database
The main error I keep getting is
Additional information: Argument 'Prompt' cannot be converted to type 'String'.
Which seems to mean that the file is either not there to delete, or it is already there when I am trying to create it. The delete may not be working as it should, it may be that the file is not deleted in time to recreate it?..
That's my thoughts anyway.
Found this code at http://www.mrexcel.com/forum/excel-questions/325574-visual-basic-applications-check-if-folder-file-exists-create-them-if-not.html for creating a new file (unless one already exists) and then opening it (existing or new). Once you open, you can just do a Sheets(
NAMEOFSHEET").Cells.Clearto clear the cells and then paste your data.
Sub btncontinue_Click()
Dim myFile As String, myFolder As String
myFolder = "C:\TimeCards"
myFile = myFolder & "\timecards.xls"
If Not IsFolderExixts(myFolder) Then
CreateObject("Scripting.FileSystemObject").CreateFolder myFolder
End If
If Not IsFileExists(myFile) Then
MsgBox "No such file in the folder"
Exit Sub
End If
Set wb = Workbooks.Open(myFile)
' Your code here
End Sub
Function IsFolderExists(txt As String) As Boolean
IsFolderExists = _
Createobject("Scripting.FileSystemObject").FolderExists(txt)
End Function
Function IsFileExists(txt As String) As Boolean
IsFileExists = _
CreateObject("Scripting.FilesystemObject").FileExists(txt)
End Function
You could try this, it should work in VB, VBA and VBScript.
objFs = CreateObject("Scripting.FileSystemObject")
If objFs.FileExists(location & "\" & fileName & ".xml") Then Kill(location & "\" & fileName & ".xml")
Open location & "\" & fileName & ".xml" For Output As #1
Print #1, recordXml
Close #1
Try to use FSO to delete the file. Also the objTextStream needs to be set because it is object.
Sub AnySub()
Dim objFs As FileSystemObject
Set objFs = CreateObject("Scripting.FileSystemObject")
If (objFs.FileExists(Location & "\" & Filename & ".xml")) Then
objFs.DeleteFile Location & "\" & Filename & ".xml"
End If
Set objTextStream = objFs.CreateTextFile(Location & "\" & Filename & ".xml", True)
objTextStream.Write recordXml
End Sub
I m not sure the .write method work with UTF8.
I m using this function:
Sub File_WriteToUTF8(File_Path As String, s_Content As String)
On Error GoTo ende
Dim LineStream As Object
Set LineStream = CreateObject("ADODB.Stream")
With LineStream
.Type = 2
.Mode = 3
.Charset = "utf-8"
.Open
.WriteTEXT s_Content
.SaveToFile File_Path, 2
ende:
.Close
End With
End Sub
So instead of
objTextStream.Write recordXml
it would be
File_WriteToUTF8 Location & "\" & Filename & ".xml", recordXml
Saving a file attachment in an Outlook mail item with the VBA method Attachment.SaveAsFile() call produces the expected result (file saved with same filename on the filesystem), even for file names with non-ASCII characters.
However, VBA apparently stores the file name in a 16-bit composite format String where accented letters are stored as a (letter, accent) pair. I can't find a way to output the string inside the message body with accented letters showing up as one glyph ("é") instead of two ("e´").
Concretely, the attachment is properly saved under the correct file name on disk when using the following code:
' Save the Outlook attachment
oAttachment.SaveAsFile (sTempFileLocation)
This results in a file being written to the folder specified in sTempFileLocation and the file name complies with the way it appears in the Outlook message (accents, non-ASCII characters etc).
However, when retrieving and manipulating the file name, it appears that a 16-bit composite internal representation of special characters is used. This means that the file name "à présent.txt" is displayed as "a` pre´sent.txt" (accented characters are represented with the character + the accent in 2 consecutive bytes).
For instance:
sAttachmentName = fso.getfilename(sTempFileLocation)
Debug.Print ("Attachment name = [" & sAttachmentName & "]")
will result in:
Attachment name = [a` pre´sent.txt]
There is little information available on this matter, all I found so far was this MSDN link describing the MultiByteToWideChar() function. From there it appears that the 16-bit internal VBA rendering happens implcitly and is even computer dependent (depending on code page and locale in use).
Here follows a self-contained minimalistic example that tries to save the email attachments of the first selected message to your My Documents folder unless it already exists:
Sub SaveMessageAttachments()
Dim objApp As Outlook.Application
Dim oSelection As Outlook.Selection
Dim aMail As Outlook.MailItem
Dim fso As Object
On Error Resume Next
' Instantiate an Outlook Application object.
Set objApp = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set oSelection = objApp.ActiveExplorer.Selection
If oSelection Is Nothing Then
Exit Sub
End If
' Select the 1st mail item in the current selection
Set aMail = oSelection.item(1)
Dim sAttachmentFolder As String
' Get the path to your "My Documents" folder
sAttachmentFolder = CreateObject("WScript.Shell").SpecialFolders(16)
Set fso = CreateObject("Scripting.FileSystemObject")
Dim oAttachments As Outlook.Attachments
Dim lItemAttachmentCount As Long
Set oAttachments = aMail.Attachments
lItemAttachmentCount = oAttachments.Count
If (lItemAttachmentCount > 0) Then
Dim lAttachmentIndex As Long
For lAttachmentIndex = 1 To lItemAttachmentCount
Dim oAttachment As Outlook.attachment
Set oAttachment = oAttachments.item(lAttachmentIndex)
Dim sFileName As String
sFileName = oAttachment.FileName
If LenB(sFileName) > 0 Then
Dim sFilePath As String
sFilePath = sAttachmentFolder & "\" & sFileName
If fso.fileexists(sFilePath) Then
MsgBox "Cannot save attachment " & lAttachmentIndex & vbCr _
& "File already exists: " & vbCr _
& sFilePath, vbExclamation + vbOKOnly
Else
If MsgBox("Saving atachment " & lAttachmentIndex & "?" & vbCr _
& "Save location: " & vbCr & sFilePath, _
vbQuestion + vbOKCancel) = vbOK Then
' Save the attachment to the temporary folder
oAttachment.SaveAsFile (sFilePath)
Dim sAttachmentName As String
sAttachmentName = fso.getfilename(sFilePath)
Dim lAttachmentLength As Long
lAttachmentLength = fso.getfile(sFilePath).size
Dim sURL As String
sURL = "file://" & Replace(sFilePath, "\", "/")
MsgBox "Attachment " & lAttachmentIndex _
& " saved as: " & sAttachmentName & vbCr _
& "Size: " & lAttachmentLength & vbCr _
& "URL = " & sURL, _
vbInformation + vbOKOnly
End If
End If
End If
Next lAttachmentIndex
End If
End Sub
As you will see, the SaveMessageAttachments() subroutine correctly saves the file to the filesystem, with the proper file name. However, Outlook dialogs (as well as when trying to write the attachment file name or URL to the message body in VBA) will always render the file names having accents differently. Please give it a try with an Outlook message having an attachment named e.g. "à présent.txt").
What is strange, however, is that if I try to paste sURL in the message body, although the URL is incorrectly written (2 character decomposition of accented letters) Outlook seems to find and open the file.
How can I transform this accented string (sAttachmentName) with VBA in order to correctly paste it ("à présent.txt" instead of "a` pre´sent.txt") into the message body?