unable to paste the formula - excel

Below is the powershell command which is used to copy the data from one excel to multiple excel file in destination directory.
But my question is, the formulas are not pasting as formula instead it is pasting as value.
can any one alter this script to paste the formula?
$sourceFile = "c:\tmp\source.xlsx"
$destinationDirectory = "c:\tmp"
$sheetName = "Sheet1"
$rangeToCopyStart = "B19"
$rangeToCopyEnd = "B49"
#----------------------------------------------
# Open Excel source file
#----------------------------------------------
$excelApplication = New-Object -comobject Excel.Application
$excelWorkbook = $excelApplication.Workbooks.Open($sourceFile, 2, $True)
$excelWorksheet = $excelWorkbook.Worksheets.Item($sheetName)
#----------------------------------------------
# Copy the cell value
#----------------------------------------------
"Value to copy:" + $excelWorksheet.Range($rangeToCopyStart, $rangeToCopyEnd).Value2;
"From:" + $sourceFile;
$excelWorksheet.Range($rangeToCopyStart, $rangeToCopyEnd).Copy() | out-null;
$excelWorkbook.Close();
#----------------------------------------------
# Get all Excel files from destination directory
#----------------------------------------------
$Files = Get-ChildItem $destinationDirectory -Filter *.xlsx
Foreach ($Item in $Files) {
$destinationFile = $Item.FullName
#----------------------------------------------
# Skip the source file if it's in the same directory
#----------------------------------------------
If ($sourceFile.ToLower() -eq $destinationFile.ToLower()) { continue; }
$destinationWorkbook = $excelApplication.Workbooks.Open($destinationFile, 2, $False)
$destinationWorkSheet = $destinationWorkbook.Worksheets.Item($sheetName)
#----------------------------------------------
# Paste the value into the destination file
#----------------------------------------------
$destinationWorkSheet.Paste($destinationWorkSheet.Range($rangeToCopyStart, $rangeToCopyEnd));
$destinationWorkbook.Close($True); #save changes and close
"Copied to: " + $destinationFile;
}
#----------------------------------------------
# Quit Excel and release the object
#----------------------------------------------
$excelApplication.Quit();
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelApplication) | out-null;

You can use Range.PasteSpecial instead of Range.Copy method.
$xl=new-object -com excel.application
$wb1=$xl.workbooks.open($Source_Workbook, $null, $true)
$wb2=$xl.workbooks.open($Destination_Workbook)
$target=$wb2.Worksheets.Item($Target_Worksheet).Range('B2','B2')
$wb1.Worksheets.Item($Source_Worksheet).Range('a2','a2').copy()
$wb2.Worksheets.Item($Target_Worksheet).Activate()
$target.PasteSpecial(-4163)
Hope it helps

Related

Merge content of multiple Excel files into one using PowerShell

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

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.

Powershell - Excel Rename Worksheets base upon filename

I have multiple excel files that I am combining into one excel document with multiple sheets. I would like to rename these sheets based upon the current file being processed name. CODE:
$files = Get-ChildItem "C:\Stuff\" -exclude "Pauls*"
$DestFile = 'C:\Stuff\Pauls Weekly KPI.xlsx' # source's fullpath
foreach($file in $files)
{
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($file.fullname)
Write-Host $baseName
$xl = new-object -c excel.application
$xl.displayAlerts = $false # don't prompt the user
$wb1 = $xl.workbooks.open($file, $null, $true) # open source, readonly
$wb2 = $xl.workbooks.open($DestFile) # open target
$sh1_wb2 = $wb2.sheets.item(1) # first sheet in destination workbook
$sheetToCopy = $wb1.sheets.item('Report') # source sheet to copy
$sheetToCopy.copy($sh1_wb2) # copy source sheet to destination workbook
$wb1.close($false) # close source workbook w/o saving
$wb2.close($true) # close and save destination workbook
}
$xl.quit()
spps -n excel
Example:
After the script has run the final notebook would contain multiple sheets named by their original files name
Solved it by renaming the sheet prior to copying:
$files = Get-ChildItem "C:\Stuff\" -exclude "Pauls*"
$DestFile = 'C:\Stuff\Pauls Weekly KPI.xlsx' # source's fullpath
$xl = new-object -c excel.application
$xl.displayAlerts = $false # don't prompt the user
foreach($file in $files){
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($file.fullname)
Write-Host $baseName
$wb1 = $xl.workbooks.open($file, $null, $true) # open source, readonly
$wb2 = $xl.workbooks.open($DestFile) # open target
$sh1_wb2 = $wb2.sheets.item(1) # first sheet in destination workbook
$sheetToCopy = $wb1.sheets.item('Report') # source sheet to copy
$sheetToCopy.name = $baseName
$sheetToCopy.copy($sh1_wb2) # copy source sheet to destination workbook
$wb1.close($false) # close source workbook w/o saving
$wb2.close($true) # close and save destination workbook
}
$xl.quit()
spps -n excel

