Add any number of rows from any row within a table

Steve
Platinum 4
Platinum 4

Definitely a frequently-asked question: how do I add some number of rows to a table automatically? It’s possible, but it’s not easy.

This article details an approach that can be accomplished entirely within AppSheet (no API use), within the app itself (no workflow use), and accommodates an arbitrary number of rows (no built-in count maximum).

While I’ve tried to make the guide accessible for less-experienced app creators, make no mistake: this is an advanced technique.

I hope you find this useful.

Sample app

Show More
Add Rows 1

I’ve also posted a follow-on app that simplifies the looping method used here and offers more examples:
Looping with actions

Step-by-step guide

Show More

1. In this guide, the table from which and to which rows will be added is named Rows. For your app, choose an existing table to which you want the user to be able to add multiple rows. Remember, though, to use your own table’s name wherever the Rows table is referenced in these instructions.

2. The Rows table must allow at least Adds and Updates: Adds to add rows, and Updates to keep track of how many more rows are needed.
Screenshot: Data >> Tables >> Rows
2X_b_beab09b778ff8823a60ea0dcb231d3cb2622e84e.png

3. To add multiple rows, we need to keep track of how many more are needed. For this, add a column (named, e.g., Count) of a numeric type (e.g., Number) to the Rows table.
Screenshot: Data >> Columns >> Rows
2X_3_3eeea9af35166aa2b1886da534b4bbb311ad5b70.png

4. The Count column tracks the number of rows still needed. As each new row is added, the count should go down. Create an action (e.g., Decrement count) for the Rows table of type Data: set the values of some columns in this row to lower the value of the Count column by one: ([Count] - 1).
Screenshot: Behavior >> Actions >> Decrement count
2X_0_0bfd5790c9a522571b7ffa8dbef0f41958198fd9.png


5. Of course, the whole point here is to add rows, so we need an action (e.g., Add one row) for the Rows table of type Data: add a new row to another table using values from this row to add one row, to be used repeatedly as many times as needed.
Screenshot: Behavior >> Actions >> Add one row
2X_c_c97c3bbe4871f43c13cb59f95ce92e31c3428e13.png
The action to add a new row must set at least one column value of the new row. A common approach is to set the row’s key column value (commonly using UNIQUEID()), but if the key column has an Initial value expression, you could choose to set another column value instead. In fact, you can set any column values of the new row with this action.

6. Above, we identified two actions that need to occur with the addition of each row: the row addition itself, and lowering the count of rows still needed. We need a third action to perform those other two actions together.

Create an action (e.g., For each row to add, do this…) for the Rows table of type Grouped: execute a sequence of actions to perform both of the actions above: Add one row and Decrement count.
Screenshot: Behavior >> Actions >> For each row to add, do this...
2X_7_746cfc168ac6390f3f19f88968d027053b661bae.png

7. The magic in this process is finding a way to repeat the row addition process an arbitrary number of times. We can accomplish this repetition using a process called recursion. Recursion is an advanced topic in computer programming, so I won’t try to detail it here. Happily, though, AppSheet can do it, and it’s reasonably easy to setup.

Create an action (e.g., Add more rows) for the Rows table of type Data: execute an action on a set of rows to perform the For each row to add, do this… action above only on the current row (set Referenced Rows to LIST([_THISROW])).
Screenshot: Behavior >> Actions >> Add more rows
2X_1_154b494c41078fc06d2649e55243d2a5e372899f.png

8. This new Add more rows action should only do anything if the number of wanted rows expressed by the current row’s Count column value is more than zero. To enforce this, set the Add more rows action’s Only if this condition is true property to the expression, ([Count] > 0).
Screenshot: Behavior >> Actions >> Add more rows >> Only if this condition is true
2X_1_1bd8d5ff3378aa3092e3555f2baf8caac0f359df.png
This step is absolutely critical! If not done, the row addition process will repeat continuously (a condition called “infinite recursion”) until the app crashes or is force-stopped.

9.To complete the recursion setup that provides the repetition needed to add multiple rows, add the Add more rows action to the list of actions in the For each row to add, do this… action.
Screenshot: Behavior >> Actions >> For each row to add, do this...
2X_4_491212251223fd3e53c55c97acfbb5156ece8840.png

10. At this, point, the Add more rows action is ready for use. When performed for a row of the Rows column that has a Count column value more than zero, the action will add the number of rows and reset the count to zero.

To see the Add more rows action work, add the action as the Form Saved event action for the Rows_Form view. Then, add a new row or edit an existing row, and include a value for Count.
Screenshot: UX >> Views >> Rows >> Rows_Form
2X_d_dabdff74b31144169dc26429f2537912b56bdfdd.png

