Finding if excel sheet contains array using powershell - excel

I'm trying to find out if an excel sheet contains an array (in any cell in the fourth sheet). The variable is a user input as shown:
$j = Read-Host "Enter sensor serial number"
$Sens_name = #("$j")
And the act of it trying to find the input looks like this, where $EPRB2_loca is the location of the excel file including file extension:
#Checking in EPRB 2 file
$Excel = New-Object -ComObject Excel.Application
$Workbook = $Excel.Workbooks.Open("$EPRB2_loca")
$WorkSheet = $Workbook.Sheets.Item(4)
$WorkSheet.Name
$EPRB2_file = $WorkSheet.Cells.Find("$Sens_name")
if ($EPRB2_file.HasArray -eq $false)
{
$EPRB2_file = $null
}
Can someone please help me figure out why it won't show as it containing the array when I know it does?

I was using the wrong command.
If anyone comes across this, use .Count instead of .HasArray

Related

How to use PowerShell to write a files content to different rows in Excel

I am trying to automate the following manual task, and am struggling with part of it:
1) Open a text file that contains multiple lines containing data.
2) Copy the contents of this file to the clipboard.
3) Open and Excel spreadsheet.
4) Rename the spreadsheet to Test.
5) Paste the contents of the clipboard.
When this is done manually the content is pasted and each line in the text file is inserted as a new row in column A.
Originally the customer wanted all of the file content to be injected into cell A1. I was able to achieve this with the below PowerShell code.
However they have since changed this back to wanting each line of text to go into a separate row in column A.
I cannot figure out how to do this gracefully via the Get-Content method of copying out the text data. I have seen workarounds to this issue whereby Excel opens the text file and copies the text into an intermediate workbook and then into the final workbook.
Could someone please let me know if it's possible to amend my already working code below so that it adds the text to rows in column A rather than to cell A1?
# Clear the screen of any previous text.
cls
$ExcelFile="C:\Users\User\Desktop\Test\Test.xlsx"
$TextFile="C:\Users\User\Desktop\Test\TestText.txt"
$Content = Get-Content $TextFile -Raw
# Perform operations in Excel based on content of the downloaded file.
$Excel = New-Object -ComObject Excel.Application
# For troubleshooting enable the below to view Excel as file is manipulated:
#$Excel.Visible=$true
# Disable Excel alerts. Hash this line out for troubleshooting.
$Excel.DisplayAlerts = $false
# Set up workbook...
$Workbook = $Excel.Workbooks.Add()
$Data = $Workbook.Worksheets.Item(1)
$Data.Name = 'Test'
# Insert Data
$Data.Cells.Item(1,1) = "$Content"
# Format, save and quit excel
$UsedRange = $Data.UsedRange
$UsedRange.EntireColumn.AutoFit() | Out-Null
$Workbook.SaveAs("$ExcelFile")
$Excel.Quit()
I know that the part I would need to change is as follows, but I'm not sure what to change it to:
# Insert Data
$Data.Cells.Item(1,1) = "$Content"
Many thanks in advance.
To do this, you need to find the last used row in the sheet and write each line from there:
$ExcelFile = "C:\Users\User\Desktop\Test\Test.xlsx"
$TextFile = "C:\Users\User\Desktop\Test\TestText.txt"
# Perform operations in Excel based on content of the downloaded file.
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Excel.DisplayAlerts = $false
# open the file and select the first worksheet
$WorkBook = $Excel.Workbooks.Open($ExcelFile)
$WorkSheet = $Workbook.Worksheets.Item(1)
# get the first unused row
$row = ($WorkSheet.UsedRange.Rows).Count + 1
# fill in the data
Get-Content -Path $TextFile | ForEach-Object {
$WorkSheet.Cells.Item($row++, 1) = $_
}
# format column A and save the file
$UsedRange = $WorkSheet.UsedRange
$UsedRange.EntireColumn.AutoFit() | Out-Null
$WorkBook.Save()
# quit excel and clean up the used COM objects
$Excel.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WorkSheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WorkBook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
I think the solution would be to read each line in content by for or foreach loop
in loop, write the line's content into the last row of column A in the excel file.
It's will be something like this
foreach($line in $Content){
$Data.Cells.Item($LastRow,1) = $line
}

