How can I copy a column value from excel to csv file without using ComObject - excel

I'm new to Power shell. I have a number of excel files (500+) having a column Animal Count that I would like to save in a new '.csv' file. I have a code to do this using excel Com Objects.
I want to achieve the same without using ComObjects. Could anyone help me in achieving this.

Download PSExcel module from
https://github.com/RamblingCookieMonster/PSExcel
Import it using Import-Module.
then use the following code:
$AnimalCount = #()
$Source = 'D:\Test' # the path to where the Excel files are
ForEach ($File in Get-ChildItem -Path $Source -Filter '*.xlsx' -File) {
$Excel = New-Excel -Path $File
$Cell = ($Excel | Get-WorkSheet | % {$_.Cells | ? {$_.Text -eq "AnimalCount"}})
$count = (($Excel | Get-WorkSheet -Name $Cell.Worksheet).Cells | ? {($_.Start.Row -eq $Cell.Start.Row) -and ($_.Start.Column -eq $Cell.Start.Column + 1)}).Text
$AnimalCount += [PsCustomObject] #{'File' = $File.FullName; 'AnimalCount' = $count }
}
$AnimalCount | Format-Table -AutoSize
$AnimalCount | Export-Csv -Path 'D:\Test\AnimalCount.csv' -UseCulture -NoTypeInformation
The best thing here is that you do not need excel to be installed on the machine that runs this script.

Related

Searching contents of text files on remote computers and exporting to excel file using powershell and export-excel

I'm trying to search the contents of text files on remote computers from computers.txt which includes
Pc1
Pc2
Pc3
Pc4
And export it using export-excel PowerShell module
using this code:
$directory = $PSScriptRoot
$computers = Get-Content -Path $directory\computers.txt
$searchwords = 'word1','word2','word3'
Foreach ($computer in $computers) {
$path = "\\$computer\C$\test\logs"
Foreach ($sw in $searchwords) {
$excel = Get-Childitem -path $path -recurse -Include "*.txt" |
Select-string -pattern "$sw" |
Select-object pattern, linenumber, line, path |
Export-excel $file -autosize -startrow 1 -tablename pattern -worksheetname "errors" -passthru
$ws = $excel.workbook.worksheets['errors']
$excel.save()
}
}
The problem is that it will only export the contents of pc4 which is the last in the computers.txt list.
Thanks in advance
Adding the -append switch on export-excel will get this working.
It was added as part of the release on 10/30/2017 - https://github.com/dfinke/ImportExcel#whats-new-in-release-52

Convert TXTto CSV

