function h = ExcelSource(filename, sheetname, columns, startrow, endrow)

% Check arguments
if ~ischar(filename) || length(filename)<1
    error('ExcelSource:ExcelSource:filearg','Filename must be a non-empty string')
end
if ~ischar(sheetname) || length(sheetname)<1
    error('ExcelSource:ExcelSource:sheetarg','Sheetname must be a non-empty string')
end
if ~isnumeric(columns) || length(columns)<1
    error('ExcelSource:ExcelSource:colarg', ...
        'Column argument must be a non-empty vector of column numbers')
end
if ~isnumeric(startrow) || ~isnumeric(endrow) || length(startrow)~=1 || ...
        length(endrow)~=1 || startrow>endrow
    error('ExcelSource:ExcelSource:rowarg', ...
        'Row arguments must be a non-empty integer scalars properly ordered')
end

h = tsdata.ExcelSource;
apphandle = h.comserver; % Gets handle to current Excel session (comserver method)

% Filename must include the path. If it is not provided add the current dir
if isempty(fileparts(filename))
    filename = [pwd '\' filename];
end

set(h,'Filename', filename, 'Sheetname', sheetname,'Column', columns, ...
     'StartRow',startrow,'EndRow',endrow);
eWorkbooks = get(apphandle, 'Workbooks');

% Find or create a workbook with the specified name
fileinfo = dir(filename);
if length(fileinfo)==0 % Open a new workbook and sheet
    warning('ExcelSource:ExcelSource:notfound','File not found, creating a new workbook');
  	eActiveWorkbook = Add(eWorkbooks);
	SaveAs(eActiveWorkbook, filename);
else
	% Open a new workbook if it has not aleady been opened
	% (Re-opening invalidates previous handles
	wbookclosed = true;
	for k=1:eWorkbooks.count  
       if strcmpi(get(Item(eWorkbooks,k),'FullName'),h.filename);
           wbookclosed = false;
           eActiveWorkbook = Item(eWorkbooks,k);
           break
       end
	end
	% If its not open, open it
	if wbookclosed
       Open(eWorkbooks, h.filename);
       eActiveWorkbook = get(apphandle, 'ActiveWorkBook');
	end
end     

% Find or create a sheet with the specified name
% Find the right sheet
eSheets = get(eActiveWorkbook, 'Sheets');
selectedSheet = [];
for k=1:eSheets.count
    thisSheet = Item(eSheets, k);
    if strcmp(thisSheet.name,sheetname)
            selectedSheet = thisSheet;
            break
    end
end
% If no handle the sheet does not exist
if isempty(selectedSheet)
    selectedSheet = Add(eSheets);
    set(selectedSheet, 'Name', sheetname);
    h.comhandle = newsheet;
    warning('ExcelSource:ExcelSource:nosheet','Worksheet not found, creating a new worksheet');
end
h.comhandle = selectedSheet;

% Add destructor listener
h.addlisteners(handle.listener(h,'ObjectBeingDestroyed', {@localDelete h}));
%h.addlisteners(handle.listener(h.comserver,'ObjectBeingDestroyed', {@localDelete h}));
% Store handles
h.Handles = {apphandle, eActiveWorkbook,eSheets,eWorkbooks};
% Update instance counter
localInstance('add');

function localDelete(eventSrc, eventData,h)

instances  = localInstance('del');
h.comhandle.release;
if instances <=0
	% Deletes COM interface 
	h.setvisibility(false);
    % TO DO: Need to mark all open workbooks to be saved
	set(h.comserver.ActiveWorkbook,'Saved',1);
	h.comserver.Quit;
	h.comserver.delete;
end


function instances = localInstance(action)

persistent instance;

switch action
    case 'add'
        if isempty(instance)
            instance = 1;
        else
            instance = instance+1;
        end
    case 'del'
        if isempty(instance) % A clear action has cleared the persistent var
            instance = 0;
        else    
            instance = instance-1;
        end
end
instances = instance;