Use powershell clipboard to copy rows from excel in browser - excel

I hope you can help me with my PowerShell problem. I want to use the Set-Clipboaed and Get-Clipboard commands from PowerShell to copy specific rows from my excel file in two different textfields in a specific browser site.
The problem is that I always get the content copied from the rows in my excel file, only in the first textfield. For example: The content of row A1 is "Hello" and the content from row A2 is "World". If I copy the rows in the textfields of the browser site, both Strings "Hello" "World" will be displayed only in textfield1. My goal is to have the string "Hello" in textfield1 and the string "World" in textfield2 and later to have a command to use keys on my keyboard to paste the content like in KeePass with the credentials.
Here's what I've done so far. I used a little help from the site https://lazywinadmin.com/2014/03/powershell-read-excel-file-using-com.html and tried to split both rows in two different strings and then tried to copy both string with "Get-Clipboard" in the browser site.
#Specify the path of the excel file
$FilePath = "PathToMyExcelFile\Test-Excel-Auto2.xlsx"
#Specify the Sheet name
$SheetName = "table1"
# Create an Object Excel.Application using Com interface
$objExcel = New-Object -ComObject Excel.Application
#$objExcel = new-object -c excel.application
# Disable the 'visible' property so the document won't open in excel
$objExcel.Visible = $false
# Open the Excel file and save it in $WorkBook
$WorkBook = $objExcel.Workbooks.Open($FilePath)
# Load the WorkSheet 'BuildSpecs'
$WorkSheet = $WorkBook.sheets.item($SheetName)
Set-Clipboard $WorkSheet.Range("A1").Text
Set-Clipboard $WorkSheet.Range("A2").Text -Append
(Get-Clipboard) -split "'n'"
# Get-Clipboard) -split '\t|\r?\n'
# Get-Clipboard.Split ( "'\t|\r?\n'")
# Set-Clipboard $WorkSheet.Range("A1").Text
# $variable = Get-Clipboard
# Set-Clipboard $WorkSheet.Range("A2").Text -Append
# $variable2 = Get-Clipboard
I miss the part, how to get both strings copied in the two different textfields in my browser site.
Thanks in advance for your help.
MarT22

Setting $WorkSheet.Range("A2").Text means you're only copying the cell text ("world"). You're then appending the text with what's already in your clipboard ("hello"), which gives you just a concatenated string ("helloworld").
You need to set the clipboard content to a variable and store it for later. Depending on how many different fields you need, you'll either want to set the content into a temporary string or two, or you will want to look into hashtables.
It looks like you were going in the right direction in your commented out code. You'll want to do something like:
$Hello = Set-Clipboard $Worksheet.Range("A1").Text
$World = Set-Clipboard $Worksheet.Range("A2").Text
Then later when you need to paste the content you need to put the variables back into your clipboard, then paste the content.
For example, with something like KeePass you're going to be looking at username/password combos, so what you'd get would be:
PS C:\> $Username = Set-Clipboard $Worksheet.Range("A1").Text # ("Hello")
PS C:\> $Password = Set-Clipboard $Worksheet.Range("A2").Text # ("World")
PS C:\> Set-Clipboard $Username
PS C:\> Get-Clipboard
Hello
PS C:\> Set-Clipboard $Password
PS C:\> Get-Clipboard
World

Related

How to change delimiter in excel CSV saving using powershell