Powershell how to I copy() a worksheet and saveas it's own workbook

I'm not to great with powershell, but I am writing a script that opens an excel file, reads content from a .txt file, and throws that data into the excel sheet. The data entered in will give values to a chart on another worksheet. I want to ask the user if they would like to create a copy of this chart or not (not always required) If the user would like to then it will copy only the chart worksheet, and saveas its own workbook (..copyedChart.xls).
Now, I know when I use the .Copy() function it will take the current active sheet and already open up a new instance of excel. My problem is actually being able "control" this new instance of excel, I am having trouble understanding how to actually call that sheet and save it.
Here is what I have..
#Create an instance of Excel
$excel = New-Object -comobject Excel.Application
Write-Host "Initializing applications.." #all Write-Host are for the users..
#declaring sheet names..
$sheetName = "Sheet1"
$sheetName2 = "Sheet2"
$excel.displayAlerts = $false
Try{
#open Excel file
[string]$file = "C:\Users\Desktop\test.xls"
#create a reference to the specified excel workbook
$workBook = $excel.Workbooks.open($file)
#activates sheet
$sheet = $workBook.WorkSheets.Item($sheetName).activate()
$excel.Visible = $true
$data = Get-Content C:\Users\Desktop\input.txt
}#end try
Catch{
Write-Host "An error has occured."
}#end catch
Write-Host "Inputting new data.."
$i = 0
$rowNumber = 2
#Im just parsing the input.txt and spitting it out into excel
foreach($row in $data){
if($row){
[Array] $index = $row.Split(" ")
$i++
$column = 1
if($i -ge 1){
foreach($item in $index){
$excel.Cells.Item($rowNumber, $column) = "$item"
$column++
}#end foreach
$rowNumber++
}#end if $i
}#end if $row
}#end foreach
$date = $excel.Cells.Item(2, 1).Value().toString("MMMM-dd-yyyy") #row, column
#changes the active sheet
$sheet2 = $workBook.Sheets.Item($sheetName2).Select()
#references the active chart on the active page
$chart = $workBook.ActiveChart
Write-Host "Updating charts.."
#changes the title of the chart to include the current date
$chart.ChartTitle.Text = "Some title - $date"
#saves the files to these locations
$save = 'C:\Users\Desktop\'+$date+'-text.xls'
$saveChartCopy = 'C:\Users\Desktop\'+$date+'-CHARTCOPY.xls'
Write-Host "Saving new file.."
#save this workbook
$workBook.SaveAs($save)
#asks the user if they would like to create a copy of the chart
$makeCopy = Read-Host ("Would you like to create a copy of the chart? (y/n)")
#-----------------------------------------------------------STUCK HERE
#if yes, copy and save the chart as a new workbook.
if($makeCopy -eq "y" -or $makeCopy -eq "Y"){
$copiedChart = $chart.Copy() #Copies the chart and opens into a new instance of excel...
$copiedChart.SaveAs($saveChartCopy) #My sad attempt at trying to save the copied chart...
}
#if no, than close excel
elseif($makeCopy -eq "n" -or $makeCopy -eq "N"){
#close excel
Write-Host "Closing Excel.."
$excel.Quit()
Write-Host "Complete!"
}
else{
Read-Host "Please enter a valid option!"
}
If there is any confusion as to what I am asking please ask and I will try to further explain.
Also, because I am new to powershell and I am kind of a noob programmer.. I am open to all other input in regards to my code.
You have to create a new workbook object with $Excel.Workbooks.add():
$NewWorkBook = $Excel.Workbooks.Add()
# Copy and paste your sheet
$NewWorkBook.SaveAs($FileName)
$NewWorkBook.Close()
If I understand your problem correctly(and please tell me if I'm not), all you have to do is catch the handle to the new workbook in another variable. I was curious about this myself and decided to throw something quick and dirty to play around with it. Try something like this:
$Excel = New-Object -ComObject "Excel.Application"
$Workbook = $Excel.Workbooks.Add()
$Sheet = $Workbook.Worksheets.Item(1)
$Excel.Visible = $true
$Cells = $Sheet.Cells
$Workbook2 = $Excel.Workbooks.Add()
$Sheet2 = $Workbook2.Worksheets.Item(1)
$Cells2 = $Sheet2.Cells
$Cells.Item(1,1) = "Book 1"
$Cells2.Item(1,1) = "Book 2"
$Workbook.Close()
$Workbook2.Close()
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
Also, don't forget to cleanup that ComObject!

How to export a CSV to Excel using Powershell

I'm trying to export a complete CSV to Excel by using Powershell. I stuck at a point where static column names are used. But this doesn't work if my CSV has generic unknown header names.
Steps to reproduce
Open your PowerShell ISE and copy & paste the following standalone code. Run it with F5
"C:\Windows\system32\WindowsPowerShell\v1.0\powershell_ise.exe"
Get-Process | Export-Csv -Path $env:temp\process.csv -NoTypeInformation
$processes = Import-Csv -Path $env:temp\process.csv
$Excel = New-Object -ComObject excel.application
$workbook = $Excel.workbooks.add()
$i = 1
foreach($process in $processes)
{
$excel.cells.item($i,1) = $process.name
$excel.cells.item($i,2) = $process.vm
$i++
}
Remove-Item $env:temp\process.csv
$Excel.visible = $true
What it does
The script will export a list of all active processes as a CSV to your temp folder. This file is only for our example. It could be any CSV with any data
It reads in the newly created CSV and saves it under the $processes variable
It creates a new and empty Excel workbook where we can write data
It iterates through all rows (?) and writes all values from the name and vm column to Excel
My questions
What if I don't know the column headers? (In our example name and vm). How do I address values where I don't know their header names?
How do I count how many columns a CSV has? (after reading it with Import-Csv)
I just want to write an entire CSV to Excel with Powershell
Ups, I entirely forgot this question. In the meantime I got a solution.
This Powershell script converts a CSV to XLSX in the background
Gimmicks are
Preserves all CSV values as plain text like =B1+B2 or 0000001.
You don't see #Name or anything like that. No autoformating is done.
Automatically chooses the right delimiter (comma or semicolon) according to your regional setting
Autofit columns
PowerShell Code
### Set input and output path
$inputCSV = "C:\somefolder\input.csv"
$outputXLSX = "C:\somefolder\output.xlsx"
### Create a new Excel Workbook with one empty sheet
$excel = New-Object -ComObject excel.application
$workbook = $excel.Workbooks.Add(1)
$worksheet = $workbook.worksheets.Item(1)
### Build the QueryTables.Add command
### QueryTables does the same as when clicking "Data » From Text" in Excel
$TxtConnector = ("TEXT;" + $inputCSV)
$Connector = $worksheet.QueryTables.add($TxtConnector,$worksheet.Range("A1"))
$query = $worksheet.QueryTables.item($Connector.name)
### Set the delimiter (, or ;) according to your regional settings
$query.TextFileOtherDelimiter = $Excel.Application.International(5)
### Set the format to delimited and text for every column
### A trick to create an array of 2s is used with the preceding comma
$query.TextFileParseType = 1
$query.TextFileColumnDataTypes = ,2 * $worksheet.Cells.Columns.Count
$query.AdjustColumnWidth = 1
### Execute & delete the import query
$query.Refresh()
$query.Delete()
### Save & close the Workbook as XLSX. Change the output extension for Excel 2003
$Workbook.SaveAs($outputXLSX,51)
$excel.Quit()
I am using excelcnv.exe to convert csv into xlsx and that seemed to work properly.
You will have to change the directory to where your excelcnv is. If 32 bit, it goes to Program Files (x86)
Start-Process -FilePath 'C:\Program Files\Microsoft Office\root\Office16\excelcnv.exe' -ArgumentList "-nme -oice ""$xlsFilePath"" ""$xlsToxlsxPath"""
This topic really helped me, so I'd like to share my improvements.
All credits go to the nixda, this is based on his answer.
For those who need to convert multiple csv's in a folder, just modify the directory. Outputfilenames will be identical to input, just with another extension.
Take care of the cleanup in the end, if you like to keep the original csv's you might not want to remove these.
Can be easily modifed to save the xlsx in another directory.
$workingdir = "C:\data\*.csv"
$csv = dir -path $workingdir
foreach($inputCSV in $csv){
$outputXLSX = $inputCSV.DirectoryName + "\" + $inputCSV.Basename + ".xlsx"
### Create a new Excel Workbook with one empty sheet
$excel = New-Object -ComObject excel.application
$excel.DisplayAlerts = $False
$workbook = $excel.Workbooks.Add(1)
$worksheet = $workbook.worksheets.Item(1)
### Build the QueryTables.Add command
### QueryTables does the same as when clicking "Data » From Text" in Excel
$TxtConnector = ("TEXT;" + $inputCSV)
$Connector = $worksheet.QueryTables.add($TxtConnector,$worksheet.Range("A1"))
$query = $worksheet.QueryTables.item($Connector.name)
### Set the delimiter (, or ;) according to your regional settings
### $Excel.Application.International(3) = ,
### $Excel.Application.International(5) = ;
$query.TextFileOtherDelimiter = $Excel.Application.International(5)
### Set the format to delimited and text for every column
### A trick to create an array of 2s is used with the preceding comma
$query.TextFileParseType = 1
$query.TextFileColumnDataTypes = ,2 * $worksheet.Cells.Columns.Count
$query.AdjustColumnWidth = 1
### Execute & delete the import query
$query.Refresh()
$query.Delete()
### Save & close the Workbook as XLSX. Change the output extension for Excel 2003
$Workbook.SaveAs($outputXLSX,51)
$excel.Quit()
}
## To exclude an item, use the '-exclude' parameter (wildcards if needed)
remove-item -path $workingdir -exclude *Crab4dq.csv
Why would you bother? Load your CSV into Excel like this:
$csv = Join-Path $env:TEMP "process.csv"
$xls = Join-Path $env:TEMP "process.xlsx"
$xl = New-Object -COM "Excel.Application"
$xl.Visible = $true
$wb = $xl.Workbooks.OpenText($csv)
$wb.SaveAs($xls, 51)
You just need to make sure that the CSV export uses the delimiter defined in your regional settings. Override with -Delimiter if need be.
Edit: A more general solution that should preserve the values from the CSV as plain text. Code for iterating over the CSV columns taken from here.
$csv = Join-Path $env:TEMP "input.csv"
$xls = Join-Path $env:TEMP "output.xlsx"
$xl = New-Object -COM "Excel.Application"
$xl.Visible = $true
$wb = $xl.Workbooks.Add()
$ws = $wb.Sheets.Item(1)
$ws.Cells.NumberFormat = "#"
$i = 1
Import-Csv $csv | ForEach-Object {
$j = 1
foreach ($prop in $_.PSObject.Properties) {
if ($i -eq 1) {
$ws.Cells.Item($i, $j++).Value = $prop.Name
} else {
$ws.Cells.Item($i, $j++).Value = $prop.Value
}
}
$i++
}
$wb.SaveAs($xls, 51)
$wb.Close()
$xl.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
Obviously this second approach won't perform too well, because it's processing each cell individually.
If you want to convert CSV to Excel without Excel being installed, you can use the great .NET library EPPlus (under LGPL license) to create and modify Excel Sheets and also convert CSV to Excel really fast!
Preparation
Download the latest stable EPPlus version
Extract EPPlus to your preferred location (e.g. to $HOME\Documents\WindowsPowerShell\Modules\EPPlus)
Right Click EPPlus.dll, select Properties and at the bottom of the General Tab click "Unblock" to allow loading of this dll. If you don't have the rights to do this, try [Reflection.Assembly]::UnsafeLoadFrom($DLLPath) | Out-Null
Detailed Powershell Commands to import CSV to Excel
# Create temporary CSV and Excel file names
$FileNameCSV = "$HOME\Downloads\test.csv"
$FileNameExcel = "$HOME\Downloads\test.xlsx"
# Create CSV File (with first line containing type information and empty last line)
Get-Process | Export-Csv -Delimiter ';' -Encoding UTF8 -Path $FileNameCSV
# Load EPPlus
$DLLPath = "$HOME\Documents\WindowsPowerShell\Modules\EPPlus\EPPlus.dll"
[Reflection.Assembly]::LoadFile($DLLPath) | Out-Null
# Set CSV Format
$Format = New-object -TypeName OfficeOpenXml.ExcelTextFormat
$Format.Delimiter = ";"
# use Text Qualifier if your CSV entries are quoted, e.g. "Cell1","Cell2"
$Format.TextQualifier = '"'
$Format.Encoding = [System.Text.Encoding]::UTF8
$Format.SkipLinesBeginning = '1'
$Format.SkipLinesEnd = '1'
# Set Preferred Table Style
$TableStyle = [OfficeOpenXml.Table.TableStyles]::Medium1
# Create Excel File
$ExcelPackage = New-Object OfficeOpenXml.ExcelPackage
$Worksheet = $ExcelPackage.Workbook.Worksheets.Add("FromCSV")
# Load CSV File with first row as heads using a table style
$null=$Worksheet.Cells.LoadFromText((Get-Item $FileNameCSV),$Format,$TableStyle,$true)
# Load CSV File without table style
#$null=$Worksheet.Cells.LoadFromText($file,$format)
# Fit Column Size to Size of Content
$Worksheet.Cells[$Worksheet.Dimension.Address].AutoFitColumns()
# Save Excel File
$ExcelPackage.SaveAs($FileNameExcel)
Write-Host "CSV File $FileNameCSV converted to Excel file $FileNameExcel"
This is a slight variation that worked better for me.
$csv = Join-Path $env:TEMP "input.csv"
$xls = Join-Path $env:TEMP "output.xlsx"
$xl = new-object -comobject excel.application
$xl.visible = $false
$Workbook = $xl.workbooks.open($CSV)
$Worksheets = $Workbooks.worksheets
$Workbook.SaveAs($XLS,1)
$Workbook.Saved = $True
$xl.Quit()
I had some problem getting the other examples to work.
EPPlus and other libraries produces OpenDocument Xml format, which is not the same as you get when you save from Excel as xlsx.
macks example with open CSV and just re-saving didn't work, I never managed to get the ',' delimiter to be used correctly.
Ansgar Wiechers example has some slight error which I found the answer for in the commencts.
Anyway, this is a complete working example. Save this in a File CsvToExcel.ps1
param (
[Parameter(Mandatory=$true)][string]$inputfile,
[Parameter(Mandatory=$true)][string]$outputfile
)
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$wb = $excel.Workbooks.Add()
$ws = $wb.Sheets.Item(1)
$ws.Cells.NumberFormat = "#"
write-output "Opening $inputfile"
$i = 1
Import-Csv $inputfile | Foreach-Object {
$j = 1
foreach ($prop in $_.PSObject.Properties)
{
if ($i -eq 1) {
$ws.Cells.Item($i, $j) = $prop.Name
} else {
$ws.Cells.Item($i, $j) = $prop.Value
}
$j++
}
$i++
}
$wb.SaveAs($outputfile,51)
$wb.Close()
$excel.Quit()
write-output "Success"
Execute with:
.\CsvToExcel.ps1 -inputfile "C:\Temp\X\data.csv" -outputfile "C:\Temp\X\data.xlsx"
I found this while passing and looking for answers on how to compile a set of csvs into a single excel doc with the worksheets (tabs) named after the csv files. It is a nice function. Sadly, I cannot run them on my network :( so i do not know how well it works.
Function Release-Ref ($ref)
{
([System.Runtime.InteropServices.Marshal]::ReleaseComObject(
[System.__ComObject]$ref) -gt 0)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
Function ConvertCSV-ToExcel
{
<#
.SYNOPSIS
Converts one or more CSV files into an excel file.
.DESCRIPTION
Converts one or more CSV files into an excel file. Each CSV file is imported into its own worksheet with the name of the
file being the name of the worksheet.
.PARAMETER inputfile
Name of the CSV file being converted
.PARAMETER output
Name of the converted excel file
.EXAMPLE
Get-ChildItem *.csv | ConvertCSV-ToExcel -output ‘report.xlsx’
.EXAMPLE
ConvertCSV-ToExcel -inputfile ‘file.csv’ -output ‘report.xlsx’
.EXAMPLE
ConvertCSV-ToExcel -inputfile #(“test1.csv”,”test2.csv”) -output ‘report.xlsx’
.NOTES
Author: Boe Prox
Date Created: 01SEPT210
Last Modified:
#>
#Requires -version 2.0
[CmdletBinding(
SupportsShouldProcess = $True,
ConfirmImpact = ‘low’,
DefaultParameterSetName = ‘file’
)]
Param (
[Parameter(
ValueFromPipeline=$True,
Position=0,
Mandatory=$True,
HelpMessage=”Name of CSV/s to import”)]
[ValidateNotNullOrEmpty()]
[array]$inputfile,
[Parameter(
ValueFromPipeline=$False,
Position=1,
Mandatory=$True,
HelpMessage=”Name of excel file output”)]
[ValidateNotNullOrEmpty()]
[string]$output
)
Begin {
#Configure regular expression to match full path of each file
[regex]$regex = “^\w\:\\”
#Find the number of CSVs being imported
$count = ($inputfile.count -1)
#Create Excel Com Object
$excel = new-object -com excel.application
#Disable alerts
$excel.DisplayAlerts = $False
#Show Excel application
$excel.V isible = $False
#Add workbook
$workbook = $excel.workbooks.Add()
#Remove other worksheets
$workbook.worksheets.Item(2).delete()
#After the first worksheet is removed,the next one takes its place
$workbook.worksheets.Item(2).delete()
#Define initial worksheet number
$i = 1
}
Process {
ForEach ($input in $inputfile) {
#If more than one file, create another worksheet for each file
If ($i -gt 1) {
$workbook.worksheets.Add() | Out-Null
}
#Use the first worksheet in the workbook (also the newest created worksheet is always 1)
$worksheet = $workbook.worksheets.Item(1)
#Add name of CSV as worksheet name
$worksheet.name = “$((GCI $input).basename)”
#Open the CSV file in Excel, must be converted into complete path if no already done
If ($regex.ismatch($input)) {
$tempcsv = $excel.Workbooks.Open($input)
}
ElseIf ($regex.ismatch(“$($input.fullname)”)) {
$tempcsv = $excel.Workbooks.Open(“$($input.fullname)”)
}
Else {
$tempcsv = $excel.Workbooks.Open(“$($pwd)\$input”)
}
$tempsheet = $tempcsv.Worksheets.Item(1)
#Copy contents of the CSV file
$tempSheet.UsedRange.Copy() | Out-Null
#Paste contents of CSV into existing workbook
$worksheet.Paste()
#Close temp workbook
$tempcsv.close()
#Select all used cells
$range = $worksheet.UsedRange
#Autofit the columns
$range.EntireColumn.Autofit() | out-null
$i++
}
}
End {
#Save spreadsheet
$workbook.saveas(“$pwd\$output”)
Write-Host -Fore Green “File saved to $pwd\$output”
#Close Excel
$excel.quit()
#Release processes for Excel
$a = Release-Ref($range)
}
}

Resources