I got the compile error
"Function call on left-hand side of assignment must return Variant or Object"
Trying to fix an inherited Excel file that calculates various values related to HVAC. The file relies on a couple of Add-In .xla files which contain many functions. I am unable to get results from most of the functions. Either I get numbers that immediately turn to zeros, or I just get #VALUE and #NAME errors.
My VBA skills are somewhat limited as well as my knowledge of the calculations this file is performing.
Function EvapDeltaGrn(altitude, evap_on, tdb_ma, hr_ma, sat_goal, hr_min)
'use to calculate the delta grain when tdb_oa > than sat_goal
EvapDeltaGrn = 0
If tdb_ma = "" Then Exit Function
If hr_ma = "" Then Exit Function
If evap_on Then
If tdb_ma >= (sat_goal) Then 'use evaporative cooling
Enthalpy = Application.Run("'psychrometric functions.xla'!TdbGrainstoEnthalpy", altitude, tdb_ma, hr_ma)
'Range("v14") = enthalpy
EvapDeltaGrn = Application.Run("'psychrometric functions.xla'!TdbEnthalpytoGrains", altitude, sat_goal, Enthalpy)
EvapDeltaGrn = EvapDeltaGrn - hr_ma
EvapDeltaGrn = Round(EvapDeltaGrn, 2)
Else 'evaporative humidification
If hr_ma < hr_min Then EvapDeltaGrn = Round(hr_min - hr_ma, 2)
End If
End If
End Function
The error seems to be at Enthalpy =.
Related
Hi im doing a bluetooth project using bluetooth toolbox in matlab, and encountered a problem. So I have been following one of the example from https://www.mathworks.com/help/bluetooth/ug/noncollaborative-bluetooth-le-coexistence-with-wlan-signal-interference.html this error occurred.
ble_wlan_interference
Argument to dynamic structure reference must evaluate to a valid field
name.
Error in helperBluetoothChannelClassification (line 102)
obj.(varargin{idx}) = varargin{idx+1};
Error in ble_wlan_interference (line 58)
classifierObj = helperBluetoothChannelClassification(centralNode,peripheralNode,PERThreshold=50);
At line 102 of helperBluetoothChannelClassification.m is as follows,
methods
% Constructor
function obj = helperBluetoothChannelClassification(varargin)
% Set name-value pairs
for idx = 1:2:nargin
obj.(varargin{idx}) = varargin{idx+1};
end
At line 58 of main code is as follows,
%enable channel classification
enableChannelClassification = true;
if enableChannelClassification
classifierObj = helperBluetoothChannelClassification(centralNode,peripheralNode,PERThreshold=50);
classifyFcn = #(varargin) classifierObj.classifyChannels;
userData = []; % User data needed to be passed to the callback function
callAt = 0; % Absolute simulation time, in seconds
periodicity = 125e-3; % In seconds
scheduleAction(networkSimulator,classifyFcn,userData,callAt,periodicity); % Schedule channel classification
end
I think the centralNode and peripheralNode parameter is not recognizable in helperBluetoothChannelClassification function, but don't know what is a problem.. Thanks :)
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 am trying to find the data between two values. I am using this code in a GUI programme, the starting_value and ending_value which you can see in the code below are selected from 2 listboxes in a previous part of the code.
% --- Executes on button press in CalculateIntensity.
function CalculateIntensity_Callback(hObject, eventdata, handles)
% hObject handle to CalculateIntensity (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Trapz function
starting_value = getappdata(0,'StartValue');
ending_value = getappdata(0,'EndValue');
StartingValue = str2mat(starting_value)
EndingValue = str2mat(ending_value)
A = getappdata(0,'XYarray')
data_found = A(A(:,[1,2]) > StartingValue & A(:,[1,2]) < EndingValue)
I found help on:
http://www.mathworks.com/matlabcentral/answers/8556-how-to-find-vector-elements-between-two-values-efficiently
However the
data_found = A(A(:,[1,2]) > StartingValue & A(:,[1,2]) < EndingValue)
part of the code wont work for me, I think starting_value and ending_value are strings so I tried converting it to a matrix but I get the error:
Error using <
Matrix dimensions must agree.
Error in MichelleLaycockGUImainwindow>CalculateIntensity_Callback (line 119)
data_found = A(A(:,[1,2]) > StartingValue & A(:,[1,2]) < EndingValue)
an example of data used is:
A =
1.0e+03 *
0.1660 1.1570
0.1664 0.4650
0.1668 0
0.1672 1.0200
0.1676 1.0110
0.1680 1.0200
0.1684 1.0640
0.1688 1.1100
0.1692 1.0370
0.1696 1.0050
0.1700 1.0750
0.1704 1.0850
0.1708 1.1310
0.1712 1.0630
0.1716 1.0370
0.1719 1.1070
0.1724 1.1450
I'm not really sure where I'm going wrong, any help would be greatly appreciated as it's all I need to complete my work. Thanks in advance!
As some of the values in my data vary rather than just decreasing or increasing the greater than or equal to method I was originally trying to use did not work. So rather than using the loop to get the data between the two points selected I went with a different method.
I use[~,indx1]=ismember(StartingValue,A,'rows') this finds the row number of the selected data and then I use this information to extract the data between and including the selected data.
Here is the full code I used to do this:
starting_value = getappdata(0,'StartValue');
ending_value = getappdata(0,'EndValue');
StartingValue = str2num(starting_value);
EndingValue = str2num(ending_value);
A = getappdata(0,'XYarray');
[~,indx1]=ismember(StartingValue,A,'rows');
[~,indx2]=ismember(EndingValue,A,'rows');
arrayfortrapz = A(indx1:indx2,1:2); %array of data including and between selected data
I hope this of some help to anybody that may run into a similar issue.
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!
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