Delete worksheet from excel workbook using powershell - excel

Below is the code I have which is creating graph and saving the graph as image
$excel = New-Object -ComObject excel.application
$outputXLSX = "C:\report_10_02.xlsx"
$data = Import-Excel -Path $outputXLSX
$cd = New-ExcelChartDefinition -XRange Name -YRange Count -ChartType ColumnStacked3D -Height 300 -Title "Latency Count" -Width 1000 -SeriesHeader Count
$data | Export-Excel $outputXLSX -ExcelChartDefinition $cd -AutoNameRange -WorksheetName "Sheet2"
$macros_wb = $excel.Workbooks.open($outputXLSX)
$chart_worksheets = #("Sheet2")
$OutputType = "JPG"
foreach ($item in $chart_worksheets)
{
$macros_ws = $macros_wb.WorkSheets.item($item)
$macros_ws.activate()
$excelchart = $macros_ws.ChartObjects(1)
$Excel.Goto($excelchart.TopLeftCell,$true)
$ImagePath = "C:\Imagee.jpg"
if ($excelchart.Chart.Export($ImagePath, $OutputType)) #Export returns true/false for success/failure
{Write-Output "Exported $ImagePath"}
else
{Write-Output "Failure Exporting $ImagePath"}
}
$WorkSheet = $macros_wb.sheets.item($chart_worksheets)
#Deleting the worksheet
$WorkSheet.Delete()
#Saving the worksheet
$macros_wb.Save()
$macros_wb.close($true)
$excel.Quit()
The excel workbook is having 2 worksheet in which I want to delete Sheet2. I tried Delete() but it is not deleting the sheet.
Please let me know what is wrong here

I'm not sure why are you using ComObject if you already have the ImportExcel Module installed, it doesn't require manipulation with ComObject. Here is how you can remove a Worksheet from an Excel file:
$path = 'path/to/excelfile.xlsx'
$workSheetToRemove = 'worksheetName'
Remove-Worksheet -WorksheetName $workSheetToRemove -FullName $path
If you're not sure what's the name of the Worksheet you want to remove, you use:
Get-ExcelFileSummary $path

Ok, so you have an Excel file containing a chart you want to export to a JPG file and afterwards delete the worksheet containing that chart.
Using COM objects you can do this like so:
$outputXLSX = "C:\report_10_02.xlsx"
$chart_worksheet = "Sheet2"
$ImagePath = "C:\Imagee.jpg"
$OutputType = "JPG"
$excel = New-Object -ComObject excel.application
$excel.DisplayAlerts = $false
$macros_wb = $excel.Workbooks.open($outputXLSX)
$macros_ws = $macros_wb.WorkSheets.item($chart_worksheet)
$macros_ws.activate()
$excelchart = $macros_ws.ChartObjects(1)
$excel.Goto($excelchart.TopLeftCell,$true)
if ($excelchart.Chart.Export($ImagePath, $OutputType)) {Write-Host "Exported $ImagePath"}
else {Write-Warning "Failure Exporting $ImagePath"}
$macros_ws.Delete()
#Saving the worksheet
$macros_wb.Save()
$macros_wb.Close($true)
$excel.Quit()
# important, remove the used COM objects from memory
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($macros_ws)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($macros_wb)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Related

Excel COM paste not working - Unable to get the Paste property of the Worksheet class

I am using the following code to paste values from one sheet to another. It used to work but after migrating to EXCEL 2013 stopped working with error "Unable to get the Paste property of the Worksheet class"
$excelFrom = New-Object -ComObject Excel.Application
$excelFrom.visible = $false
$excelFrom.DisplayAlerts = $false
$excelTo = New-Object -ComObject Excel.Application
$excelTo.visible = $false
$excelTo.DisplayAlerts = $false
$excelFrom.Workbooks.OpenText("inputfile.xls")
$worksheetFrom = $excelFrom.Worksheets.Item(1)
$excelTo.Workbooks.OpenText("templatefile.xlsx")
$worksheetTo = $excelTo.Worksheets.Item(1)
write-host $worksheetTo.cells[1][2].text
$lastRow1 = $worksheetFrom.UsedRange.rows.count - 11
$lastRow2 = $lastRow1 + 1
#copy account numbers
$worksheetFrom.activate()
$range1 = $worksheetFrom.Range("B15:B17")
$range1.copy()
$worksheetTo.activate()
$range2 = $worksheetTo.Range("A2:A4")
write-host $range2.rows.count
$worksheetTo.Paste($range2)
$excelFrom.quit()
while([System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelFrom)){}
Remove-Variable excelFrom
$excelTo.quit()
while([System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelTo)){}
Remove-Variable excelTo
If it helps anyone I had to use this -
$worksheetTo.Range("A2:A$lastRow2").Value2 = $worksheetFrom.Range("B15:B$lastRow1").Value2
It seems .Value doesn't work if we are copying from an xls file to xlsx –

Split Excelfile .xlxs with Powershell based on column values

