Creating EXCEL File with parfor command in MATLAB for parallel processing - excel

I want to create excel file outside parfor loop (in the starting of the code) then updating excel file with each loop and finally storing excel file to specific location after loop is complete. But I am getting some errors. with following command :
matlabpool('open',2);
pwd='C:\Users\myPC\Desktop';
fName = fullfile(pwd, 'file.xls');
%# create Excel COM Server
Excel = actxserver('Excel.Application');
Excel.Visible = true;
%# create new XLS file
wb = Excel.Workbooks.Add();
wb.Sheets.Item(1).Activate();%line 10
offset = 0;
C1 = {'NAME', 'Max', 'Min','Average'};
%# calculate cell range to fit matrix (placed below previous one)
cellRange = xlcalcrange('A1', offset,0, size(C1,1),size(C1,2));
offset = offset + size(C1,1);
%# insert matrix in sheet
Excel.Range(cellRange).Select();
Excel.Selection.Value =C1;
parfor i=1:2
%some code , eg :
MAX =1
MIN =2
AVG=3
name='jpg'
row2 = { name MAX MIN AVG };
%# calculate cell range to fit matrix (placed below previous one)
cellRange = xlcalcrange('A1', offset,0, size(row2,1),size(row2,2));
offset = offset + size(row2,1);
Excel.Range(cellRange).Select(); %line32
Excel.Selection.Value =row2;
end
%# parsave XLS file
wb.SaveAs(fName,1);
wb.Close(false);
%# close Excel
Excel.Quit();
Excel.delete();
matlabpool('close');
Above code shows following error:
1. The variable Excel in a parfor cannot be classified.,
2. The PARFOR loop cannot run used due to the way variable 'offset' is used.,
3. The PARFOR loop cannot run used due to the way variable 'Excel' is used.,
4. Valid indices for 'Excel' are restricted in PARFOR loops.,
5. Call was rejected by callee.Error in line 10 (wb.Sheets.Item(1).Activate();).
Pls. help to use above code so that I can create excel file which updates inside PARFOR loop and EXCEL file get saved outside PARFOR loop

It is not safe to write to a file simultaneously from different threads. This is why MATLAB will automatically error when you try to do this sort of thing.
The answer to this problem will be one of the two:
Within the parfor loop, write your outputs to some sort of independent buffers, and then outside the parfor loop write the buffers to the file, serially. Or,
Don't use parfor. Use for instead.
See this: http://blogs.mathworks.com/loren/2009/10/02/using-parfor-loops-getting-up-and-running/ to learn more about the restrictions of the parfor command.

Related

MATLAB: Save multiple tables in Excel using a while loop

