Excel putting blanks into the sheets - powershell

I have two sheets on my excel spread sheet. The script is placing the info in the proper sheets but it is putting blanks in the sheet. If Computer1 is placed in the first sheet and the Computer2 is in the second sheet. The first cell in the second sheet will be blank and the Computer2 entry will be in the second second row instead of the first. How can I stop this from happening? It is creating a ghost cell for the one that is in the first sheet.
Here is my code:
$erroractionpreference = "SilentlyContinue"
$date = 0
$date = get-date -format "yyyy-MMM-dd-hhmm"
$date
$Excel = New-Object -Com Excel.Application
$Excel.visible = $True
# Create 3 worksheets
$Excel = $Excel.Workbooks.Add()
$Sheet = $Excel.Worksheets.Add()
# Assign each worksheet to a variable
$Sheet1 = $Excel.Worksheets.Item(1)
$Sheet2 = $Excel.WorkSheets.Item(2)
# name the worksheet.
$Sheet1.Name = "Machines with PerfStat"
$Sheet2.Name = "No PerfStat"
#Create Heading for General Sheet
$Sheet1.Cells.Item(1, 1) = "Machine_Name"
$Sheet1.Cells.Item(1, 2) = "PerfStat Installed"
$Sheet2.Cells.Item(1, 1) = "Machine_Name"
$Sheet2.Cells.Item(1, 2) = "PerfStat_Installed"
#Create Heading for No PerfStat
$colSheets = ($Sheet1, $Sheet2)
#Auto Fit all sheets in the Workbook
foreach ($colorItem in $colSheets)
{
$WorkBook = $colorItem.UsedRange
$WorkBook.EntireColumn.AutoFit()
clear
}
foreach ($colorItem in $colSheets)
{
$intRow = 2
$WorkBook = $colorItem.UsedRange
$WorkBook.Interior.ColorIndex = 20
$WorkBook.Font.ColorIndex = 11
$WorkBook.Font.Bold = $True
}
$Computers = Get-Content -Path C:\temp\servers.txt
foreach ($Server in $computers)
{
remove-variable reply
$reply = Invoke-WebRequest http://$Server":1055" | Select-Object Content
if ($reply.Content -like "*Windows PerfStat v1.1.4*")
{
$Sheet1.Cells.Item($intRow, 1) = $server
$Sheet1.Cells.Item($intRow, 2) = "Yes"
}
else
{
$Sheet2.Cells.Item($intRow, 1) = $server
$Sheet2.Cells.Item($intRow, 2) = "No"
}
$intRow = $intRow + 1
}
$outputfile = "c:\temp\" + $date.toString() + "-PerfStat"
$Excel.SaveAs($outputfile)
$Excel.Close()

I have figured it out! I placed this code at the bottom of the script and it sorts both sheets before creating the file and saving it.
$Range1 = $Sheet1.range('A2:D2500')
$Range2 = $sheet1.Range('B2')
$Range1.Sort($Range2, 1)
$Range.entirecolumn.autofit()
$Range1 = $Sheet2.range('A2:D2500')
$Range2 = $sheet2.Range('B2')
$Range1.Sort($Range2, 1)
$Range.entirecolumn.autofit()

Related

Powershell Word Document Page Numbers

$Doc = $Word.Documents.Add();
$Section = $Doc.Sections.Item(1);
$Header = $Section.Headers.Item(1);
$Header.Range.Text = "document1_${FirstName}_${SecondName}_${StaffID}.doc";
$objRange = $Doc.Range()
$objRange.Font.Name = “Arial”
$objRange.Font.Size = 12
$Doc.SaveAs("$fileserver\document1_${FirstName}_${SecondName}_${StaffID}.docx");
$Doc.Close();
I am using this script to create word documents and deploy them to staff areas on a fileserver. Is there a way to add page numbers into the documents?
The easiest way of doing this is as below:
$Word = New-Object -ComObject word.application
$word.Visible = $false
$Doc = $Word.Documents.Add()
$Section = $Doc.Sections.Item(1)
$Header = $Section.Headers.Item(1)
$Header.Range.Text = "document1_${FirstName}_${SecondName}_${StaffID}.docx"
$objRange = $Doc.Range()
$objRange.Font.Name = "Arial"
$objRange.Font.Size = 12
# ad a pagenumber (for demo centered to the page width)
# for other values see https://learn.microsoft.com/en-us/office/vba/api/word.wdpagenumberalignment
$wdAlignPageNumberCenter = 1
[void]$Section.Footers(1).PageNumbers.Add($wdAlignPageNumberCenter)
$Doc.SaveAs("$fileserver\document1_${FirstName}_${SecondName}_${StaffID}.docx")
$Doc.Close()
# IMPORTANT Cleanup COM objects after use
$Word.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objRange)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Section)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Header)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