Using Powershell and Excel 2016, I'm trying to open a .xlsx file, extract a single page, and save this page as a .csv with a " ; " delimiter. The problem is that while Excel expects " ; " delimiter when opening a csv file, it always saves them with a " , " delimiter.
I'd prefer to not have to change any settings, this is a script i'm writing for a project that needs to work natively on any pc, so having to go and change settings every time I need it to run on another computer would be problematic.
I already checked that the list delimiter settigs in windows was indeed a " ; ", and it is.
I tried every type of CSV saving described in the microsoft doc (https://learn.microsoft.com/fr-fr/office/vba/api/excel.xlfileformat),
what's weird is that when saving a file from the GUI version, I only have 3 versions of CSV, instead of 5 listed on the website, and one of them is "CSV with " ; " delimiter", which works as intended, but I can't seem to use this type of file when saving using Excel via Powershell
There's apparently a "local" flag that can be activated for Excel to use the delimiter settings of windows, but I have no idea of how ot activate it in Powershell and I'd prefer not to use this since it means that the program wouldn't work on a Windows with a different delimiter configuration.
# Args[0] : file to open
# [1] : file to save
# page_to_extract : name of the page I need
# I open an Excel session
$excel_session = New-Object -Com Excel.Application
$excel_session.displayAlerts = $false
# I open the file I need to extract the page from
$excel_workbook = $excel_session.workbooks.open($args[0])
# I load in the page
$excel_worksheet = $excel_workbook.worksheets($page_to_extract)
# I save the page using a csv type (6,22,24,62,23)
$excel_worksheet.saveAs($args[1], 6)
$excel_session.quit()
This code always saves my csv with a " , " delimiter, I need " ; " instead.
I need to use Powershell and ONLY Powershell for this, no windows settings, no excel settings.
I had success with the following code with my own data. This uses your COM Object assignment code. I added logic to extract the cells that contain data, add that data to a new custom object on each row iteration, store each custom object in an array, and finally pipe the array into Export-Csv. Your specified delimiter ; is used in the Export-Csv command.
$excel_session = New-Object -Com Excel.Application
$excel_session.displayAlerts = $false
# I open the file I need to extract the page from
$excel_workbook = $excel_session.workbooks.open($args[0])
# I load in the page
$excel_worksheet = $excel_workbook.worksheets($page_to_extract)
# Get Range of Used Cells in Worksheet
$range = $excel_worksheet.usedrange
# Get First Row Column Text to be Used as Object Properties
$headers = $range.rows.item(1).value2
# Loop through Rows and Columns to Extract Data
# First loop traverses rows
# Second loop traverses columns
$output = for ($i = 2; $i -le $range.rows.count; $i++) {
$hash = [ordered]#{}
for ($j = 1; $j -le $range.columns.count; $j++) {
[void]$hash.Add($headers.GetValue(1,$j),$range.rows.item($i).columns.item($j).Text)
}
[pscustomobject]$hash
}
$output | Export-Csv file.csv -NoType -Delimiter ';'
# Clean Up COM Objects
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel_workbook)
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel_session)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
An inefficient, but simple and pragmatic workaround is to:
Use your code as-is to let Excel temporarily produce an interim ,-separated CSV file.
Import that file with Import-Csv (which uses , by default), and export again with Export-Csv -Delimiter ';'.
In the context of your code:
(Import-Csv $args[1]) | Export-Csv $args[1] -Delimiter ';' -NoTypeInformation
Note:
The Import-Csv call is enclosed in (...) to ensure that the input file is read in full up front, which enables writing back to the same file in the same pipeline.
Export-Csv, sadly, defaults to ASCII(!) encoding; if your data contains non-ASCII characters, specify an appropriate encoding with -Encoding.
The List Separator is a Windows regional setting.
To change it, please see :
https://support.office.com/en-us/article/import-or-export-text-txt-or-csv-files-5250ac4c-663c-47ce-937b-339e391393ba
Change the separator in all .csv text files In Microsoft Windows,
click the Start button, and then click Control Panel.
Open the dialog box for changing Regional and Language settings.
Type a new separator in the List separator box.
Click OK twice.
Note: After you change the list separator character for your
computer, all programs use the new character as a list separator. You
can change the character back to the default character by following
the same procedure.
You should now be able to change the csv character delimiter.
Please note that you'll need to restart your computer to make the change in effect. You can check your current List Separator value in your Powershell session with (Get-Culture).TextInfo.ListSeparator
You can also check this post, which has a lot of screenshot and different other options on how to do so: https://superuser.com/questions/606272/how-to-get-excel-to-interpret-the-comma-as-a-default-delimiter-in-csv-files
My recommendation is to avoid Excel and use the database objects instead. Example:
[CmdletBinding()]
param(
[Parameter(Position = 0,Mandatory = $true)]
[ValidateNotNullOrEmpty()]
$ExcelFileName,
[Parameter(Position = 1,Mandatory = $true)]
[ValidateNotNullOrEmpty()]
$SheetName
)
$queryString = 'SELECT * FROM [{0}$A1:end]' -f $SheetName
$connectionString = ("Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=$((Get-Item -LiteralPath $ExcelFileName -ErrorAction Stop).FullName);" +
"Extended Properties=Excel 8.0;")
try {
$connection = New-Object Data.OleDb.OleDbConnection($connectionString)
$command = New-Object Data.OleDb.OleDbCommand($queryString)
$command.Connection = $connection
$connection.Open()
$adapter = New-Object Data.OleDb.OleDbDataAdapter($command)
$dataTable = New-Object Data.DataTable
[Void] $adapter.Fill($dataTable)
$dataTable
}
catch [Management.Automation.MethodInvocationException] {
Write-Error $_
}
finally {
$connection.Close()
}
If the above script is Import-ExcelSheet.ps1, you could export to a ;-delimited CSV file by running a command such as:
Import-ExcelSheet "C:\Import Files\ExcelFile.xlsx" "Sheet1" |
Export-Csv C:\Import Files\Test.Csv" --Delimiter ';' -NoTypeInformation
If you have the 32-bit version of Excel installed, you will need to run the above script in the 32-bit version of PowerShell.
If you don't want to license Excel or can't install it on some computer where you want to run the script, you can install the Access database engine instead:
https://www.microsoft.com/en-us/download/details.aspx?id=54920

