Skip to main content
Announcements
Join us at Qlik Connect for 3 magical days of learning, networking,and inspiration! REGISTER TODAY and save!
cancel
Showing results for 
Search instead for 
Did you mean: 
nigel987
Creator II
Creator II

Include all subroutines from directory

Hi, 

I have a directory where all my subroutines are stored. I want to load them all at once, so that I can call every subroutine without the necessity to include the text file with the subroutine first. 

When I use Version A in the script (without a loop), everthing is fine:

 

//Version A:

$(Include=z:\documents\functions\CreateCalendar.txt);

Call CreateCalendar ('01.01.2018',Today());

 

But when I use the loop, it get an error (Syntax error Call >>>>>>CreateCalendar<<<<<< ('01.01.2018',Today()))

//Version B:
SET pathDataOrigin = 'z:\documents\functions\';

FOR Each File in filelist ('$(pathDataOrigin)'&'CreateCal*.txt')

$(Include=$(File));

Next File;

Call CreateCalendar ('01.01.2018',Today());

 

I cannot find the reason for the error. Can anyone help me with that?

 

 

 

 

The subroutine is very simple:

SUB CreateCalendar (StartDate, EndDate)


LET vDateMin = Num(StartDate);
LET vDateMax = Num(EndDate);


Calendar:
LOAD
Date($(vDateMin) + RowNo() - 1) AS Date
AUTOGENERATE 1
WHILE
$(vDateMin)+IterNo()-1<= $(vDateMax)
;

End Sub;

13 Replies
marcus_sommer

There is no breaking point (right click on the row-number will set/remove one) set and therefore it just runs into an error without giving you the possibility to monitor what's loaded within the include-file - you noticed that there is now another tab above the debugger-script-window?

Because of the fact that this tab/window is created and is called CreateCalendar I assume that the include-file is really loaded - in the most cases it's exactly the reason (an invalid path) why anything didn't work. Nevertheless you may to ensure that it worked like expected and if not to trace the issue - for this you should use must_include instead of include and TRACE $(File);.

Therefore I think that there is something wrong with your sub-routine probably any small syntax-issue, for example I noticed that there is a space between the routine-name and the parameter (I'm not sure if it lead to an error) ...

- Marcus

nigel987
Creator II
Creator II
Author

Hi @marcus_sommer ,

you're right, you can't see a breaking point in the screenshot, because I debugged step-by-step. And yes, I noticed the new tab with the sub, hence I assume that the sub is loaded properly. 

And I know that the sub itself is working, because when I include this file only (Version A) it works as expected. 

//Version A:
$(Include=z:\documents\functions\CreateCalendar.txt);
Call CreateCalendar('01.01.2018',Today());

 

But still, when using the loop, I cannot get it running, and the debugger isn't helpful either. 

 

 

SUB CreateCalendar(StartDate, EndDate)


LET vDateMin = Num(StartDate);
LET vDateMax = Num(EndDate);


Calendar:
LOAD
Date('$(vDateMin)' + RowNo() - 1) AS Date
AUTOGENERATE 1
WHILE
'$(vDateMin)'+IterNo()-1<= '$(vDateMax)'
;

End Sub;

marcus_sommer

I just dived a bit deeper in the matter and think you are right that it's not working in this way - without that there are "obvious" logically or syntactically errors. Every part "seemed" to be loaded and executed in the right order.

But it's not completely true. The cause of the sub-error here is that the sub-routine was created within a control-statement.

Control-statements like sub … end sub, if … end if, for … next have special properties in regard to their validity. This means either the existence and execution-order of them as well as the objects (tables, variables, further control-statements) which are created within them. This means they aren't available from everywhere.

In your case it means the sub was created within the for-loop and is only within the loop available and each call from the outside called a non exists statement.

I don't know if it's anywhere sufficient documented how Qlik has implemented the control-statements and which requirements are following from it. I remember that I have seen already postings where the guru's discussed this topic - maybe Rob Wunderlich  could shed some light on the matter.

In the end I doubt that there is a way to apply your mentioned approach and that the already made suggestion of applying multiple (nested) include-variables is probably the most suitable solution (I use this approach since many years and it's IMO quite practical).

Nevertheless I tried to develop a workaround with a logic which loads these include-files within a table, aggregated the records, creates multiple variables within a loop, called them outside from the loop, executed the routines and cleanes everything. It worked - but it's not really simpler and you will further need to specify each variable … but maybe somebody has further ideas to make this snippet more useful:

set pathDataOrigin = 'YourPath\';

for each File in filelist ('$(pathDataOrigin)CalendarIncludeT*.txt')
   t1: load [@1:n] as Statement, filebasename() as Filebasename, rowno() as RowNo from [$(File)] (fix, codepage is 1252); 
next File
 
t2: load Filebasename, concat(Statement, chr(10), RowNo) as Statement resident t1 group by Filebasename;
drop tables t1;
 
for i = 0 to noofrows('t2') - 1
   let s$(i) = peek('Statement', $(i), 't2');
   $(s$(i));
next
 
$(s0);
$(s1);
 
call CreateCalendar('01.01.2018',Today());
call CreateCalendarMonth('01.01.2018',Today());
 
for i = 0 to noofrows('t2') - 1
   let s$(i) = null();
next
 
let i = null();

 

Just came another thought that the above mentioned control-statements are the most usual ones but there more available like do while loop, case switch, … and maybe there are any differences how their validity worked ... in the case you want a bit play with them ...

- Marcus

nigel987
Creator II
Creator II
Author

Hi @marcus_sommer ,

many thanks for your elaborate explanation. I wasn't aware of the fact, that control statements behave in this way. Now I understand why the workaround as suggested by  @albertovarela is so extensively used, and I guess it is okay to use it, as it can be expected that functions are not changed very often. Understanding the reason behind this solution makes it even more acceptible. Thanks for shedding light on this topic.

 

Kind Regards,

Nigel