How to read an Excel file in PowerShell on Linux? - excel

As many of you are aware, PowerShell can now be installed and used on Linux and it has worked surprisingly well for me so far. However, I wonder if the content of an Excel file can be read given that Excel cannot be installed on Linux. What I have found online is that the PS script to open an Excel file is:
# Script copied and pasted from https://stackoverflow.com/questions/48443536/how-to-read-excel-files-in-powershell
$excel = New-Object -com excel.application
$wb = $excel.workbooks.open("c:\users\administrator\my_test.xls")
But I get the error:
New-Object: A parameter cannot be found that matches parameter name 'com'.
When I remove the parameter and run the script, this is the error I get:
New-Object: Cannot find type [excel.application]: verify that the assembly containing this type is loaded.
Since I'm on Linux (ubuntu 22.04), I can use xls2csv on bash to convert the Excel file to csv and then use Get-Content on PowerShell. But I would like to know if there is a way to do it on PowerShell since I am currently learning it.
Thank you.

I am grateful to #Olaf who pointed out the ImportExcel module from Doug Finke.
After installing the module with:
Install-Module -Name ImportExcel
importing the file is as easy as:
$data = Import-Excel c:\users\administrator\my_test.xls

Related

Timeout while executing Powershell script

I don't have much experience with Powershell yet, I'm looking for a solution for my script.
I work with a process automation platform called "Firestart" and in it you can run powershell scripts.
The purpose of the script: to read a single cell from an .xlsx file.
Right now I am trying to run a script with this application and then the script keeps running for 10 minutes. Because of this I automatically get a Timeout error which is logical.
If I run this script on the same server in Powershell, I get the desired outout within 1 seconds.
It might be an problem of the application itself, but maybe someone can review my script.
Script:
$objExcel = New-Object -ComObject Excel.Application
$ExcelFile = '#.xlsx file'
$WorkBook = $objExcel.Workbooks.Open($ExcelFile)
$workbook.sheets.item(1).activate()
$WorkbookTotal=$workbook.Worksheets.item(1)
$value = $WorkbookTotal.Cells.Item(10, 2)
return $value.Text

WinSCP - How to download only folders/files 1 day old while excluding empty folders/files? [duplicate]

