I'm trying to convert an Excel .xls file that has several worksheets into a .csv with Powershell 4.0. I know the SaveAs in the for each loop isn't phrased right, and that the error is pointing to line 17 and character 9, I just don't know how to fix it or how to interpret the error code 0x800A03EC.
Here's the script:
Function ExportWSToCSV ($inputWorkbookPath, $outputFilePrefix, $outputDirectory)
{
#Start Excel invisibly without pop-up alerts.
$inputWorkbookPath = "R:\Unclaimed Property\NC State\Jun 2015\" + `
"NC_RAW_JUL1986thruMAR2013" + ".xls"
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$excel.DisplayAlerts = $false
#Open Excel file.
$workBook = $excel.Workbooks.Open($inputWorkbookPath)
foreach ($workSheet in $workBook.Worksheets)
{
$n = $inputWorkbookPath + "_" + $workSheet.Name
$workSheet.SaveAs($outputDirectory + $n + ".csv", 6)
}
$excel.Quit()
}
ExportWSToCSV -inputWorkbookPath "R:\Unclaimed Property\NC State\Jun 2015\NC_RAW_JUL1986thruMAR2013.xls" `
-outputFilePrefix "output_" `
-outputDirectory "R:\Unclaimed Property\NC State\Jun 2015\"
Here's the error:
Exception calling "SaveAs" with "2" argument(s): "Exception from HRESULT: 0x800A03EC"
At \\ncdfs1\documents$\ANDREWN\My Documents\PSscript_for_NC.ps1:17 char:9
+ $workSheet.SaveAs($outputDirectory + $n + ".csv", 6)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
I strongly feel your issue is coming from your path concatenation logic. Lets look at the following code from within your loop.
$n = $inputWorkbookPath + "_" + $workSheet.Name
$workSheet.SaveAs($outputDirectory + $n + ".csv", 6)
In your example call your variables I think are mapped as follows:
$inputWorkbookPath equals "R:\Unclaimed Property\NC State\Jun 2015\NC_RAW_JUL1986thruMAR2013.xls"
$workSheet.Name equals "Bagel" # I made that up.
$outputDirectory equals "R:\Unclaimed Property\NC State\Jun 2015\"
So you are going to try and set the new file name as:
R:\Unclaimed Property\NC State\Jun 2015\R:\Unclaimed Property\NC State\Jun 2015\NC_RAW_JUL1986thruMAR2013.xls_Bagel.csv
Which does not look right at all. If you just had the line in your loop
$outputDirectory + $n + ".csv"
I think you would see the issue. Just some simple debugging.
Lets fix this
First guess is that you just need to change it to something like this
$path = $outputDirectory + $workSheet.Name + ".csv"
$workSheet.SaveAs($path, 6)
Outside the scope of this question it would be a good idea to check if that path exists before saving it. It would save some potential headache.
Related
I know this is a very generic error message and I have spent many hours looking through similar questions without any luck.
Here is my PowerShell script producing this error:
$ExcelObject = New-Object -ComObject excel.application
$excelProcessId = ((get-process excel | select MainWindowTitle, ID, StartTime | Sort StartTime)[-1]).Id
$ExcelObject.visible = $true
$ExcelObject.DisplayAlerts = $true
$folderpath = "C:\myfiles\TESTER.xlsx"
$Workbook = $ExcelObject.Workbooks.Open($folderpath)
$WorkSheet = $Workbook.Worksheets.Item("TAB1")
$sourceList = "value1,value2,value3"
$missing = [system.type]::missing
$sourceRange = $WorkSheet.Range("A3:A22")
$sourceRange.Validation.add(3,1,$missing,$sourceList,$missing)
$Workbook.save()
$Workbook.close()
$ExcelObject.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($Workbook)
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelObject)
[GC]::Collect()
Remove-Variable ExcelObject
Stop-Process -Id $excelProcessId -Force
resulting error:
Exception from HRESULT: 0x800A03EC
At line:11 char:1
+ $sourceRange.Validation.add(3,1,$missing,$sourceList,$missing)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
I have tried to use the value list directly but same error:
$sourceRange.Validation.add(3,1,$missing,"value1,value2,value3",$missing)
I replaced the $missing but same error:
$sourceRange.Validation.add(3,1,1,$sourceList)
I have no more ideas on how to resolve this issue and would appreciate any suggestions.
Thanks a lot for your time.
I have found the problem: the specified range had to be cleared of any existing validation:
$sourceRange = $WorkSheet.Range("A3:A22")
$sourceRange.Validation.Delete()
$sourceRange.Validation.add(3,1,$missing,$sourceList,$missing)
I feel a little embarrassed, but maybe it is of use to someone down the line.
I am trying to perform arithmetic on an existing excel sheet that has figures in it. My code:
$Excel = New-Object -ComObject Excel.Application
$ExcelWorkBook = $Excel.Workbooks.Open($temp)
$ExcelWorkSheet = $Excel.WorkSheets.item(1)
$ExcelWorkSheet.activate()
$Prehit = $ExcelWorkSheet.Cells.Item(2,1)
$Hit1 = $ExcelWorkSheet.Cells.Item(2,2)
$Hit2 = $ExcelWorkSheet.Cells.Item(2,3)
$Hit3 = $ExcelWorkSheet.Cells.Item(2,4)
$Remain = 0
If ($hit -eq 1) {
$Remain = $Prehit - $Hit1
}
If ($hit -eq 2) {
$Remain = $Prehit - $Hit1- $Hit2
}
Yields the following error:
Method invocation failed because [System.__ComObject] does not contain a method named 'op_Subtraction'.
At C:\path_to_ps1_file.ps1:40 char:3
+ $Remain = $Prehit - $Hit1- $Hit2
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Subtraction:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
I have tried casting all the variables as ints yet that yields the same error. I even casted the numbers as ints in the powershell modules used to create this excel file. What am I missing?
I realize now I was referencing the cell values incorrectly. The correct way is to do:
$Prehit = $ExcelWorkSheet.Cells.Item(2,1).Text
$Hit1 = $ExcelWorkSheet.Cells.Item(2,2).Text
$Hit2 = $ExcelWorkSheet.Cells.Item(2,3).Text
$Hit3 = $ExcelWorkSheet.Cells.Item(2,4).Text
Whenever I've run into this sort of thing, I just the 'Excel Marco Recorder' and review the VBA code it produces and then convert that to PowerShell for later automation use cases.
Yet at no point in the code you posted are you making the XLS visible for you to act on it.
For example:
# Instantiate Excel instnace
$excel_test = New-Object -ComObject Excel.Application
# Make the instance visiable to work with it
$excel_test.visible = $true
# Catch alerts
$excel_test.DisplayAlerts = $true
# Add in the file source
$excel_test.Workbooks.Add('D:\Temp\Test.xlsx')
# Choose a sheet in the workbook
$Sheet = $excel_test.Worksheets.Item(1)
# Assign a formula to the target variable
$strFormula = '=(SUM(A1:C3)/3) - 1'
# Assign the formula to the target variable
$Sheet.Cells.Item(4,4) = $strFormula
$SourcecellCell = ($Sheet.Cells.Item(4,4)).Value2
$NewCell = 3
$sheet.Cells.Item(5,5) = $SourcecellCell - $NewCell
# Exit the XLS without saving
$excel_test.Quit()
Whenever I've run into this sort of thing, I just the 'Excel Marco Recorder' and review the VBA code it produces and then convert that to PowerShell for later automation use cases.
Yet at no point in the code you posted are you making the XLS visible for you to act on it. Since it is not visible, you cannot perform UI actions on it.
Secondly, this...
$excel_test.Worksheets.Item(2).Cells.Item(2,2).Formula() = $strFormula
... is where your issues begin. If you step through this one step at a time, you'll immediately see the aforementioned will simply fail.
For example:
# Instantiate Excel instance
$excel_test = New-Object -ComObject Excel.Application
# Make the instance visible to work with it
$excel_test.visible = $true
# Catch alerts
$excel_test.DisplayAlerts = $true
# Add in the file source
$excel_test.Workbooks.Add('D:\Temp\Test.xlsx')
# Results
<#
Application : Microsoft.Office.Interop.Excel.ApplicationClass
Creator : 1480803660
Parent : Microsoft.Office.Interop.Excel.ApplicationClass
...
#>
# Assign a formula to the target variable
$strFormula = "=((A1:C4/10000)-1)"
# Assign the formula to the target variable
$excel_test.Worksheets.Item(2).Cells.Item(2,2).Formula() = $strFormula
<#
Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))
At line:1 char:1
+ $excel_test.Worksheets.Item(2).Cells.Item(2,2).Formula() = $strFormul ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
#>
$Error | Format-List -Force
<#
Exception : System.Management.Automation.RuntimeException: The variable '$command' cannot be retrieved because it has not been set.
at System.Management.Automation.VariableOps.GetVariableValue(VariablePath variablePath, ExecutionContext executionContext,
VariableExpressionAst varAst)
at Prompt(Closure , FunctionContext )
TargetObject : command
CategoryInfo : InvalidOperation: (command:String) [], RuntimeException
FullyQualifiedErrorId : VariableIsUndefined
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Prompt, C:\Users\Daniel\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1: line 55
at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}
PSMessageDetails :
...
#>
The formula =LEFT(AB4,FIND(" ",AB5)-1 works perfectly in Excel, but seems to be causing errors in PowerShell where I get this error:
Exception from HRESULT: 0x800A03EC
At C:\Scripts\Excel_NUID2.ps1:21 char:1
+ $worksheet.range("AH5:AH$rows").formula = "=LEFT(AB4,FIND(" ",AB5)-1"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
My PowerShell Script Code;
#Open Up the Workbook#
$excel = new-object -comobject Excel.Application
$excel.visible = $false
$workbook =
$excel.workbooks.open("c:\Users\Jack\documents\NUID_Status_Report.xlsx")
$worksheet = $workbook.Worksheets.Item(1)
$rows = $worksheet.range("A1").currentregion.rows.count
### Set up a filter ###
$headerRange = $worksheet.Range("a4","aj4")
$headerRange.AutoFilter() | Out-Null
#### Trims Password Expiration Date Name ###
$worksheet.range("AH4").formula = "Shortened Expiration Date"
[void]$worksheet.Cells.Item(1,1).select()
$excel.visible = $true
#### Trims Password Expiration Date Formula ###
$worksheet.range("AH5:AH$rows").formula = "=LEFT(AB4,FIND(" ",AB5)-1"
[void]$worksheet.Cells.Item(1,1).select()
$excel.visible = $true
Quotes within a quoted string need to be doubled-up.
$worksheet.range("AH5:AH$rows").formula = "=LEFT(AB4,FIND("" "",AB5)-1)"
'you can also get rid of the inside quotes with the CHAR function
$worksheet.range("AH5:AH$rows").formula = "=LEFT(AB4, FIND(CHAR(32), AB5)-1)"
ASCII character 32 is a space. I've also added a bracket to make a legal formula.
I have a file which file extension is .xls, but the weird thing is when save as, the default is go to html file.
This caused a problem when I'm using my powershell script to perform some action on the file and saved it as xls file. The result is the script generate one xls file and one folder which contain html file. Is there a way to fix this issues ? I just want to save the file as xls file wihout any html files. Any helps are much appreciated.
Here the code that I use to save file as .xls
Function RenameTab ($ExcelFileName, $OutLoc)
{
$excelFile = "D:\Projects\" + $excelFileName + ".xls"
$xldoc = New-Object -ComObject "Excel.Application"
$xldoc.Visible = $false
$xldoc.DisplayAlerts = $false
$workbook = $xldoc.Workbooks.Open($excelFile)
foreach ($worksheet in $workbook.Worksheets)
{
$n = $ExcelFileName ##+ "_" + $worksheet.Name
$worksheet = $workbook.worksheets.item(1)
$worksheet.name = "Sheet1"
$workbook.SaveAs($OutLoc + $n + ".xlsx")
$workbook.Close()
}
$xldoc.Quit()
}
When you call SaveAs, you should really specify the file format.
According to the documentation for SaveAs, it would be the second argument, so the corrected line would be:
$workbook.SaveAs($OutLoc + $n + ".xlsx", 51) # 51 = xlOpenXMLWorkbook
I don't have all that much experience with COM interaction, but you might be able to use the enumeration directly somehow and make the line similar to:
$workbook.SaveAs($OutLoc + $n + ".xlsx", $xldoc.XlFileFormat.xlOpenXMLWorkbook)
I'm a sys admin and I am trying to learn how to use powershell... I have never done any type of scripting or coding before and I have been teaching myself online by learning from the technet script centre and online forums.
What I am trying to accomplish is to open an excel spreadsheet get information from it (usernames and password) and then output it into the command prompt in powershell. When ever I try to do this I get an Exception calling "InvokeMember" anyway, here is the code I have so far:
function Invoke([object]$m, [string]$method, $parameters)
{
$m.PSBase.GetType().InvokeMember(
$method, [Reflection.BindingFlags]::InvokeMethod, $null, $m, $parameters,$ciUS )
}
$ciUS = [System.Globalization.CultureInfo]'en-US'
$objExcel = New-Object -comobject Excel.Application $objExcel.Visible = $False $objExcel.DisplayAlerts = $False
$objWorkbook = Invoke $objExcel.Workbooks.Open "C:\PS\User Data.xls" Write-Host "Numer of worksheets: " $objWorkbook.Sheets.Count
$objWorksheet = $objWorkbook.Worksheets.Item(1) Write-Host "Worksheet: " $objWorksheet.Name
$Forename = $objWorksheet.Cells.Item(2,1).Text $Surname = $objWorksheet.Cells.Item(2,2).Text
Write-Host "Forename: " $Forename Write-Host "Surname: " $Surname
$objExcel.Quit() If (ps excel) { kill -name excel}
I have read many different posts on forums and articles on how to try and get around the en-US problem but I cannot seem to get around it and hope that someone here can help!
Here is the Exeption problem I mentioned:
Exception calling "InvokeMember" with "6" argument(s): "Method 'System.Management.Automation.PSMethod.C:\PS\User Data.x
ls' not found."
At C:\PS\excel.ps1:3 char:33
+ $m.PSBase.GetType().InvokeMember <<<< (
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Numer of worksheets: You cannot call a method on a null-valued expression. At C:\PS\excel.ps1:18 char:45 + $objWorksheet = $objWorkbook.Worksheets.Item <<<< (1) + CategoryInfo : InvalidOperation: (Item:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull
Worksheet: You cannot call a method on a null-valued expression. At C:\PS\excel.ps1:21 char:37 + $Forename = $objWorksheet.Cells.Item <<<< (2,1).Text + CategoryInfo : InvalidOperation: (Item:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression. At C:\PS\excel.ps1:22 char:36 + $Surname = $objWorksheet.Cells.Item <<<< (2,2).Text + CategoryInfo : InvalidOperation: (Item:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull
Forename:
Surname:
This is the first question I have ever asked, try to be nice! :))
Many Thanks
Max
I find OLE DB and the Office 2007 drivers a little easier to use. If you don't have Office 2007, you can download the drivers from MS.
$filepath = 'C:\Users\u00\documents\backupset.xlsx'
$connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=`"$filepath`";Extended Properties=`"Excel 12.0 Xml;HDR=YES`";"
#Connection String for Excel 2003:
#$connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=`"$filepath`";Extended Properties=`"Excel 8.0;HDR=Yes;IMEX=1`";"
$qry = 'select * from [sheet1$]'
$conn = New-Object System.Data.OleDb.OleDbConnection
$conn.ConnectionString = $connString
$conn.open()
$cmd = new-object System.Data.OleDb.OleDbCommand($qry,$conn)
$da = new-object System.Data.OleDb.OleDbDataAdapter($cmd)
$dt = new-object System.Data.dataTable
[void]$da.fill($dt)
$conn.close()
$dt
thanks for your help...I have fixed the problem! I was using PowerShell V2 CTP2, now I have upgraded to CTP3 this has fixed the language barrier problem and I can now run scripts without worrying about the invoke function and all is fine!
Many Thanks
Max