For some reason, inserting formula into Excel table using Powershell script. If formula is entered manually, it works fine. Suppose I have 3 elements in $names array:
$excel = New-Object -ComObject excel.application
$excel.visible = $true
$workbook = $excel.Workbooks.Add()
$names = #()
foreach ($i in 1,2,3) {
$ws = $workbook.Worksheets.Add()
$names += $ws.Name
}
$i = 1
foreach ($sheet in $names) {
$formula = "=COUNT('$sheet'!D:D)"
write-host $formula
$excel.cells.item($i, 1).Formula = $formula
$i++
}
What happens: The first cell gets the correct value, but the formula name is missing (e.g. instead of =COUNT('Sheet2'!D:D) I get =('Sheet2'!D:D), and the other 2 throw 0x800A03EC exception. The sheet I reference definitely exists, because if I copy and paste values printed by write-host $formula manually, it works as expected.
It also seems to work correctly If I don't reference another sheet. The code below doesn't throw any exceptions:
$formula = "=COUNT(D:D)"
$excel.cells.item($i, 1).Formula = $formula
UPDATE:
Seems like an issue specific to Excel 2010. In Excel 2016, the same code works fine.
I have tried to mock your approach and came up with the following working code:
foreach($ws in $b.Sheets) {
$ws.Cells.Item(1,1).Formula = "=COUNT($($ws.Name)!D:D)"
}
I've managed to make it work using FormulaLocal instead of Formula. I still believe it's a bug in Excel 2010, since Formula works perfectly fine in Excel 2016. I also still can't insert array formulas containing sheet references in Excel 2010 from script: even assigning FormulaLocal first, and then assigning it's value to FormulaArray doesn't work.
Related
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
I have a script that will create worksheets based on the number of files that it finds in a directory. From there it changes the name of the sheets to the file name. During that process, I am attempting to add two Column header values of "Hostname" and "IP Address" to every sheet. I can achieve this by activating each sheet individually but this becomes rather cumbersome as the amount of sheets goes past 20+ and thus I am trying to find a dynamic way of doing this regardless the amount of sheets that are present.
This is the code that I have to do everything up to the column header portion:
$WorksheetCount = (Get-ChildItem $Path\Info*.txt).count
$TabNames = Get-ChildItem $Path\Info*.txt
$NewTabNames = Foreach ($file IN $TabNames.Name){$file.Substring(0,$file.Length-4)}
$Break = 0
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$Workbook = $Excel.Workbooks.Add()
$null = $Excel.Worksheets.Add($MissingType, $Excel.Worksheets.Item($Excel.Worksheets.Count),
$WorksheetCount - $Excel.Worksheets.Count, $Excel.Worksheets.Item(1).Type)
1..$WorksheetCount
Start-Sleep -s 1
ForEach ($Name In $NewTabNames){
$Break++
$Excel.Worksheets.Item($Break).Name = $Name
}
I have attempted to insert my code as such:
ForEach ($Name In $NewTabNames){
$Break++
$Excel.Worksheets.Item($Break).Name = $Name
$cells=$Name.Cells
$cells.item(1,1)="Hostname"
$cells.item(1,2)="IP Address"
}
When I attempt to run the script, I get the following error..
You cannot call a method on a null-valued expression.
And then it proceeds to list each line of the code that I had put in. I thought that since I created a variable during the operation, that it was the issue:
$cells=$Name.Cells
I thought That perhaps if I moved it before the ForEach command that it would resolve it but I still receive the same issue. I have looked through various ways of trying to select ranges of sheets within excel via powershell but have not found anything helpful.
Would appreciate any assistance on this.
This is actually my first post in StackOverflow ever and I feel pretty excited to finally help out. I made some small modifications to your code and seems to work fine. I noticed some odd behavior when I removed the $null variable that was getting assigned because it seemed strange to me why it was being done, but after removing that assignment my outlook application open by itself automatically every time I ran the script. I found the site where you got the code from just to see if there were any changes to the original code.
I found this Microsoft documentation very helpful to figure this out.
This is what I modified
ForEach ($Name In $NewTabNames){
$Break++
$Excel.Worksheets($Break).Name = $Name
$Excel.Worksheets($Break).Cells(1,1).Font.Bold = $true
$Excel.Worksheets($Break).Cells(1,1) = "Hostname"
$Excel.Worksheets($Break).Cells(1,2).Font.Bold = $true
$Excel.Worksheets($Break).Cells(1,2) = "IP Address"
}
I have this problem where i have 2 files and the output are:
value from file A is "No data"
value from file B is "prior to versions 0.9.8zd"
when I tried to write it on excel cell using powershell, value B always override value A. How to prevent this?
$outlook = new-object -comobject outlook.application
$dir="c:\users\john\desktop\"
$msgs=get-childitem $dir -filter "*.msg"
$rgx="blabla"
$regex="blablabla"
$xl=New-Object -ComObject Excel.Application
$xl.visible=$true
$wkbk=$xl.workbooks.add()
$wkbk.worksheets.add()
$wksht=$workbook.worksheets.item(1)
$wksht.name="TEST"
$wksht.cells.item(1,11)="Version(s)"
foreach($msg in $msgs)
{
$msg=$outlook.CreateitemFromTemplate($dir+$msg)
$body=$msg.body
if($body -match $rgx)
{
#echo "true"
$version=$body|select-string -pattern $regex -allmatches |%{$_.matches}|%{$_.value}
}
$row=$wksht.usedrange.rows.count+1
$usedrange=$wksht.usedrange
$usedrange.entirecolumn.autofit()|out-null
if([string]::IsNullOrEmpty($version))
{
$wksht.cells.item($row,11)="No data"
}
else
{
$wksht.cells.item($row,11)=$version
}
Expected result :
No Data <----first row,
prior to versions 0.9.8zd <-------2nd row
But what I got :
prior to versions 0.9.8zd <----first row,
prior to versions 0.9.8zd <-------2nd row
Your help highly appreciated. That's basically the whole code. do I missing something
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
As the title suggested, I'm not sure how to do the equivalent of selecting only a portion of a row and insert cells (shift rows down) using Powershell. It seems like all tutorials online are about inserting the entire row or entire column which is not what I want to do.
Any ideas?
Thanks.
Try something like this:
$xl = New-Object -COM "Excel.Application"
$xl.Visible = $true
$wb = $xl.Workbooks.Open "C:\path\to\your.xlsx"
$ws = $wb.Sheets.Item(1)
$ws.Range("C5:E9").Insert(-4121)