Im use Powershell module "ImportExcel" for generating xlsx report.
Some string, as "openstack-9cea5509-ed06-4301-b9e2-10f742e8c174:8", add in cell as HyperLink.
I cant remove HyperLink, next method not work:
$d = #(
[PSCustomObject]#{
HLUNID = "String11`nString22"
HostID = "String33`nStrong44"
}
[PSCustomObject]#{
HLUNID = "String55`nString552"
HostID = "openstack-9cea5509-ed06-4301-b9e2-10f742e8c174:8"
}
)
Export-Excel -Path "out1.xlsx" -InputObject $d -WorksheetName 'Luns' -AutoNameRange
$Excel = Open-ExcelPackage -Path "out1.xlsx"
$Excel.Workbook.Worksheets['Luns'].Cells['HostID'] | Set-ExcelRange -ResetFont
$Excel.Workbook.Worksheets['Luns'].Cells[3,2].HyperLink = ''
Close-ExcelPackage -ExcelPackage $Excel
String steel stay clickable:
Image - "Clickable cell"
Next method is not exist:
$Excel.Workbook.Worksheets['Luns'].Cells[3,2].HyperLink.Remove()
$Excel.Workbook.Worksheets['Luns'].Cells[3,2].HyperLink.Dispose()
Please, give me another method for delete HyperLynk.
Try setting the hyperlink $null
$Excel.Workbook.Worksheets['Luns'].Cells[3,2].HyperLink = $null
It will remove the hyperlink, but won't touch the formatting.
Have a read about the method and the functions to manage hyperlink I have proposed to be included into the module.
How to make Excel hyperlinks with PowerShell?
Related
I've created and script with Powershell that copy the result of a dataTable into the clipboard in order to paste it in Excel:
$excelArray = New-Object 'object[,]' $dt_table1.Rows.Count, $dt_table1.Columns.Count
$excelArray = ForEach($Row in $dt1.Tables[0].Rows)
{
$Record = New-Object PSObject
ForEach($Col in $dt1.Tables[0].Columns.ColumnName)
{
Add-Member -InputObject $Record -NotePropertyName $Col -NotePropertyValue $Row.$Col
}
$Record
}
$excelArray | ConvertTo-CSV -NoType -Del "`t" | Select -Skip 1 | Clip
[void]$WorkSheet.columns.Item(1).cells.Item(2).PasteSpecial()
$WorkSheet.Visible = $false
When i Exceute the script using "Powershell ISE" the script works fine, the problem came when i schedule this script using a CMD batch from the "Windows Task Scheduler". When the admin user is connected to the RDP and this batch is executed trough the scheduler it does not copy the result into the excel sheet, it copy the last thing i have in the clipboard.
When executing the batch and closing the RDP session, the batch fails without giving me an error..... What is happening? Maybe there is another way to copy the result of a datatable or dataset into an xcel sheet to avoid the clipboard?
Thanks!
A better way for working with Excel files is by using the module ImportExcel. It uses the EPPLUS library so you don't have to use any COM-objects, install Excel on a server or use the clipboard.
One way of exporting data to an Excel file is simply using Export-Excel.
First you need to install the module from the PowerShell Gallery:
Install-Module ImportExcel
Then you can use it in your scripts:
# myScript.ps1
#Requires -Module ImportExcel
Param (
$Path = 'C:\path\to\the.xlsx'
)
$exportToExcel = ForEach ($Row in $dt1.Tables[0].Rows) {
$properties = #{}
ForEach ($Col in $dt1.Tables[0].Columns.ColumnName) {
$properties[$Col] = $Row.$Col
}
[PSCustomObject]$properties
}
$params = #{
Path = $Path
WorksheetName = 'Data'
TableName = 'Data'
FreezeTopRow = $true
# HideSheet = 'Data'
}
$exportToExcel | Export-Excel #params
Some helpful commands to get you started:
Get-Help Export-Excel # displays what a function, its parameters, ..
Get-Help Export-Excel -Examples # displays how to use the function
Get-Command -Module ImportExcel # list all available functions in a module
I am writing a script that scans each cell in an excel file for PII. I've got most of it working, but I am experiencing two issues which may be related.
First of all, I am not convinced that the "Do" loop is performing as intended. The goal here is if the text in a cell matches the regex string, create a PSCustomObject with the location information, then use the object to add a line to a csv file.
It appears that the loop is running for every file, regardless of whether or not it actually found a match.
The other issue is that I can't seem to actually pull the cell value for the matched cell. I've tried several different variables and methods, the latest attempt being "$target.text," but the value of the variable is always null.
I've been racking my brain on this for days, but I'm sure it'll be obvious once I see it.
Any help here would be appreciated.
Thanks.
$searchtext = "\b(?!0{3}|6{3})([0-6]\d{2}|7([0-6]\d|7[012]))([ -]?)(?!00)\d\d\3(?!0000)\d{4}\b"
$xlsFiles = Get-ChildItem $searchpath -recurse -include *.xlsx, *.xls, *.xlxm | Select-object -Expand FullName
$Excel = New-Object -ComObject Excel.Application
$excel.DisplayAlerts = $false;
$excel.AskToUpdateLinks = $false;
foreach ($xlsfile in $xlsfiles) {
Write-host (Get-Date -f yyyymmdd:hhmm) $xlsfile
try{
$Workbook = $Excel.Workbooks.Open($xlsFile, 0, 0, 5, "password")
}
Catch {
Write-host $xlsfile 'is password protected. Skipping...' -ForegroundColor Yellow
continue
}
ForEach ($Sheet in $($Workbook.Sheets)) {
$i = $sheet.Index
$Range = $Workbook.Sheets.Item($i).UsedRange
$Target = $Sheet.UsedRange.Find($Searchtext)
$First = $Target
Do {
$Target = $Range.Find($Target)
$Violation = [PSCustomObject]#{
Path = $xlsfile
Line = "SSN Found" + $target.text
LineNumber = "Sheet: " + $i
}
$Violation | Select-Object Path, Line, LineNumber | export-csv $outputpath\$PIIFile -append -NoTypeInformation
}
While ($NULL -ne $Target -and $Target.AddressLocal() -ne $First.AddressLocal())
}
$Excel.Quit()
}
Figured it out. Just a simple case of faulty logic in the loops.
Thanks to everyone who looked at this.
I have multiple Excel files with different names in path.
e.g. C:\Users\XXXX\Downloads\report
Each file has a fixed number of columns.
e.g. Date | Downtime | Response
I want to create a new Excel file with merge of all Excel data. New column should be added with client name in which i want to enter file name. Then each Excel file data append below one by one.
e.g. Client name | Date | Downtime | Response
Below code can able to append all excel data but now need to add Client name column.
$path = "C:\Users\XXXX\Downloads\report"
#Launch Excel, and make it do as its told (supress confirmations)
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $True
$Excel.DisplayAlerts = $False
$Files = Get-ChildItem -Path $path
#Open up a new workbook
$Dest = $Excel.Workbooks.Add()
#Loop through files, opening each, selecting the Used range, and only grabbing the first 5 columns of it. Then find next available row on the destination worksheet and paste the data
ForEach($File in $Files)
{
$Source = $Excel.Workbooks.Open($File.FullName,$true,$true)
If(($Dest.ActiveSheet.UsedRange.Count -eq 1) -and ([String]::IsNullOrEmpty($Dest.ActiveSheet.Range("A1").Value2)))
{
#If there is only 1 used cell and it is blank select A1
[void]$source.ActiveSheet.Range("A1","E$(($Source.ActiveSheet.UsedRange.Rows|Select -Last 1).Row)").Copy()
[void]$Dest.Activate()
[void]$Dest.ActiveSheet.Range("A1").Select()
}
Else
{
#If there is data go to the next empty row and select Column A
[void]$source.ActiveSheet.Range("A2","E$(($Source.ActiveSheet.UsedRange.Rows|Select -Last 1).Row)").Copy()
[void]$Dest.Activate()
[void]$Dest.ActiveSheet.Range("A$(($Dest.ActiveSheet.UsedRange.Rows|Select -last 1).row+1)").Select()
}
[void]$Dest.ActiveSheet.Paste()
$Source.Close()
}
$Dest.SaveAs("$path\Merge.xls")
$Dest.close()
$Excel.Quit()
Suggest any effective way to do this. Please provide links if available.
Convert XLS to XLSX :
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
$excel = New-Object -ComObject excel.application
$excel.visible = $true
$folderpath = "C:\Users\xxxx\Downloads\report\*"
$filetype ="*xls"
Get-ChildItem -Path $folderpath -Include $filetype |
ForEach-Object `
{
$path = ($_.fullname).substring(0,($_.FullName).lastindexOf("."))
"Converting $path to $filetype..."
$workbook = $excel.workbooks.open($_.fullname)
$workbook.saveas($path, $xlFixedFormat)
$workbook.close()
}
$excel.Quit()
$excel = $null
[gc]::collect()
[gc]::WaitForPendingFinalizers()
If you are willing to use the external module Import-Excel, you could simply loop through the files like so:
$report_directory = ".\reports"
$merged_reports = #()
# Loop through each XLSX-file in $report_directory
foreach ($report in (Get-ChildItem "$report_directory\*.xlsx")) {
# Loop through each row of the "current" XLSX-file
$report_content = foreach ($row in Import-Excel $report) {
# Create "custom" row
[PSCustomObject]#{
"Client name" = $report.Name
"Date" = $row."Date"
"Downtime" = $row."Downtime"
"Response" = $row."Response"
}
}
# Add the "custom" data to the results-array
$merged_reports += #($report_content)
}
# Create final report
$merged_reports | Export-Excel ".\merged_report.xlsx"
Please note that this code is not optimized in terms of performance but it should allow you to get started
In a folder i have around 20 excel workbooks,each workbook having MIS for upload excel sheet i want to consolidate all data from each workbook from MIS for upload excel sheet to new csv file using powershell
below is the code which i have tried.But i want Browse for a Folder method.
#Get a list of files to copy from
$Files = GCI 'C:\Users\r.shishodia\Desktop\May 2018' | ?{$_.Extension -Match "xlsx?"} | select -ExpandProperty FullName
#Launch Excel, and make it do as its told (supress confirmations)
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $True
$Excel.DisplayAlerts = $False
#Open up a new workbook
$Dest = $Excel.Workbooks.Add()
#Loop through files, opening each, selecting the Used range, and only grabbing the first 6 columns of it. Then find next available row on the destination worksheet and paste the data
ForEach($File in $Files[0..20]){
$Source = $Excel.Workbooks.Open($File,$true,$true)
If(($Dest.ActiveSheet.UsedRange.Count -eq 1) -and ([String]::IsNullOrEmpty($Dest.ActiveSheet.Range("A1").Value2))){ #If there is only 1 used cell and it is blank select A1
$Source.WorkSheets.item("MIS for Upload").Activate()
[void]$source.ActiveSheet.Range("A1","R$(($Source.ActiveSheet.UsedRange.Rows|Select -Last 1).Row)").Copy()
[void]$Dest.Activate()
[void]$Dest.ActiveSheet.Range("A1").Select()
}Else{ #If there is data go to the next empty row and select Column A
$Source.WorkSheets.item("MIS for Upload").Activate()
[void]$source.ActiveSheet.Range("A2","R$(($Source.ActiveSheet.UsedRange.Rows|Select -Last 1).Row)").Copy()
[void]$Dest.Activate()
[void]$Dest.ActiveSheet.Range("A$(($Dest.ActiveSheet.UsedRange.Rows|Select -last 1).row+1)").Select()
}
[void]$Dest.ActiveSheet.Paste()
$Source.Close()
}
$Dest.SaveAs("C:\Users\r.shishodia\Desktop\Book2.xlsx",51)
$Dest.close()
$Excel.Quit()
For this purpose you could use ImportExcel module - installation guide included in repo README.
Once you install this module you can easily use Import-Excel cmdlet like this:
$Files = GCI 'C:\Users\r.shishodia\Desktop\May 2018' | ?{$_.Extension -Match "xlsx?"} | select -ExpandProperty FullName
$Temp = #()
ForEach ($File in $Files[0..20]) { # or 19 if you want to have exactly 20 files imported
$Temp += Import-Excel -Path $File -WorksheetName 'MIS for Upload' `
| Select Property0, Property1, Property2, Property3, Property4, Property5
}
To export (you wrote CSV but your destination file format says xlsx):
$Temp | Export-Excel 'C:\Users\r.shishodia\Desktop\Book2.xlsx'
or
$Temp | Export-Csv 'C:\Users\r.shishodia\Desktop\Book2.csv'
That ImportExcel module is really handy ;-)
I have over 150 excel files where some have an extra column (let's call it "ExtraColumn"), while some do not have this column. Instead of opening each file manually to see which ones have the extra column, I want to use powershell to figure it out.
The code I have tried so far hasn't seemed to have gotten me anywhere. If you have any suggestions or can point me to the correct answer, that would be very wonderful and much appreciated!
gci -Path C:\Test -Recurse | % {
$ExcelFile = (Get-Content $_.FullName -TotalCount 1)
if ($ExcelFile -like "ExtraColumn") {
Write-Host "$_ has the extra column"
} else {
Write-Host "$_ does not have the extra column"
}
}
You can use Excel ComObject, for the code simplicity just name the sheet otherwise you can find the sheet as well, add foreach section to run it on all files,
For the example i named the column - 'extracol'
$excel = New-Object -ComObject excel.application
$WB = $excel.Workbooks.Open('C:\exceltest.xlsx')
$WS = $Excel.WorkSheets.item("Sheet1")
$ExtraCol = ($ws.Columns.Find('extracol'))
if ($ExtraCol) {$ExtraCol.Delete()}
$wb.Save()
$wb.Close()
$excel.Quit()