Print hidden excel sheet from multiple workbooks with Powershell

I have monthly task os printing some data for pure accounting.
this data are in some excel workbooks on a hidden sheet, as it is now I have to open the workbook, reveal the sheet, print it and hide it again.
I would like to this task to automated.
All the workbooks are in the same directory
I have a Powershell script that can print every thing i one directory, but i don't know how to target a specific sheet let alone a hidden sheet
Code to print from one directory:
$files = Get-ChildItem “Y:\Booking\Send*.*”
foreach ($file in $files){
start-process -FilePath $file.fullName -Verb Print
}
how would i do this ?
The below will allow you to print the hidden sheet of a single excel workbook that you could extend to print multiple in a loop.
This will use the default printer set in windows.
$FilePath = Get-ChildItem "Y:\Booking\November\*.xls"
$HiddenSheet = "Administration"
$xl = New-Object -ComObject Excel.Application
$xl.Visible = $False
foreach ($file in $FilePath){
$wb = $xl.Workbooks.Open($file)
$ws = $wb.WorkSheets.Item($HiddenSheet)
$ws.Visible = $True
$ws.PrintOut()
$wb.close($false)
}
$xl.quit()
To be able to print the hidden sheet it needs to be set to visible, the script handles this and then closes the workbook and does not keep the changes.
You must declare the name of the $hiddensheet so if the name is different on each workbook I would suggest making a CSV with filepath and name of the sheet so that these can be passed through and handled accordingly.

Inserting text from text file into existing Excel worksheet with PowerShell

I'm trying to insert the contents of my text file into cell A1 on Sheet1 but all I get is the filename inserted instead of the contents of the text file.
$Path = 'C:\folder\Test.xlsx'
$Text='C:\folder\text.txt'
# Open the Excel document and pull in the 'Play' worksheet
$Excel = New-Object -Com Excel.Application
$Excel.Visible=$true #For troubleshooting purposes only.
$Workbook = $Excel.Workbooks.Open($Path)
$page = 'Sheet1'
$ws = $Workbook.worksheets | where-object {$_.Name -eq $page}
# Set variables for the worksheet cells, and for navigation
$cells=$ws.Cells
$row=1
$col=1
$cells.item($Row,$col)=$Text
$col++
# Close the workbook and exit Excel
$workbook.Close($true)
$excel.quit()
That is because you set $Text to just the path to the file. You have to actually read the contents of the file with a cmdlet like Get-Content.
For example:
$Text = Get-Content 'C:\folder\text.txt'
However, depending on the contents of that text file, you may want to do that differently or you could end up with a messy result.

Finding content of Excel file in Powershell

I am currently working on a fairly large powershell script. However, I got stuck at one part. The issue is the following.
I have various reports with the same file name, they just have a different time stamp at the end. Within the report, I have a field displaying the date from when to when the report is from.
---> 2/1/2015 5:00:00AM to 3/1/2015 5:00:00AM <--- This is what it looks like.
This field is randomly placed on the Excel Sheet. Pretty much in the range of A5 to Z16. What I would like the script to do is:
Read the file / Check the range of cells for the dates, if the date is found and it matches my search criteria, close the sheet and move it to a different folder / If date does not match, close and check next XLS file
This is what I got so far:
$File = "C:\test.XLS"
$SheetName = "Sheet1"
# Setup Excel, open $File and set the the first worksheet
$Excel = New-Object -ComObject Excel.Application
$Excel.visible = $true
$Workbook = $Excel.workbooks.open($file)
$Worksheets = $Workbooks.worksheets
$WorkSheet = $WorkBook.sheets.item($SheetName)
$SearchString = "AM" #just for test purposes since it is in every report
$Range = $Worksheet.Range("A1:Z1").EntireColumn
$Search = $Range.find($SearchString)
If you want it to search the entire column for A to Z you would specify the range:
$Range = $Worksheet.Range("A:Z")
Then you should be able to execute a $Range.Find($SearchText) and if the text is found it will spit back the first cell it finds it in, otherwise it returns nothing. So start Excel like you did, then do a ForEach loop, and inside that open a workbook, search for your text, if it is found close it, move it, stop the loop. If it is not found close the workbook, and move to the next file. The following worked just fine for me:
$Destination = 'C:\Temp\Backup'
$SearchText = '3/23/2015 10:12:19 AM'
$Excel = New-Object -ComObject Excel.Application
$Files = Get-ChildItem "$env:USERPROFILE\Documents\*.xlsx" | Select -Expand FullName
$counter = 1
ForEach($File in $Files){
Write-Progress -Activity "Checking: $file" -Status "File $counter of $($files.count)" -PercentComplete ($counter*100/$files.count)
$Workbook = $Excel.Workbooks.Open($File)
If($Workbook.Sheets.Item(1).Range("A:Z").Find($SearchText)){
$Workbook.Close($false)
Move-Item -Path $File -Destination $Destination
"Moved $file to $destination"
break
}
$workbook.close($false)
$counter++
}
I even got ambitious enough to add a progress bar in there so you can see how many files it has to potentially look at, how many it's done, and what file it's looking at right then.
Now this does all assume that you know exactly what the string is going to be (at least a partial) in that cell. If you're wrong, then it doesn't work. Checking for ambiguous things takes much longer, since you can't use Excel's matching function and have to have PowerShell check each cell in the range one at a time.

