$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.
Related
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()
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
i have a trouble findiong a value in an excel sheet.
i want to get the cell number that contains a value with a string, but i need to use wildcars.
the cell that i am searching begins with B- and i am using this code:
$excel = New-Object -ComObject excel.application
$destinationPath = "C:\Users\john\Desktop\wb.xlsx"
$workbook = $excel.Workbooks.Open($destinationPath)
$sheet1 = $workbook.WorkSheets.item("Sheet1")
$sheet1.activate()
$range = $sheet1.Range("A:A").EntireColumn
$s = $range.find("B-")
write-host "Range found: " $s.address().tostring()
this returns me the first cell that contains B- .... but i need to know the first cell that begins with this. So i think i must use wildcards but i don't know how.
please, could anyone help me to achieve this??
thank you!! BR.
Here a working solution which is able to use regex as well:
Add-Type -AssemblyName Microsoft.Office.Interop.Excel
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $True
$excel.DisplayAlerts = $False
$workbook = $excel.Workbooks.Open( "C:\Users\john\Desktop\wb.xlsx", [System.Type]::Missing, $false )
$worksheet = $workbook.WorkSheets.item("Sheet1")
[void]$worksheet.activate()
$searchRange = $worksheet.Range("A:A").EntireColumn
$searchFor = '^.*B\-.*$'
$foundCell = $null
foreach( $cell in $searchRange.Cells ) {
if( $cell.Value2 -match $searchFor ) {
$foundCell = $cell
break
}
}
if( $foundCell ) {
$foundCell.Value2
}
[void]$workbook.Close()
[void]$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
$if = '\\portal2010.brand.com\sites\HC\2017 count.xlsx'
$excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($if)
$page = 'HC'
$ws = $Workbook.worksheets | where-object {$_.Name -eq $page}
$range = $ws.Range("V2:AF")
$rows = $range.Rows.Count
$hcTableCopy = $ws.Range("V2:AF$rows").Copy()
$hcTablePaste = $hcTableCopy.PasteSpecial($default, $default, $default, $default, 9, $default, $default)
$SendTo = "e.mail#brand.com"
$SMTPServer = "smtp.brand.com"
$EmailFrom = "e.mail2#brand.com"
$EmailSubject = "Weekly Email"
$Image2 = '\\portal2010.brand.com\sites\HC\HC Dashboards\2017 HC_files\2017 count_25311_image002.png'
$Image4 = '\\portal2010.brand.com\sites\HC\HC Dashboards\2017 HC_files\2017 count_25311_image004.png'
$Image6 = '\\portal2010.brand.com\sites\HC\HC Dashboards\2017 HC_files\2017 count_25311_image006.png'
$Image8 = '\\portal2010.brand.com\sites\HC\HC Dashboards\2017 HC_files\2017 count_25311_image008.png'
$Message = new-object Net.Mail.MailMessage
Add-PSSnapin Microsoft.Exchange.Management.Powershell.Admin -erroraction silentlyContinue
$att2 = new-object Net.Mail.Attachment($Image2)
$att2.ContentId = "att2"
$att4 = new-object Net.Mail.Attachment($Image4)
$att4.ContentId = "att4"
$att6 = new-object Net.Mail.Attachment($Image6)
$att6.ContentId = "att6"
$att8 = new-object Net.Mail.Attachment($Image8)
$att8.ContentId = "att8"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$body = '
<img src="cid:att2" /><br/><br/>
<img src="cid:att4" /><br/><br/>
<img src="cid:att6" /><br/><br/>
<img src="cid:att8" /><br/><br/>
'
$Message.From = $EmailFrom
$Message.To.Add($SendTo)
$Message.Cc.Add($CCTo1)
$Message.Cc.Add($CCTo2)
$Message.Cc.Add($CCTo3)
$Message.Cc.Add($CCTo4)
$Message.Subject = $EmailSubject
$Message.Body = $body + $hcTablePaste
$Message.IsBodyHTML = $true
$Message.Attachments.Add($att2)
$Message.Attachments.Add($att4)
$Message.Attachments.Add($att6)
$Message.Attachments.Add($att8)
$smtp.Send($Message)
$excel.DisplayAlerts = $False
Start-Sleep -s 5
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
The above code is what I have tried so far. I get an error that says it can't open the file from sharepoint at this point and I am not sure the table paste portion of this is going to work right.
I tried modifying the following, but I really don't think I should have to check out and make editable the file just to copy the table range to an email.
foreach ($file in $excelfiles)
{
$workbookpath = $file.fullname
if ($excel.workbooks.canCheckOut($workbookpath)) {
# open the worksheet and check it out
$excelworkbook = $excel.workbooks.Open($workbookpath)
$excelworkbook = $excel.workbooks.CheckOut($workbookpath)
# Don't ask cuz I don't know (yet). You have to open it again.
$excelworkbook = $excel.workbooks.Open($workbookpath)
# Refresh all the pivot tables with the new data.
$excelworkbook.RefreshAll()
# Save and Check it in
$excelworkbook.Save()
$excelworkbook.CheckInWithVersion()
}
}
$excel.quit()
So any help to get the table pasting part would be great. The email send with images just fine other than that.
I have a script that places everything nicely into a spread sheet. The problem is, I need it to export as a csv file instead. All the foreach loops are completely baffling me here as far as where to put the export csv functions in the script. If someone could could school me on how to get the fields into a csv file, It would be greatly appreciated.
$date = 0
$date = get-date -format "yyyy-MMM-dd-hhmm"
$date
#New Excel Application
$Excel = New-Object -Com Excel.Application
$Excel.visible = $False
# Create 1 worksheets
$Excel = $Excel.Workbooks.Add()
# Assign each worksheet to a variable and
# name the worksheet.
$Sheet1 = $Excel.Worksheets.Item(1)
$Sheet1.Name = "HH_SERVERS"
#Create Heading for General Sheet
$Sheet1.Cells.Item(1, 1) = "Machine_Name"
$Sheet1.Cells.Item(1, 2) = "OS"
$Sheet1.Cells.Item(1, 3) = "Software"
$Sheet1.Cells.Item(1, 4) = "Vendor"
$Sheet1.Cells.Item(1, 5) = "Version"
$colSheets = ($Sheet1)
foreach ($colorItem in $colSheets)
{
$intRow = 2
$intRowDisk = 2
$intRowSoft = 2
$intRowNet = 2
$WorkBook = $colorItem.UsedRange
$WorkBook.Interior.ColorIndex = 20
$WorkBook.Font.ColorIndex = 11
$WorkBook.Font.Bold = $True
}
#Auto Fit all sheets in the Workbook
foreach ($colorItem in $colSheets)
{
$WorkBook = $colorItem.UsedRange
$WorkBook.EntireColumn.AutoFit()
clear
}
$Servers = get-content "c:\temp\HH_Servers.txt"
foreach ($Server in $Servers)
{
$GenItems2 = gwmi Win32_OperatingSystem -Comp $Server
$Software = gwmi Win32_Product -Comp $Server
# Populate General Sheet(1) with information
foreach ($objItem in $GenItems2)
{
$Sheet1.Cells.Item($intRow, 2) = $objItem.Caption
}
#Populate Software Sheet
foreach ($objItem in $Software)
{
$Sheet1.Cells.Item($intRowSoft, 1) = $Server
$Sheet1.Cells.Item($intRowSoft, 3) = $objItem.Name
$Sheet1.Cells.Item($intRowSoft, 4) = $objItem.Vendor
$Sheet1.Cells.Item($intRowSoft, 5) = $objItem.Version
$intRowSoft = $intRowSoft + 1
}
}
$outputfile = "c:\temp\" + $date.toString() + "-HH_Server_Software"
$Excel.SaveAs($outputfile)
$Excel.Close()
Write-Host "*******************************" -ForegroundColor Green
Write-Host "The Report has been completed." -ForeGroundColor Green
Write-Host "*******************************" -ForegroundColor Green
# ========================================================================
# END of Script
# ==================
You can't save an entire workbook as CSV. You need to save the individual worksheet instead. The file format value for CSV is 6 (don't remember where I found that out though):
$xlCSV = 6
$outputfile = "c:\temp\" + $date.toString() + "-HH_Server_Software.csv"
$Sheet1.SaveAs($outputfile, $xlCSV)
(Tested on Windows 7 with Excel 2013.)
Thanks to #Matt for a comment with a link to the XLFileFormat Enumerations.