Exception calling "Open" with "1" argument(s): ..." in Excel after installing my addin - excel

I have been trying to automate excel automation that installs our company addin in excel and then load the library file (library.xlsm that contains the library macro subroutines and functions). After this for each test, I load the corresponding test.xlsm file and execute the macros. All this, I am doing using powershell (V3). My script gets called on one machine and executes on another remote machine.
This is how I install my addin:
kill -processname excel
$Release1RootDir = $workspace + "\Release1"
$release1Path = Get-ChildItem -Force $release1RootDir
if($release1Path -eq $Null) {
echo "Error: No sub-folder found having MyAddin Installer inside "$release1RootDir
}
else {
$release1 = $release1Path.name.replace('_', '.')
$ExcelAddinInstaller = ($release1Path.FullName + "\MyAddin.msi")
$ExcelAddinTargetDir = ($Release1Path.FullName)
$msiexecPath = "msiexec.exe"
if(Test-Path -Path $ExcelAddinInstaller){
echo "Version for MyAddin inside Release1: "$Release1
$proc = Start-Process $msiexecPath -ArgumentList /x, `"$ExcelAddinInstaller`", TARGETDIR=$ExcelAddinTargetDir, /quiet, /lvx, "D:\Temp\uninstall.log" -Wait
$proc = Start-Process $msiexecPath -ArgumentList /i, `"$ExcelAddinInstaller`", TARGETDIR=$ExcelAddinTargetDir, /quiet, /lvx, "D:\Temp\install.log" -Wait -ErrorAction Stop
echo "Installing addin"
Start-Process "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" -ArgumentList /tlb, "C:\Users\Serviceadmin\Addin\MyAddin\Release\MyAddin.dll"
}
else{
echo $ExcelAddinInstaller
}
}
PS: I am adding the .dll file since, the helper function in my Macros call my C# code.
However, while opening any of these xlsm files, I get the following error:
Exception calling "Open" with "1" argument(s): "Microsoft Excel cannot access the file 'D:\ABC\XYZ\workspace\library.xlsm'. There are
several possible reasons:
The file name or path does not exist.
The file is being used by another program.
The workbook you are trying to save has the same name as a currently open workbook."
At C:\Users\Serviceadmin\AppData\Local\Temp\hudson.ps1:94 char:3
+ $libraryBook = $excel.workbooks.open("$xlLibraryPath\$xlLibraryFileName");
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
The above error comes up despite the path of the files being correct. This is how I open my files using powershell:
$excel = new-object -comobject excel.application;
$excel.visible = $true;
$libraryBook = $excel.workbooks.open("$xlLibraryPath\$xlLibraryFileName");
$testWorkbook = $excel.workbooks.open("$testFile")
$excel.Run("$xlLibraryFileName!Initialize", "$testAct")
$loginsuccess = $excel.Run("$xlLibraryFileName!Login", "$xlenvironment", "$xlUserName", "$xlPassword");
if($loginsuccess)
{
$excel.Run("PerformTest");
$excel.Run("$xlLibraryFileName!Logout");
}
$testWorkbook.close($false)
$libraryBook.close($false)
$excel.quit()
I have verified the following:
1. Excel is installed in the required machine- Yes, Excel 2013
2. The path of the xlsm files- All are present
3. Successful installation of the addin
Is there something that I am missing?
Thanks in advance! :)

Well, it turns out that I had to add the folder- "Desktop" in each of the following paths. The solution is quite weird but it is now working for me:
C:\Windows\System32\config\systemprofile\Desktop (should be present for 32 bit machine and even for 64 bit)
C:\Windows\SysWOW64\config\systemprofile\Desktop (only for 64 bit machine)

Related

Powershell excel to csv script works in ISE but not in powershell console

