Programmatically Add Links to Excel Spreadsheet - excel

I am working on adding links to a spreadsheet of variable length through PowerShell and I am running into an error no matter how I do it. This is the loop I am currently trying to make work, which is nested within an excel comobject, with $sheet representing $excel.activeworkbook.activesheet :
$v = 2
foreach($i in $list){
$r = "A"+$v
$link = "www.url.com"
$sheet.Hyperlinks.Add($r,$link)
$v++
}
Which keeps throwing the following error:
Exception setting "Add": Cannot convert the "A2" value of type "string" to type "Object".
At C:\hyperlink_wip.ps1:31 char:5
+ $sheet.Hyperlinks.Add($r,$link)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : RuntimeException
in this example, $list is a list which contains the information from one column of this spreadsheet and will always be the same length as the spreadsheet itself. The spreadsheet also has a header row, so the cells I want to hyperlink start at A2. I also tried the method outlined here for adding links to an excel spreadsheet but got an incorrect format error each time I tried it.

$r isn't a Range or Shape. Here's the Add Method on MSDN
Here's an example of how you could use it in your code:
$v = 2
foreach($i in $list){
$r = $sheet.range("A"+$v)
$link = "www.url.com"
$sheet.Hyperlinks.Add($r,$link)
$v++
}

Related

How to subtract Excel cells using Powershell

I am trying to perform arithmetic on an existing excel sheet that has figures in it. My code:
$Excel = New-Object -ComObject Excel.Application
$ExcelWorkBook = $Excel.Workbooks.Open($temp)
$ExcelWorkSheet = $Excel.WorkSheets.item(1)
$ExcelWorkSheet.activate()
$Prehit = $ExcelWorkSheet.Cells.Item(2,1)
$Hit1 = $ExcelWorkSheet.Cells.Item(2,2)
$Hit2 = $ExcelWorkSheet.Cells.Item(2,3)
$Hit3 = $ExcelWorkSheet.Cells.Item(2,4)
$Remain = 0
If ($hit -eq 1) {
$Remain = $Prehit - $Hit1
}
If ($hit -eq 2) {
$Remain = $Prehit - $Hit1- $Hit2
}
Yields the following error:
Method invocation failed because [System.__ComObject] does not contain a method named 'op_Subtraction'.
At C:\path_to_ps1_file.ps1:40 char:3
+ $Remain = $Prehit - $Hit1- $Hit2
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Subtraction:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
I have tried casting all the variables as ints yet that yields the same error. I even casted the numbers as ints in the powershell modules used to create this excel file. What am I missing?
I realize now I was referencing the cell values incorrectly. The correct way is to do:
$Prehit = $ExcelWorkSheet.Cells.Item(2,1).Text
$Hit1 = $ExcelWorkSheet.Cells.Item(2,2).Text
$Hit2 = $ExcelWorkSheet.Cells.Item(2,3).Text
$Hit3 = $ExcelWorkSheet.Cells.Item(2,4).Text
Whenever I've run into this sort of thing, I just the 'Excel Marco Recorder' and review the VBA code it produces and then convert that to PowerShell for later automation use cases.
Yet at no point in the code you posted are you making the XLS visible for you to act on it.
For example:
# Instantiate Excel instnace
$excel_test = New-Object -ComObject Excel.Application
# Make the instance visiable to work with it
$excel_test.visible = $true
# Catch alerts
$excel_test.DisplayAlerts = $true
# Add in the file source
$excel_test.Workbooks.Add('D:\Temp\Test.xlsx')
# Choose a sheet in the workbook
$Sheet = $excel_test.Worksheets.Item(1)
# Assign a formula to the target variable
$strFormula = '=(SUM(A1:C3)/3) - 1'
# Assign the formula to the target variable
$Sheet.Cells.Item(4,4) = $strFormula
$SourcecellCell = ($Sheet.Cells.Item(4,4)).Value2
$NewCell = 3
$sheet.Cells.Item(5,5) = $SourcecellCell - $NewCell
# Exit the XLS without saving
$excel_test.Quit()
Whenever I've run into this sort of thing, I just the 'Excel Marco Recorder' and review the VBA code it produces and then convert that to PowerShell for later automation use cases.
Yet at no point in the code you posted are you making the XLS visible for you to act on it. Since it is not visible, you cannot perform UI actions on it.
Secondly, this...
$excel_test.Worksheets.Item(2).Cells.Item(2,2).Formula() = $strFormula
... is where your issues begin. If you step through this one step at a time, you'll immediately see the aforementioned will simply fail.
For example:
# Instantiate Excel instance
$excel_test = New-Object -ComObject Excel.Application
# Make the instance visible to work with it
$excel_test.visible = $true
# Catch alerts
$excel_test.DisplayAlerts = $true
# Add in the file source
$excel_test.Workbooks.Add('D:\Temp\Test.xlsx')
# Results
<#
Application : Microsoft.Office.Interop.Excel.ApplicationClass
Creator : 1480803660
Parent : Microsoft.Office.Interop.Excel.ApplicationClass
...
#>
# Assign a formula to the target variable
$strFormula = "=((A1:C4/10000)-1)"
# Assign the formula to the target variable
$excel_test.Worksheets.Item(2).Cells.Item(2,2).Formula() = $strFormula
<#
Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))
At line:1 char:1
+ $excel_test.Worksheets.Item(2).Cells.Item(2,2).Formula() = $strFormul ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
#>
$Error | Format-List -Force
<#
Exception : System.Management.Automation.RuntimeException: The variable '$command' cannot be retrieved because it has not been set.
at System.Management.Automation.VariableOps.GetVariableValue(VariablePath variablePath, ExecutionContext executionContext,
VariableExpressionAst varAst)
at Prompt(Closure , FunctionContext )
TargetObject : command
CategoryInfo : InvalidOperation: (command:String) [], RuntimeException
FullyQualifiedErrorId : VariableIsUndefined
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at Prompt, C:\Users\Daniel\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1: line 55
at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}
PSMessageDetails :
...
#>