I need to split and save an excel file based on the values of the first column via a powershell script. Here is how the excel file is build up (app 30.000 rows)
´´´Column1 # Column2 # Column3´´´
´´´AA # data # data # data´´´
´´´AA # data # data # data´´´
´´´AB # data # data # data´´´
´´´AC # data # data # data´´´
´´´AC # data # data # data´´´
The result should be multiple files with filenames AA.xlxs, AB.xlxs, AC.xlxs and of course the according rows data.
What I have so far is the following code:
$objexcel = New-Object -ComObject Excel.Application
$wb = $objexcel.WorkBooks.Open("C:\Test.xlsx")
$objexcel.Visible = $true
$objexcel.DisplayAlerts = $False
$ws = $wb.Worksheets.Item(1)
$doc = $ws.Range("A:A")
foreach ($doc in $docs) {
$newfile,$objexcel = $objexcel.where({$doc -eq $doc})
$newfile | Export-Excel "C:\$doc.xlxs"
}
It just opens the file, but nothing happens.
It would be great if some coder could have a look at the code or provide a working one.
Thanks in advance.
Following is a working code that will iterate through unique elements in column one and make a copy of it in a new spreadsheet and save it.
Function Create-Excel-Spreadsheet {
Param($NameOfSpreadsheet)
# open excel
$excel = New-Object -ComObject excel.application
$excel.visible = $true
# add a worksheet
$workbook = $excel.Workbooks.Add()
$xl_wksht= $workbook.Worksheets.Item(1)
$xl_wksht.Name = $NameOfSpreadsheet
return $workbook
}
$objexcel = New-Object -ComObject Excel.Application
$wb = $objexcel.WorkBooks.Open("C:\Temp\Test.xlsx") # Changing path for test.xlsx file.
$objexcel.Visible = $true
$objexcel.DisplayAlerts = $False
$ws = $wb.Worksheets.Item(1)
$usedRange = $ws.UsedRange
$usedRange.AutoFilter()
$totalRows = $usedRange.Rows.Count
$rangeForUnique = $usedRange.Offset(1, 0).Resize($UsedRange.Rows.Count-1)
[string[]]$UniqueListOfRowValues = $rangeForUnique.Columns.Item(1).Value2 | sort -Unique
for ($i = 0; $i -lt $UniqueListOfRowValues.Count; $i++) {
$newRange = $usedRange.AutoFilter(1, $UniqueListOfRowValues[$i])
$workbook = Create-Excel-Spreadsheet $UniqueListOfRowValues[$i]
$wksheet = $workbook.Worksheets.Item(1)
$range = $ws.UsedRange.Cells
$range.Copy()
$wksheet.Paste($wksheet.Range("A1"))
$workbook.SaveAs("C:\temp\" + $UniqueListOfRowValues[$i], $xlFixedFormat)
$workbook.Close()
}
Reason nothing is happening is because you are iterating over $docs which does not contain any elements. It is currently null.
When you make a reference to look up the data, you are using $objexcel, but thats your excel application.. not the worksheet that you want to iterate over. Use $as for accessing the worksheet.
You need to iterate over Cells of your $ws and take the data when cells.Item(x, 0) and create a new file based on that with values in other two columns.
Link to example on SO -> Create and Update excel file

PowerShell select range of cells from Excel file and convert to CSV

I want to extract a range of cells from an Excel sheet and output them in CSV form for further use. So far I have written this:
script.ps1:
$excel = New-Object -ComObject Excel.Application
$WB = $excel.Workbooks.Open('c:\users\me\desktop\temp\nouveau dossier\superstore.xls')
$WS = $WB.Sheets.Item(1)
$data = $WS.Range("A1", "E10")
$data | select text | Export-Csv 'YATry.csv' -NoTypeInformation -Delimiter ';'
$excel.Quit()
but what I get is this:
"Text"
"Row ID"
"Order ID"
"Order Date"
"Ship Date"
"Ship Mode"
"1"
"CA-2016-152156"
"2016-11-08"
"2016-11-11"
"Second Class"
"2"
"CA-2016-152156"
"2016-11-08"
"2016-11-11"
"Second Class"
"3"
"CA-2016-138688"
"2016-06-12"
"2016-06-16"
"Second Class"
[...]
What am I missing?
Try this as an alternative method. I haven't tried this out in your environment, but something similar worked for me. Hope this helps.
$excel = New-Object -ComObject Excel.Application
$WB =
$excel.Workbooks.Open('c:\users\me\desktop\temp\nouveau dossier\superstore.xls')
$WS = $WB.Sheets.Item(1)
$data = $WS.Range("A1", "E10")
$XLcsv = 6 # Parameter to tell SaveAs to produce a CSV format
$data.worksheet.SaveAs('c:\users\me\desktop\temp\nouveau dossier\YATry.csv', $XLcsv)
$excel.Quit()
SaveAs is a method in the Excel application that does what the interactive user does by clicking 'Save As'. The second parameter tells SaveAs what format to generate, in this case CSV.
The tricky part is figuring out that you have to say $data.worksheet instead of $data in order to gain access to the SaveAs method.
$objExcel = New-Object -ComObject Excel.Application
$workbook = $objExcel.Workbooks.Open("d:\Test.xlsx")
$workbook.sheets.item(1).activate()
$workbook.Worksheets.Item(1).Range("A1", "C3") | foreach { $_.Text}
$workbook.close()

Reading value from Excel sheet

$filepath = "C:\Users\Desktop\New folder\Tangent.xlsx"
$sheetname = "sheet"
$objExcel = New-Object -ComObject Excel.Application
$objExcel.Visible = $false
$WorkBook = $objExcel.Workbooks.Open($filepath)
$WorkBook.sheets | Select-Object -Property Name
$WorkSheet = $WorkBook.Sheets.Item($sheetname)
$myObj = [PSCustomObject][ordered]#{
john = $WorkSheet.Range("B1").Text
Rebel = $WorkSheet.Range("B2").Text
MArk = $WorkSheet.Range("B3").Text
Susan = $WorkSheet.Range("B4").Text
Patty = $WorkSheet.Range("B5").Text
}
I have hardcoded all the names into the code which is a weird way of doing it. I want it to read from the Excel directing using command. Can anyone help me please?
Create an empty hashtable and fill it as you iterate over the rows in your Excel sheet, then create the object.
$ht = #{}
$i = 1
while ($WorkSheet.Cells.Item($i, 1).Text) {
$ht[$WorkSheet.Cells.Item($i, 1).Text] = $WorkSheet.Cells.Item($i, 2).Text
$i++
}
$obj = [PSCustomObject]$ht
Untested, as I don't have Excel at hand here.

