I am using MatlabR2011a on my Windows 7 machine.
I have a folder of 635 text files. Each file contains multiple rows and 2 columns. I am trying to loop through the folder and read each file and write these values to excel. So far this is what I have:
close all; clc;
dirname = uigetdir;
Files = dir(fullfile(dirname,'*.txt'))
for k = 1:635
j =1
filename = fullfile(dirname,Files(k).name);
fid = fopen(filename);
x = fgetl(fid)
while ischar(x)
x = fgetl(fid)
a2 = strtrim(x);
a3 = textscan(a2,'%s');
a4 = a3{1}{1};
a5= a3{1}{2};
pos3 = strcat('A',num2str(j));
xlswrite('sample_output',{a4,a5},'Sheet1',pos3)
j = j+1;
end
fclose(fid);
end
It keeps giving me the following error after finishing reading the first file.
Error using ==> strtrim Input should be a string or a cell array of strings.
A sample input file looks like this:
15076 4636259
15707 4636299
15714 1781552
15721 4204950
15730 2174919
16209 4636510
16413 4758572
16470 4445808
17519 311397
17667 2116489
17739 1729694
18024 3210756
18627 3714194
18695 4192858
19141 632766
19318 1923574
19438 1255216
19493 4635020
19771 4770250
How can I fix this? Would appreciate help with this!
In the while loop, cut the line
x=fgetl(fid)
...and paste it before the end statement right after j=j+1.
The error occurs because you get a line before the while statement, then you use the while statement to test validity of the string (all fine so far), but then immediately get the subsequent line before you perform your string operation. The call to fgetl at the start of the while block could return an EOF, causing subsequent string manipulation functions to fail.
Also... The code would be more robust if you set your for loop like so
for k=1:numel(Files)
Since all your data are numeric this should work. Give it a try.
dirname = uigetdir;
Files = dir(fullfile(dirname,'*.txt'))
j =0;
for k = 1:numel(Files)
filename = fullfile(dirname,Files(k).name);
x = dlmread(filename,'\t'); %# I assume tab-delimiter
j = j + size(x, 1);
xlswrite( 'sample_output', x, 'Sheet1',sprintf('A%d',j) )
end
Related
I'm in need of optimizing import of .xls files to matlab due to xlsread being very time consuming with large amount of files. Current xlsread script as follows:
scriptName = mfilename('fullpath');
[currentpath, filename, fileextension]= fileparts(scriptName);
xlsnames = dir(fullfile(currentpath,'*.xls'));
xlscount = length(xlsnames);
xlsimportdata = zeros(7,6,xlscount);
for k = 1:xlscount
xlsimport = xlsread(xlsnames(k).name,'D31:I37');
xlsimportdata(:,1:size(xlsimport,2),k) = xlsimport;
end
I have close to 10k files per week that needs processing and with approx. 2sec per file processed on my current workstation, it comes in at about 5½ hours.
I have read that ActiveX can be used for this purpose however that is far beyond my current programming skills and have not been able to find a solution elsewhere. Any help on how to make this would be appreciated.
If it is simple to perform with ActiveX (or other proposed method), I would also be interested in data on cells D5 and G3, which I am currently grabbing from 'xlsnames(k,1).name' and 'xlsnames(k,1).date'
EDIT: updated to reflect the solution
% Get path to .m script
scriptName = mfilename('fullpath');
[currentpath, filename, fileextension]= fileparts(scriptName);
% Generate list of .xls file data
xlsnames = dir(fullfile(currentpath,'*.xls'));
xlscount = length(xlsnames);
SampleInfo = cell(xlscount,2);
xlsimportdata = cell(7,6,xlscount);
% Define xls data ranges to import
SampleID = 'G3';
SampleRuntime = 'D5';
data_range = 'D31:I37';
% Initiate progression bar
h = waitbar(0,'Initiating import...');
% Start actxserver
exl = actxserver('excel.application');
exlWkbk = exl.Workbooks;
for k = 1:xlscount
% Restart actxserver every 100 loops due limited system memory
if mod (k,100) == 0
exl.Quit
exl = actxserver('excel.application');
exlWkbk = exl.Workbooks;
end
exlFile = exlWkbk.Open([dname filesep xlsnames(k).name]);
exlSheet1 = exlFile.Sheets.Item('Page 0');
rngObj1 = exlSheet1.Range(SampleID);
xlsimport_ID = rngObj1.Value;
rngObj2 = exlSheet1.Range(SampleRuntime);
xlsimport_Runtime = rngObj2.Value;
rngObj3 = exlSheet1.Range(data_range);
xlsimport_data = rngObj3.Value;
SampleInfo(k,1) = {xlsimport_ID};
SampleInfo(k,2) = {xlsimport_Runtime};
xlsimportdata(:,:,k) = xlsimport_data;
% Progression bar updater
progress = round((k / xlscount) * 100);
importtext = sprintf('Importing %d of %d', k, xlscount);
waitbar(progress/100,h,sprintf(importtext));
disp(['Import progress: ' num2str(k) '/' num2str(xlscount)]);
end
%close actxserver
exl.Quit
% Close progression bar
close(h)
Give this a try. I am not an ActiveX Excel guru by any means. However, this works for me for my small amount of test XLS files (3). I never close the exlWkbk so I don't know if memory usage is building or if it automatically cleaned up when descoped after the next is opened in its place ... so use at your own risk. I am seeing an almost 2.5x speed increase which seems promising.
>> timeit(#getSomeXLS)
ans =
1.8641
>> timeit(#getSomeXLS_old)
ans =
4.6192
Please leave some feedback if this work on large number of Excel sheets because I am curious how it goes.
function xlsimportdata = getSomeXLS()
scriptName = mfilename('fullpath');
[currentpath, filename, fileextension]= fileparts(scriptName);
xlsnames = dir(fullfile(currentpath,'*.xls'));
xlscount = length(xlsnames);
xlsimportdata = zeros(7,6,xlscount);
exl = actxserver('excel.application');
exlWkbk = exl.Workbooks;
dat_range = 'D31:I37';
for k = 1:xlscount
exlFile = exlWkbk.Open([currentpath filesep xlsnames(k).name]);
exlSheet1 = exlFile.Sheets.Item('Sheet1'); %Whatever your sheet is called.
rngObj = exlSheet1.Range(dat_range);
xlsimport = cell2mat(rngObj.Value);
xlsimportdata(:,:,k) = xlsimport;
end
exl.Quit
I want to save pitch,yaw and roll data in excel file for all frames. Eg: if i have 200 frames then i want to save 200 frames information in excel file. I have tried but my code only stores one frame data.exceldata
fitting_model='models/Chehra_f1.0.mat';
load(fitting_model);
mov=VideoReader('7_a.avi'); %Read video file and create an object
c=mov.NumberOfFrames;
for k=1:c
a = read(mov, k);
img=im2double(a);
disp(['Detecting Face in ']);
faceDetector = vision.CascadeObjectDetector(); % detect face in an image
bbox = step(faceDetector, img); %create boundary box around face
test_init_shape = InitShape(bbox,refShape); %initialize facial points in variable
test_init_shape = reshape(test_init_shape,49,2);
if size(img,3) == 3
test_input_image = im2double(rgb2gray(img));
else
test_input_image = im2double((img));
end
disp(['Fitting']);
MaxIter=6;
test_points = Fitting(test_input_image,test_init_shape,RegMat,MaxIter);
load('3D_Shape_Model.mat');
n=49;
test_image=img;
imshow(test_image);hold on;
% % Compute 3D Head Pose
if(n==49)
test_shape=test_points;
[pitch,yaw,roll] = ComputePose(PDM_49,test_shape(:));
filename='framesdata.xlsx';
header = {'Pitch', 'yaw ','roll'};
new_data = num2cell([pitch(:), yaw(:), roll(:)]);
output = [header; new_data];
xlswrite(filename,output);
end
plot(test_shape(:,1),test_shape(:,2),'b*');
title([num2str(i),' : Pitch = ',num2str(pitch),' ; Yaw = ',num2str(yaw),' ; Roll = ',num2str(roll)]);
set(gcf,'units','normalized','outerposition',[0 0 1 1]);
pause(0.5);
close all;
end
As #excaza stated, you will need to move the xlswrite command out of your loop or specify the cells you are writing. Please see the xlswrite Doc for more information. The correct syntax would be :
xlswrite(filename,A,xlRange)
The following is the example they provide:
filename = 'testdata.xlsx';
A = {'Time','Temperature'; 12,98; 13,99; 14,97};
sheet = 2;
xlRange = 'E1';
xlswrite(filename,A,sheet,xlRange)
You will just need to provide xlswrite the address to start writing data.
I have points data in .xlsx and I want to read and store them in p array in Matlab. These points are only 3D co-ordinates of x,y,z such that having understood three columns and not prdfined rows. How I can retrieve them from .xlsx or .csv if I need fast retrieval as I tried to retrieve .xlsx and its response time is slow and returns an empty array. Possibly store them in transposed form and transpose it back.
My Code: .Xls read
A = xlsread('data.xlsx')
Output:
A =
[]
My Code: .CSV read
M = csvread('data.csv')
Output:
Error using dlmread (line 139)
Mismatch between file and format string.
Trouble reading number from file (row 2u, field 1u) ==> ;\n
Error in csvread (line 48)
m=dlmread(filename, ',', r, c);
Points Set 1:
-191.2442 187.7193 1.0000;
-155.2995 152.6316 2.0000;
-182.0276 104.6784 3.0000;
-148.8479 84.7953 4.0000;
Points Set 2:
-142.3963 83.6257 5.0000;
-102.7650 133.9181 6.0000;
-56.6820 164.3275 7.0000;
-30.8756 124.5614 8.0000;
-23.5023 118.7135 7.0000;
-9.6774 110.5263 6.0000;
26.2673 90.6433 5.0000;
-42.8571 -6.4327 4.0000;
10.5991 7.6023 3.0000;
Points Set 3:
-73.2719 84.7953 9.0000;
-137.7880 15.7895 10.0000;
-92.6267 -30.9942 9.0000;
-42.8571 19.2982 8.0000;
41.0138 -15.7895 4.0000;
71.4286 -41.5205 6.0000;
90.7834 -14.6199 5.0000;
See if this slightly twisted one using importdata works for you -
C1 = importdata(file1) %%// file1 is your CSV filename
t1 = regexp(C1,'\s','Split')
t2 = horzcat(t1{:})
t2 = strrep(t2,';','')
M = cellfun(#str2num,reshape(t2(~strcmp(t2,'')),3,[])')
Edit 1: This case assumes you have a CSV file that has all the Point Sets clustered together but one by one (without spaces between the Point Sets and their data and also between the end of a Point Set and the declaration of the arrival of the next Point Set).
So, the input CSV file would look like this for the given data in the question -
Points Set 1:
-191.2442 187.7193 1.0000;
-155.2995 152.6316 2.0000;
-182.0276 104.6784 3.0000;
-148.8479 84.7953 4.0000;
Points Set 2:
-142.3963 83.6257 5.0000;
-102.7650 133.9181 6.0000;
-56.6820 164.3275 7.0000;
-30.8756 124.5614 8.0000;
-23.5023 118.7135 7.0000;
-9.6774 110.5263 6.0000;
26.2673 90.6433 5.0000;
-42.8571 -6.4327 4.0000;
10.5991 7.6023 3.0000;
Points Set 3:
-73.2719 84.7953 9.0000;
-137.7880 15.7895 10.0000;
-92.6267 -30.9942 9.0000;
-42.8571 19.2982 8.0000;
41.0138 -15.7895 4.0000;
71.4286 -41.5205 6.0000;
90.7834 -14.6199 5.0000;
Please note that the result from the codes would be a struct of arrays.
Code
C1 = importdata(file1) %%// file1 is your CSV filename
ind1 = cellfun(#isempty,strfind(C1,'Points'))
start_ind = find(~ind1)+1
s1 = find(~ind1)-1;
stop_ind = [s1(2:end) ; numel(ind1)]
for k = 1:numel(start_ind)
data1 = C1(start_ind(k):stop_ind(k))
t1 = regexp(data1,'\s','Split')
t2 = strrep(horzcat(t1{:}),';','')
t2 = t2(~strcmp(t2,''))
array(k).data = cellfun(#str2num,reshape(t2,3,[])'); %%//'
end
You are using the row separator ;\n (semicolon + new line). I don't know any function understand this format. Using texstscan is probably the best option:
fid=fopen(...)
M=cell2mat(textscan(line,'%f,%f,%f;\n'));
fclose(fid);
The data in my Excel files is supposed to be contentious (index in the first column). But some data is missing in the file. For example, # 5, and 6 are missing between $ 4 and 7. My purpose are (1) identify the file with missing data and (2) if data is missing insert rows to make it continuous. Can anyone tell me how to add in rows in the existing data? Using xlswrite I can only add in rows at the end of the file or replace some rows.
EDIT 1:
I have another set of file in which the index is not so direct. The first 3 columns are described below (as shown in the Excel file):
Column 1:Year: 2003 (read as number in matlab)
Column 2:Date: 1-Sep (read as text in matlab)
Column 3:Time: 1:00 (1:00 read as number 0.04167 and 2:00 read as 0.0833, not sure how it works)
Then the way to tell if it is continuous will be quite complicate since there will be different years, months, and days. Could you give some hint on this?
Basically you need to read the entire data, preferably in raw(cell) format, add the missing rows(with respect to the indices) and write back.
Based on your question, this code might work -
% NOTE: We are assuming that the indexing starts with 1
% Read data from input excel file with missing indices
[num,txt,raw] = xlsread('input.xls');
% Error-checking
if (size(num,1)-num(end,1)~=0)
disp('At least one index is missing!');
end
% Expand data such that all indices are covered.
data1=NaN(num(end,1),size(raw,2));
data1(:,1) = 1:num(end,1);
data1=num2cell(data1);
k1=1;
for k = 1:num(end,1)
if(num(k1,1)==k)
data1(k,:)= raw(k1,:);
k1 = k1+1;
end
end
% Write data
xlswrite('output.xls',data1);
EDIT 1:
In view of your new requirements, additional code is added next.
Please note few things about this code -
The code adds data for every year and not from a specific month, date and time to another specific month, date and time. If you wish to achieve that, please edit the associated
function - 'create_comp_sheet'.
It saves an intermediate file named - 'proper_base_data.xls', which maybe deleted at the end of the code.
%% MAIN CODE - CODE1.M
INPUT_FILENAME = 'input.xls'; % Excel file that has some missing year,date and time info
OUTPUT_FILENAME = 'output.xls'; % Excel file that has data from the input file along with all the missing year,date and time info
%% Base data
start_year=2003;
end_year=2005;
proper_base_data = create_comp_sheet(start_year,end_year);
xlswrite('proper_base_data.xls',proper_base_data);
[num,txt,raw] = xlsread('proper_base_data.xls');
base_data=cell(size(num,1),1);
for row_ID = 1:size(num,1)
base_data(row_ID) = {strcat(num2str(cell2mat(raw(row_ID,1))),'-', cell2mat(raw(row_ID,2)),'-',num2str(round(24*cell2mat(raw(row_ID,3)))))};
end
%% Input data
[num,txt,raw] = xlsread(INPUT_FILENAME);
input_data=cell(size(num,1),1);
for row_ID = 1:size(num,1)
input_data(row_ID) = {strcat(num2str(cell2mat(raw(row_ID,1))),'-', cell2mat(raw(row_ID,2)),'-',num2str(round(24*cell2mat(raw(row_ID,3)))))};
end
%% Setup final data
final_data = num2cell(NaN(size(proper_base_data,1),size(raw,2)));
final_data(:,1:3) = proper_base_data;
for k1=1:size(input_data,1)
for k2=1:size(base_data,1)
if strcmp(cell2mat(base_data(k2)),cell2mat(input_data(k1)))
final_data(k2,4:end) = raw(k1,4:end);
end
end
end
%% Write final data to excel
xlswrite(OUTPUT_FILENAME,final_data);
Associated function -
function data1 = create_comp_sheet(start_year,end_year)
months_string = {'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'};
date_count = [31 28 31 30 31 30 31 31 30 31 30 31];
num_hours = 24;
data1=[];
for year_ID = start_year:end_year
for month_ID = 1:numel(months_string)
days_per_month = date_count(month_ID);
if rem(year_ID,4)==0 && month_ID ==2
days_per_month = days_per_month+1;
end
for date_ID = 1:days_per_month
year = repmat({num2str(year_ID)},[num_hours 1]);
date = repmat({strcat(num2str(date_ID),'-',char(months_string(month_ID)))},[num_hours 1]);
time=cell(num_hours,1);
for k = 1:num_hours
time(k) = {strcat(num2str(k),':00')};
end
data1 = [data1 ; [year date time]];
end
end
end
return;
Hope this saves all your troubles!
this code has to color the J1 cell by a given rgb.
row_number_excel = 1;
representative_red = 205;
representative_green = 211;
representative_blue = 201;
headers = {'J'};
rgb = [representative_red representative_green representative_blue]; %# if you have 0 to 1 values multiply by 255 and round
clr = rgb * [1 256 256^2]'; %# convert to long number Excel understands
pwd = 'D:\grapes\main';
e = actxserver ('Excel.Application'); % open Activex server
filename = fullfile(pwd,'example.xls'); %# full path required
if exist(filename,'file')
ewb = e.Workbooks.Open(filename); %# open the file
else
error('File does not exist.') %# or create a new file
end
esh = ewb.ActiveSheet;
for c = 1:row_number_excel
str = num2str(row_number_excel);
esh.Range(strcat(headers{1},str)).Interior.Color = clr;
end
ewb.Save
ewb.Close(false)
e.Quit
I tried to run this code, but the cell was colored by a different color than the given rgb. When I ran the code in the second time, a file was created in my directory, named: "2E60F720". its type is 'file'. Then the program ran and ran and wasn't stopped till I stopped 'EXCEL.EXE' by the task manager. After that the matlab wrote me this:
"??? Error: The remote procedure call failed.
Error in ==> test1 at 212 ewb.
Close(false);"
can someone help me please?
I captured the screen. in the left side, the program is still running, in the right side, this is my directory. I marked the file that was created.
thanks!
the solution that solved my question is:
row_number_excel = 1;
representative_red = 205;
representative_green = 211;
representative_blue = 201;
headers = {'J'};
rgb = [representative_red representative_green representative_blue]; %# if you have 0 to 1 values multiply by 255 and round
clr = rgb * [1 256 256^2]'; %# convert to long number Excel understands
pwd = 'D:\grapes\main';
e = actxserver ('Excel.Application'); % open Activex server
filename = fullfile(pwd,'example.xls'); %# full path required
if exist(filename,'file')
ewb = e.Workbooks.Open(filename); %# open the file
else
error('File does not exist.') %# or create a new file
end
esh = ewb.ActiveSheet;
for c = 1:row_number_excel
str = num2str(row_number_excel);
esh.Range(strcat(headers{1},str)).Interior.Color = clr;
end
xlWorkbookDefault = 51; %# it's the Excel constant, not sure how to pass it other way
ewb.SaveAs(fullfile(pwd,'example2'), xlWorkbookDefault)
ewb.Close(false)
e.Quit
thanks to #yuk!
The trouble line is saving the file with ewb.Save.
Your file is actually in the old format (excel 2003), not sure if it's support true RGB colors, it might be the reason.
I'd recommend to save the file with a new name and the latest format. Put this as the last lines:
xlWorkbookDefault = 51; %# it's the Excel constant, not sure how to pass it other way
ewb.SaveAs(fullfile(pwd,'example2'), xlWorkbookDefault)
ewb.Close(false)
e.Quit