I'm working on a project where I need to take a text file and make it an excel file. So far what I've come up with is this.
cls
Remove-Item -path D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv
Add-Content -path D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv -Value '"Part_Number","Cost","Price"'
$csvPath = 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv'
#region Excel Test
If (test-path HKLM:SOFTWARE\Classes\Word.Application) {
Write-host "Microsoft Excel installed"
} else {
Write-host "Microsoft Excel not installed"
}
#endregion
#region Patterns
$mainpattern1 = '(?<Partnumber>\d*\s*\w*,)(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'
$mainpattern2 = '(?<Part_number>\d*-\d*-\d*),(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'
#endregion
get-Content 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv' | #grabs the content
Select-String -Pattern $mainpattern1, $mainpattern2 | #selects the patterns
Foreach-Object {
$Part_Number, $Cost, $Price = $_.Matches[0].Groups['Part_number', 'Cost','Price']
[PSCustomObject] #{
part_number = $Part_Number
Cost = $Cost
Price = $Price
}
$objResults | Export-Csv -Path $csvPath -NoTypeInformation -Append
}
some sample data is here
00001143 SP,136.41,227.35
00001223 SP,48.66,81.10
00001236 SP,149.72,249.53
0001-0003-00,100.95,168.25
00015172 W,85.32,142.20
I'm getting the file created and the header values are correct but I'm not sure how to get the values to import.
Continuing from my comment... with the resources and a simple example.
Find-Module -Name '*excel*' | Format-Table -AutoSize
# Results
<#
Version Name Repository Description
------- ---- ---------- -----------
7.1.1 ImportExcel PSGallery PowerShell module to import/export Excel spreadsheets, without Excel....
0.1.12 PSWriteExcel PSGallery Little project to create Excel files without Microsoft Excel being installed.
1.0.2 PSExcel PSGallery Work with Excel without installing Excel
...
0.6.9 ExcelPSLib PSGallery Allow simple creation and manipulation of XLSX file
2.1 Read-ExcelFile PSGallery PowerShell module to import Excel spreadsheets, without Excel....
...
#>
MSExcel will read properly formatted CSV's natively. So, to convert to a true XLS file, use PowerShell, MSOffice COM to open MSExcel with the CSV file, then save it as an XLS format.
$FileName = "$env:temp\Report"
Get-Process |
Export-Csv -UseCulture -Path "$FileName.csv" -NoTypeInformation -Encoding UTF8
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$excel.Workbooks.Open("$FileName.csv").SaveAs("$FileName.xlsx",51)
$excel.Quit()
explorer.exe "/Select,$FileName.xlsx"
Your use case is of course as noted:
Import-Csv -Path 'D:\temp\book1.txt' -header Title, Author
Then using COM as noted above.
I ended up solving this after I asked the question I had alot of flaws in this code
Add-Content -path D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv -Value '"Part_Number","Cost","Price"'
$csvPath = 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\MainWarehouse.csv'
#region Excel Test
If (test-path HKLM:SOFTWARE\Classes\Excel.Application) {#these next few lines will check if excel is installed on the system
Write-host "Microsoft Excel installed"
} else {
Write-host "Microsoft Excel not installed"
}
#endregion
#region Patterns
$mainpattern1 = '(?<Part_number>\d*\s*\w*),(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'#These two line will use REGEX to help seperate the data
$mainpattern2 = '(?<Part_number>\d*-\d*-\d*),(?<Cost>\d*.\d*),(?<Price>\d*.\d*)'
#endregion
get-Content 'D:\Users\zabin\OneDrive\Desktop\ITS3410\WEEK8\Main.rtf' | #grabs the content
Select-String -Pattern $mainpattern2, $mainpattern1 | #selects the patterns
Foreach-Object {
$Part_number, $Cost, $Price = $_.Matches[0].Groups['Part_number', 'Cost','Price'] #Gets the groups of a call to select-string
$results = [PSCustomObject] #{#the list here is what i use to seperate the data onto the CSV file
part_number = $Part_Number
Cost = $Cost
Price = $Price
}
$results | Export-Csv -Path $csvPath -NoTypeInformation -Append #moves the results to the CSV file
}

I would like to know how to apply Excel column B (Powershell source) to the same folder name as Excel column A value

There are A, B, C, D, E folders in the "image folder".(C:image)
Excel column A value refers to the folder name in "Image Folder".(Destination)
The Excel column B value is the source of the PowerShell and plays a role of changing the name of the file in the A~E folder.
When the Excel column A and the folder name match, the power cell source in Excel column B is applied at once. In other words, it tries to apply the PowerShell source in column B to each file in folders A to F at once. I want to implement it as a powershell source. Can you help? please
As commented, the code you use in the Excel is the same for every subfolder mentioned. That is why I don't think you need that Excel at all, it would just provide more overhead.
Why not do
Change all filenames inside the (1 level) of subfolders inside the rootfolder:
$rootFolder = 'C:\Image'
Get-ChildItem -Path $rootFolder -Filter '*.jpg' -File -Recurse -Depth 1 |
Group-Object -Property #{Expression = {$_.Directory.Name}} |
ForEach-Object {
$dir = $_.Name
$nr = 1
foreach ($file in $_.Group) {
$file | Rename-Item -NewName ('{0}_{1}.jpg' -f $dir, $nr++ )
}
}
Or if you have more folders inside the C:\Image folder and you want to limit to certain subfolders
$rootFolder = 'C:\Image'
$subfolders = 'A','B','C','D','E' # array of folders to process
foreach ($dir in $subfolders) {
$path = Join-Path -Path $rootFolder -ChildPath $dir
Get-ChildItem -Path $path -Filter '*.jpg' -File |
Group-Object -Property #{Expression = {$_.Directory.Name}} |
ForEach-Object {
$dir = $_.Name
$nr = 1
foreach ($file in $_.Group) {
$file | Rename-Item -NewName ('{0}_{1}.jpg' -f $dir, $nr++ )
}
}
}

