{{ transformations:RepeatAction.png}}
====== REPEAT ======
Category: Workflow / Internal \\
\\
=====Description=====
The //Repeat// action allows for arranging "DO…WHILE" and "DO…UNTIL" types of loops. It repeatedly calls a module (or another project) until/while its result table is not empty, or empty, depending on the settings.\\
\\
=====Use cases=====
The action can be used in various cases, for instance:
* Obtaining data from REST APIs with data pagination ([[https://community.easymorph.com/t/how-to-pull-data-from-web-apis-with-pagination/2160|See Community example]])
* Polling a web API until an external task is complete
* Waiting until a file appears in a folder
* Dealing with parent-child data structures ([[https://community.easymorph.com/t/how-to-process-parent-child-data-structures/2156|See Community example]])
* Repeatedly apply the same calculation to a dataset until it no longer changes
\\
=====Action settings=====
^Setting^Description^
|Module/Project to run*|Select whether to call a module (within the current project), or an external project (.morph file), then select the\\ module, or browse to the project file.|
|Result table|Select the table in the called module (or projet) that will be returned to the calling //Repeat// action.|
|Repeat|Select whether the //Repeat// loop with stop once the result table is //empty//, or finally contains data. Options: //UNTIL result table is empty// or //WHILE result table is empty//.|
|Mode|Select the appropriate options for handling the return of results, and the timing of loops. See the Mode settings table, below.|
|Fail if number of iterations exceeds*|Enter a value to represent the maximum number of loops the //Repeat// will perform before failing. This prevents malformed //Repeat// actions from running infinite loops by stopping at a pre-defined point.|
|Assign parameters|If values will be passed into the called module/project via parameters, select the name(s) of parameter(s) to assign,\\ and enter the value* being passed in.|
* Setting can be specified using a [[:parameters|parameter]].\\
\\
====Mode settings====
^Setting ^Description ^
|Don't return result|Select this when a returned dataset is not required in the calling workflow.|
|**//UNTIL result table is empty// loops** ||
|Return the last not empty result|Select to return the last non-empty dataset before workflow iterations produced an empty table.|
|Append and return all results|Select this to continually append the results from all iterations and return the accumulated results.|
|**//WHILE result table is empty// loops** ||
|Return the first not empty result|Select to return the first non-empty dataset once the module's (or project's) criteria have been met.|
|Delay between iterations|Check this setting to insert a delay between loops and enter the number of seconds* to delay.|
* Setting can be specified using a [[:parameters|parameter]].\\
\\
=====Remarks=====
If the called module contains the [[transformations:input|Input]] action, the first iteration is populated with the input dataset of the //Repeat// action that calls it. In the following iterations, it's populated with the result dataset from the previous iterations. In other words, the result of an iteration is automatically passed as the input to the next iteration.
{{ :transformations:repeat-inputs.png?nolink640 |}}
When using the [[transformations:input|Input]] action in the called module, you can use the "Populate automatically" button to import the current dataset from the calling module to use as test data to build the rest of the module with.
You may need to balance the "Delay..." and "Fail after..." settings so your workflow succeeds or fails within an acceptable period of time.
\\
=====Examples=====
**Example:** Set up a process that waits for a file to appear in a "watched" folder before proceeding.\\
**Module 1 ("Main"):** Set up a //Repeat// action to call Module 2 (below).\\
**Action parameters:**
> Module to run is "WatchFolder"
> Result table is "Return filenames in Watched Folder"
> Repeat "WHILE result table is empty" (waiting for a file to appear in an empty folder)
> Mode is "Return the first not empty result" (return the file name)
> Delay is "unchecked" (no delay between iterations)
> Fail if the number of iterations exceeds "1000"
> There are no parameters in this example.
\\
**Module 2 ("WatchFolder"):** Set up a //List of files// action pointing to the watched folder.\\
**Action parameters:**
> Folder is the full path to the watched folder
> Columns is simply "File name with full path"
\\
The //Repeat// will continue to call the "WatchFolder" module until the //List of files// action returns a file name - which will occur when a file appears in the folder.
If a file does not appear in the target folder before //Repeat// has run 1000 iterations, the //Repeat// will fail with an error.
{{ transformations:repeat_flow.png?550 }}
\\
====Community examples====
* [[https://community.easymorph.com/t//2156/1|How to process parent-child data structures]] ([[https://community.easymorph.com/uploads/short-url/zmylfn4Qr0ovzu3e5rybl0LVMNG.morph|Project]]; Module: //Module 1//; Group: //Tab 1//; Table: //Scan all folders//; Action position: //2//)
* [[https://community.easymorph.com/t//2160/1|How to pull data from web APIs with pagination]] ([[https://community.easymorph.com/uploads/short-url/dvCSpcEDXYZ8aB0B2gtnt7qulTF.morph|Project]]; Module: //Main//; Group: //Group 1//; Table: //Query API with pagination//;\\ Action position: //2//)
* [[https://community.easymorph.com/t//2186/2|Excel IRR formula]] ([[https://community.easymorph.com/uploads/short-url/r3hO74ebEfwvCgq0YqkKt7bqGM2.morph|Project]]; Module: //IRR_TWO_NEAREST//; Group: //Group 1//; Table: //INPUT//; Action position: //3//)
\\
=====See also=====
* [[transformations:input|Input]]
* [[transformations:iterate|Iterate]]
* [[https://easymorph.com/learn/iterations.html| Tutorial: Iterations (loops)]]