Execute .vbs from a batch for a specific workbook - vba

I have a .bat file and I'm using it to execute a .vbs which I've pulled out of an excel workbook.
Currently, my .bat file looks like:
echo Starting program
start C:\Users\midi\Desktop\Refresh_Data_Connection.vbs
echo Finish program
However, the issue with my .vbs file is that it doesn't reference a specific workbook which I need it to. How could I set the .vbs to alter a specific workbook stored on my desktop? Any help/feedback or push in the right direction would be really helpful, thanks in advance!
My vbs is:
Sub RefreshConns()
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Sheets("Run Macro").Activate
Dim connName As String ' connection name
Dim connStr As String ' connection string
Dim sqltext ' SQL text
Dim TempconnName As String ' temporary connection name
Dim TempconnStr As String ' temporary connection string
Dim Tempsqltext ' temporary SQL text
Dim i As Integer
Dim SiteName As String
SiteName = ActiveSheet.Cells(1, 2)
'MsgBox (SiteName)
For i = 5 To 11
connName = ActiveSheet.Cells(i, 1).Value
connStr = ActiveSheet.Cells(i, 2).Value
sqltext = ActiveSheet.Cells(i, 4).Value
'MsgBox (connName)
TempconnStr = Replace(connStr, "SiteNameVBA", SiteName)
'Debug.Print (ActiveWorkbook.Connections(connName).ODBCConnection.Connection)
'MsgBox (TempconnStr)
'Tempsqltext = Replace(sqltext, "SiteNameVBA", SiteName)
'On Error Resume Next
ActiveWorkbook.Connections(connName).ODBCConnection.CommandText = sqltext
ActiveWorkbook.Connections(connName).ODBCConnection.Connection = "ODBC;" & TempconnStr
ActiveWorkbook.Connections(connName).Refresh
Next i
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Public Function ZeroToBlank(x As String) As String
If x = "0" Then
ZeroToBlank = ""
Else
ZeroToBlank = x
End If
End Function

One way is to declare a system environment variable using setx.
Running your batch with administration privilege try this:
setx PATHFILE "/path/file.xls" /M
Check if is declared:
set | find "PATHFILE"
And read it with the function Environ() to open you Workbook in your vbs:
Workbooks.Open Environ("PATHFILE")
EDIT
You do not need to use system environment variable (/m argument) as you can use only user environment. You need to just remember that the programs need to restart to read the user and system environment variable.

Set xlBook = GetObject("C:\Users\User\Documents\Super.xls")
For each wsheet in xlbook.worksheets
msgbox wsheet.name
next
Is how. Remember there are no excel constants in VBS, there is no dim x as something as vbs only does variants. so just dim x.
Other ways to a running copy of excel
Set GetExcelApp = GetObject("", "Excel.Application")
Msgbox GetExcelApp
To start a new excel and showing an excel constant replaced by it's value (43).
set xlapp = createobject("Excel.Application")
xlapp.Workbooks.Open "C:\Users\User\Documents\Super.xls"
'43 is 95/97 look up xlExcel9795 in object browser to see other options
xlapp.ActiveWorkbook.SaveAs "C:\Users\User\Documents\Super.xls", 43

Related

Check which file is open VBA