I am limited to PuTTY and WinSCP only.
I am trying to download log directories with log files. For example, I want to grab all log_files 6 days old or newer. log_dir2 and log_dir3 including the folders match the criteria, while log_dir1 and its files does not.
DIR/log_dir1/log_files % older than 6 days
DIR/log_dir2/log_files % meets criteria
DIR/log_dir3/log_files % meets criteria
My problem is that while the log_files of log_dir1 are not downloaded, the syntax I am currently using downloads the log_dir1 folder. Normally, not a big deal, but we are talking hundreds of log_dir folders (all empty as the files are older than 6 days). For reasons beyond my control, I cannot move or archive these old log directories with their log files.
My question is simply, how do I change my syntax to ignore folders that are older than 6 days as well as files.
get -filemask="*>6D" /DIR/* C:\temp
I have tried several different combinations of parameters and I have read the support page about Directory Masks and Path Masks. I cannot get any of them working (version issue?). Can anyone explain their syntax better than the help page. I will update tomorrow with the current version of WinSCP that I am using.
Time constraint in WinSCP file mask cannot be used for directories.
But you can prevent WinSCP from creating the empty folders. Use -rawtransfersettings switch with ExcludeEmptyDirectories setting.
get -rawtransfersettings ExcludeEmptyDirectories=1 -filemask="*>6D" /DIR/* C:\temp
This is the original answer, before WinSCP supported ExcludeEmptyDirectories. It might still be useful as a basis for implementations that have even more specific constraints.
You can implement this custom logic easily in PowerShell script with a use of WinSCP .NET assembly:
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "example.com"
UserName = "username"
Password = "password"
SshHostKeyFingerprint = "..."
}
$remotePath = "/remote/path"
$localPath = "C:\local\path"
$limit = (Get-Date).AddDays(-6)
$session = New-Object WinSCP.Session
# Connect
$session.Open($sessionOptions)
# Enumerate files to download
$fileInfos =
$session.EnumerateRemoteFiles(
$remotePath, $Null, [WinSCP.EnumerationOptions]::AllDirectories) |
Where-Object { $_.LastWriteTime -gt $limit }
foreach ($fileInfo in $fileInfos)
{
$localFilePath =
[WinSCP.RemotePath]::TranslateRemotePathToLocal(
$fileInfo.FullName, $remotePath, $localPath)
# If the corresponding local folder does not exist yet, create it
$localFileDir = Split-Path -Parent $localFilePath
if (!(Test-Path -Path $localFileDir))
{
Write-Host "Creating local directory $localFileDir..."
New-Item $localFileDir -ItemType directory | Out-Null
}
Write-Host "Downloading file $($fileInfo.FullName)..."
# Download file
$sourcePath = [WinSCP.RemotePath]::EscapeFileMask($fileInfo.FullName)
$transferResult = $session.GetFiles($sourcePath, $localFilePath)
# Did the download succeeded?
if (!$transferResult.IsSuccess)
{
# Print error (but continue with other files)
Write-Host ("Error downloading file ${remoteFilePath}: " +
$transferResult.Failures[0].Message)
}
}
$session.Dispose()
Write-Host "Done."
Run the script (download.ps1) like:
powershell.exe -ExecutionPolicy Unrestricted -File download.ps1

unable to append data to sharepoint file via Azure Automation

Ok I have asked a question like this but now I am trying to perform the task via Azure Automation. I can connect to the SharePoint site via Azure Automation (powershell). with the correct credentials. I can download the file and append data to it. But I can when I try and upload the file back to SharePoint it adds the contents 3 times and then Azure Automation suspends the Runbook after 3 times.
It does run perfect if I upload this file as a different file name.
$siteurl="https://abc.sharepoint.com/sites/xxx/teamsites/os"
$credSP = Get-AutomationPSCredential -Name 'test'
$fileFolder = "$Env:temp"
Connect-PnPOnline -Url $siteurl -Credentials $credSP
Get-PnPFile -Url "/sites/xxx/teamsites/os/Directory and Operating
Systems/test.csv" -Path $fileFolder -Filename test.csv -AsFile -Force
$test = "31-07-2019 -11:35"
Add-Content -Path $fileFolder\test.csv $test
Add-PnPFile -Path $fileFolder\test.csv -Approve -Folder "Directory and
Operating Systems" #-ErrorAction Ignore
Here are the results
test test
31-07-2019 -11:35
31-07-2019 -11:35
31-07-2019 -11:35
As you can see it added $test 3 times. But I dont have this issue if I upload it as a new file name.
Ok after a while I have fix the issue.
After the add-pnpfile ...... you pipe it to | out-null
Thats it. the sript stops after it uploads ,
happy days

Not able to read Excel 2013 file with Spreadsheet::ParseExcel in perl

I have a simple piece of code,that is not loading the excel file. Can't figure out what I'm doing wrong :
my $parser = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse("test.xlsx");
if ( !defined $workbook ) {
print("Unable to load workbook \n");
}
I also tried running with the full path of the file.
The test.xlsx is an Excel 2013 file
I am running in Windows with Perl 5.14.2 and the file is in the same folder as the .pl file.
From the documentation for Spreadsheet::ParseExcel:
The Spreadsheet::ParseExcel module can be used to read information from Excel 95-2003 binary files.
The module cannot read files in the Excel 2007 Open XML XLSX format. See the Spreadsheet::XLSX module instead.

Powershell script cannot access a file when run as a Scheduled Task

My Powershell (2.0) script has the following code snippet:
$fileName = "c:\reports\1.xlsx"
$xl = new-object -comobject excel.application
$xlFormat = [Microsoft.Office.Interop.excel.XlFileFormat]::xlWorkbookDefault
$xl.displayalerts = $false
$workbook = $xl.workbooks.open($fileName)
#Code to manipulate a worksheet
$workbook.SaveAs($fileName, $xlformat)
$xl.quit()
$error | out-file c:\reports\error.txt
I can run this script in the Powershell command prompt with no issues. The spreadsheet gets updated, and error.txt is empty. However, when I run it as a task in Task Scheduler, I get errors with the first line.
Exception calling "Open" with "1" argument(s): "Microsoft Office Excel cannot access the file 'C:\reports\1.xlsx'. There are several possible reasons:
The file name or path does not exist.
The file is being used by another program.
The workbook you are trying to save has the same name as a currently open workbook.
I run the task with the same credentials I use to run the script in the Powershell command prompt. When I run the script manually, it can open, update, and save the spreadsheet with no issues. When I run it in Task Scheduler, it can't access the spreadsheet.
The file in question is readable/writeable for all users. I've verified I can open the file in Excel with the same credentials. If I make a new spreadsheet and put its name in as the $filename, I get the same results. I've verified that there are no instances of Excel.exe in Task Manager.
Oddly, if I use get-content, I don't have any problems. Also, if I make a new spreadsheet, I don't have any problem.
$fileName = "c:\reports\1.xlsx"
$xl = get-content $spreadsheet
$xl = new-object -comobject excel.application
$xlFormat = [Microsoft.Office.Interop.excel.XlFileFormat]::xlWorkbookDefault
$xl.displayalerts = $false
# Commented out $workbook = $xl.workbooks.open($fileName)
$workbook = $xl.workbooks.add()
#Code to manipulate a worksheet
$workbook.SaveAs($fileName, $xlformat)
$xl.quit()
$error | out-file c:\reports\error.txt
That works fine. So Get-ChildItem can open the file with no issue. ComObject can open the file if I run it manually, but not if it's run as task.
I'm at a loss. Any ideas?
I think you've hit a bug in Excel:
You have to create a folder (or two on a 64bit-windows):
(32Bit, always)
C:\Windows\System32\config\systemprofile\Desktop
(64Bit)
C:\Windows\SysWOW64\config\systemprofile\Desktop
I have had the same problem and this was the only solution i have
found.
From TechNet Forums (via PowerShell and Excel Issue when Automating )
The solutions above didn't work in my SCSM 2012 Scorch environment, instead I used PSExcel (https://github.com/RamblingCookieMonster/PSExcel) which has no dependency on having Excel installed or the ComObject.
To extend what #TessellatingHeckler provided, you can run the following commands in Powershell(As Admin/Elevated) to create the folders before opening excel, in my script this fixed the issue:
New-Item -ItemType Directory -Force -Path C:\Windows\System32\config\systemprofile\Desktop
if ([Environment]::Is64BitProcess -ne [Environment]::Is64BitOperatingSystem)
{
New-Item -ItemType Directory -Force -Path C:\Windows\SysWOW64\config\systemprofile\Desktop
}
I had to set my Scheduled Task to run 'only when user is logged on' (logged on to server as the service account that runs task then disconnect session) as it seems to be a limitation with the Task Scheduler and Excel. It's a pretty lame workaround but it works.
To reiterate what TessellatingHeckler said. I had to resolve this issue on a 64 bit system, so I used the following command which made the PowerShell script finally work via Task Scheduler:
New-Item -ItemType Directory -Force -Path C:\Windows\SysWOW64\config\systemprofile\Desktop

Resources