Opening an excel file using New-Object breaks formulas, using Invoke-Item doesn't

I need to run a script that just opens an excel file, calculates an excel cell connected with a Pi DataLink, then tells me the value.
If I try to do that in the way that's standard:
$objExcel = New-Object -com Excel.Application
$objExcel.Visible = $True
$WorkBook = $objExcel.Workbooks.Open("C:\Users\crclayton\sheet.xlsx")
$WorkSheet = $WorkBook.Sheets.Item("Sheet1")
write-host $worksheet.Range("A1").Text
$WorkBook.Save()
$WorkBook.Close()
$objExcel.Quit()
I get a #NAME? error. And even if I just use the first three lines to just open an excel file and look at it, I can't run calculations, =PICurrVal("TAGNAME",0,"SERVERNAME") is just a dead formula that excel doesn't understand if I open it this way. I've also tried to UpdateLinks when I open the file, but no dice.
However, if I open the file like so:
Invoke-Item "C:\Users\crclayton\sheet.xlsx"
I don't get a #NAME? error and I can run the calculations and excel understands this formula.
Maybe something like this?
Invoke-Item "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE"
Start-Sleep 10
$objExcel = Get-Process "EXCEL.EXE"
$WorkBook = $objExcel.Workbooks.Open("C:\Users\crclayton\sheet.xlsx")
$WorkSheet = $WorkBook.Sheets.Item("Sheet1")
write-host $worksheet.Range("A1").Text
Is there some way to get the value in cell A1 having opened the spreadsheet using Invoke-Item?
I'm not sure why you're getting #NAME? as Excel should be doing all the calculations within the sheet all we're doing in Powershell is getting the value of the cell.
However what you can try is outputting the value of your formula to a nearby cell and getting the value of it instead, for example:
Your formula is in D18 -> =PICurrVal("TAGNAME",0,"SERVERNAME")
Your value is in D19 -> =D18
Call the value in your Powershell:
$objExcel = New-Object -com Excel.Application
$objExcel.Visible = $True
$WorkBook = $objExcel.Workbooks.Open("C:\Users\crclayton\sheet.xlsx")
$WorkSheet = $WorkBook.Sheets.Item(1)
write-host $worksheet.Range("D18").Text
$WorkBook.Save()
$WorkBook.Close()
$objExcel.Quit()
Update
Excel addins can be added in powershell by using the Addins property like so:
$MyAddin = $Workbook.AddIns.Add('C:\test.xla', $True)
$MyAddin.Installed = "True"
Your new complete code might look something like
$objExcel = New-Object -com Excel.Application
$objExcel.Visible = $True
$WorkBook = $objExcel.Workbooks.Open("C:\Users\crclayton\sheet.xlsx")
$MyAddin = $Workbook.AddIns.Add('C:\test.xla', $True)
$MyAddin.Installed = "True"
$WorkSheet = $WorkBook.Sheets.Item(1)
write-host $worksheet.Range("D18").Text
$WorkBook.Save()
$WorkBook.Close()
$objExcel.Quit()
Edit 2:
Yes, add-ins were the problem. I needed to add each the following files:
$ExcelAddin = $WorkBook.Application.AddIns.Add("C:\Program Files (x86)\PIPC\Excel\PITrendXL.xla", $True)
$ExcelAddin.Installed = "True"
$ExcelAddin = $WorkBook.Application.AddIns.Add("C:\Program Files (x86)\PIPC\Excel\pipc32.xll", $True)
$ExcelAddin.Installed = "True"
$ExcelAddin = $WorkBook.Application.AddIns.Add("C:\Program Files (x86)\PIPC\Excel\OSIsoft.PIDataLink.UI.dll.manifest", $True)
$ExcelAddin.Installed = "True"

Resources