A vbs file has been written that calls an Excel macro. However, when this vbs file is scheduled using Jenkins, the macro is not executed, though the console shows a success message.
Please suggest if there is some other way for scheduling Excel macro using Jenkins. vbs file code is this:
Option Explicit
On Error Resume Next
ExcelMacroExample
Sub ExcelMacroExample()
Dim xlApp
Dim xlBook
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("C:\Demo\Migration\Compare_Tool_For_Demo.xlsm", 0, True)
xlApp.Application.Run "Compare_Tool_For_Demo.xlsm!OpenSupport2Tool"
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
Jenkins build command :-
call "C:\Demo\Migration\Start_Report_Tool_For_Demo.bat
Macro operations are executed perfectly when the vbs file is executed manually. However whenever executed from Jenkins, it does not work.(Console shows "SUCCESS" however)
This sounds like a permissioning issue. I have no idea what 'Jenkins' is, but I think you should make sure it has Administrator rights.
Found the solution .
write a powershell file with contents -:
**
$macroBook = ".\Excel.xlsm"
$procedureName = "Macro"
$macroBookFullPath = (ls $macroBook).FullName
$macroProcName = (ls $macroBook).Name + "!" + $procedureName
$excelApp = New-Object -com "Excel.Application"
try {
$excelApp.DisplayAlerts = $false
$excelApp.Workbooks.Open($macroBookFullPath)
$excelApp.Run($macroProcName)
} finally {
$excelApp.DisplayAlerts = $false
$excelApp.Quit()
}
**
You would need powershell plugin for Jenkins . Follow the steps
1. Add build step "Windows Powershell"
2. Write this command - "mkdir C:\Windows\system32\config\systemprofile\Desktop"
3. Execute the powershell file (.ps1) by using "./" as a powershell step ("./Powershell_Test.ps1")
Then go your merry way.
Related
I have been struggling with what seems to be a common problem regarding opening, running Excel workbook macros, and closing the application from a visual basic script file (.vbs). I cannot terminate the Excel.exe.
I have found a number of recommendations about closing out the objects in the correct order, quitting before setting to nothing, being explicit about each object belonging to the parent object, but I still cannot seem to close of out EXCEL.EXE without manual intervention.
Some mention running a cmd script to kill Excel. I kick off a script like this manually when I have verified it is safe to do so but it is often not. I have dozens of individual batches kicked off each day, and some may be running halfway through during the kick off and completion of another. I would like the .vbs to close its created Excel instance so as to not overrun the memory.
Here is the skeleton of my script:
Set Params = Wscript.Arguments ' some arguments used in the run
Set eApp = CreateObject("Excel.Application")
eApp.Application.DisplayAlerts = False
' CreateObject("WScript.Shell").Run happens here for a log start
Set objWorkbook = eApp.Workbooks.Open("...")
eApp.Application.Visible = True
eApp.Windows(1).Visible = True
eApp.Worksheets(1).Activate
eApp.Application.Run "'...'!...", Cstr(Params(0)), Cstr(Params(1))
objWorkbook.Close False
eApp.Application.DisplayAlerts = True
Set objWorkbook = Nothing
' CreateObject("WScript.Shell").Run happens here for a log complete
eApp.Application.Quit
Set eApp = Nothing
Set Params = Nothing
Wscript.Quit
Is there anything that those more experienced can spot with the above code?
I want to put some Raw Data into a new Excel File with PowerShell. I'm aware how to use the comobject Excel.Application which PowerShell delivers.
Now my problem is the Data has to be processed in different ways inside the Excel (while the script is running). I already created some VBA Macros to do so a while back and now I'd like to reuse them. Is it possible to "use" the VBA through the Script inside the newly created and filled up Excel? Or do I need to recreate the VBA in Powershell?
Essentially, VBA is a language that connects to the Excel object library. PowerShell is also a language that can connect to Excel object library. Still others including Java, C#, Python, PHP, R, and more have this facility via Component Object Model (COM) available in Windows environments.
Therefore, simply translate your VBA code to PowerShell as any Excel method should be available. VBA tends to be tied to MS Office products because it is the defacto connected language but is actually a separate component (see how it is first reference checked under Tools\References... in IDE). Below are examples of simpler VBA to PowerShell translations:
Initialize Office objects
VBA
' EARLY BINDING
Set xlObj = New Excel.Application
Set accObj = New Access.Application
Set wrdObj = New Word.Application
...
' LATE BINDING
Set xlObj = CreateObject("Excel.Application")
Set accObj = CreateObject("Access.Application")
Set wrdObj = CreateObject("Word.Application")
...
PowerShell
$xlObj = new-object -comobject excel.application
$accObj = new-object -comobject access.application
$wrdObj = new-object -comobject word.application
...
Open Office objects with Excel's Workbooks.Open, Access' OpenCurrentDatabase, Word's Documents.Open. Note: None of these methods are restricted to VBA.
VBA
Set xlWB = xlObj.Workbooks.Open("C:\Path\To\Workbook.xlsx")
Set accDB = accObj.OpenCurrentDatabase("C:\Path\To\Access.accdb")
Set wrdDOC = wrdObj.Documents.Open("C:\Path\To\Document.docx")
...
PowerShell
$xlWB = $xlObj.Workbooks.Open("C:\Path\To\Workbook.xlsx")
$accDB = $accObj.OpenCurrentDatabase("C:\Path\To\Access.accdb")
$wrdDOC = $wrdObj.Documents.Open("C:\Path\To\Document.docx")
...
Handle collections (e.g., Excel sheets, Access tables, Word paragraphs).
VBA
' SELECT SINGLE OBJECTS
Set xlSheet = xlWB.Worksheets("mySheet")
Set accTable = accObj.Currentdb().TableDefs("myTable")
Set wrdParag = wrdDOC.Paragraphs(1)
...
PowerShell
# EXCEL WORKSHEETS LOOP
$xlObj = new-object -comobject excel.application
$xlWB = $xlObj.Workbooks.Open("C:\Path\To\Workbook.xlsx")
Foreach($wsh in $xlWB.Worksheets)
{
Write-host $wsh.name
}
$xlWB.Close($false)
$xlObj.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlObj )
# ACCESS DB TABLES LOOP
$accObj = new-object -comobject access.application
$accDB = $accObj.OpenCurrentDatabase("C:\Path\To\Access.accdb")
Foreach($tbl in $accObj.CurrentDb().TableDefs())
{
Write-host $tbl.name
}
$accDB.DoCmd.CloseDatabase
$accObj.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($accObj )
I want to create a Windows script to execute excel and open a file p and using the password
Example
Start excel c:\Documents\ExcelFile.xls
but also I want to add the password
Start excel c:\Documents\ExcelFile.xls Password
But when I try to do that is not recognized
You can create a PowerShell script to perform that using Workbook Open function.
$path = "c:\temp\1.xls"
$password = "123"
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.Workbooks.Open($path,$false,$false,5,$password)
$excel.Visible = $true
Save the script to a text file OpenExcel.ps1.
Usage:
powershell -file OpenExcel.ps1
Excel has no command line switch to submit a password.
See Command-line switches for Microsoft Office products
But you can use a VBScript StartExcel.vbs instead of a batch file StartExcel.bat to do that:
Set oExcel = CreateObject("Excel.Application")
Set oWorkbook = oExcel.Workbooks.Open("c:\Documents\ExcelFile.xls", 0, 0, 5, "<myPassword")
I have a vbscript that opens a workbook and runs a procedure in the module1 of the workbook, then closes the workbook. Works great. But here's the thing. The path to the workbook is hard coded, like this:
Set xlBook = xlApp.Workbooks.Open("E:\FolderName\WorkbookName.xlsm", 0, True)
I don't mind requiring the user to have the script and the workbook in the same folder, and requiring that they not change the name of the workbook file, but I'd like to just substitute the hard coded path with something dynamic, like:
Set xlBook = xlApp.Workbooks.Open(VBSPath & "\WorkbookName.xlsm", 0, True)
So the path is whatever is the path of the script.
Is that possible? Any other ideas?
tod
VBScript provides various information about the current script and host process via properties of the WScript object, among them:
ScriptFullName: The full path to the current script.
ScriptName: The filename of the current script.
You can derive the script folder from the ScriptFullName property in a number of ways, e.g.
By using the GetParentFolder method:
Set fso = CreateObject("Scripting.FileSystemObject")
dir = fso.GetParentFolderName(WScript.ScriptFullName)
By using the Len and Left functions:
dir = Left(WScript.ScriptFullName, Len(WScript.ScriptFullName)-Len(WScript.ScriptName))
By using the InStrRev and Left functions:
dir = Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName, "\"))
By using the Split and Join functions:
a = Split(WScript.ScriptFullName, "\")
a(UBound(a)) = ""
dir = Join(a, "\")
By using the Replace function:
dir = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
Note that this approach might prove problematic if (for whatever reason) the script name appears somewhere else in the full name of the script as well (e.g. C:\script.vbs\script.vbs).
You can try like that :
VBSPath = Left(WScript.ScriptFullName,(Len(WScript.ScriptFullName) - (Len(WScript.ScriptName) + 1)))
msgbox VBSPath
I figured out one solution, very similar to what has been posted here.
I created a WScript.Shell object:
Set WshShell = CreateObject("WScript.Shell")
Then I used the CurrentDirectory as the path of the workbook:
Set xlBook = xlApp.Workbooks.Open(WshShell.CurrentDirectory & "\WorkbookName.xlsm", 0, True)
Works!
I've read many post looking for my answer, but all are similar to this:
Reading excel files in vb.net leaves excel process hanging
My problem is that I don't quit the app...
The idea is this:
If a User has Excel Open, if he has the file I'm interested in open... get that Excel instance and do whatever I want to do...
But I don't to close his File after I'm done... I want him to keep working on it, the problem is that when he closes Excel... The process keeps running... and running... and running after the user closes Excel with the X button...
this is how I try to do it
This piece is used to know if he has Excel open, and in the For I check for the file name I'm interested in.
Try
oApp = GetObject(, "Excel.Application")
libroAbierto = True
For Each libro As Microsoft.Office.Interop.Excel.Workbook In oApp.Workbooks
If libro.Name = EquipoASeccionIdSeccion.Text & ".xlsm" Then
Exit Try
End If
Next
libroAbierto = False
Catch ex As Exception
oApp = New Microsoft.Office.Interop.Excel.Application
End Try
here would be my code... if he hasn't Excel open, I create a new instance, open the file and everything else.
My code ends with this:
If Not libroAbierto Then
libroSeccion.Close(SaveChanges:=True)
oApp.Quit()
Else
oApp.UserControl = True
libroSeccion.Save()
End If
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(libroOriginal)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(libroSeccion)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(origen)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(copiada)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oApp)
libroOriginal = Nothing
libroSeccion = Nothing
oApp = Nothing
origen = Nothing
copiada = Nothing
nuevosGuardados = True
So you can see that, if I opened the file, I call oApp.Quit() and everything else and the Excel Process ends after a few seconds (maybe 5 aprox.)
BUT if I mean the user to keep the file open (not calling Quit()), Excel process keeps running after the user closes Excel with the X button.
Is there any way to do what I try to do?? Control a open instance of excel and releasing everything so when the user closes it with the X button, the Excel Process dies normally???
Thanks!!!
It seems to me it would be better to use CreateObject instead of GetObject(, "Excel.Application") (see http://support.microsoft.com/kb/288902/en and http://technet.microsoft.com/en-us/library/ee176980.aspx). Then call of Quit method before calling of FinalReleaseComObject and assigninh Nothing will be have a clear sense.