I have a short script that takes certain worksheets out of an excel file and saves them individually as a CSV file.
Function ExcelToCsv ($File) {
$myDir = Split-Path -Parent $($global:MyInvocation.MyCommand.Definition)
$path = "$myDir\csv_files"
If(!(test-path -PathType container $path))
{
Write-Host "Folder csv_files not found, creating..."
New-Item -ItemType Directory -Path $path
}
$excelFile = "$myDir\" + $File + ".xlsx"
$Excel = New-Object -ComObject Excel.Application
$wb = $Excel.Workbooks.Open($excelFile)
$excel.DisplayAlerts = $false;
foreach ($ws in $wb.Worksheets) {
if($ws.name -like '*sheet*') {
$ws.SaveAs("$myDir\csv_files\" + $ws.name + ".csv", 6, 0, 0, 0, 0, 0, 0, 0, $true)
Write-Host "Saved file: $myDir\csv_files\"$ws.name".csv"
} else {
Write-Host "Worksheet "$ws.name" not an correct sheet. Not saved"
}
}
$Excel.Quit()
}
$FileName = "myexcel"
ExcelToCsv -File $FileName
Write-Host "`nCSV files successfully created"
read-host "Press ENTER to exit...."
This is the entire code, not much to it and this is the correct output when run from ISE:
PS U:\excel_to_csv> U:\excel_to_csv\create_csv_files.ps1
Saved file: U:\excel_to_csv\csv_files\ 1sheet .csv
Saved file: U:\excel_to_csv\csv_files\ 2sheet .csv
Saved file: U:\excel_to_csv\csv_files\ 3sheet .csv
CSV files successfully created
Press ENTER to exit....:
But when I use a Powershell console:
Folder csv_files not found, creating...
New-Item : Cannot find drive. A drive with the name 'if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -
Scope Process Bypass }; & 'U' does not exist.
At U:\excel_to_csv\create_csv_files.ps1:7 char:9
+ New-Item -ItemType Directory -Path $path
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (if((Get-Executi... Bypass }; & 'U:String) [New-Item], DriveNotFoundExce
ption
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.NewItemCommand
Ľutujeme, if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & 'U:\excel_to_csv\
myexcel.xlsx sa nepodarilo nájsť. Je možné, že bol premiestnený, premenovaný alebo odstránený.
At U:\excel_to_csv\create_csv_files.ps1:11 char:5
+ $wb = $Excel.Workbooks.Open($excelFile)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
CSV files successfully created
Press ENTER to exit....:
Some of it is written in Slovakian, it roughly translates to:
Sorry, if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & 'U:\excel_to_csv\
myexcel.xlsx could not be found. It is possible it was moved, renamed or deleted.
I have tried searching for a solution but nothing worked yet.
I tried making a bash script like this:
powershell.exe -noexit -file U:\create_csv_files.ps1
But that didn't work, not sure if I screwed it up.
As I am on a company computer I am unable to use administrator privileges, but if you believe the lack of them is the problem, I might be able to do something about it.
Thank you for any and all help!
Replace
$myDir = Split-Path -Parent $($global:MyInvocation.MyCommand.Definition)
with
$myDir = $PSScriptRoot
The automatic $PSScriptRoot variable reliably reports the full path of the directory in which the currently executing script is located, irrespective of how the script was invoked. The related $PSCommandPath variable contains the script file's own full path.
Your symptom implies that you invoked your script from outside a PowerShell session, via powershell.exe -Command (with the -Command CLI parameter potentially being positionally implied), in which case $global:MyInvocation.MyCommand.Definition contains the entire command text passed to -Command.

How to save a read-only file using PowerShell

I have an Excel file that I am opening, applying a password to it, and then saving it using PowerShell. I am getting the following error:
Exception calling "SaveAs" with "3" argument(s): "Cannot save as that name. Document was opened as read-only."
At C:\PasswordProtectExcelFiles.ps1:38 char:45
+ $a = $wb.SaveAs("$($FilePath)",$xlNormal,"$($Password)")
+ ~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
I have searched a lot but nothing has resolved my issue. Here are some questions I refered to already:
Powershell - SaveAs function when file already exists and
How to Remove ReadOnly Attribute on File Using PowerShell?.
My code:
param([string]$FilePath, [string]$Password )
$xl = new-object -comobject excel.application
$xl.Visible = $True
$xl.DisplayAlerts = $False
$wb = $xl.Workbooks.Open("$($FilePath)")
$a = $wb.SaveAs("$($FilePath)",$xlNormal,"$($Password)")
$a = $xl.Quit()
$a = Release-Ref($wb)
$a = Release-Ref($xl)
I have tried these codes after the Workbooks.Open statement to see if it will save the read-only file, and it worked, but then when I closed and reopened the code it stopped working:
Code1:
$file = Get-Item "$($FilePath)"
if ($file.IsReadOnly -eq $true)
{
$file.IsReadOnly = $false
}
Code2:
Set-ItemProperty "$($FilePath)" -name IsReadOnly -value $false
Actually, the file is not read only but the folder is and I am unable to check out the box that says read only. Same as this problem: https://social.technet.microsoft.com/Forums/windowsserver/en-US/f7ec4fc5-3bbe-4fd0-a8ca-c4ead75b010c/unable-to-removeclear-readonly-attribute-from-folder-in-windows-server-2008
According to the documentation for the Open() method, the third argument allows you to specify whether to open the file in read-only mode.
Set it to $false:
$wb = $xl.Workbooks.Open("$($FilePath)", 0, $false)

Why does PowerShell not want to save my file as a CSV

$Path = 'D:/ETL_Data/TwitchTVData.xlsx'
$csvPath = 'D:/ETL_Data/TwitchTVData2.csv'
# Open the Excel document and pull in the 'Sheet1' worksheet
$Excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($Path)
$page = 'Sheet1'
$ws = $Workbook.Worksheets | Where-Object {$_.Name -eq $page}
$Excel.Visible = $true
$Excel.DisplayAlerts = $false
# Set variables for the worksheet cells, and for navigation
$cells = $ws.Cells
$row = 1
$col = 4
$formula = #"
=NOW()
"#
# Add the formula to the worksheet
$range = $ws.UsedRange
$rows = $range.Rows.Count
for ($i=0; $i -ne $rows; $i++) {
$cells.Item($row, $col) = $formula
$row++
}
$ws.Columns.Item("A:D").EntireColumn.AutoFit() | Out-Null
$ws.Columns.Range("D1:D$rows").NumberFormat = "yyyy-MM-dd hh:mm"
$Excel.ActiveWorkbook.SaveAs($csvPath)
$Excel.Quit()
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
https://www.experts-exchange.com/questions/27996530/How-to-convert-and-xlsx-spreadsheet-into-CSV.html#answer38780402-20
I was attempting to follow that, but for some reason for me the SaveAs() doesn't work. It gives me an error
cannot access the file 'D://ETL_Data/E567DF00
What do I have to do to get this to save over to CSV?
Edit:
Exact error without the fileformat parameter 6 as suggested in the comments:
Microsoft Excel cannot access the file 'D:\//ETL_Data/8011FF00'. There are
several possible reasons:
o The file name or path does not exist.
o The file is being used by another program.
o The workbook you are trying to save has the same name as a currently open
workbook.
At D:\PS_Scripts\twitchExcelAddSnapShot.ps1:32 char:1
+ $Excel.ActiveWorkbook.SaveAs($csvPath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
Exact error with fileformat parameter 6:
The file could not be accessed. Try one of the following:
o Make sure the specified folder exists.
o Make sure the folder that contains the file is not read-only.
o Make sure the file name does not contain any of the following characters:
< > ? [ ] : | or *
o Make sure the file/path name doesn't contain more than 218 characters.
At D:\PS_Scripts\twitchExcelAddSnapShot.ps1:32 char:1
+ $Excel.ActiveWorkbook.SaveAs($csvPath,6)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
While PowerShell is pretty forgiving when it comes to path separators, COM+ servers (like Excel.Application) might not be.
Change the $csvPath variable value to use \ instead of /:
$csvPath = 'D:\ETL_Data\TwitchTVData2.csv'
To complement Mathias R. Jessen's helpful answer with background information:
It seems that Excel's application-specific behavior is the cause of your problem, unrelated to the underlying foundational subsystems or APIs used.
(Excel's automation API happens to be a COM server.)
I'm unclear on why Excel acts this way - it also does so in interactive use, though you could argue that at least in programmatic use it should allow / too.
To offer generalized advice:
On Windows, to be safe, use \, especially when dealing with application-level automation APIs, though at the level of system APIs / should work as well - see below.
In cross-platform code, use / (but watch out for the exceptions above; [System.IO.Path]::DirectorySeparatorChar reports the platform-appropriate (primary) character).
Though rarely used, Windows at the API level allows interchangeable use of \ and / (which apparently goes back to the DOS 2.0 days), when support for directories was introduced), and that is also reflected in higher-level subsystems, as the following examples demonstrate.
# PS: OK
# Should output c:\windows\win.ini
(Get-Item c:/windows/win.ini).FullName
# .NET: OK
# Should return the 1st child dir.'s path.
# Note that the child directory names will be appended with "\", not "/"
[System.IO.Directory]::GetDirectories('c:/windows/system32') | Select-Object -First 1
# COM (see Excel exception below): OK
# Should return $true
(New-Object -ComObject Scripting.FileSystemObject).FileExists('c:/windows/win.ini')
# Windows API: OK
# Should return a value such as 32.
(Add-Type -PassThru WinApiHelper -MemberDefinition '[DllImport("kernel32.dll")] public static extern uint GetFileAttributes(string lpFileName);')::GetFileAttributes('c:/windows/win.ini')
# cmd.exe: INCONSISTENTLY SUPPORTED
# Note: *quoting matters* here, so that tokens with / aren't mistaken for options.
# attrib: works
cmd /c 'attrib "c:/windows/win.ini"'
# dir: works with DIRECTORIES, but fails with FILES
cmd /c 'dir /b "c:/windows/system32"' # OK
cmd /c 'dir /b "c:/windows/win.ini"' # FAILS with 'File not found'
cmd /c 'dir /b "c:/windows\win.ini"' # Using \ for the FILE component (only) works.
Here's a minimal example that demonstrates Excel's problem with /:
# Create temporary dir.
$null = mkdir c:\tmp -force
$xl=New-Object -Com Excel.Application
$wb = $xl.Workbooks.Add()
# OK - with "\"
$wb.SaveAs('c:\tmp\t1.xlsx')
# FAILS - with "/":
# "Microsoft Excel cannot access the file 'C:\//tmp/F5D39400'"
$wb.SaveAs('c:/tmp/t2.xlsx')
$xl.Quit()
# Clean up temp. dir.

Powershell Send Key Excel

I would like to write a script in Powershell which does the following:
Opens Excel Workbook.
Click two times enter on the 2 appearing DialogBoxes.
Runs a macro, saves workbook and quits.
I have a problem with the 2nd step. In my script enter is sent to Powershell window and I see two lines added to the code.
Could anyone help me? Here is my code:
$p1 = "C:\"
$eo = new-object -comobject excel.application;
$eoc = dir $p1 -Include *.xlsm -Recurse
Foreach ($f1 in $eoc)
{
$wb = $eo.workbooks.open($f1.fullname)
while (!$eo.Ready){sleep 0.1}
$eo.Application.SendKeys('~')
while (!$eo.Ready){sleep 0.1}
$eo.Application.SendKeys('~');
$eo.Run("macro_name");
$eo.Application.CalculateFull;
while (!$eo.Ready){sleep 0.1};
$wb.save(); $wb.close()
}
$eo.quit()
You need something like this.
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('window name of your excel file') | Out-Null
This will focus your excel workbook and execute your send key commands.

Creating Powershell script to loop through excel file and create folders

I'm new to Powerscript and looking at writing a solution to loop through an excel file and create a folder for each row in the file.
At the moment I have the following:
$objExcel = new-object -comobject excel.application
$objExcel.Visible = $True
$ExcelFilesLocation = “D:\Users\”
$UserWorkBook = $objExcel.Workbooks.Open($ExcelFilesLocation + “ProjectCodes.xlsx”)
$UserWorksheet = $UserWorkBook.Worksheets.Item(1)
$intRow = 2
Do {
$Projectcode = $UserWorksheet.Cells.Item($intRow, 1).Value()
$pos = $userLogOnEmail.IndexOf(“#”)
$intRow++
} While ($UserWorksheet.Cells.Item($intRow,1).Value() -ne $null)
$objExcel.Quit()
$a = Release-Ref($UserWorksheet)
$a = Release-Ref($UserWorkBook)
$a = Release-Ref($objExcel)
The idea is to loop through the project code column for each row. Then create a folder that is named for the project code.
Having spent painful hours wrangling Excel COM objects with PowerShell, my advice is to give up! Office COM objects are confusing, unwieldy and slow.
Replace the technology you use to access Excel in PowerShell with something better. For example, this module: https://github.com/dfinke/ImportExcel. You can use Install-Module ImportExcel -Scope CurrentUser if you're using PS 5.
Apart from being easier to use and much faster it doesn't require Excel to be installed, making your final script more portable.
Admitedly, you don't get full Excel functionality with this module but since you seem to be doing no more than reading cells, you should be fine.
Alternatively, Save your Excel file as CSV and use Import-Csv instead.
To create a new directory, use New-Item
For example, assuming $Projectcode is a string containing a valid path:
New-Item -Path $Projectcode -Type Directory

Resources