At the moment I have a worksheet with Prior Students Names and ID#. There are at the moment about 3000 records.
In a second worksheet I have new names listed (which are entered via a form).
At the moment I am using the following to check if there is a prior record:
=IFERROR(INDEX(Students!A:A,MATCH(K2, Students!B:B; 0)), "NEW STUDENT")
But the spreadsheet is getting quite slow.
Would a google script be better? And if so how?
Thanks
You can try a different formula. For example, in this example spreadsheet I have added 10,000 rows of fake data, in Sheet1. I have joined the first name column with the second name column in a cell, in Sheet2!A1, as below:
=arrayformula(join(";", Sheet1!B:B & " " & Sheet1!C:C))
Then I can perform a text search for a new name into this long string. Eg the following:
=find("Peter Piper"&";", Sheet2!A1)
It is fast.
"Better"? That's just too subjective. Let's only talk performance.
You should be able to write a script that will perform these specific look-ups much faster than your current spreadsheets. The dominant factor is the number of calculations being performed;
Spreadsheet formulas are recalculated every time there is a change in the sheet. So your "new student" checks on students that you already have in the second worksheet are wasting time.
A form submission trigger function would ideally do the lookup in response to a form, and only for the new student data.
A script could use ScriptDB to store all the Prior student names & ids, thereby eliminating the need to read the Prior student spreadsheet over and over, and providing fast lookups.
...
var db = ScriptDb.getMyDb();
var result = db.query({id: newId});
if (!result.hasNext()) {
event.range.offset(0,statusColumn).setValue("NEW STUDENT");
}
Counter-points do exist, here's just a couple.
You need to write javascript code, rather than spreadsheet functions. It's a different skill set.
If you're using ScriptDb for performance, you need to include some maintenance capability; at the very least, you need to load the database the first time.
May be this will work
=dget(Students!A:B,Students!$A$1,{Students!$B$1;$K$2})
given k2 is the search text.
if you get #na!, you get new student. if #num! then you have multiple match. dget is a database function. Thus it can handle large data quite well. however it is not as flexible but efficient function.
Related
I have a workbook that contains a comprehensive list of Test Scenarios my developers are responsible for. In the workbook I would like to create a "generator" that will return a complete list of tests that need to be completed based on a specific criteria.
Criteria List. When a specific answer is selected on Sheet2 it correlates to a specific column on Sheet3, and I want to populate all rows associated with that answer AND remove duplicates onto Sheet1.
For example If B2 in Sheet2 is Yes, then I want to return all rows from Sheet3 where YES appears in Column D but if Sheet2!B2 is No, I want to return all rows where No appears in Sheet3!D.
I can successfully queue an individual line/criteria using ARRAYFORMULA(IF(TestCaseGenerator!B2="YES", IF(Disputes1!D:D="YES",Disputes1!A:M,""),""))
But I have tried several =ARRAYFORMULA, =IFS, =QUERY combinations and as I stack the criteria the formula breaks; I get one of two errors:
a parse erorr and as of yet cannot determine where exactly the formula is breaking down
Not enough arguments
I know a script may be a better option, but have not written many scripts and am unsure where to even start.
I have a google spreadsheet which we use to feed inventory purchase and issue data. The only problem is my staff can manipulate purchased quantity, prices and other variables at a later date. I want that if they enter data in a cell, they cannot edit it post-midnight but I can.
Also, I have filled most of the cells with formula, for example- there is formula in A1:H999, so that when they enter data, it calculates the values in other cells, and suppose my staff has entered data till A1:H500. In this case, the script should work On A1:H500, it should not consider the whole range just because i have filled it with formula. Thanks
If you want to limit access to the script to particular hours it's fairly simple. This can be done with one function if written in a clever way or with 2 functions.
Function1 will simply lock the spreadsheet and allow only you to edit by using the protection class, then use function2 (or write function1 in a clever way to do different things depending on when it starts) that is triggered at a different time to remove that protection.
I'm writing a script for an insurance agency that will work like this:
When an employee makes a sale, they enter information about each policy they sold (name, policy number, etc.) in their own Google Spreadsheet, one policy per row.
Script takes spreadsheets from every employee as input and writes them to a table in database.
When policies get paid, they get written to a separate table.
I use an OUTER JOIN to see which employee sold each paid policy.
The issue I'm having is that in step 2, I don't want to write policies to the database that have already been written (i.e. because they were there last time I ran the script). I can think of a few ways to solve this...
Clear the table every time I run the script, so it's being written fresh every time.
Loop through and check if a given policy is already in the database before writing it to DB.
Add a boolean column called "copied to DB", when adding rows to DB check if "copied to DB" is equal to "Yes": if true, don't write the row to DB; if false, change "copied to DB" to yes and write the row to the DB.
I think any of the above methods would work, but they all seem pretty inefficient. Is there anything in SQL or Google Apps Script that would do this more efficiently and minimize database writes?
Currently, the way I'm doing step 2 is I'm copying all the employee sheets to a single "master sheet" that contains all the employees policies, and every time I run the script I clear the master spreadsheet and then copy all the data in, so there are no duplicate rows. This is basically equivalent to method #1 above, but again, it seems like there should be a better way to do this than clearing the spreadsheet every time. (And I'd rather use a database table than writing all the data to a spreadsheet.)
Thank you!
Its easy if the spreadsheet rows are 1) always appended, 2) never changed or deleted.
Loop for each spreadsheet:
Remember in a script property the last row written to the db (one property per spreadsheet, base the script property name on the spreadsheet id).
Start from the row after that last one, write to db and afterwards write the property.
Make your db row primary key something like 'spreadsheet id + row number', and use 'insert or ignore' or equivalent. This is a must for integrity as a script could fail after a db write but before writing the script property for that spreadsheet.
I have a popular chrome extension that does this well for thousands of users.
Here is my issue. I have a spreadsheet with multiple sheets, and each sheet has about 300-500 rows. I am using ScriptDb to store the data for each sheet.
What I am currently doing is calling a custom function in 300-500 cells in each sheet to populate certain cells with data, and what happens is that some will populate and the rest will error out saying i've queried the database too many times in a short period. Obviously having to query the database for each cell isn't the best solution.
How would I go about querying all the data for the current sheet and then having that data available to grab for each cell. What I've read is that you can't really have "global" variables in GAS, but have to use things such as CacheService or ScriptDB, which is what i'm trying to do. I'm just querying it too much.
Is there some way to populate all the cells from 1 function call instead of 1 call for each cell? What am I missing or what other solutions are there?
Just realized a similar question was asked earlier today: Google Spreadsheet Script invoked too many times per second for this Google user account
Yes its possible. Simply return an array from your function. It will work like an arrayformula.
Of course your cells would need to be contiguous.
I have a two-part question about master/child relationships in workbooks. I have beginner experience with writing code for excel & google spreadsheets so any extra detail would be truly appreciated.
Here is what I'm trying to achieve:
I want to make a google form to collect a set of data for (potentially 100's of people). The option to make changes to the form after submission will be enabled, so the data flow will be pretty dynamic. I've gotten as far as setting this up and creating the master spreadsheet where I can view all of the responses. But there's too much information in one spreadsheet and I'd like to make some child-workbooks to simplify the viewable data for various needs. So here are my questions:
1) How would I write the script to create a child worksheet from the master worksheet with these conditions: on run create a new worksheet called i.e "Child 1-Basic Info", delete all the columns and shift left with the exception of the ones I explicitly want to keep (based on the cell value) i.e "Name", "Age" & "Interests". Bear in mind I would want to eventually create multiple children workbooks, but basically do the same job each time. Just different column parameters i.e "Child 2-Education Info".
2) Along with this, I want to make sure that these children will be automatically updated every time someone submits a new response from my form or updates one they have already submitted. Essentially, the goal is to have any changes in the master ripple into all of the children. Also keep in mind that every time someone submits a new form, the row numbers will change. So the children will need to also recognize this change and update accordingly.
Thank you all in advanced!
With the QUERY() function, you can have secondary sheets that will dynamically update, with no need to use scripts at all. See more here.
Here's an example, a spreadsheet with rows of form-submitted data:
On a secondary sheet in the same spreadsheet, cell A1 contains a query formula that selects only the columns you asked for, "Name, Age, and Interests".
Every new form submission or update will result in recalculation of the query, so it will be kept up-to-date with no further intervention.