How to edit a .bat file with Excel VBA - vba

I'm developing an Excel Add-in for .bat / .vbs files. The add-in has 2 options (1) create a new .bat / and .vbs file and (2) modify an existing .bat and .vbs file.
The "create" option is working great and does exactly what we need it to do.
I'm having issues with the "modify" piece. When the user selects "modify", and Excel form is displayed with a List Box. The user scrolls through the list and selects the one they need to modify. So far so go.
The next step is for the add-in to open (not run) both the .bat and .vbs file. I've been able to get the .bat file to execute; which in turns executes the .vbs file. But that is not what I need it to do.
If I was going to manually open the .bat or .vbs file. I would right click on the .bat or .vbs file and select "edit". The appropriate file opens in NotePad. I can then make any changes and save the file.
What I'm looking duplicate is the "right click and select edit steps" with VBA.
Any suggestions would be greatly appreicated. Thanks for your help in advance....

I am not familiar with Add-Ins, sorry if misleading. This does work in normal code:
Assume there is a userform frmTest7 with TextBox1, ListBox1 and CommandButton1 (to save changes). The userform code as follows.
Option Explicit
Private Sub CommandButton1_Click()
Dim fso As FileSystemObject
Dim oFile As TextStream
Dim FilePath As String
Dim strFile As String
FilePath = "C:\Users\" & Environ("UserName") & "\desktop\test_bat.bat"
Dim i As Long
For i = 0 To frmTest7.ListBox1.ListCount - 1
strFile = strFile & frmTest7.ListBox1.List(i) & vbCrLf
Next i
Set fso = New FileSystemObject
If fso.FileExists(FilePath) Then
'fso.DeleteFile (FilePath)
Set oFile = fso.CreateTextFile(FilePath, True)
oFile.WriteLine strFile
End If
If Not (oFile Is Nothing) Then oFile.Close
Set oFile = Nothing
Set fso = Nothing
End Sub
Private Sub ListBox1_Click()
frmTest7.TextBox1.Text = frmTest7.ListBox1.List(frmTest7.ListBox1.ListIndex)
End Sub
Private Sub TextBox1_AfterUpdate()
frmTest7.ListBox1.List(frmTest7.ListBox1.ListIndex) = frmTest7.TextBox1.Text
End Sub
Private Sub UserForm_Activate()
Dim fso As FileSystemObject
Dim oFile As TextStream
Dim FilePath As String
Dim strFile As String
FilePath = "C:\Users\" & Environ("UserName") & "\desktop\test_bat.bat"
Set fso = New FileSystemObject
Set oFile = fso.OpenTextFile(FilePath, ForReading)
strFile = oFile.ReadAll
oFile.Close
Dim arrStrFile() As String
strFile = Replace(strFile, vbCr, "")
arrStrFile = Split(strFile, Chr(10))
frmTest7.ListBox1.Clear
frmTest7.ListBox1.List = arrStrFile
Set oFile = Nothing
Set fso = Nothing
End Sub

I found a way to do this but not sure whether it works for you or not.
1. We cannot open .bat files but we can open .txt files so I converted the .bat file to .txt file and opening it using hyperlink.
In below example, Reminder is a .bat file and on clicking the Open button it converts the Reminder.bat to Reminder.txt and opens the file.
Sub RenameFileExtensionFromBatToTextAndOpen()
Dim fileName As String
Dim fileLocation As String
Dim originalExtension As String
Dim renamedExtenstion As String
fileLocation = "C:\Users\Nandan\Downloads\"
fileName = Sheets("Sheet1").Range("B5")
originalExtension = fileLocation & fileName & ".bat"
renamedExtenstion = fileLocation & fileName & ".txt"
Name originalExtension As renamedExtenstion
ActiveWorkbook.FollowHyperlink Address:=renamedExtenstion
End Sub
2. After changes saved, on clicking Done it will change the file format from Reminder.txt to Reminder.bat
Sub RenameFileExtensionFromTxtToBat()
Dim fileName As String
Dim fileLocation As String
Dim originalExtension As String
Dim renamedExtenstion As String
fileLocation = "C:\Users\Nandan\Downloads\"
fileName = Sheets("Sheet1").Range("B5")
originalExtension = fileLocation & fileName & ".bat"
renamedExtenstion = fileLocation & fileName & ".txt"
Name renamedExtenstion As originalExtension
End Sub
On opening file,
After clicking on Done,