Exception from HRESULT: 0x800A03EC when setting value of a cell (through Powershell)

I am trying to set a value to an excel cell through Powershell, and I am getting the error HRESULT: 0x800A03EC, which ends the script prematurely. I realize there have been other questions relating to this error or similar, but none of the solutions have worked for me, so I am assuming this is a separate problem.
I have run my script before but it is only now giving me this error.
Relevant code:
$Output_Location = "Z:\Documents\Powershell"
$Excel_File = "Report.xlsx"
$ExcelWorkBook = $Excel.Workbooks.open("$Output_Location\$Excel_File")
$MainSheet = $ExcelWorkBook.worksheets.Item("Report")
$Sheet1 = $ExcelWorkBook.worksheets.Item("Sheet1")
$Sheet1.name = "Statistics"
$StatisticsSheet = $ExcelWorkBook.worksheets.Item("Statistics")
$row = 3
$column = 2
$StatisticsSheet.Cells.Item(2,2)= 'KeyToMatch'
$StatisticsSheet.Cells.Item($row,$column) = '=COUNTIFS(Report!E2:E200000,B$3,Report!G2:G200000,"UserMailbox")'
$row++
$StatisticsSheet.Cells.Item($row,$column) = '=COUNTIFS(Report!E2:E200000,B$3,Report!G2:G200000,"RemoteUserMailbox")'
$row++
The code loads up the excel file and hits the line which sets the cell (2,2)/(B,2) to its value just fine. But when the code hits the line setting the cell value the row below the KeyToMatch (B,3), it throws the error 0x800A03EC.
Full error:
Exception from HRESULT: 0x800A03EC
At Z:\Documents\Powershell\Reporting\Report.ps1:113 char:1
+ $StatisticsSheet.Cells.Item($row,$column).value = '=COUNTIFS(Report! ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
I have tried spacing out the '=' between the cell and value, I have also tried the following:
$StatisticsSheet.Cells.Item($row,$column).value = ...
$StatisticsSheet.Cells.Item($row,$column).value2 = ...
$StatisticsSheet.Cells.Item($row,$column).text = ...
$StatisticsSheet.Cells.Item($row,$column).formula = ...
I can comment out any number of lines which set the cell's value to a formula and the first one to attempt to do so will throw the mentioned error.
Like I said, I have run this script before but it is only now giving me troubles. How can I fix this so the code runs smoothly?
Moved solution from question to answer:
RESOLUTION:
To resolve this issue, in the text I assigned to the cell, I replaced single quotes with double quotes, and because of this, had to escape the '$' and ' " ' characters. I also ADDED single quotes around "Report" (The table name from which data is being pulled) each time it came up within the text.
It ended up looking like this, and running fine:
$StatisticsSheet.Cells.Item($row,$column) = "=COUNTIFS('Report'!E2:E200000,B`$3,'Report'!G2:G200000,`"UserMailbox`")"
Still not sure why this error occurred-the code had worked every week prior to this! Before changing the script and finding the resolution, I tested it on multiple machines (5+) and it threw the error mentioned in the title every single time.
this is very simple issue, which in range put the values like
ExcelSheet.Cells.Range("A1:A1").Value = "'asdf"

Excel & PowerShell - PasteSpecial Failure With VLOOKUPs

I have a VLOOKUP being inserted into my spreadsheet's F column like this:
$vLookup = "=VLOOKUP($refCol,'$xlsLocsDIR[locs.xlsx]Device'!`$B`$2:`$C$rowsDvcs,2,FALSE)"
$sheetSave.Cells.Item(2,6).Formula = $vLookup
Which is, to be clear, saved properly in Excel like this:
=VLOOKUP(E2,'[locs.xlsx]Device'!$B$2:$C24549,2,FALSE)
(There are ~25k lines in the reference file, but there are over 200k in the file I have the VLOOKUP in.)
Because of the size of the file in which I'm doing the VLOOKUP within, and the customer could be utilizing 32-bit OS or Excel, I have to Copy/Paste no more than around 30000 rows at a time, to fill all 200k rows out, like so:
#32-bit OS/Excel app compatibility
#Excel/32-bit OS/memory errors occur if doing more than 30k cells
#instead, we do 20k, save, 20k, save, etc
for ($i=2; $i -le $rowsTrans; ($i+30000))
{
#set the stop point, not to exceed total usedrows
if (($i + 30000) -gt $totalRows)
{$j = $totalRows}
else
{$j = ($i+30000)}
#copy the data
$copyCell = (("F" + $i))
$copyRange = $sheetTrans.Range($copyCell)
$copyRange.Copy() | Out-Null
$sheetSave.Activate()
$pasteRange = $sheetTrans.Range(("F"+$i+":F"+$j)).Select()
$sheetSave.PasteSpecial(7)
$fileWorking.Save()
}
I only want to copy the VLOOKUP formula from Cell F2, into the next 20k rows of column F, then save the file, and iterate through again until I've populated the entire file.
When I do the above, and I've tried different methods aside from this example, I always receive a MethodInvocation Error, unless I explicitly make the file/sheet visible, like so, before the above loop:
$xlsObject.Visible = $true
What am I misunderstanding about the Copy() / PasteSpecial() function calls? Why does the sheet have to be visible?
NOTE: I've tried to anonymize the above code and limit what is necessary to understand the issue. The code functions, I just don't want to require the Excel instance to be brought into view at any point. I'd prefer the script run invisible to the end-user.
The MethodInvocation error I receive is typically as follows:
Exception calling "PasteSpecial" with "1" argument(s): "PasteSpecial method of
Worksheet class failed"
At line:1 char:25
+ $sheetTrans.PasteSpecial <<<< (9)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
I was able to solve this by doing a few direct references, and changing the way I assigned the range, and then calling PasteSpecial, like so:
$pasteRange = $sheetTrans.Range(("F"+$i+":F"+$j))
$pasteRange.PasteSpecial($xlPasteValues) | Out-Null
With declarations like this:
Add-Type -ASSEMBLY "Microsoft.Office.Interop.Excel" | out-null
$global:xlPasteFormulas = -4123
$global:xlPasteValues = -4163