All,
I have a large module which in the earlier part checks whether a files is in use (Readonly) format and if it is in use to open the next file. I.e. if file one is in use open file two etc..
In a later part of the module I wish to use the file which has been opened. However I am struggling to identify the file which is opened in the earlier part of the automation and set is as WB.
The code I am currently using is;
Dim wb As Object
On Error Resume Next
Workbooks("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions1.csv").Activate
If Err.Number = 0 Then
wb = GetObject("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions1.csv")
GoTo skipline
End If
On Error GoTo 0
On Error Resume Next
Workbooks("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions2.csv").Activate
If Err.Number = 0 Then
wb = GetObject("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions2.csv")
GoTo skipline
End If
On Error GoTo 0
On Error Resume Next
Workbooks("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions3.csv").Activate
If Err.Number = 0 Then
wb = GetObject("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions3.csv")
GoTo skipline
End If
On Error GoTo 0
On Error Resume Next
Workbooks("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions4.csv").Activate
If Err.Number = 0 Then
wb = GetObject("\\Csdatg04\psproject\Robot\Project Preload\Transactions\Transactions4.csv")
GoTo skipline
End If
skipline:
On Error GoTo 0
Can anyone recommend how I can identify which file is open and set is as WB
Any help would be much appreciated.
Thanks
Don't try to match the path: mapped drives and aliases will spoof your matches.
Your match term is the file name, with the extension, and you can iterate the Excel workbooks collection to see if there's a matching name:
Option Explicit
Public Function WorkbookIsOpen(WorkBookName As String) As Boolean
' Returns TRUE if a workbook (or csv file open in Excel) is open
Dim wbk As Excel.Workbook
WorkbookIsOpen = False
If IsError(WorkBookName) Then
WorkbookIsOpen = False
ElseIf WorkBookName = "" Then
WorkbookIsOpen = False
Else
For Each wbk In Application.Workbooks
If wbk.Name = WorkBookName Then
WorkbookIsOpen = True
Exit For
End If
Next wbk
End If
End Function
Public Function FileName(FilePath As String) As String
' Returns the last element of a network path
' This is usually the file name, but it mat be a folder name if FilePath is a folder path:
' FileName("C:\Temp\Readme.txt") returns "ReadMe.txt"
' ?FileName("C:\Temp") returns "Temp"
' FileName("C:\Temp\") returns ""
' This function does not perform any file checking - the file need not exist, the path
' can be invali or inaccessible. All we're doing is String-handling.
Dim arr() As String
Dim i As Integer
If IsError(FilePath) Then
FileName = "#ERROR"
ElseIf FilePath = "" Then
FileName = ""
Else
arr = Split(Trim(FilePath), "\")
i = UBound(arr)
FileName = arr(i)
Erase arr
End If
End Function
Then it's just a matter of checking if the open workbook is open read-only:
Dim bReadOnly As Boolean
If WorkbookIsOpen("C:Temp\Brian.csv") Then
bReadOnly = Application.WorkBooks(FileName("C:Temp\Brian.csv")).ReadOnly
End If
Things get a lot more interesting if you need to check that the file isn't open in another session of Excel, or another application: this code won't test that for you.
I need to answer the other point in your question: opening the file in Excel if it isn't already open in this session.
I would recommend using Application.Workbooks.Open(FileName) for that, as it's smarter than GetObject() and will open the file - csv, xml, xls, xlsx - in Excel, as a workbook, with Excel guessing the necessary format parameters. Also,the native 'open' function allows you to specify additional parameters, like Read-Only.

Pass variable from PowerShell to VBA macro?

I have a PowerShell script that automates some report processing, and I have numerous separate macros to perform very similar autofilter functions, but on different criteria.
Is it possible to pass this criteria from PowerShell into the macro? I could then just have the 1 macro.
ColNum = Application.Match("*header", Range("A1:Z1"), 0)
If Not IsError(ColNum) Then
ActiveSheet.Range("A1").AutoFilter Field:=ColNum, Criteria1:="$criterafromPowerShell", Operator:=xlAnd
End If
I currently do a similar thing but the other way round, the output from these macros I insert to the workbook and extract back to PowerShell like so:
$counts = $workbook.worksheets.item(2)
$xRows = $counts.cells.item(1,1).Text
$yeRows = $counts.cells.item(1,2).Text
I concede I could possibly do this the other way round, and insert the text I want to use in a worksheet after the file is opened and before the macros are run, then pick it up inside the macro... but it seems messy.
Any suggestions?
Example:
$xlApp = New-Object -ComObject "Excel.Application"
$xlApp.Workbooks.Open("C:\Users\MacroMan\Documents\MyMacroWorkbook.xlsm")
$returnValue = $xlApp.Run("'MyMacroWorkbook.xlsm'!GenerateString", 6)
Echo $returnValue
FOOBAR
$returnValue = $xlApp.Run("'MyMacroWorkbook.xlsm'!GenerateString", 3)
Echo $returnValue
FOO
In the "MyMacroWorkbook" (VBA):
Public Function GenerateString(strLength As Integer) As String
GenerateString = Left("FOOBAR_SOMETHING", strLength)
End Function
I use the below code to pass two arguments from my VBscript to open a prticular workbook and launch required macro, you could pass the variable you want as a variable to the sub, i.e. Sub test(passedvariablehere) and make the sub to account for it:
'Create a WshShell to get the current directory
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
If (Wscript.Arguments.Count < 2) Then
Wscript.Quit
End If
'retrieve the arguments
Dim strWorkerWB
strWorkerWB = Wscript.Arguments(0)
Dim strMacroName
strMacroName = Wscript.Arguments(1)
' Create an Excel instance
Dim myExcelWorker
Set myExcelWorker = CreateObject("Excel.Application")
myExcelWorker.Application.Visible = True
' Open the Workbook specified on the command-line
Dim oWorkBook
Set oWorkBook = myExcelWorker.Workbooks.Open(strWorkerWB)
on error resume next
' Run the calculation macro
myExcelWorker.Run strMacroName
if err.number <> 0 Then
' Error occurred - just close it down.
oWorkBook.Close
Set oWorkBook = Nothing
myExcelWorker.Quit
Wscript.Quit
End If
err.clear
oWorkBook.Close
Set oWorkBook = Nothing
myExcelWorker.Quit
Set myExcelWorker = Nothing
Set WshShell = Nothing
on error goto 0
First argument is the fullpath/name to workbook, second argument is the sub name

How to parse a .doc file using a word VBA

I am stuck with this word VBA and in need of some assistance.I have 160 word documents in a folder and each .doc contains atleast one phrase like 'IO:' I want to copy all the file names that starts after 'IO:' and stop copying when the cursor finds Report Output:. Here is one sample input:
`Step Name: Step 3 – GP00BMDR
Step Description:: GENISYS main batch driver which processes external transactions and internal transactions, updates masters, generates transaction records to the accounting subsystem and produces print files.
File Specification:
Input: 1. GPFTRNW – PHGP.GPFTRNW.TRN.STD.KSDS
2. GPFSCIM – PHGP.GPFSCIM.SCI.KSDS
3. GPFSCSM – PHGP.GPFSCSM.SCS.KSDS
IO: 1. GPFPDGT – PHGP.GPFPDGT.PDG.TRN.KSDS
2. GPFRTXT – PHGP.GPFRTXT.RTX.KSDS
Report Output: Nil`
So I want to copy the .doc name and the file names after IO: and stops when the cursor reaches Report Output: . Here is my script:
Sub Ftp_Step_Details()
'this macro checks for FTP in respective steps and copy and writes in a cell along with the corresponding JCL
Dim wordApplication As Word.Application
Dim wordDocument As Word.Document
Dim flag As String
Dim Folder As String, J As String, FLD As Object
Dim Objfile As Object
Dim objfso As Object
Dim intRow As String
Dim contents As String
flag = True
Dim intResult As Integer
Dim strPath As String
'the dialog is displayed to the user
intResult = Application.FileDialog(msoFileDialogFolderPicker).Show
'checks if user has cancled the dialog
If intResult <> 0 Then
'dispaly message box
strPath = Application.FileDialog( _
msoFileDialogFolderPicker).SelectedItems(1)
End If
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("D:\FILE-LIST\File-List.xlsx")
objExcel.Visible = True
objExcel.Workbooks.Add
objExcel.Cells(1, 1).Value = "Jcl Name"
objExcel.Cells(1, 2).Value = "File Names"
'Folder = "D:\TEST-IO" 'JCL source goes here
Set objfso = CreateObject("Scripting.FileSystemObject")
Set wordApplication = CreateObject("Word.Application")
intRow = 2
'Opening the file in READ mode
Set FLD = objfso.GetFolder(strPath)
For Each file In FLD.Files
Set Objfile = wordApplication.Documents.Open(file)
Do While Not Objfile.AtEndOfStream
contents = Objfile.ReadLine
If contents Like "*IO:" Then
flag = True
End If
If contents Like "*Report Output:*" Then
flag = False
End If
If flag = True Then
objExcel.Cells(intRow, 1).Value = file.Name
objExcel.Cells(intRow, 2).Value = contents3
intRow = intRow + 1
End If
Loop
Next
Objfile.Close
MsgBox "THANK YOU"
End Sub
Now whie testing the code i am getting TYPE MISMATCH in the step Set Objfile = wordApplication.Documents.Open(file) why is that?
Another doubt I have does Readline function works in word VBA as well?
Now whie testing the code i am getting TYPE MISMATCH in the step Set Objfile = wordApplication.Documents.Open(file) why is that?
Because File is type Scripting.File which is an Object, and the Documents.Open method expects a string.
You could try:
Documents.Open(file.Path)
Another doubt I have does Readline function works in word VBA as well?
No, I don't think so.

Application defined or Object defined error in excel vba

I am new to excel. I need to create a new excel from the macro written and need to add some data and save it as a csv file. I am getting Application defined or Object defined error. Her is the code
Sub splitIntoCsv()
Dim wbIn
Dim wbIn1 As Workbook
Dim header As Variant
Set wbIn = CreateObject("Excel.Application")
wbIn.Workbooks.Add
'wbIn.Worksheets(1).Name = "TestData"
'Set wbIn1 = Workbooks.Open(Sheet1.Range("b25").Value, True, False)
header = Split(ThisWorkbook.Sheets(1).Range("B2").Value, ",")
For k = 1 To 10
DoEvents
Next k
For i = LBound(header) To UBound(header)
'MsgBox header(i)
**wbIn.Worksheets(1).Range("a" & i).Value = header(i)**
Next i
wbIn.Worksheets(1).SaveAs Filename:="D:\file.csv" & Filename, FileFormat:=xlCSV, CreateBackup:=False
End Sub
I got the error at the Starred lines.Help needed,
Thanks in advance,
Raghu.
The following code now work, Please have a look
Sub splitIntoCsv()
Dim wbIn As Excel.Application
Dim wbIn1 As Workbook
Dim header As Variant
Set wbIn = CreateObject("Excel.Application")
Set wbIn1 = wbIn.Workbooks.Add
header = Split(ThisWorkbook.Sheets(1).Range("B2").Value, ",")
For k = 1 To 10
DoEvents
Next k
For i = LBound(header) To UBound(header)
'**wbIn1.Worksheets(1).Range("a" & i).Value = header(i)**
Next i
wbIn1.SaveAs Filename:="D:\file.csv" & Filename, FileFormat:=xlCSV, CreateBackup:=False
wbIn1.Close
Set wbIn1 = Nothing
wbIn.Application.Quit
Set wbIn = Nothing
End Sub
The first problem in the code was that you were trying to save using the worksheets. Worksheets do not have a save method, Workbooks do.
While fixing the code, I had a large number of excel objects in memory. Please have a look at how to close and exit a excel application.
For the starred line you asked about, note that the Split function returns a zero-based array, so in your first time through the loop you are trying to refer to cell A0. So, change the line to:
wbIn.Worksheets(1).Range("a" & i+1).Value = header(i)

VBScript - How do I get these workbooks to talk?

I posted earlier about getting my VBScript to wait until a process had finished before continuing (further info: VBScript - How to make program wait until process has finished?.
I was given an adequate answer after some discussion. However, it seems that I am now going in a new direction with the code as the solution presented another problem that I am hoping you may be able to help me with.
Basically I have some code which I have provided below. It takes in 4 arguments, one of which is a PATH to a folder containing many files which I want to use along with the other three in my VBA macro.
If WScript.Arguments.Count = 4 Then
' process input argument
Set args = WScript.Arguments
arg1 = args.Item(0)
arg2 = args.Item(1)
arg3 = args.Item(2)
arg4 = args.Item(3)
' Create a WshShell instance
Dim WShell
Set WShell = CreateObject("WScript.Shell")
' Create an Excel instance
Dim x1
Set x1 = CreateObject("Excel.Application")
' Disable Excel UI elements
x1.DisplayAlerts = False
x1.AskToUpdateLinks = False
'x1.AlertBeforeOverwriting = False
x1.FeatureInstall = msoFeatureInstallNone
' Open the Workbooks specified on the command-line
Dim x1WB
Dim x2WB
Dim x3WB
Dim x4WB
Dim strWB1
Dim strWB2
Dim strWB3
Dim strWB4
Dim FSO
Dim FLD
Dim FIL
Dim strFolder
strWB1 = arg1
Set x1WB = x1.Workbooks.Open(strWB1)
' Show the workbook/Excel program interface. Comment out for silent running.
x1WB.Application.Visible = True
strWB2 = arg2
Set x2WB = x1.Workbooks.Open(strWB2)
' Show the workbook/Excel program interface. Comment out for silent running.
x2WB.Application.Visible = True
strWB3 = arg3
Set x3WB = x1.Workbooks.Open(strWB3)
' Show the workbook/Excel program interface. Comment out for silent running.
x3WB.Application.Visible = True
'To hold the string of the PATH to the multiple files
strFolder = arg4
Set FSO = CreateObject("Scripting.FileSystemObject")
'Get a reference to the folder I want to search
set FLD = FSO.GetFolder(strFolder)
Dim strMyMacro
strMyMacro = "my_excel_sheet_with_vba_module.xlsm!Sheet1.my_vba_macro"
'loop through the folder and get the file names
For Each Fil In FLD.Files
WshShell.run """C:\Program Files\Microsoft Office\Office14\EXCEL.exe"" " & Fil, 1, true
x1.Run strMyMacro
'~~> Problem - How do I get the macro to run before opening the above file but run after it has opened (due to setting the bWaitOnReturn to true)
'~~> Problem - How do I get the file on current iteration to close after the macro has completed?
'~~> Problem - If this is not the issue, can you identify it?
Next
x1WB.close
x2WB.close
x3WB.close
'x4WB.close
' Clean up and shut down
Set x1WB = Nothing
Set x2WB = Nothing
Set x3WB = Nothing
Set x4WB = Nothing
Set FSO = Nothing
Set FLD = Nothing
x1.Quit
Set x1 = Nothing
Set WshShell = Nothing
WScript.Quit 0
Else
WScript.Quit 1
End If
The script works like this:
4 arguments are passed to the script. The 3rd argument is a .xlsm file which contains my VBA macro. The last argument is a PATH to a folder containing multiple files.
It then opens up the first three Excel files.
Then I run a loop to iterate through the files Fil in the folder that was specified as the 4th argument. AFAIK this has to be done via a WScript.shell using the .run method so that the rest of the script will hang until the Excel file it is processing finishes before closing it and opening up the next file in the folder.
After opening up file Fil, I then run the macro (albeit at this moment in time unsuccessfully).
I was tempted to simply open up all of the Excel files using the WScript.shell object however AFAIK I would not be able to run the macro this way.
Hopefully I have been able to define my aims of this piece of VBScript though if I haven't let me know and I shall clarify. Can you help?
Thanks,
QF.
Something along these lines might work for you (in Excel). A few things I'm not clear on though:
Where is your existing VBA macro - I'm guessing it's in one of the 3 files you're opening?
What types of files are in the folder you're looping through? I guessed Excel.
How is the vbscript being run? It looks like you're shelling out from your HTA, but why not include it directly in the HTA? That would save you from having to shell out and pass arguments...
Option Explicit
Dim wb1 As Workbook, wb2 As Workbook
Sub ProcessFolder(path1, path2, sFolder)
Dim wb As Workbook
Dim s
Set wb1 = Workbooks.Open(path1)
Set wb2 = Workbooks.Open(path2)
If Right(sFolder, 1) <> "\" Then sFolder = sFolder & "\"
s = Dir(sFolder & "*.xls*", vbNormal)
Do While Len(s) > 0
Set wb = Workbooks.Open(sFolder & s)
ProcessFile wb
wb.Close False
s = Dir()
Loop
wb1.Close False
wb2.Close False
End Sub
Sub YourExistingMacro(wb As Workbook)
'do stuff with wb and presumably the other 3 open files...
End Sub