Related

How can I run a SQL query within an Excel Workbook saved to OneDrive?

I would like to run SQL queries on tables all contained within a single Excel workbook. My VBA code uses ADODB to run these SQL queries.
Opening connection fails when the workbook is saved in OneDrive, but works when workbook is saved to a local drive.
How can I run SQL on tables within a single excel workbook, while saved on OneDrive?
The code works when the book is saved locally but not on OneDrive. The only change is the file path which looks fairly different in each case:
OneDrivePathExample = "https://d.docs.live.net/....xlsb"
LocalPathExample = "C:\My Documents\....xlsb"
I've experimented with a few things around the file path in the connection string but, unsurprisingly, they didn't work:
Original
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=https://d.docs.live.net/.../Documents/Financial Tracker.xlsb;Extended Properties="Excel 12.0;HDR=Yes;IMEX=1";
Replacing "/" with "\"
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=https:\\d.docs.live.net\...\Documents\Financial Tracker.xlsb;Extended Properties="Excel 12.0;HDR=Yes;IMEX=1";`
Adding square brackets around path
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=[https://d.docs.live.net/.../Documents/Financial Tracker.xlsb];Extended Properties="Excel 12.0;HDR=Yes;IMEX=1";
Adding quotes around path
Provider=Microsoft.ACE.OLEDB.12.0;Data Source="https://d.docs.live.net/.../Documents/Financial Tracker.xlsb";Extended Properties="Excel 12.0;HDR=Yes;IMEX=1";
I realize that I can avoid this by saving it locally when running this code, and then save it back to OneDrive afterwards but I would like to avoid this if possible.
I also realize that I can write VBA code that does what I'm trying to do with SQL, however I did that originally but switched to the SQL method because SQL was way faster.
Here's my code:
Function OpenRST(strSQL As String) As ADODB.Recordset
''Returns an open recordset object
Dim cn As ADODB.Connection
Dim strProvider As String, strExtendedProperties As String
Dim strFile As String, strCon As String
strFile = ThisWorkbook.FullName
strProvider = "Microsoft.ACE.OLEDB.12.0"
strExtendedProperties = """Excel 12.0;HDR=Yes;IMEX=1"";"
strCon = "Provider=" & strProvider & _
";Data Source=" & strFile & _
";Extended Properties=" & strExtendedProperties
Set cn = CreateObject("ADODB.Connection")
Set OpenRST = CreateObject("ADODB.Recordset")
cn.Open strCon ''This is where it fails
OpenRST.Open strSQL, cn
End Function
On the cn.Open strCon line, the following error appears:
Run-time error '-2147467259 (80004005)';
Method 'Open' of object '_Connection' failed
Thanks!
this is my solution to get file path.
'This Function search root folder as C: ,D: ...
'Search into all OneDrive folders
Option Explicit
Private Const strProtocol As String = "Http"
Private Const pathSeparator As String = "\"
Function MainFindFile(ByRef NullFilePath As String, Optional FileName As String) As Boolean
Dim fso As FileSystemObject 'Necessary enable microsoft scripting runtime in references
Dim UserRootFolder As Folder
Dim SecondSubFolders As Folder
Dim ThirdSubFolders As Folder
Dim InitialPath As String
Dim OneDriveFolderName As String
Set fso = New Scripting.FileSystemObject
InitialPath = ActiveWorkbook.FullName
If FileName = vbNullString Then FileName = ActiveWorkbook.Name
If InStr(1, InitialPath, strProtocol, vbTextCompare) > 0 Then
InitialPath = Environ("SystemDrive")
InitialPath = InitialPath & Environ("HomePath")
'Gets all folders in user root folder
Set UserRootFolder = fso.GetFolder(InitialPath)
For Each SecondSubFolders In UserRootFolder.SubFolders
'Searches all folders of OneDrive, you may have how many Onedrive's folders as you want
If InStr(1, SecondSubFolders.Name, "OneDrive", vbTextCompare) > 0 Then
OneDriveFolderName = InitialPath & pathSeparator & SecondSubFolders.Name
'Verifies if file exists in root of Onedrive Folder
MainFindFile = SearchFile(OneDriveFolderName, FileName, NullFilePath)
If MainFindFile Then Exit For
'Uses recursive function to percur all subfolders in root of OneDrive
For Each ThirdSubFolders In fso.GetFolder(OneDriveFolderName).SubFolders
MainFindFile = RecursiveFindFile(ThirdSubFolders, FileName, NullFilePath)
If MainFindFile Then Exit For
Next ThirdSubFolders
End If
If MainFindFile Then Exit For
Next SecondSubFolders
End If
MsgBox NullFilePath
End Function
Private Function RecursiveFindFile(Folder As Folder, FileName As String, ByRef NullFilePath As String) As Boolean
Dim fso As FileSystemObject
Dim objFolder As Folder
Dim Result As Boolean
Set fso = New Scripting.FileSystemObject
'Verifies if file exists in root of Onedrive Folder
RecursiveFindFile = SearchFile(Folder.Path, FileName, NullFilePath)
If RecursiveFindFile Then Exit Function
For Each objFolder In Folder.SubFolders
If Not SearchFile(objFolder.Path, FileName, NullFilePath) Then
RecursiveFindFile = RecursiveFindFile(objFolder, FileName, NullFilePath)
If RecursiveFindFile Then Exit For
Else
RecursiveFindFile = True
Exit For
End If
Next objFolder
End Function
Private Function SearchFile(Path As String, FileName As String, ByRef NullFilePath As String) As Boolean
'NullFilePath is a byref variable to be filled by this function
Dim fso As New Scripting.FileSystemObject
If fso.FileExists(Path & pathSeparator & FileName) Then
NullFilePath = Path & pathSeparator & FileName
SearchFile = True
End If
End Function
Replace the htpps: with "". This will bring you one step further.

Opening pdf files through MS-Word

I am trying to open a pdf file through MS Word, perform certain action such as evaluating calculations, printing the files, etc. and then proceed with closing the file. The error message I received is "Microsoft Excel is waiting for another application to complete an OLE action."
I have previously tried hyperlinkfollow and Shell MyPath & " " & MyFile, vbNormalFocus method, it doesn't work. I am still at the starting phase of opening the pdf files, please advice. Thanks!
Sub Extract_PDF_Data()
Dim mainData As String
Dim strFile As String
Dim Oldname As String
Dim Newname As String
Dim Folderpath As String
Dim s As String
Dim t As Excel.Range
Dim wd As New Word.Application
Dim mydoc As Word.Document
Folderpath = InputBox("Folder path: ")
Folderpath = Folderpath & "\"
strFile = Dir(Folderpath & "", vbNormal)
Do While Len(strFile) > 0
Oldname = Folderpath & strFile
Set wd = CreateObject("Word.Application")
Set mydoc = Word.Documents.Open(Filename:=Oldname, Format:="PDF Files",
ConfirmConversions:=False)
mainData = mydoc.Content.Text
mydoc.Close False
wd.Quit
strFile = Dir
Loop
End Sub
Don't us the New keyword in the line that declares the object variable. This will "block" the object variable - it causes the error when the code laters tries to instantiate it. This method can work in VB.NET but not in VBA.
Do it more like this:
Dim wd As Word.Application
Set wd = New Word.Application. 'Or use CreateObject
I think a combination of those three sources will lead to the answer:
How to open a pdf with Excel?
How to extract data from pdf using VBA?
How to open and print a pdf using VBA?
I think it will be something like this:
Sub Extract_PDF_Data()
Dim mainData As String
Dim strFile As String
Dim Oldname As String
Dim Newname As String
Dim Folderpath As String
Dim s As String
Dim t As Excel.Range
Dim Appshell As Variant
Dim ap As String
Dim Browsedir As Variant
Dim f As Variant
Dim KeyWord As String
' This is a suggestion, I use it because it is more convenient than copy-pasting folder paths
Dim FSO As Object
Set FSO = CreateObject("Scripting.Filesystemobject")
' Get Folder over user input
Set Appshell = CreateObject("Shell.Application")
Set Browsedir = Appshell.BrowseForFolder(0, "Select a Folder", &H1000, "E:\Xample\Path")
' check if not cancalled
If Not Browsedir Is Nothing Then
Folderpath = Browsedir.items().Item().Path
Else
GoTo Quit
End If
KeyWord = "The_Materialist_Example"
' go through all files in the folder
For Each f In FSO.GetFolder(Folderpath).Files
' if file is a pdf , open, check for keyword, decide if should be printed
If LCase(Right(f.Name, 3)) = "pdf" Then
' Here the methods suggest different answers.
' You can either use FollowHyperLink or use the Adobe Library to OPEN PDF
' I would write a function that checks the active pdf for the keyword : IsKeyFound
Debug.Print Folderpath & "\" & f.Name
Call PrintPDF(Folderpath & "\" & f.Name)
If IsKeyFound(f, KeyWord) Then
f.Print
End If
End If
Next f
Quit:
End Sub
Private Sub PrintPDF(strPDFFileName As String)
Dim sAdobeReader As String 'This is the full path to the Adobe Reader or Acrobat application on your computer
Dim RetVal As Variant
sAdobeReader = "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
'Debug.Print sAdobeReader & "/P" & Chr(34) & strPDFFileName & Chr(34)
RetVal = Shell(sAdobeReader & " /P " & Chr(34) & strPDFFileName & Chr(34), 0)
End Sub
Private Function IsKeyFound(PDF As Variant, KeyWord As String) As Boolean
'Decide if file needs to be printed, insert your criteria and search algorithm here
End Function
I have not been able to figure out how to extract the keywords, you could however use a user input as a first approach and later move on to a automated scan of the pdf.
I hope this gets you further on the way to the solution.

Save a copy of Database then email it to a shared email box

I have a script that saves a backup database (with a date stamp) to a shared drive.
Private Sub Command0_Click()
Dim fs As Object Dim oldPath As String, newPath As String
Dim CurrentDate As String
CurrentDate = Format(Now, "MMDDYY")
oldPath = "\\xxx\xxx Database" 'Folder file is located in
'newPath = "\\xxx\xxx\FINANCE\USERS\xxx\xxx Operations\xxx\xxx\" 'Folder to copy file to
newPath = "C:\Users\xxx\Documents\xxx\xxx" 'Folder to copy file to
Set fs = CreateObject("Scripting.FileSystemObject")
fs.CopyFile oldPath & "\" & "xxx Database Update v.1.6_be.accdb", newPath & "\" _
& "xxx Database Update v.1.6_be_" & CurrentDate & ".accdb"
Set fs = Nothing
MsgBox "Database Backed up", , "Backup Complete"
End Sub
This worked fine.
However I have now been asked to also send the database to a shared inbox email address.
Private Sub btnbrowse_click()
Dim filediag As FileDialog
Dim file As Variant
Set filediag = FileDialog(msofiledialogfilepicker)
filediag.allowmultiselect = False
If filediag.show Then
For Each file In filediag.selecteditems
Me.txtattachment = file
Next
End If
End Sub
Private Sub btnSend_Click()
Dim oApp As New Outlook.Application
Dim oEmail As Outlook.MailItem
Set oEmail = oApp.CreateItem(olMailItem)
oEmail.To = Me.txtto
oEmail.Subject = Me.txtsubject
oEmail.Body = Me.txtbody
If Len(Me.txtattachment) > 0 Then
oEmail.Attachments.Add Me.txtattachment.Value
End If
With oEmail
If Not IsNull(.To) And Not IsNull(.Subject) And Not IsNull(.Body) Then
.Send
MsgBox "Email Sent!"
Else
MsgBox "Please fill out the required fields."
End If
End With
End Sub
Please can somebody help me link the two scripts so that instead of using the FileDialog to choose the email attachment, I can use the path in the first query to select the attachment and the script will run both the save file and the email file commands at the same time.
It's just the filename, so it could be just passing the value from your script:
oEmail.Attachments.Add newPath & "\xxx Database Update v.1.6_be_" & CurrentDate & ".accdb"
If you want to just automatically send after the backup, make the email code a Sub that can be called in Backup button click procedure.
Sub SendEmail(strFile As String)
...
oEmail.Attachments.Add strFile
...
End Sub
Then calling the sub at end of the Backup button click:
SendEmail(newPath & "\xxx Database Update v.1.6_be_" & CurrentDate & ".accdb")
Many email systems reject emails with Access file as an attachment because of malicious code risk. However, a zipped Access file should pass security. Example code:
Dim strZip As String
strZip = CurrentProject.Path & "\Construction.zip"
'create empty zip folder
'found this on web, no idea what the Print line does but if it isn't there, this won't work
Open strZip For Output As #1
Print #1, "PK" & Chr$(5) & Chr$(6) & String(18, 0)
Close #1
'copy file into zip folder
Dim objApp As Object
Set objApp = CreateObject("Shell.Application")
'variable for source file doesn't seem to work in this line
'also double parens not in original example code but won't work without
objApp.NameSpace((strZip)).CopyHere CurrentProject.Path & "\Construction.accdb"
As noted in code comment, issue is passing source file via variable. Sorry, I never needed to solve.
Creating zip file code could be in the email procedure and then attach the zip file:
oEmail.Attachments.Add strZip
Then at the end of email procedure, can delete the zip file:
Kill strZip

Combining powerpoints in target folder

I have never posted here before, so I thought I would give it a try. I have a macro that I have been using for over a year, and at beginning of the week it started to give me some problems. It will either just pull in the first slide of each powerpoint, or it will give me a Run-Time error "Slides (Unknown Member): Invalid request. Clipboard is empty or contains data which may not be pasted here."
The macro works fine if I just step through it using F8, the only time that I have issues is if I try to run it. It may be something super obvious, as I am pretty new to VBA. Thanks for the help!
Public Sub DoFiles()
Dim strFileName As String
Dim strFolderName As String
Dim objPresentation As Presentation
'set default directory here if needed
strFolderName = "Target Folder"
strFileName = Dir(strFolderName & "\*.ppt*")
Do While Len(strFileName) > 0
Set objPresentation = Presentations.Open(strFolderName & "\" &
strFileName)
On Error Resume Next
Dim i As Integer
For i = 1 To objPresentation.Slides.Count
objPresentation.Slides.Item(i).Copy
Presentations.Item(1).Slides.Paste
Presentations.Item(1).Slides.Item(Presentations.Item(1).Slides.Count).Design
= _
objPresentation.Slides.Item(i).Design
Next i
objPresentation.Close
strFileName = Dir
Loop
End Sub
Did Steve's suggestion work?
Public Sub DoFiles()
Dim strFileName As String
Dim strFolderName As String
strFolderName = "Target Folder"
strFileName = Dir(strFolderName & "\*.ppt*")
Do While Len(strFileName) > 0
ActivePresentation.Slides.InsertFromFile strFolderName & "\" & strFileName, ActivePresentation.Slides.Count
strFileName = Dir
Loop
End Sub

How to convert all *.potx files to *.pptx files with VBA?

I have a folder of ~20 *.potx files and I would like to convert all *.potx files to *.pptx, then delete the *.potx files.
The following will loop through all your templates, convert, and delete the template files.
Sub loopFiles()
Dim fso As New FileSystemObject
Dim fil As File
Dim fold As Folder
Set fold = fso.GetFolder(yourFolder)
For Each fil In fold.Files
If InStr(1, fil.Name, ".potx") > 0 Then
Application.Presentations.Open fil.Path
ActivePresentation.SaveAs Replace(fil.Path, ".potx", ".pptx"), ppSaveAsDefault
ActivePresentation.Close
'if you truly want to delete them, don't recommend since they are .potx
fil.Delete True
End If
Next fil
End Sub
You could try something like this: (replace YOUR FOLDER HERE with your folder name)
Public Sub ConvertPP()
Dim pApp As Object
Set pApp = CreateObject("Powerpoint.Application")
Dim sFile As String
Dim sFolder As String
sFolder = "YOUR FOLDER HERE"
sFile = Dir(sFolder & "\*.potx")
Do Until sFolder = ""
pApp.Presentations.Open sFolder & "\" & sFile
pApp.ActivePresentation.SaveAs sFolder & "\" & Replace(sFile, "potx", "pptx"), 11
pApp.ActivePresentation.Close
sFile = Dir()
Loop
pApp.Quit
Set pApp = Nothing
End Sub