Powershell script to filter a particular item in excel

I have created a Powershell script to filter out a particular item in an coulmn . The script so far :
$file1 = "C:\Users\ab270510\Desktop\t.xlsx" # source's fullpath
$xl = new-object -c excel.application
$xl.displayAlerts = $false # don't prompt the user
$wb1 = $xl.workbooks.open($file1) # open target
$sh1 = $wb1.sheets.item('Sheet1') # sheet in workbook
$sh1.Select()
$sh1.Range("C1").Select()
$xlFilterValues = 7 # found in MS documentation
$filterList = “Jan”,”feb” # array
$xl.Selection.AutoFilter(2, $filterList ,$xlFilterValues)
$sh1.cells.Item.EntireColumn.AutoFit
$wb1.close($true) # close and save workbook
$xl.quit()
But the above code is giving error like :
Exception calling "AutoFilter" with "3" argument(s): "AutoFilter method of Range class failed"
At line:1 char:25
+ $xl.Selection.AutoFilter <<<< (2, $filterList ,$xlFilterValues)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Please help me to write a Powershell script that will filter out only "Jan" & "Feb" item from a particular coulmn of an excel file . Also suggest me how can I filter single or multiple item .
Please see my answer here, after much reaserch i have figured this out, and it works.. Howerver, i am still working on how to do the reverse and only not choose a few items...Have to give credit to the above post... But i have tested and it works great...
Here is the working code, and a link to the thread...
# Filter for an array of values IE: choose muipliple items.... in one column
$xlFilterValues = 7 # found in MS documentation
$FL = #("value 1", "value2")
$rng=$Worksheet.cells.item(2,38).entirecolumn
$rng.select | Out-Null
$excel.Selection.AutoFilter(20,$FL,$xlFilterValues)
http://social.msdn.microsoft.com/Forums/office/en-US/81e4a2b0-d016-4a56-92e6-c3d4befa75db/powershell-excel-autofilter-on-multiple-items?forum=exceldev

