I am new to Perl.Can anyone tell me how to append data from one excel file to another existing excel file?
I have 2 excel files and 1 excel file is created every time I run the program but I need to copy the data from new excel file to another one as a backup. so I want to append the data to the backup file.
I tried searching in web but all i am getting is creating new files.
I think you want Spreadsheet::ParseExcel::SaveParser
# Open an existing file with SaveParser
my $parser = Spreadsheet::ParseExcel::SaveParser->new();
my $template = $parser->Parse('template.xls');
my $row = #Enter row value here, keep incrementing it for appending
my $col = #Enter column value here
# Add a cell
$worksheet->AddCell( $row, $col, 'New string' );
# Write over the existing file or write a new file.
$template->SaveAs('newfile.xls');
Related
I have here my XML, CSV and Excel files.
I'm trying to get all the Numbers from the "Key" of my XML file.
$DocNo = $XML.Settings.Setting.Key
then get all the Corresponding File Name of that Numbers from my CSV file.
Foreach ($Line in $CSVContent) {
# (-split) the Array of Strings by Separating them from ","
$LineSplit = $Line -split ","
# Find the $Line that has the Value of $DocNo
If ($LineSplit -like $DocNo) {
# Store the String Value of $DocNo in "$FileNames"
$FileNames = $LineSplit
}
}
Write-Host $FileNames
then use the $FileNames as the File Name to be opened as a workbook.
# For every Number of Key
ForEach($Files in $DocNo){
# Open their Excel Workbook (INSERT THE FILENAME OF THE FILE NO. FROM CSV)
$WorkBook = $Excel.Workbooks.Open($Files.$FileNames)
}
The problem is there's no value showing in my $FileNames.
I can display the $FileNames but I have to specifically call them one by one.
Any suggestions and help will be appreciated :)
In the first block of code, $LineSplit is the result of using -split on a line from a CSV file. $LineSplit is an array, in your case the array contains two elements for each line from the CSV file:
$LineSplit[0] = '1'
$LineSplit[1] = 'File1.xlsx'
The square bracket notation allows you to select an element from the array by its position in the array, starting from zero.
The issue with the first block of code is that a condition ($LineSplit -like $DocNo) is comparing an array to an array using the like operator, I'm not sure what that will do but it's hard to follow. I would consider recoding it as follows:
if ($LineSplit[0] -in $DocNo)
This asks if the first column of the CSV row is in the list pulled from your XML file, then proceed.
The next issue is the building of the $FileNames variable. Each time this statement is executed in your code:
$FileNames = $LineSplit
The two element array $LineSplit representing the current CSV row, split by comma, overwrites the value of $FileNames. By the end of the loop, this only contains the last CSV line which matched the condition. This should be recoded as an array. Before the loop set up an empty array:
$FileNames = #()
Now, during the loop when the condition is met:
$FileNames += $LineSplit[1]
Recalling that $LineSplit[1] contains the filename, as it is the second element of the CSV row when split by comma. By the end of the loop the $FileNames variable should contain an array of files that are in both the CSV and the XML. The += bit is an operator that adds new elements without overwriting.
Finally, the second block of code is close, but not quite there. The loop runs through the values in $DocNo, which according to your screenshot are:
1,2,3,4,5,6
These values are placed into the $Files variable for each loop - and then the $File.$FileNames syntax is incorrect, it is attempting to retrieve a property from the numbers retrieved from the $DocNo values. The values are just integers, so there is no $FileNames property to retrieve. The loop should run through the list we already constructed
ForEach ($File in $FileNames) {
# Open their Excel Workbook (INSERT THE FILENAME OF THE FILE NO. FROM CSV)
$WorkBook = $Excel.Workbooks.Open($File)
}
Final tip, use Write-Host to display the value of variables as you go, e.g.
Write-Host $LineSplit[0]
Using Powershell, I need to loop through each cell of a column and check to see if that value exists in another loop through of .txt files, in any of the files then populate an additional column(s) in the spreadsheet indicating which .txt files contain the value(s)
So far, I have a Powershell script which looks through a set of files from a selected destination. The script allows you to choose filename and extension and content. This part is good because I want to be able to loop through a selection of files, but I want the $SearchText value that it looks for in the files, to be looped through, changing one by one to each value in column A of a Worksheet I have in Excel. Once it finds the value in any of the selected files that are being looped through, it'll add a column to the Worksheet giving the file name it has been found in. If it's found in more than one file, it'll add columns for each it finds.
clear;
$Files = "";
$FileNameEnds = "";
$FileExt = ".txt";
$SearchText = "";
Foreach ($file in [System.IO.Directory]::GetFiles($Files,"*"+"$FileNameEnds."+$FileExt, [System.IO.SearchOption]::AllDirectories))
{
$Textfile = [System.IO.File]::ReadAllLines($file);
$FileContains = $false;
foreach ($line in $Textfile.Split([System.Environment]::NewLine))
{
if($line.Contains($SearchText))
{
$FileContains = $true;
}
}
if ($FileContains)
{
Write-Host "Contains:" $file;
Write-Host $FileContains
}
}
Write-Host "Done";
I want a successful double loop, one for setting the $SearchText value to each of the cells in a column from an Excel Worksheet I have, one by one, then use that value to search through a loop of files in a given destination, which is the bit I already have code for.
I have been at this for a while and can't seem to find anything that does exactly what I want. I was working off this post: How to use PowerShell to copy several Excel worksheets and make a new one but it doesn't do exactly what I am looking for. I am attempting to copy all worksheets from multiple workbooks and place them in a new workbook. Ideally, I would like to get the file name from one of the workbooks and use it to name the new file in a new directory.
I have found numerous examples of code that can do this, but there are a couple of key features that I am missing and not sure how to implement them. Here is an example of what I have working now:
$file1 = 'C:\Users\Desktop\TestFolder\PredictedAttritionReport.xlsx' # source's fullpath
$file2 = 'C:\Users\Desktop\TestFolder\AdvisorReport' # destination's fullpath
$xl = new-object -c excel.application
$xl.displayAlerts = $false # don't prompt the user
$wb2 = $xl.workbooks.open($file1, $null, $true) # open source, readonly
$wb1 = $xl.workbooks.open($file2) # open target
$sh1_wb1 = $wb1.sheets.item('Report') # second sheet in destination workbook
$sheetToCopy = $wb2.sheets.item('Report') # source sheet to copy
$sh1_wb1.Name = "DeleteMe$(get-date -Format hhmmss)" #Extremely unlikely to be a duplicate name
$sheetToCopy.copy($sh1_wb1) # copy source sheet to destination workbook
$sh1_wb1.Delete()
$wb2.close($false) # close source workbook w/o saving
$wb1.close($true) # close and save destination workbook
$xl.quit()
spps -n excel
The problem that I have is that I need this to work, such that I don't have to input the actual file name since those names may be different each time they are created and there may be 3 or 4 files with more than one worksheet, where this example works off of only two named files. Additionally, I would like to be able to copy all worksheets in a file instead of just a single named worksheet, which in this case is 'Report'. The final piece is saving it as a new Excel file rather than overwriting the existing destination file, but I think I can figure that part out.
You could specify parameters when you call the script, and use the specified values in place of the sheet/file names as required. Read about PowerShell Parameters here. Reply if you need more info on how to implement.
This function will copy over sheets from one excel workbook to other.
You can call with Copy-AllExcelSheet command one, it is loaded into memory.
See below in example:
Function Copy-AllExcelSheet()
{
param($TargetXls, $sourceXls)
$xl = new-object -c excel.application
$xl.displayAlerts = $false
$sourceWb = $xl.Workbooks.Open($sourceXls,$true,$false)
$targetWB = $xl.Workbooks.Open($TargetXls)
foreach($nextSheet in $sourceWb.Sheets)
{
$nextSheet.Copy($targetWB.Sheets[1])
}
$sourceWb.close($false)
$targetWB.close($true)
$xl.Quit()
}
#To call the function
Copy-AllExcelSheet "c:\Targetfile.xlsx" "c:\sourceFile.xlsx"
I am trying to write a perl script which reads an excel file(which has many sheets in it) using the sheet name.
I know how to access a particular sheet of the excel file using the sheet number, but not sure how to read it using sheet name.
Any help provided is highly appreciated.
Below is the code I wrote to access the sheet using sheet number:
my $Sheet_Number = 26;
my $workbook = ReadData("<path to the excel file>");
for (my $i =2; $i<$limit; $i++){
my $cell = "A" . $i;
my $key_1 = $workbook->[$Sheet_Number]{$cell};
}
Thanks
----Edit----
I want to open the particular sheet within the Excel file by using the sheet name. And then read the data from that particular sheet. The name of the sheet will be entered by the user while running the script from the command line arguments.
Below is the code that I am using after getting suggested answers for my earlier question:
my $parser = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse("$path");
my $worksheet;
if ($worksheet->get_name() eq "$Sheet_Name"){
for (my $i =2; $i<$limit; $i++){
my $cell = $worksheet->get_cell($i,"A");
my $value = $cell->value();
push #array_keys, $value;
}
}
I want to read the values of Column A of the particular sheet and push it into an array.
$Sheet_Name : It is the name of the sheet which is entered by the user as cmd line arg.
$path : It is the complete path to the Excel file
Error Message: Can't call method "get_name" on an undefined value at perl_script.pl (The error points to the line where the if-condition is used.)
Thanks for the help.
-----EDIT----
Anyone, with any leads on this post, please post your answer or suggestions. Appreciate any responses.
Thanks
The get_name() method of the worksheet object, in conjunction with Perl's grep command should get you this:
my ($worksheet) = grep { $_->get_name() eq 'Sheet2' } $workbook->worksheets();
This would be an un-golfed version of the same:
my $worksheet;
foreach $worksheet ($workbook->worksheets()) {
last if $worksheet->get_name() eq 'Sheet2';
}
Assuming there is a match... if not, I guess my un-golfed version would give you the last worksheet if there was no match.
-- Edit --
I made assumptions and -- you certainly do need to first call the method to load the workbook:
use strict;
use Spreadsheet::ParseExcel;
my $parser = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse('/var/tmp/foo.xls');
Then the code above should work.
I have some data in an excel file.
At first, I read the file and create a list of names stored in a cell through this command:
[status,sheets] = xlsfinfo(filename);
and I get:
sheets = {'A1','A2','B1','B2','C1'};
(these are the names of excelsheets in the excel file)
and through some process I obtain a matrix for each of these names (excelsheets). The final matrix for each is called:
completeData = [x,v,z,y,s];
Now, I want to:
change the name of "completeData" variable to each of its corresponding excelsheet (from the "sheets" cell).
then save this newly renamed variable (the old "completeData") with the name of its corresponding excelsheet (again from the "sheets" cell).
So far, I have only managed to save each completeData matrix resulting for each excel sheet separately with the name of the sheets [which is point number 2] through this command:
save(sprintf('%s',sheets{excelSheet}),'completeData');
(here I have a loop over "excelsheet")
The problem is that when I have mange excel sheets, and save all of them in a folder my hard disk, whenever I run any of these saved variables I get "completeData" in the workspace which is not what I want. I want to get also the name of the excelsheet.
How can I do this?
P.S. through this command:
eval(sprintf([sheets{excelsheet} '=completeData;']));
(again another loop over excelsheet)
I have managed to create several matrices with the names of excel sheets. But I do not know how I can save these very good newly created variables through a loop so that I do not do it one by one.
Following up the comments above, I tried to write you a simplified example:
%% Initialise
names = {'name1', 'name2', 'name3'};
data = randn(10, 3);
%% it create three fields called name1, name2 and name3 from data, in s
for ind=1:size(data, 2)
s.(names{ind}) = data(:, ind);
end
Hope it helps!
So this is how it worked:
First read information:
[status,sheets] = xlsfinfo(filename);
NamesList = sheets(:,1);
Now, apply the primarily collected information to read again with details:
for ind = 1:length(NamesList)
% Only read those particular sheets
[num,txt,raw] = xlsread(filename,NamesList{ind,:});
var.(NamesList{ind})={txt(:,MyColumn),num};
clear num txt raw
end