How to loop in Excel to apply GPOs list to OUs in Powershell

I need to loop through an Excel file for OUs and GPOs then apply them to the GPO Management Console. I'm stuck for understand the loop process.
get-module activedirectory,grouppolicy
#Open Excel and read info in file
$filepath = "C:\temp\AllGPOsLinkWin10toApply-report date 13-05-2019.xlsx"
$sheetname = "AllGPOsWin10 date 13-05"
$objExcel = New-Object -ComObject Excel.Application
$objExcel.Visible = $false
$WorkBook = $objExcel.Workbooks.Open($filepath)
$WorkSheet = $WorkBook.Sheets.Item($sheetname)
$OU = #{}
$destinationOU = #{}
$i = 1
$j= 2
#Read the OU cells (A,$i) column 1, row 1 to 13
$destinationOU = $WorkSheet.Cells.Item($i, 1).Text
#Read the GPO cells (all cells to the right of the OU cell)
#then loop and apply each GPO to the OU until cells are empty
$GPO = $WorkSheet.Cells.Item($i+1, $j).Text
set-GPLink -Name $GPO -Target $destinationOU -LinkEnabled yes
i = i + 1
#Loop all OUs cells in column A and start again the process
I suggest this:
#Loop from row 1 to 13
for ($row = 1; $row -le 13; $row++) {
$destinationOU = $WorkSheet.Cells.Item($row, 1).Text
#Read all the cells to right of column 2 (until an empty cell is found)
$col = 2
while (($WorkSheet.Cells.Item($row, $col).Text) -ne "") {
$GPO = $WorkSheet.Cells.Item($row, $col).Text
set-GPLink -Name $GPO -Target $destinationOU -LinkEnabled yes
$col++
}
}
It may be safer to loop through the used range:
for ($row = 1; $row -le $WorkSheet.UsedRange.Row.Count; $row++) {
$destinationOU = $WorkSheet.Cells.Item($row, 1).Text
for ($col = 2; $col -le $WorkSheet.UsedRange.Columns.Count; $col++) {
$GPO = $WorkSheet.Cells.Item($row, $col).Text
set-GPLink -Name $GPO -Target $destinationOU -LinkEnabled yes
}
}

Extract sections from range found in word document

Below code works fine, we got start and end point which needs to be extracted but im not able to get range.set/select to work
I'm able to get the range from below, just need to extra and save it to CSV file...
$found = $paras2.Range.SetRange($startPosition, $endPosition) - this piece doesn't work.
$file = "D:\Files\Scan.doc"
$SearchKeyword1 = 'Keyword1'
$SearchKeyword2 = 'Keyword2'
$word = New-Object -ComObject Word.Application
$word.Visible = $false
$doc = $word.Documents.Open($file,$false,$true)
$sel = $word.Selection
$paras = $doc.Paragraphs
$paras1 = $doc.Paragraphs
$paras2 = $doc.Paragraphs
foreach ($para in $paras)
{
if ($para.Range.Text -match $SearchKeyword1)
{
Write-Host $para.Range.Text
$startPosition = $para.Range.Start
}
}
foreach ($para in $paras1)
{
if ($para.Range.Text -match $SearchKeyword2)
{
Write-Host $para.Range.Text
$endPosition = $para.Range.Start
}
}
Write-Host $startPosition
Write-Host $endPosition
$found = $paras2.Range.SetRange($startPosition, $endPosition)
# cleanup com objects
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($doc) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
This line of code is the problem
$found = $paras2.Range.SetRange($startPosition, $endPosition)
When designating a Range by the start and end position it's necessary to do so relative to the document. The code above refers to a Paragraphs collection. In addition, it uses SetRange, but should only use the Range method. So:
$found = $doc.Range.($startPosition, $endPosition)

How PowerShell Sum an Excel column and print the result?