Paste Special with powershell and excel

Using Powershell 2.0 I am trying to copy the results of a formula in one worksheet to another. In order to do this I need to use paste special (otherwise I get #value error).
However, the following code is not working. The first block is just a regular paste that works fine, but the second block has the paste special and it doesn't work. The error I get is below.
The question does anyone know what this error means or what the best way to do a paste special using Powershell and Excel is?
Works:
$worksheet.activate()
$sessionidcopyrange = $worksheet.Range("J1").EntireColumn
$sessionidcopyrange.copy()
$worksheet2.activate()
$sessionidpasterange =$worksheet2.Range("A1")
$worksheet2.paste($sessionidpasterange, $false)
Doesn't work:
$worksheet.activate()
$codecopyrange = $worksheet.Range("Q1").EntireColumn
$codecopyrange.copy()
$worksheet2.activate()
$codepasterange = $worksheet2.Range("B1")
$worksheet2.pastespecial(-4163, $false)
Exception calling "PasteSpecial" with "2" argument(s): "PasteSpecial method of
Worksheet class failed"
At line:33 char:25
+ $worksheet2.pastespecial <<<< (-4163, $false)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Example:
$Dest = $Excel.Workbooks.Add()
$Dest.ActiveSheet.Range("B:C").copy()
$Dest.ActiveSheet.Range("D1").Select()
$Dest.ActiveSheet.Range("D1").PasteSpecial(-4163)
Paste special with PowerShell and Excel:
The second value is of type XlPasteSpecialOperation.
$worksheet2.pastespecial(-4163, $false)
should be
$worksheet2.pastespecial(-4163, xlPasteSpecialOperationNone)

Resources