Recently I began my adventure with excel and COM objects via powershell. This adventure as every adventure began as a really bumpy ride. First I had to find out how to create an excel document the powershell way. The background for this is provided to me by PowerCLI, I have to create all kinds of reports to the Managers in a readable old way fashion like excel… I don’t really understand this approach because a nice HTML with unique CSS template can be very-very delighting. So in a nutshell I have some virtual machines which are running on ESXi hosts and I want to add their current location to an XLSX file.
First I create my COM object and initialize it.
$excel = New-Object -ComObject excel.application
$excel.visible = $false
$workbook = $excel.Workbooks.Add()
$workbook.Worksheets.Add()
$machines= $workbook.Worksheets.Item(1)
$machines.Name = ‘VirtualMachines’
Then all I have to do is add the actual data from the machines. All I do is cycle through the virtual machines with a foreach loop like this then add the data.
foreach($VM in $VirtualMachines)
{
$machines.Cells.Item($ROW,$Column) = $VM.Name
$machines.Cells.Item($ROW,$Column+1) = $PowerState
$machines.Cells.Item($ROW,$Column+2) = $VM.NumCpu
$machines.Cells.Item($ROW,$Column+3) = $(($VM.MemoryMB -as [string]) + ” MB”)
$machines.Cells.Item($ROW,$Column+4) = $($VM.Host.Name)
$ROW++
$i++
}
Actually this is quite what I want, if I change the $excel.visible = $true I can see as the excel being filled up right before my eyes. But I was hoping for something faster, and more dynamic. When I have 100 machines to add to the excel and some formatting it becomes very-very slow. To be honest it’s quite faster than manually creating the excel, but you know how it goes. Here is a way to add some formating and eyecandy to the report.
$machines.Cells.Item($ROW,$Column+1).ColumnWidth = 13
$machines.Cells.Item($ROW,$Column+1).HorizontalAlignment = -4108
$machines.Cells.Item($ROW,$Column+1).Font.Bold=$False
$machines.Cells.Item($ROW,$Column+1).Font.ColorIndex= 1
$machines.Cells.Item($ROW,$Column+1).Interior.ColorIndex = 15
$machines.Cells.Item($ROW,$Column+1).Borders.LineStyle = 1
This will align the width, font, color of the cell, to the disadvantage of the speed. It’s bugged me so much I began looking for another ways to add data to the excel. Here is what I found… I don’t know if it is happening as I belive it is happening but It’s how I percive it.
$Colnames = New-Object ‘object[,]’1,5
$Colnames[0,0] = $VM.Name
$Colnames[0,1] = $PowerState
$Colnames[0,2] = $VM.NumCpu
$Colnames[0,3] = $(($VM.MemoryMB -as [string]) + ” MB”)
$Colnames[0,4] = $($VM.Host.Name)
$range = $machines.range(“A$($row):E$($row)”)
$range.Value2 = $Colnames
The just decribed way of adding values to the excel shows more impressive speed then the one before. My conclusion is that adding a value to a cell counts as 1 operation. The same as adding a 2-D array’s values to a range of cells. So this is where the speed difference my reside. I don’t think it is always more efficient than the other but even if the 2D array consists of 1 row and 1 column we can never go below the speed of the older way.
This post is dedicated to Don Jones, Ed Wilson, Dr. Tobias Weltner they are amazing people, they are the reason I started my journey with powershell, they made me love it. 🙂
Cheers,
Daniel