I have the following while loop in which an image is read and analyzed, then the results are saved in a table, that is saved in an Excel worksheet. I initially did this code for one single image/table, then realized I need to develop it for n images.
I basically want the results to be saved in the same Excel worksheet without overwriting, ideally the tables are vertically separated by an empty row.
Here's my effort as for now:
while(1)
...
%code code code
...
message = sprintf('Do you want to save the results in an Excel
worksheet?');
reply = questdlg(message,'Run Program?','OK','Cancel', 'OK');
if strcmpi(reply, 'Cancel')
% User canceled so exit.
return;
end
% Table creation.
% code code code
% Saving table to Excel
T = table(Diameter,BandWidth,n1,n2,P1,P2,Damage,...
'RowNames',Band);
filename = 'Results.xlsx';
writetable(T, filename, 'Sheet',1, 'Range', 'A1','WriteRowNames',true);
% Create a while loop to save more experiments to the Excel worksheet.
promptMessage = sprintf('Do you want to process another photo?');
button = questdlg(promptMessage, 'Continue', 'Continue', 'Cancel',
'Continue');
if strcmpi(button, 'Cancel')
break;
end
end
If it can help you to get an idea, each table is a 6x8.
Prior to your while loop, declare a cell array to hold the table that you will eventually write to an excel file.
cellArrayOfTableToBeWritten = {};
Also prior to the loop, define a cell array that will serve as a blank row.
rowWidth = 8;
blankrow = repmat({''},1,rowWidth);
Where you currently write the table, instead add what you would have written to the cell array with a blank row at the bottom.
cellArrayOfTableToBeWritten = [cellArrayOfTableToBeWritten;
T.Properties.VariableNames;
table2cell(T);
blankrow];
Once your while loop is done, write the combined cell array to a file as an excel file.
xlswrite(filename, cellArrayOfTableToBeWritten);

Working with Excel sheets in MATLAB

I need to import some Excel files in MATLAB and work on them. My problem is that each Excel file has 15 sheets and I don't know how to "number" each sheet so that I can make a loop or something similar (because I need to find the average on a certain column on each sheet).
I have already tried importing the data and building a loop but MATLAB registers the sheets as chars.
Use xlsinfo to get the sheet names, then use xlsread in a loop.
[status,sheets,xlFormat] = xlsfinfo(filename);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(filename,sheets{sheetindex});
data{sheetindex}=num; %keep for example the numeric data to process it later outside the loop.
end
I 've just remembered that i posted this question almost 2 years ago, and since I figured it out, I thought that posting the answer could prove useful to someone in the future.
So to recap; I needed to import a single column from 4 excel files, with each file containing 15 worksheets. The columns were of variable lengths. I figured out two ways to do this. The first one is by using the xlsread function with the following syntax.
for count_p = 1:2
a = sprintf('control_group_%d.xls',count_p);
[status,sheets,xlFormat] = xlsfinfo(a);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(a,sheets{sheetindex},'','basic');
data{sheetindex}=num;
FifthCol{count_p,sheetindex} = (data{sheetindex}(:,5));
end
end
for count_p = 3:4
a = sprintf('exercise_group_%d.xls',(count_p-2));
[status,sheets,xlFormat] = xlsfinfo(a);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(a,sheets{sheetindex},'','basic');
data{sheetindex}=num;
FifthCol{count_p,sheetindex} = (data{sheetindex}(:,5));
end
end
The files where obviously named control_group_1, control_group_2 etc. I used the 'basic' input in xlsread, because I only needed the raw data from the files, and it proved to be much faster than using the full functionality of the function.
The second way to import the data, and the one that i ended up using, is building your own activeX server and running a single excelapplication on it. Xlsread "opens" and "closes" an activeX server each time it's called so it's rather time consuming (using the 'basic' input does not though). The code i used is the following.
Folder=cd(pwd); %getting the working directory
d = dir('*.xls'); %finding the xls files
N_File=numel(d); % Number of files
hexcel = actxserver ('Excel.Application'); %starting the activeX server
%and running an Excel
%Application on it
hexcel.DisplayAlerts = true;
for index = 1:N_File %Looping through the workbooks(xls files)
Wrkbk = hexcel.Workbooks.Open(fullfile(pwd, d(index).name)); %VBA
%functions
WorkName = Wrkbk.Name; %getting the workbook name %&commands
display(WorkName)
Sheets=Wrkbk.Sheets; %sheets handle
ShCo(index)=Wrkbk.Sheets.Count; %counting them for use in the next loop
for j = 1:ShCo(index) %looping through each sheet
itemm = hexcel.Sheets.Item(sprintf('sheet%d',j)); %VBA commands
itemm.Activate;
robj = itemm.Columns.End(4); %getting the column i needed
numrows = robj.row; %counting to the end of the column
dat_range = ['E1:E' num2str(numrows)]; %data range
rngObj = hexcel.Range(dat_range);
xldat{index, j} = cell2mat(rngObj.Value); %getting the data in a cell
end;
end
%invoke(hexcel);
Quit(hexcel);
delete(hexcel);

Write data to excel and change sheet name using ActiveX--Matlab

I need to export data to excel sheet with a specific name using Activex. Here is what I did: First i export the data to excel in first for loop and then modify the names of the sheet using second for loop. Can it be done even in one single for loop? I think there should be another better idea.
Note: The size of the data varies.
try
filename = fullfile(pwd,'example.xlsx');
for i=1:5
xlswrite(filename,[1 2;3 4]*i,i);
end
for i = 1:5
myExcel = actxserver('Excel.Application');
excelWorkBook = myExcel.Workbooks.Open(filename,0,false);
excelWorkBook.Worksheets.Item(i).Name = ['new_sheet_' num2str(i)];
excelWorkBook.Save;
excelWorkBook.Close;
myExcel.Quit;
end
catch
% Disp Error message.....
end
The xlswrite function also accepts a string as sheet parameter. So just replace your call by this one:
xlswrite(filename,[1 2;3 4]*i,['new_sheet_' num2str(i)]);
Fratyx's answer is the simplest to implement, but a bit of knowledge of the Excel Object Model goes a long way, so here's how to implement your solution with ActiveX in one loop:
e = actxserver('excel.application');
w = e.Application.Workbooks.Add();
numnewsheets = 4;
for i = 1:numnewsheets
w.Worksheets.Add([],w.Sheets.Item(w.Sheets.Count),1);
w.Worksheets.Item(i).Name = ['new_sheet_' num2str(i)];
w.Worksheets.Item(i).Cells.Range('A1:B2').Value = [1 2;3 4];
end
w.SaveAs(filename)
w.Close
e.Quit
e.delete
To calculate the range required for the size of your data, you will have to open file "xlswrite" and copy out the sub-function "calcrange".

How to import lots of data into matlab from a spreadsheet?

I have an excel spreadsheet with lots of data that I want to import into matlab.
filename = 'for_matlab.xlsx';
sheet = (13*2)+ 1;
xlRange = 'A1:G6';
all_data = {'one_a', 'one_b', 'two_a', 'two_b', 'three_a', 'three_b', 'four_a', 'four_b', 'five_a', 'five_b', 'six_a', 'six_b', 'seven_a', 'seven_b', 'eight_a', 'eight_b', 'nine_a', 'nine_b', 'ten_a', 'ten_b', 'eleven_a', 'eleven_b', 'twelve_a', 'twelve_b', 'thirteen_a', 'thirteen_b', 'fourteen_a'};
%read data from excel spreadsheet
for i=1:sheet,
all_data{i} = xlsread(filename, sheet, xlRange);
end
Each element of the 'all_data' vector has a corresponding matrix in separate excel sheet. The code above imports the last matrix only into all of the variables. Could somebody tell me how to get it so I can import these matrices into individual matlab variables (without calling the xlsread function 28 times)?
You define a loop using i but then put sheet in the actual xlsread call, which will just make it read repeatedly from the same sheet (the value of the variable sheet is not changing). Also not sure whether you intend to somehow save the contents of all_data, as written there's no point in defining it that way as it will just be overwritten.
There are two ways of specifying the sheet using xlsread.
1) Using a number. If you intended this then:
all_data{i} = xlsread(filename, i, xlRange);
2) Using the name of the sheet. If you intended this and the contents of all_data are the names of sheets, then:
data{i} = xlsread(filename, all_data{i}, xlRange); %avoiding overwriting