Quick reference

Show More
Data >> Tables >> Rows
  • Are updates allowed?: Adds, Updates (at least)
Data >> Columns >> Rows >> Count
  • Type: Number (or any other numeric type)
    Minimum value: 0 (recommended)
Behavior >> Actions >> Rows >> Decrement count
  • Do this: Data: set the values of some columns in this row
  • Set these columns: 
    Count: ([Count] - 1)
Behavior >> Actions >> Rows >> Add one row
  • Do this: Data: add a new row to another table using values from this row
  • Table to add to: Rows
  • Set these columns:
    • Key: UNIQUEID() (commonly)
    • (others as desired)
Behavior >> Actions >> Rows >> For each row to add, do this…
  • Do this: Grouped: execute a sequence of actions
  • Actions:
    • Add one row
    • Decrement count
Behavior >> Actions >> Rows >> Add more rows
  • Do this: Data: execute an action on a set of rows
  • Referenced Table: Rows
  • Referenced Rows: LIST([_THISROW])
  • Referenced Action: For each row to add, do this…

Behavior >> Actions >> Rows >> Add more rows

  • Only if this condition is true: ([Count] > 0)

Behavior >> Actions >> Rows >> For each row to add, do this…

  • Actions:
    • Add more rows (add to existing actions list)

UX >> Views >> Rows >> Rows_Form

  • Event actions:
    • Form Saved: Add more rows

 

77 51 14.3K
51 REPLIES 51

Thanks Steve for responding…I figured the way I envisaged it to work was incorrect. I unnecessarily was triggering from a new view instead of triggering from an existing view which adds the record in the first place…so all ok now…the requirement to add multiple lines for each row in the source table is also now redundant…learning the hard way

I’m crating a app for a organization and they want to invite there friends with their name personally with a text msg so created a from to ad a msg template and now I want to figure out a new table and form to give the user a selection for the table and column (what i have actually done with a sheet with all table and clm names), and then i need to set up a way that the list with names shell be generated into the msg body and to the number for that name
So i thing with your Idea maybe can i make it work
Any Ideas I would Really Appreciate

Have finally used the recursion example. And now this has opened doors for a lot of things.

Nonetheless, have tried to summarize the thing in a diagram. Hopw this will be of help.

Thank you @Steve
This is recursively brilliant!

Hi @Steve ! Hope you are doing fine.

I got this thread today. It should be fantastic to read the way of looping. Would you please give the link of this guide.

 

Thanks and Regards.

Hi @shahappsheetyou should see the post updated now so you can click on "Show More" to reveal the additional content below. Hope this helps!

Hi Steve

I tried to click on the links in your topic but they are dead - can you please repost them. 

Many thanks

Chris

Hi @Chris_Bean1, you should see the post updated now so you can click on "Show More" to reveal the additional content below. Hope this helps!

Sure @Steve doing things are hard but not impossible but it's for the industrious and confidential one.

Thanks

Thank you!! This is better than GOLD!

I know I'm very late to reply to this post, but this will solve my needs very nicely.

I've built the recursive setup exactly as outlined, and it works perfect. For the 'count' field, I made it a user defined field, and I'll explain why. I'm using this as an Incoming Shipment tracker. (Clients send shipments with unknown quantities of items so I need to give them the choice of how many to create.) I've set it up to copy over data that needs to be identical (client, tracking #, etc). What I need to do is create a 'pause' between each row creation so that the person inputting the data can fill in the new unique fields before moving on. I have a Key (UNIQUEID) column for each row that is auto-populated. I also have a shipment column (also UNIQUEID) which is used as a shipment ID. This column does get copied from the initial row to the new ones.

I'd thought of doing this a little bit differently by having two choices when the form is filled and saved. A button for "finish" and a button for "add another item" which would create an additional row, and then show them a form to fill data in the new row. The finish button would simply end the process. I do not know how to have the multi-button option.

Either of the two different approaches is good for me. I think it would be cleaner and simpler if all of the new rows were displayed on a single new form in tidy rows.

Any help and advice how to make this work will be massively appreciated. Thank you in advance!

Hola! gracias por la información! actualmente pude crear un bot para dar de alta insumos (cada fila es un insumo) a partir de un remito que contiene x cantidad del mismo insumo. El problema que tengo es que solo genera alrededor de 60 filas y luego se interrumpe el bot por exceder el limite de 120 segundos de ejecución. ¿Alguna idea de cómo puedo optimizar para ejecutar la acción en ese tiempo disponible? Muchas gracias!

Top Labels in this Space