Powershell get infos about files and try to Export them

I try do write a script where i can choose a folder and powershell shows me the Name, Size,.... of all the files in that folder. After that powershell should export the Informations in a Excel Table.
But im stuck and dont know what to do :C
Here is my code that i tried to build
Function Get-Folder($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")|Out-Null
$foldername = New-Object System.Windows.Forms.FolderBrowserDialog
$foldername.Description = "Select a folder"
$foldername.rootfolder = "MyComputer"
if($foldername.ShowDialog() -eq "OK")
{
$folder += $foldername.SelectedPath
}
return $folder
}
$a = Get-Folder
$folder = $a
Get-ChildItem -Path $folder | SELECT Name, #{Name="Size In KB";Expression={$_.Length / 1Kb}}, Attributes, LastaccessTime, #{n='Owner';e={(get-acl $_.Fullname).Owner}}| Format-Table -AutoSize
Export-Csv "C:\Users\DZimmermann\Desktop\Test.csv" -Delimiter ";" -Append
As commented, using Format-Table -AutoSize simply outputs the info in a table format to console. It returns nothing, so there is nothing to write in the csv file..
Doing like this will create the CSV file and writes the info in there:
Get-ChildItem -Path $folder |
Select-Object Name,
#{Name="Size In KB";Expression={$_.Length / 1Kb}},
Attributes, LastaccessTime,
#{n='Owner';e={(get-acl $_.Fullname).Owner}} |
Export-Csv "C:\Users\DZimmermann\Desktop\Test.csv" -Delimiter ";"
This will not get you the info on screen. If you also want that, capture the result in a variable first:
$result = Get-ChildItem -Path $folder |
Select-Object Name,
#{Name="Size In KB";Expression={$_.Length / 1Kb}},
Attributes, LastaccessTime,
#{n='Owner';e={(get-acl $_.Fullname).Owner}}
#output on screen
$result | Format-Table -AutoSize
# write the CSV file:
$result | Export-Csv "C:\Users\DZimmermann\Desktop\Test.csv" -Delimiter ";"
P.S. judging by the title of this question, I think you only want info about Files, not Directories..
If that is the case, add -File switch to the Get-ChildItem cmdlet (for PS 3 and up). For PS versions below 3 use
Get-ChildItem -Path $folder | Where-Object { !$_.PSIsContainer }

add colum to merged csv file

Ok heres what I have code wise:
$a = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\*.csv"
$b = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
(get-content $a) | set-content $b
This pulls all the data of all the files into one merged file, but I need one additional item, I need to pull the name of the individual files and append it to the first column of the file for multiple files, several hundred at a time.
Not tested but something like this should do it:
$a = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\*.csv"
$b = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
Get-ChildItem $a | % {
Import-Csv $_.Fullname | Add-Member -MemberType NoteProperty -Name 'File Name' -Value $_.Name
} | Export-Csv $b
Assuming the CSV files each have the same column headings, I would lean toward using Import-CSV instead of Get-Content so that you can work with the CSV contents as arrays of objects with named properties.
Then all you need to do is iterate through each item of the array and append a property containing the file path, which you can do using the Add-Member cmdlet. Once that's done, export the array of objects using the Export-CSV cmdlet.
$directory = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\"
$search = $directory + "*.csv"
$exportpath = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
$paths = get-childitem $search
$objectArrays = #()
$paths | %{
$filepath = $_.fullname;
$objectArray = Import-CSV $filepath;
$objectArray | %{
Add-Member -inputobject $_ -Name "SourceFile" -Value $filepath -MemberType NoteProperty};
$objectArrays += $objectArray}
$objectArrays | export-csv -path $exportpath -notype
This puts the SourceFile property as the last column in the outputted CSV file
Ok, simplification... Search target folder, pipe to a ForEach-Object loop (shorthand % used), capture the file name as variable, import the CSV, add the sourcefile using the Select-Object cmdlet, convert it back to a CSV, end loop, pipe to destination file.
$a = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\*.csv"
$b = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
GCI $a | %{$FileName=$_.Name;Import-CSV $_|Select #{l='SourceFile';e={$FileName}},*|ConvertTo-CSV -NoType} | set-content $b

Resources