{"id":6043,"date":"2025-01-22T03:58:48","date_gmt":"2025-01-22T03:58:48","guid":{"rendered":"https:\/\/obsidiansofteducation.com\/?page_id=6043"},"modified":"2025-01-22T04:02:49","modified_gmt":"2025-01-22T04:02:49","slug":"update-google-sheet-mit-app-inventor","status":"publish","type":"page","link":"https:\/\/obsidiansofteducation.com\/index.php\/update-google-sheet-mit-app-inventor\/","title":{"rendered":"Create, Read, Update and Delete Google Sheet in MIT App Inventor"},"content":{"rendered":"\n<p class=\"has-medium-font-size wp-block-paragraph\">Hello friends and welcome to Obsidian Soft<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">In my previous tutorials on Google Sheets, I showed you how to easily write to a Google sheet using forms and also read the entire sheet into the MIT App Inventor app. This was a simple and easy approach that came with limitations. We couldn\u2019t update the rows or delete rows programmatically. We also couldn\u2019t differentiate between different sheets in our spreadsheet. In this tutorial, which I will try my best to simplify, we will not just create rows in Google Sheets but also delete or update a particular row through our MIT App Inventor app. We will also use sheet names so that if our spreadsheet has multiple sheets, we can do our operations on a particular sheet.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">So, let\u2019s begin. First of all, let\u2019s make a google sheet:<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\"><a href=\"https:\/\/docs.google.com\/spreadsheets\/u\/0\" target=\"_blank\" rel=\"noopener\"><strong>https:\/\/docs.google.com\/spreadsheets\/u\/0<\/strong><\/a><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Make sure that you are logged in using your Gmail account. Click on the + button to create a blank spreadsheet.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Add some headers in the first row of the sheet: <strong>ID<\/strong>, <strong>Name<\/strong>, <strong>City<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Also, rename the sheet1 to <strong>Customers<\/strong>. Add some sample data to it too.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdfopeWYXdI-O8gXAw4GIHgyhFQpQDW51N17jHtkPkxXB5WaFTUd_4wn-kbux-ra6teUol7qWXmjKuoCJ-dzGj1QIaoJa_2agU_rwTlFlLzsrhWp7xVhu2cxZZdKG9YaJ6eItlymAkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:317px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, look at the address bar in your browser. You will have the spreadsheet\u2019s URL there:<\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-a47341221c17707f8bbbb7e6ead0f906 wp-block-paragraph\">https:\/\/docs.google.com\/spreadsheets\/d\/<strong>1n5kGHrAhhIhYph0c-tRedRtlILqv8aRCEyYtDeDnBJ<\/strong>\/edit?gid=0#gid=0<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">The highlighted part between d\/ and \/edit is the id of your spreadsheet. Please don\u2019t use mine. You have to create your own spreadsheet. Copy and paste this URL in some text editor like notepad as this is our spreadsheet id.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, navigate to <strong>Extensions &gt; Apps Script<\/strong> in the spreadsheet menu. A new browser window will open up.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdcf4vDNCTSe6WPqtAAmDGj4fzPn1fme8uHaxVK9Fq_JaGWUPnxEu-hrxUudYCwZHYcaPYPKLX_YZHRL7Nt_fMXzBg4LkG_f8M_AhJTCazjWxSYHREkX0Bacyj0EkfiZMmthlWbkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:668px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Remove the code from it. Copy and paste the following code in it but remember to update your spreadsheet id with the one that you got from the browser URL and that you had copied and pasted in Notepad. You have to do it for both doGet and doPost functions in this script. Also, you will have to update the script for your parameters. For example, I have id, name, and city but if you have different parameters, change it accordingly. I will explain more about this change later.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Don\u2019t forget to update the spreadsheet id for both doGet and doPost functions.<\/p>\n\n\n\n<pre class=\"wp-block-code has-text-color has-link-color wp-elements-8c53fd790358ce364a2be1a15cfed782\" style=\"color:#8e1a1a\"><code>function doGet(e) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;const sheetName = e.parameter.sheetName || \"DataSheet\";\n\n&nbsp;&nbsp;&nbsp;&nbsp;const spreadsheet = SpreadsheetApp.openById(\"your-spreadsheet-id\"); \/\/ Use your sheet ID\n\n&nbsp;&nbsp;&nbsp;&nbsp;const sheet = spreadsheet.getSheetByName(sheetName);\n\n&nbsp;&nbsp;&nbsp;&nbsp;if (!sheet) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"error\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: \"read\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Sheet not found\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;const range = sheet.getDataRange();\n\n&nbsp;&nbsp;&nbsp;&nbsp;const values = range.getValues();\n\n&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"success\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: \"read\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data: values\n\n&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n}\n\nfunction doPost(e) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;const data = JSON.parse(e.postData.contents);\n\n&nbsp;&nbsp;&nbsp;&nbsp;const sheetName = data.sheetName || \"DataSheet\";\n\n&nbsp;&nbsp;&nbsp;&nbsp;const spreadsheet = SpreadsheetApp.openById(\"your-spreadsheet-id\"); \/\/ Use your sheet ID\n\n&nbsp;&nbsp;&nbsp;&nbsp;const sheet = spreadsheet.getSheetByName(sheetName);\n\n&nbsp;&nbsp;&nbsp;&nbsp;if (!sheet) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"error\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: data.action,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Sheet not found\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;if (data.action === \"add\") {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sheet.appendRow(&#91;data.id, data.name, data.city]);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"success\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: \"add\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Row added successfully\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n&nbsp;&nbsp;&nbsp;&nbsp;} else if (data.action === \"update\") {\n\n&nbsp;&nbsp;&nbsp;&nbsp;const range = sheet.getDataRange();\n\n&nbsp;&nbsp;&nbsp;&nbsp;const values = range.getValues();\n\n&nbsp;&nbsp;&nbsp;&nbsp;let rowFound = false;&nbsp; \/\/ To track if the row is found\n\n&nbsp;&nbsp;&nbsp;&nbsp;for (let i = 1; i &lt; values.length; i++) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (String(values&#91;i]&#91;0]).trim() === String(data.id).trim()){\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ Update the name and city\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sheet.getRange(i + 1, 2, 1, 2).setValues(&#91;&#91;data.name, data.city]]);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rowFound = true;\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"success\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: \"update\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Row updated successfully\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/ If no matching row is found\n\n&nbsp;&nbsp;&nbsp;&nbsp;if (!rowFound) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"error\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: \"update\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Row not found\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n}\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (data.action === \"delete\") {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const range = sheet.getDataRange();\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const values = range.getValues();\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (let i = 1; i &lt; values.length; i++) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (String(values&#91;i]&#91;0]).trim() === String(data.id).trim()){\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sheet.deleteRow(i + 1);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"success\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: \"delete\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Row deleted successfully\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"error\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: \"delete\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Row not found\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;return ContentService.createTextOutput(JSON.stringify({\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status: \"error\",\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: data.action,\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: \"Invalid action\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;}))\n\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">You can see in the following screenshot that I have copied pasted the code and updated the spreadsheet id. I have also renamed the project to Web App for MIT App Inventor.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdsWW1VhM9m30e5QVGQK18dnXU4G1o-hxbwa52U2WDOo1TE6WIErswLbqIXK2iVOd8TQYTXIN_rDTR2gFqG73FVnS1yDloPr3Wutb8PgxnpfgzhZeMqidJhg03rMATvW5bUp0CBkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:636px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, click on the deploy button.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Choose<strong> New deployment<\/strong>.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Choose <strong>Web app<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXe7hrLFVZByUP2QK2qYgtKQCxnOUtX3MPySO-ayMqzktzR0ZjFtWG0ueBkZWYOpwFCoxfPBeNlaqkVZCZneadS8MLFQ6NVh0Dkv9iCG6VGPc4dMdtn-DEs8GZgMfRCR39SemKUdkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:614px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Set the <strong>Execute as<\/strong> field to <strong>Me<\/strong>.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Set the <strong>Who has access<\/strong> field to <strong>Anyone <\/strong>and click on <strong>Deploy <\/strong>button on the dialog.<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdEFvS2p4iVIbsqiLaRchmaQjqFAfExBInJJrB8KHsUq0mukE2mtv__0TtgMLmlE4on5_VCNduOZvc8kxXvVMmFbtn2J8AmCZS5AecEaXGHUT7o3C2WdKBDxreLl4M1gSshQaiKegkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" width=\"602\" height=\"339\"><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Since it is a new deployment, a new authorization dialog will pop up. Click on the <strong>Authorize access<\/strong> button.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXcsn-v_Lf3Qf1kUgtTfsptCcwy_kgtJgg8iNnww4wgBfc55ivp6l7gP6JiZPrObc7sFXFch1BpbHgNaKPYdU1TS73LDYSenHODLUmOfrXZ0XWfKH1UP_UO8cB1d9pLsz3XLyO9skeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:604px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">You will be asked to choose a Google Account. Choose it and click on the Advanced link on the dialog that pops up.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXcl1yr-L5wHFr94gLqTwzVbnVXOdWmstilZfumMzAphu184N_yCWkIOZJdWVl2G5zScrj6X7ajHE-wPvwEz7dJJgOzJEdbPEvGh-lCzaCwZPz33Tx3G8gmq4LCPL3zgZO228IlDagkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:603px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Click on the Go to \u201cproject name of your web app\u201d. I had renamed it to \u201cWeb App for MIT App Inventor\u201d. If you haven\u2019t renamed it, it will say \u201cUntitled Project\u201d.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXcYMNrG6k8JgyHSnIHK47eADOrMqv19lpCCs5FiQaALZXh5ci0YrWZ0GafEkLRneI-cvV4OJJdKloFFW08TlgDif4YpsDIRvIfUC7v54uhVfxJVnYkC3eat0gBkLgvB82RbklJJNQkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:501px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Another dialog will pop up. Scroll down and click on Allow button.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXecrQ5SHS5s5nG3DPbDy3NiqhaZHe02HnmbIlAofiszsJ8Ox3SwzFz9qaNKo-Kgl9tb3VOcd4SaJ8eyfwswyQ9V_XRIweDI4BuKgSt26K5hzCAvmixIkrEQJZmvJLVEiIv-DooZeQkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:627px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Copy and paste the web app URL into a text editor like notepad as we will need it later.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXfxYBkKDNvohoNJ6CzfAt9fFt_TczZtSppZT-8InK3BYl7YFESoLjMAnI8JX4hWoP9x-SfAwQqwYuEJHA2PvA5x4yd3Vq80MZHypQBgDkrOwKVbFfoUd1m8DjO7dfwjYRuzrfxjMgkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:628px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">(At any time, if you make a change to the web app script, you have to click on deploy button again and and choose manage deployments and save changes)&nbsp;<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, Open up MIT App Inventor and start a new project. Name it CRUDGoogleSheet.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Drag and drop a vertical arrangement from the Layouts palette onto the viewer. Rename this arrangement to mainScreen. Make width and height both fill parent.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Drag a listview from the user interface palette onto this mainScreen vertical arrangement and in its properties, make width: fill parent.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Add a horizontal arrangement from layouts below it. Make align horizontal and align vertical both center. Make height 15% and width fill parent. Drag and drop a button from the user interface palette inside this horizontal arrangement. Rename to addBtn. Make the background color blue, font bold, font size 20, width 30%, shape rounded and text: Add. Select the button and duplicate it by pressing Ctrl + C and Ctrl + V on the keyboard for windows OR Command + C and Command + V on the keyboard for MacOS. Rename it to updateBtn and change text to \u201cUpdate\u201d. Duplicate again and rename it to deleteBtn and change text to \u201cDelete\u201d. Now, select the mainScreen vertical arrangement and in its properties, uncheck the \u201cVisible\u201d checkbox.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, add another vertical arrangement onto the viewer. Rename it to addScreen. Make width and height fill parent. This is the concept of virtual screens. There is no need to pass data between two screens as we are technically still on the same screen.&nbsp;<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Drag and drop a horizontal arrangement onto this addScreen vertical arrangement. Make align horizontal and align vertical both center. Make height 15% and width: fill parents.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Add a label from user interface to this horizontal arrangement. Rename it to idLbl. And change text to \u201cID:\u201d.&nbsp; Add a textbox from the user interface on the right of the label. Rename it to idTxt.&nbsp;<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Select the horizontal arrangement, duplicate it and update it for Name. Do the same thing for city<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Duplicate horizontal arrangement again and remove the label and textbox from it. Add a button. Rename it to saveBtn. Give it the same properties as the ones that you gave to the addBtn. Change the text to \u201cSave\u201d. Select the button. Duplicate it and rename it to cancelBtn and change the text to \u201cCancel\u201d.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Drag a web component from the Connectivity palette onto the viewer. Also, drag a notifier from the user interface onto the viewer.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, select the addScreen arrangement and make it invisible by unchecking the visible checkbox.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Make the mainScreen visible by checking the visible checkbox.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Our screen design is done so let\u2019s go to the blocks section.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Make a global variable for sheetData (an empty list in the beginning)<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Another variable sheetName and set it to your sheetName (in my case, it is \u201cCustomers\u201d).<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Add a status variable called action (this will play a role in updating, adding, and deleting). Also, add a global variable for webAppURL and set it to your webAppURL that you had copied earlier.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXfTHWDw2hVkf6s5xCIBOEI-3bQSPjksbBinBiMqze84AtZNQbLD_IqbTuZLkH7cuEcVjFfPVW0XmDb9H2CCFD7xHwVhDIogCax18LMPoX5OZ3erOOzKLo5MUV37tff4LAKV04-pyQkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Get the screen1\u2019s initialize event.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Make addScreen visible to false and mainScreen visible to true. This is an extra step to make sure that the correct screen is visible when the app is started.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Click on the web1 component and get its setUrl block.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Set it to a join block with 3 slots. You can click on the cog wheel to add more slots.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Put the get block for webAppURL in the first slot. In the second slot, add a text block with this:&nbsp;<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\"><strong>?sheetName=<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">In the third slot, plug in the get block for the global variable sheetName. After this call Web1.Get.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdBxHqhw92-Jj1RWXUjXwqFzBoTo6FIkBGtlKsqyOca-bqDjBBeYYrFGF4NoR2Twy9Z5g8jW4t9-OBULGurgoiFvDxFyNb1L7YL_v4_euaJQiDtKzEsEpRpcdcDuilBRQNALb5_YQkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">In web1. gotText event, responseContent contains the response returned by the Web app. Make one local variable for responseDict. Use Web1\u2019s procedure JsonTextDecodeWithDictionaries to decode the ResponseContent and store it inside the local variable responseDict.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Web1.gotText event is triggered after get or post call to the web app so we need to differentiate between reading sheet data and updating\/adding\/deleting. Use an if\/else block from control to check if the value for key \u201caction\u201d inside responseDict is \u201cread\u201d.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXfy6bZIzv9OpsFZPQcw6l3M_Y0J08TqhcBhkBt4b9UnYd3ACnngbts_xFwfclpeN5eLeKp94R3-CabfWVmau9nt-dfe-YKzrH1rVr4Lu8sEC9Pq0qhZBZhwolS3bFVicg5DyDkjkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">&nbsp;If it is \u201cread\u201d then use a for each item loop from control to go through the value returned against key: \u201cdata\u201d inside our responseDict which is actually a list of lists. For each item (row) in this data, get cell data and join it all using \u201c-\u201d to make one long text item and add that item to the sheetData list.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXfCxEj_AbZ1rZmY0dhO1hNKbxpMhgBpUOBCLaiW9x2tu8QNiY6l39HZfVILmhx2JizW9pFa1_h636-ck6RSikQBhixqQ1wOKhNCsL03IN32gf0GLanGi5jP0B60pptAG195ZFjqkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">After the for loop, check if sheetData isn\u2019t empty. It will be empty if the sheet is completely blank (not even column names) or if there is some error. If it isn\u2019t empty, remove the first item from SheetData as these are the column names from the sheet i.e. ID, Name, and City. Then, provide this updated SheetData list to the listview\u2019s elements.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXcvnHI7w2wRX4Dy8Mfc5HJhSwb6E4YOLRH16tyaRM-6TX356ZrzVp2EDXH0aRVD1YGmMqYZAsMn1QYELSuJJ2zUAkH8u4ljlsQKFxM5nMjDhBZhiE-YglAiebPw3MGEgU9qPhEYkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">At the end of the if\/else block, add another if for checking for any message from the web app, and if there is any, use the notifier to show this message. So, our web1.gotText looks like this now:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXc-S60GvBVO_vQrN6cBqaAlQCpUxUvrNxTqNW6EBO4MBbcsyzNknChsM38Tz36Cb0Rkc6y79OEyJjBQeTdsPm9-dCf-4iGtVwkS6mom75Or8o7zretIqGzCx_pupaQXB2xjs4zOUwkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Try the app now and it should read the sample data from Google spreadsheet and show an error if we provide the wrong sheetName.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Before working on our add, update and delete, let\u2019s look at our web app script again. You can open it again by navigating to <strong>Extensions &gt; Apps Script<\/strong> in the spreadsheet menu.<\/p>\n\n\n\n<script async src=\"https:\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js?client=ca-pub-6094106103908730\"\n     crossorigin=\"anonymous\"><\/script>\n<!-- Tutorial Custom WP Ad -->\n<ins class=\"adsbygoogle\"\n     style=\"display:block\"\n     data-ad-client=\"ca-pub-6094106103908730\"\n     data-ad-slot=\"5828030452\"\n     data-ad-format=\"auto\"\n     data-full-width-responsive=\"true\"><\/ins>\n<script>\n     (adsbygoogle = window.adsbygoogle || []).push({});\n<\/script>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">We will call the function doPost from our MIT App Inventor app when we do any kind of updating in our Google sheet.&nbsp;<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Hence, you need to edit this if your column numbers in the Google Sheets are different from the ones that I have used.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Let me reiterate:<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">We have 3 columns: ID, Name, City. When we update, we don\u2019t update the ID, we just update the name and city.&nbsp;<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">So, let\u2019s look at the script:<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">In our update, we look for the row in the sheet where the ID is the same as the ID sent by our app. Then, we update the values in the following way:<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">&nbsp;\/\/ Update the name and city<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">sheet.getRange(i + 1, 2, 1, 2).setValues([[data.name, data.city]]);<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">This is what each value means:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>sheet.getRange(row, column, numRows, numColumns)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This method selects a range of cells in the Google Sheet based on:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\"><strong>row<\/strong>: The starting row number of the range.<\/li>\n\n\n\n<li class=\"has-medium-font-size\"><strong>column<\/strong>: The starting column number of the range.<\/li>\n\n\n\n<li class=\"has-medium-font-size\"><strong>numRows<\/strong>: The number of rows in the range.<\/li>\n\n\n\n<li class=\"has-medium-font-size\"><strong>numColumns<\/strong>: The number of columns in the range.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Our update starts from the second column so this is why the second value is 2:<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">sheet.getRange(i + 1, 2, 1, 2).setValues([[data.name, data.city]]);<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Our update updates a total of 2 columns i.e. name and city, this is why the last value is also 2.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\"><strong>A different scenario:<\/strong><\/h2>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">If I have a fourth column in my sheet such as age, my code would change to:<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">sheet.getRange(i + 1, 2, 1, 3).setValues([[data.name, data.city, data.age]]);<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">We start updating from the second column, updating one row and a total of 3 columns.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">If I had a column besides the ID that doesn\u2019t have to be updated. For example, I want to update only city and age so then, my code will change like this:<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">sheet.getRange(i + 1, 3, 1, 2).setValues([[ data.city, data.age]]);<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">We start updating from column no. 3, updating one row and a total of two columns.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\"><strong>If you make any changes to the app script, remember to deploy it again.<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Get addBtn click event. Make mainScreen invisible and addScreen visible. Set action to \u201cadd\u201d to differentiate between adding and updating. Also, empty the 3 textboxes so that if we come to this screen again, the old data isn\u2019t there anymore. Moreover, enable the idTxt as we will be disabling it when we use this screen for update.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXcU4k0tT8pRmAUtlq3m8EaxxyYSxuMhkqtb-saMhaQqBFrww6_pMhT1ck6v_HS1-F-mc_U9P4x1A3tSP-3qkTH9ACaUzcVEg7-Z6c2LdpZW4a9xs1FjrvchURcdIAM1jCo-dVRqGwkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:567px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Get saveBtn click event. And set Web1.url to the webURL global variable.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdktzGrBWkBp7nQIkC25mQIvQ5jz0zRyxYw-CWLm6HM3cOOeAg5yrlsmpx5QM46m6o_K-0BNR5I4TR2BH-O3av4XOsf4yCjYcwfmP_i3p7JdXLZYuMk6CyRl7ES8VXGUErABQYK6wkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:624px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, call Web1.postText procedure and we will provide it a join of 11 things that you have to construct very carefully to avoid errors.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li class=\"has-medium-font-size\">{&#8220;action&#8221;:&#8221;<\/li>\n\n\n\n<li class=\"has-medium-font-size\">getaction block<\/li>\n\n\n\n<li class=\"has-medium-font-size\">&#8220;,&#8221;sheetName&#8221;:&#8221;<\/li>\n\n\n\n<li class=\"has-medium-font-size\">getSheetName block<\/li>\n\n\n\n<li class=\"has-medium-font-size\">&#8220;,&#8221;id&#8221;:&#8221;<\/li>\n\n\n\n<li class=\"has-medium-font-size\">idTxt.Text<\/li>\n\n\n\n<li class=\"has-medium-font-size\">&#8220;,&#8221;name&#8221;:&#8221;<\/li>\n\n\n\n<li class=\"has-medium-font-size\">nameTxt.Text<\/li>\n\n\n\n<li class=\"has-medium-font-size\">&#8220;,&#8221;city&#8221;:&#8221;<\/li>\n\n\n\n<li class=\"has-medium-font-size\">cityTxt.Text<\/li>\n\n\n\n<li class=\"has-medium-font-size\">&#8220;}<\/li>\n<\/ol>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Our final saveBtn click event looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXeFg-jF4TI7g1Vs1jRriQ6imPqwNKDbX6dmERGNVJzRKMu3stSKABOKXPU_dnaAp5R_BpFkIRr3rRQwmhi13m1VZ4peq-LqL0NERWNsdjo8_wHqqhwb99IMKAHKIewLq8xhbLRs1QkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:620px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, let\u2019s go back to our Web1.gotText event. The event is triggered whenever we get any response from the Web app after a call such as Web1.get or Web1.postText.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">So, it will also be triggered after the save button is clicked.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Click on the cog wheel for the first if\/else block in Web1.gotText event, add 4 else if to it, and remove the else.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXf6EiAC5WHD0mrDQ-NiGr0MEOKn4cgCtNdv5GwqgE1JPJPGiBqt2M7cs7azBaj4wkdCEnbygEZuwYOqpOVIKer8s7BFHuqa7eNUydk6EKEeghnZ5l521adC8sqsBeZPNGOL3H36NAkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:640px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, in the first else\/if, we will check if our value for the action key is \u201cadd\u201d and the status key&#8217;s value is \u201csuccess\u201d in our responseDict.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXeHamhfgdwE598W3rgtQ7jyOATW54pCdW2ONbtFwEGNqfoTTN4Is5uwDf6TPh1q5oIIX08IgeEbU31I-_eA9OHk2LfYOT5ozQt5AKT1apDUbnTZeQfFHqTaET3keRlyB3JXTP2F5gkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:644px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">This means the add was successful, so we will add the item to our sheetData, update our list view\u2019s elements, hide addScreen, and make mainScreen visible..<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdcYUsoixQjVu2XwBMjKOS-ZbqeY6Iksc0t4waJW5MhHOn_hQUrZLSScMQVodsmBhjeEA-uDG4rUq-Cj6NAVkMVaoa-FEV5ZTsNX4S2cbLwLnpCACi6mQ2EFEpHwQ-TFjErNphdCgkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:643px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, let\u2019s work on updateBtn click event. In this case, we have to first check that the user did select an item on Listview before pressing update button. If he did choose then the selection index will not be 0. After that make the update screen visible while hiding the mains screen. Disable the idTxt so that the user isn\u2019t able to update the id and set the action variable to \u201cupdate\u201d so that our web app can differentiate. And most importantly, populate all the text boxes with the selected item\u2019s data. Remember that we had joined everything with \u201c &#8211; \u201c so have to split the text using it to get all individual cell items back.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdGxRCC0_22eCD65G4XeckBAZl4vL1BCXzsgnUvum5yyPrMxUHM6bchw3o9462NKAqd_Xkp_5hPsOWfbFCka1JTXzW1HOsHU0Bk2zCm0MjF8bnAxXseWS5Z04fJdzL52tuW9V397gkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:607px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">The save button code will stay the same but remember the cancel button. If the user cancels, just go back to the previous state of hiding addScreen and showing the main Screen.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdeYyH-pPhBybkLPEQbo0_-vrwsoGJsiJLe-cb_KEZwPMwoPllbmG14JaovhOpf2GNnpWDef2Gmhu1OV_pkgBN5IhrNEXJZ-s-eY1T7QLr4AkVlZSmJJ1vM5SE7cvsyyT1NsZLukeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:585px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">In our web1.gotText event, let\u2019s handle the update scenario.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">For the next else if, do the following. Here, instead of adding to SheetData, we just replace it with updated data.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXcOI0Re5rnta1Ytnn2osLuzizXhVfrOA2kl5Ndy7OuUGNSwXPgTHvbb5Ku_alnTRvVKE-8JP63kTjCVxqBxF0P_VFIFAYZ1iw5KJSdGDO_8Ss1K9THMaHRnxo_FR8sMklOXtXDrYwkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:746px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Now, let\u2019s come to the delete button click event.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Again, we need to check that something was selected from the listview before pressing the delete button. We set the action to \u201cdelete\u201d to inform our web app and we also again get individual cell items back and we call Web1.postText but this time we don\u2019t send the name and city but just the ID.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXf3FSwfx8MFbS1XxgBpzShUz6OZUpscB8F1d5jYNIXz4bSg6IFYnox94fpa_qQjqxtkKgl4M9-J5Zq6UXhtdqI9VP1Beto9fsM9fcEebpFXRDS8KHVwiwpJD548pYbtrEJzjJ-FiwkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:627px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">In our web1.gotText event, let\u2019s handle the delete scenario.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">For the next else if, do the following i.e. delete the data for selection index from sheetData and update listview\u2019s elements.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXcln0W4-gYJqRYJ4Lmc0sMu5m-ntYbcxjMoc17HqG0umjMmXE6eobVpVH5ZSJXAClCRhaYCR9ibLuZwplE6-Oodr6tHCcGijWjce2jGWKokejVKhlGeS5ubJkF_0D50Trx8nME2keyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:657px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">The last else if is for the situation when there is any error:<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXf6aG-HVTmGgvVMl-_PGID89P_LzuMzsE0S3nurlbvyfu8EO2OAUnkH4TsjbP8PC8NAoYxEvxH25aEusE_9Sd8XhmmmmMYBZJdmy7u9Z7mDqgP93vptOJliczqnDkXuyHz4Fn7vcgkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\" style=\"width:616px;height:auto\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">In this situation, just make the default mainScreen visible and hide addScreen.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">So, our final Web1.gotText event looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2025\/01\/AD_4nXdlT9pYCSOFfab5V_3AMUx0y0cVwcLpiUUv7AtTJ2ffF_1P9aGqV_2Z3x2VhVXnq3GFT8I2gG718PEGY4Mz9UrjI0Xg_LjODoz0RD_HkUau38Ba3k4PRK4IGWdhfdnSDYIfIHuQkeyKEzxRLdkJSQ2v3NKxoPMfSPG.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">By the way, while making this tutorial, I thought that I should cover automatic ID generations similar to SQL databases to avoid duplication of IDs. If you are interested, do comment to let me know.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">So, this is done. You can check out the two video tutorials for updating and deleting google sheets in MIT App Inventor below:<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<p class=\"responsive-video-wrap clr\"><iframe loading=\"lazy\" title=\"App Inventor Google Sheet Tutorial  P1 - Read and Update Google Sheet MIT App Inventor #appinventor\" width=\"1200\" height=\"675\" src=\"https:\/\/www.youtube.com\/embed\/4HACaophVto?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<p class=\"responsive-video-wrap clr\"><iframe loading=\"lazy\" title=\"App Inventor Google Sheet Tutorial  P2 - Read and Update Google Sheet MIT App Inventor #appinventor\" width=\"1200\" height=\"675\" src=\"https:\/\/www.youtube.com\/embed\/PLZoJWz5Ykg?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<\/div><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">If you like my tutorials, consider supporting me:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><a href=\"https:\/\/obsidiansoft.gumroad.com\/l\/cxdft\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"372\" height=\"196\" src=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2024\/12\/donate-button-1.png\" alt=\"\" class=\"wp-image-5381\" style=\"width:270px;height:auto\" srcset=\"https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2024\/12\/donate-button-1.png 372w, https:\/\/obsidiansofteducation.com\/wp-content\/uploads\/2024\/12\/donate-button-1-300x158.png 300w\" sizes=\"auto, (max-width: 372px) 100vw, 372px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Don\u2019t forget to subscribe to my channel if you like my work so that you don\u2019t miss the great projects that I have planned for you. Thank you for watching. Have a good day and goodbye.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Check out my other written tutorials for MIT App Inventor&nbsp;<a href=\"https:\/\/obsidiansofteducation.com\/index.php\/mit-app-inventor-projects\/\"><strong>here<\/strong><\/a>.<\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Please like my social media pages for more educational resources and tips.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Facebook:<a href=\"https:\/\/www.blogger.com\/blog\/page\/edit\/4947000819484484884\/7140650632339107612#\" target=\"_blank\" rel=\"noopener\">&nbsp;https:\/\/www.facebook.com\/ObsidianSoftClasses<\/a><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Instagram:<a href=\"https:\/\/www.blogger.com\/blog\/page\/edit\/4947000819484484884\/7140650632339107612#\" target=\"_blank\" rel=\"noopener\">&nbsp;https:\/\/www.instagram.com\/obsidiansoftapps\/<\/a><\/p>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">Pinterest:<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-pinterest wp-block-embed-pinterest\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"oceanwp-oembed-wrap clr\"><iframe loading=\"lazy\" title=\"Obsidian Soft\" src=\"https:\/\/assets.pinterest.com\/ext\/embed.html?grid=obsidiansoft&#038;src=oembed\" height=\"900\" width=\"450\" frameborder=\"0\" scrolling=\"no\" ><\/iframe><\/div>\n<\/div><\/figure>\n\n\n\n<p class=\"has-medium-font-size wp-block-paragraph\">For links to free educational apps, have a look at the&nbsp;<a href=\"https:\/\/obsidiansofteducation.com\/index.php\/mobile-apps\/\">educational apps page<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello friends and welcome to Obsidian Soft In my previous tutorials on Google Sheets, I showed you how to easily write to a Google sheet using forms and also read the entire sheet into the MIT App Inventor app. This was a simple and easy approach that came with limitations. We couldn\u2019t update the rows [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-6043","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/pages\/6043","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/comments?post=6043"}],"version-history":[{"count":2,"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/pages\/6043\/revisions"}],"predecessor-version":[{"id":6074,"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/pages\/6043\/revisions\/6074"}],"wp:attachment":[{"href":"https:\/\/obsidiansofteducation.com\/index.php\/wp-json\/wp\/v2\/media?parent=6043"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}