I have an excel file with 10 columns. I want to get the sum of the column with header "Sales" and print it on the console.
How this can be done with PowerShell? I am using the below code but I do not know how to replace H with $i in the following expression:
='=SUM(H1:H'+$RowCount')'
Where H is column "Sales"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $False
$NewWorkbook = $Excel.Workbooks.open("C:\Test.xlsx")
$NewWorksheet = $NewWorkbook.Worksheets.Item(1)
$NewWorksheet.Activate() | Out-Null
$NewWorksheetRange = $NewWorksheet.UsedRange
$RowCount = $NewWorksheetRange.Rows.Count
$ColumnCount = $NewWorksheetRange.Columns.Count
for ($i = 1; $i -lt $ColumnCount; $i++)
{
if ($NewWorksheet.cells.Item(1,$i).Value2 -eq "Sales")
{
$NewWorksheet.Cells.Item($RowCount+2,$i)='=SUM(H1:H'+$RowCount')'
Write-Host $NewWorksheet.Cells.Item($RowCount+1,$i).Value2
}
}
$Excel.Application.DisplayAlerts=$False
$NewWorkbook.SaveAs("C:\Test_New.xlsx")
$NewWorkbook.close($false)
$Excel.quit()
spps -n excel
I have replaced:
$NewWorksheet.Cells.Item($RowCount+2,$i) ='=SUM(H1:H'+(1+$RowCount)+')'
Write-Host $NewWorksheet.Cells.Item($RowCount+2,$i).Value2
with:
$FirstCell = $NewWorksheet.Cells(2,$i).Address('+True, False+')
$LastCell = $NewWorksheet.Cells(1+$RowCount,$i).Address('+True, False+')
$NewWorksheet.Cells.Item($RowCount+2,$i)='=SUM('+$FirstCell+':'+$LastCell+')'
Write-Host $NewWorksheet.Cells.Item($RowCount+2,$i).Value2
I can highly recommend the PowerShell-Module "ImportExcel". This Modules enables you to import Excel-Files as easy as with Import-Csv
Without knowing much about your files/enviroment, you could try something like this:
foreach ($data in (Import-Excel "$PSScriptRoot\test.xlsx")) {
$result += $data.Sales
}
Write-Host $result

Append from the last row on-wards Excel & Powershell

I am currently working on a script that would keep track of the size of databases across different network servers. I am outputting the results to an excel, this will run every day, hence, I need to know how I can get the last row which contains data and append from there on-wards.
#Creates heading on an excel file if the file did not exist previously
Function CreateExcelWithHeadings($intRow, $Sheet)
{
$intRow++
#Create column headers
$Sheet.Cells.Item($intRow,1)= "Date"
$Sheet.Cells.Item($intRow,1).Font.Size = 12
$Sheet.Cells.Item($intRow,1).Font.Bold = $True
$Sheet.Cells.Item($intRow,2) = "Server"
$Sheet.Cells.Item($intRow,2).Font.Size = 12
$Sheet.Cells.Item($intRow,2).Font.Bold = $True
#$intRow++
$Sheet.Cells.Item($intRow,3) = "Database"
$Sheet.Cells.Item($intRow,3).Font.Bold = $True
$Sheet.Cells.Item($intRow,4) = "Data Name"
$Sheet.Cells.Item($intRow,4).Font.Bold = $True
$Sheet.Cells.Item($intRow,5) = "Data File"
$Sheet.Cells.Item($intRow,5).Font.Bold = $True
$sheet.Cells.Item($intRow,6) = "Data Size (MB)"
$Sheet.Cells.Item($intRow,6).Font.Bold = $True
$Sheet.Cells.Item($intRow,7) = "Data Used Space (MB)"
$Sheet.Cells.Item($intRow,7).Font.Bold = $True
$Sheet.Cells.Item($intRow,8) = "Log Name"
$Sheet.Cells.Item($intRow,8).Font.Bold = $True
$Sheet.Cells.Item($intRow,9) = "Log Size (MB)"
$Sheet.Cells.Item($intRow,9).Font.Bold = $True
$Sheet.Cells.Item($intRow,10) = "Log Used Space (MB)"
$Sheet.Cells.Item($intRow,10).Font.Bold = $True
$Sheet.Cells.Item($intRow,11) = "Log File"
$Sheet.Cells.Item($intRow,11).Font.Bold = $True
}
# initalize variables
$serverList = "C:\Database Monitor\sqlservers.txt"
$filepath ='C:\Database Monitor\Log Files\'
$filename = 'database_logging.xlsx'
#Create a new Excel object using COM
$Excel = New-Object -ComObject Excel.Application
# check if file path exists, if its doesn't create one with the proper headings
If (-not (Test-Path -path $filepath))
{
New-Item -ItemType directory -Path $filepath
$Excel.visible = $True
$Excel = $Excel.Workbooks.Add()
$Sheet = $Excel.Worksheets.Item(1)
CreateExcelWithheadings 0 $Sheet
$Sheet.SaveAs($filepath+$filename)
#WritetoExcel($serverList, 0)
}
Else
{
$Excel.visible = $True
$Excel = $Excel.Workbooks.Open($filepath)
$Sheet = $Excel.Worksheets.Item(1)
$ExcelWorkSheet.activate()
#$lastRow =
}