Convert multiple xls to csv using powershell

I'm trying to convert multiple excel files (xls) to csv which is located in a folder using powershell.
I can convert a single file but need help converting multiple files in a folder.
But need advise on how to convert multiple files.
$ExcelWB = new-object -comobject excel.application
$Workbook = $ExcelWB.Workbooks.Open(c:\temp\temp.xls)
$Workbook.SaveAs("c:\temp\temp.csv",6)
$Workbook.Close($false)
$ExcelWB.quit()
You can just wrap it in a loop that iterates over all the files and change the xls extension to csv:
foreach($file in (Get-ChildItem "C:\temp")) {
$newname = $file.FullName -replace '\.xls$', '.csv'
$ExcelWB = new-object -comobject excel.application
$Workbook = $ExcelWB.Workbooks.Open($file.FullName)
$Workbook.SaveAs($newname,6)
$Workbook.Close($false)
$ExcelWB.quit()
}
There are caveats with this untested code but it should help wrap your head around your issue
$ExcelWB = new-object -comobject excel.application
Get-ChildItem -Path c:\folder -Filter "*.xls" | ForEach-Object{
$Workbook = $ExcelWB.Workbooks.Open($_.Fullname)
$newName = ($_.Fullname).Replace($_.Extension,".csv")
$Workbook.SaveAs($newName,6)
$Workbook.Close($false)
}
$ExcelWB.quit()
Take the lines in between the first and last and build a loop. Use Get-ChildItem to grab your xls files and then build a new name by replacing the extension if the FullName of the file
The conversion from xlsx files to csv can be done far quicker and without COM Objects - so without Excel installed - using the ImportExcel module developped by Doug Finke:
Install-Module -Name ImportExcel -RequiredVersion 5.4.2
gci *.xlsx | %{Import-Excel $_ | Export-Csv ($_.basename + ".csv")}
Or the other way around:
gci *.csv | %{Import-Csv $_ | Export-Excel ($_.basename + ".xlsx")}
Parameters available for the Import-Excel cmdlet:
WorksheetName
Specifies the name of the worksheet in the Excel workbook to import. By default, if no name is provided, the first worksheet will be imported.
DataOnly
Import only rows and columns that contain data, empty rows and empty columns are not imported.
HeaderName
Specifies custom property names to use, instead of the values defined in the column headers of the TopRow.
NoHeader
Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow.
StartRow
The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.
EndRow
By default all rows up to the last cell in the sheet will be imported. If specified, import stops at this row.
StartColumn
The number of the first column to read data from (1 by default).
EndColumn
By default the import reads up to the last populated column, -EndColumn tells the import to stop at an earlier number.
Password
Accepts a string that will be used to open a password protected Excel file.
Expanding on the answer from #arco444, if you are doing this in bulk you should create the excel object outside the loop for a much more performant conversion
$ExcelWB = new-object -comobject excel.application
foreach($file in (Get-ChildItem "C:\temp")) {
$newname = $file.FullName -replace '\.xls$', '.csv'
$Workbook = $ExcelWB.Workbooks.Open($file.FullName)
$Workbook.SaveAs($newname,6)
$Workbook.Close($false)
}
$ExcelWB.quit()
Apologies I can't comment and edit queue has been full for some time, so posting as an answer instead.

Resources