Pull data from a specified row in Excel spreadsheet

I'm working on a PS script to take a row of data from an Excel spreadsheet and populate that data in certain places in a Word document. To elaborate, we have a contract tracking MASTER worksheet that among other things contains data such as name of firm, address, services, contact name. Additionally, we have another TASK worksheet in the same workbook that tracks information such as project owner, project name, contract number, task agree number.
I'm writing a script that does the following:
Ask the user through a message box what kind of contract is being written ("Master", or "Task")
Opens the workbook with the appropriate worksheet opened ("Master" tab or "Task" tab)
Asks the user through a VB InputBox from which Excel row of data they want to use to populate the Word contract
Extracts that row of data from Excel
Outputs certain portions of that row of data to certain location in a Word document
Saves the Word document
Opens the Word document so the user can continue editing it
My question is this - using something like PSExcel, how do I extract that row of data out to variables that can be placed in a Word document. For reference, in case you're going to reply with a snippet of code, here are what the variables are defined as for the Excel portion my script:
$Filepath = "C:\temp\ContractScript\Subconsultant Information Spreadsheet.xlsx"
$Excel = New-Object -ComObject Excel.Application
$Workbook = $Excel.Workbooks.Open($Filepath)
$Worksheet = $Workbook.sheets.item($AgreementType)
$Excel.Visible = $true
#Choosing which row of data
[int]$RowNumber = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the row of data from $AgreementType worksheet you wish to use", "Row")
Additionally, the first row of data in the excel worksheets are the column headings, in case it matters.
I've gotten this far so far:
import-module psexcel
$Consultant = new-object System.Collections.Arraylist
foreach ($data in (Import-XLSX -path $Filepath -Sheet $AgreementType -RowStart $RowNumber))
{
$Consultant.add($data)'
But I'm currently stuck because I can't figure out how to reference the data being added to $consultant.$data. Somehow I need to read in the column headings first so the $data variable can be defined in some way, so when I add the variable $consultant.Address in Word it finds it. Right now I think the variable name is going to end up "$Consultant.1402 S Broadway" which obviously won't work.
Thanks for any help. I'm fairly new to powershell scripting, so anything is much appreciated.
I have the same issue and searching online for solutions in a royal PITA.
I'd love to find a simple way to loop through all of the rows like you're doing.
$myData = Import-XLSX -Path "path to the file"
foreach ($row in $myData.Rows)
{
$row.ColumnName
}
But sadly something logical like that doesn't seem to work. I see examples online that use ForEach-Object and Where-Object which is cumbersome. So any good answers to the OP's question would be helpful for me too.
UPDATE:
Matthew, thanks for coming back and updating the OP with the solution you found. I appreciate it! That will help in the future.
For my current project, I went about this a different way since I ran into lack of good examples for Import-XLSX. It's just quick code to do a local task when needed, so it's not in a production environment. I changed var names, etc. to show an example:
$myDataField1 = New-Object Collections.Generic.List[String]
$myDataField2 = New-Object Collections.Generic.List[String]
# ...
$myDataField10 = New-Object Collections.Generic.List[String]
# PSExcel, the third party library, might want to install it first
Import-Module PSExcel
# Get spreadsheet, workbook, then sheet
try
{
$mySpreadsheet = New-Excel -Path "path to my spreadsheet file"
$myWorkbook = $mySpreadsheet | Get-Workbook
$myWorksheet = $myWorkbook | Get-Worksheet -Name Sheet1
}
catch { #whatever error handling code you want }
# calculate total number of records
$recordCount = $myWorksheet.Dimension.Rows
$itemCount = $recordCount - 1
# specify column positions
$r, $my1stColumn = 1, 1
$r, $my2ndColumn = 1, 2
# ...
$r, $my10thColumn = 1, 10
if ($recordCount -gt 1)
{
# loop through all rows and get data for each cell's value according to column
for ($i = 1; $i -le $recordCount - 1; $i++)
{
$myDataField1.Add($myWorksheet.Cells.Item($r + $i, $my1stColumn).text)
$myDataField2.Add($myWorksheet.Cells.Item($r + $i, $my2ndColumn).text)
# ...
$myDataField10.Add($myWorksheet.Cells.Item($r + $i, $my10thColumn).text)
}
}
#loop through all imported cell values
for ([int]$i = 0; $i -lt $itemCount; $i++)
{
# use the data
$myDataField1[$i]
$myDataField2[$i]
# ...
$myDataField10[$i]
}

Copying graph from Excel to Word with Powershell

I am trying to copy a graph from excel to word. The source file in excel has two sheets, 'data' & 'graph' on the 'graph' sheet there are 4 graphs, arranged 2x2.
The Word document is empty.
I am fairly new to powershell, but i want to automate a weekly report i have to make. This might seem a little steep, but i like a challenge. Plus, the report eats my time.
This is my code:
$xl = new-object -comobject excel.application
$xl.Visible = $true
$wb = $xl.workbooks.open("H:\Reporting\ULTRAgraphTest.xlsx")
$ws = $wb.worksheets.item(1)
$charts = $ws.ChartObjects()
$chart = $charts.Item(1)
$a = $chart.copy
$wd = new-object -comobject Word.application
$wd.visible = $true
$path = "H:\Reporting\insertest.docx"
$doc = $wd.documents.open($path)
$wd.selection.Paste()
When i run this, the files get opened, but it pastes the clipboard content in the word document. It doesn't seem to copy the graph. What am i not seeing here?
Forgot the partheses
$a = $chart.copy
Should be
$a = $chart.copy()

Powershell: Hiding columns and bordering cells in Excel

I've been diving into how Powershell can use Excel as a COM object, have most of it down but there are two things I'd like to be able to do that I haven't been able to find anywhere, hoping someone can help.
1/ Would like to be able to script hiding a range of columns in the generated Excel spreadsheet.
2/ Would like to be able to have Excel add a border around all cells in the script as well.
Thanks!
Hiding a column:
Here is an example that you can adapt. This is hiding the first column in the active work sheet.
$file = "C:\Users\Micky\Desktop\not locked.xlsx"
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Excel")|Out-Null
$excel = New-Object Microsoft.Office.Interop.Excel.ApplicationClass
$excel.Visible = $true
$wb = $excel.Workbooks.Open($file)
$ws = $wb.ActiveSheet
$c = $ws.Columns
$c.Item(1).hidden = $true
Cell border:
For the example I use a double border and apply to the first cell, A1.
The XlLineStyle Enum can be found here
$xlDouble = -4119
$item = $ws.Range("A1")
$item.Borders.LineStyle = $xlDouble

Finding all values in an excel document and adding them to an array with powershell

$strPath="Path To Spreadsheet.xlsx"
$objExcel=New-Object -ComObject Excel.Application
$objExcel.Visible=$false
$WorkBook=$objExcel.Workbooks.Open($strPath)
$fname = "Facility Name"
$worksheet = $workbook.sheets.item($fname)
$Range = $Worksheet.Range("B1").EntireColumn
$Search = $Range.find("Switch")
I need to be able to find all instances of a string not just one.
I have an excel spreadsheet with IP information and in there, we have Switches ranging from one per workbook all the way up to 10, so what i need to do is be able to find all instances of the word "Switch" and add them to an array i can play with. So all i have to do is find all the values and add them to a simple array. Thanks.
I was playing with it and was able to figure out a pretty simple solution.
$i = 1
$Search = $Range.find("Switch")
while ($i -eq 1) {
if ($Search.value2 -like '*sw*') {
$Search.value2
$Search = $Search.offset(1,0)}
else {$i = 0}
}

Resources