How to modify xlsread to get a step-by-step updated flag from loading process

I have installed Matlab r2010a on my computer
I need use the function xlsread to load data from one just one *.xls or *.xlsx file. that's not a big challenge, the problem is How to modify xlsread.m to get a flag (integer) that gives the percentage of the loading process?
Thanks a lot.
so far i made this:
put a step variable to count until half then call xlsread that take a little time and after load process, the counter in 49.5% count to the end.
Not the best, but this is what I have
file = 'example.xls';
h = waitbar(0, ['Loading data from ' file], ...
'Name', 'Loading',...
'CreateCancelBtn',...
'setappdata(gcbf, ''canceling'', 1)');
steps = 200;
for step = 1 : steps
%# Check for Cancel button press
if getappdata(h, 'canceling')
okCancel = 1;
break
end
pause(0.01); %# Delay time for wait bar progres
if step == steps/2
[data, txt] = xlsread(file);
end
%# Process status report
waitbar(step/steps, h, sprintf(['Loading data from file... %3.2f%%'], step*100/steps));
end
set(h, 'CloseRequestFcn', 'closereq')
close(h)
XLSREAD function allows you to specify ranges of cells to read. Therefore you could read your data in batches (say read the first 50 rows of the table, then the next 50, and so on), each time "incrementing" the progress bar.
Note that this will be slower than reading the whole table at one, because the function has to make a connection to Excel COM then tear it down each time it is called (see this post for an explanation and a possible solution).
EDIT:
Here is a quick example:
%# path to excel file to read
fname = fullfile(pwd,'test.xls');
%# get number of rows/columns in table
Excel = actxserver('Excel.Application'); %# open Excel COM Server
wb = Excel.Workbooks.Open(fname, 0, true); %# open XLS file for reading
sheet = Excel.Worksheets.get('item',1); %# activate first sheet
numRows = sheet.Range('A1').End('xlDown').Row;
numCols = sheet.Range('A1').End('xlToRight').Column;
wb.Close(false); %# close XLS file
Excel.Quit(); %# cleanup
Excel.delete();
clear Excel wb sheet;
%# read rows in steps, and show progress-bar
numSteps = 20;
idx = fix(linspace(0,numRows,numSteps+1));
num = cell(numSteps,1);
h = waitbar(0, 'Reading excel file');
for i=1:numSteps
%# update progress-bar
waitbar(i / numSteps);
%# range of cells to read
cellRange = sprintf('%c%d:%c%d', ...
'A', idx(i)+1, char('A'+numCols-1), idx(i+1));
num{i} = xlsread(fname, 1, cellRange);
end
close(h)
%# merge all cells into a matrix
num = cell2mat(num);
This assumes the Excel file contains a table of numeric data. Feel free to adapt to your own file.

Resources