Can I show the results of COUNTIF in one column only if there is data in another column? - google-apps-script

I have a spreadsheet with multiple sheets.
Sheet A is generated from a template, and it is where users will enter in data to be formatted into a report; it will be deleted after that report is submitted.
As people enter info into Column A of Sheet A, they don't have to enter client information if we already have them entered in this spreadsheet, but otherwise they need to go over to Sheet B and enter it in.
To make it easier for them (so they don't have to check every time, or go back and enter info later after getting an error generating the report), I have used conditional formatting. The way it works is, column Z is set up as a helper column, and uses a "COUNTIF" function to check if the client ID in Sheet A, Column A is found in Sheet B, Column C. Sheet A Column Z returns 0 or 1 (or, theoretically, more than one if we had duplicates), and then Sheet A column A has conditional formatting based on Column Z's value-- if the client is already in, the cell for client ID turns green after they type it; if not, it turns red.
It works great! However, I am adding scripts to these sheets, and looping through them. This helper column is filled from Z1 to Z1000, which means I can't use sheet.maxRow() to get the last row.
I see plenty of workarounds on the script side, but I was wondering if anyone has a clever way to input a value into the helper column Z ONLY IF the corresponding cell (same row) in column A has a value using spreadsheet formulas.
I suspect that an array formula with a filter might do it, but I have little experience with either and can't get anything to work out.
Thanks for your help!

You can use this expression with INDEX, MAX and ROW to make an ARRAYFORMULA only expandable until the last cell with value in column:
A2:INDEX(A2:A,MAX(ROW(A2:A)*(A2:A<>"")))
It will go from A2 to the maximum number of row in A in which A is different than null (that's why both conditions are multiplied).
Then you can set a formula like this in Z2 (check the ranges in case something is not right from reading your text, and delete all other formulas in Z too in case you weren't using an arrayformula already):
=BYROW(A2:INDEX(A2:A,MAX(ROW(A2:A)*(A2:A<>""))),LAMBDA(each,IF(each="","",COUNTIF('Sheet B'!C:C,each))))

Related

Google sheet auto populate row script

I am using a google sheet in which a new row is added by inserting Col A thru a third party app. Once Col A is added I wish to copy the formula from the remaining row cells above to auto calculate the values using the formulas in that row.
ArrayFormula doesn't help as I don't want to have the rows created in advance before Col A is populated.
Any script which can do this?
What you are looking for can be achieved with a formula. I have created a quick sheet to demonstrate this.
Cell B1 contains the following formula:
={"Formula";ifna(arrayformula(filter(A2:A, A2:A<>"")*5))}
This formula defines the header (meaning that it is placed in the first row, ultimately not affecting any third party data inputs), and then uses an array formula for the rest of the column. This formula works because of the filter. That filters out any cells that are not blank and multiplies them by 5. The IFNA portion ensures that if there is no data at all, the second row is still left completely blank. This was verified with a script I wrote to simulate a data entry.
function test() {
SpreadsheetApp.getActive().getActiveSheet().appendRow([Math.random()]);
}
This script is simple, and uses the appendRow() method to simulate what a third party entry would do. I used this script, and the result is displayed in the screenshot above. This shows that an appended row will still populate the next blank row, despite there being an array formula in cell B1. Using this logic, it is possible to change the formula to populate the actual data that you need.

Setting array formula until last column in Google Sheets

I have a formula as follows in google sheets:
=ARRAYFORMULA(IF(LEN(F2:F),IFERROR(SPLIT(REPT("PAID ",F2:F)&REPT("- ",(24-F2:F))," ")),))
This formula will show paid according to number of paid in the cell and show "-" to the cells in the rest column. For now, this formula is only applicable for columns. I dont want like that, I want this formula to be used until the last column because the number of columns will be increased every year. I dont know whether this should be done in Google App Script or what. Anything should be fine to solve my problems. I have attached some images to explain myself clearly. Thanks in advance.
https://docs.google.com/spreadsheets/d/1bM8l6JefFsPrlJnTWf56wOhnuSjdIwg3hMbY1tN1Zp8/edit#gid=1775459006 - Link to google sheets
I will use the sheet "JALAN SANGGUL 4" as an example. Then you will need to apply to all of the other sheets that have the same structure.
Replace your current G1 formula with this:
=TRANSPOSE(FILTER(Configuration!P2:P,Configuration!P2:P<>""))
Replace your current G2 formula with this:
=ARRAYFORMULA(IF(LEN(F2:F),IFERROR(SPLIT(REPT("PAID ",F2:F)&REPT("- ",(COUNTA(FILTER(G1:1,G1:1<>""))-F2:F))," ",1,1)),))
The added FILTER in each constrains things to only areas where data exists. By counting where only data exists instead of using a set "24" in the second REPT clause, you'll always get dashes going only as far as there are months in Row 1.

Script to randomly pick from a list if cells match specific value

Looking for a basic script that will trigger if cell A1 AND B1 contain a specific text, it will return a value (name) from a random pool of entries and display it in cell C1. My goal is to create a chart, pick to values in A and B and depending if specific values match, pick a random entry from a list and display it in C.
I was trying RANDBETWEEN + CHOOSE which technically works, but every other action in the spreadsheet will automatically generate a new random and re-trigger all the randoms, altering the whole list (since it's volatile) which I don’t want to happen, I’m open to suggestions from any other formulas that might work.
Thanks a lot.
There is a way to restrict re-evaluation of random functions only when specific cells are edited. Namely:
Create another spreadsheet, call it S2 to distinguish from the original spreadsheet A1
In S2, enter importrange referring to a cell or range of spreadsheet S1
Also in S2, enter any random number formulas you need: rand, randbetween, etc.
Back in S1, enter importrange that imports the output of those random formulas.
Result: the random values will get re-calculated only when the range of S1 in item 2 changes. Entering data elsewhere in S2 will not trigger recalc.
A script is a possible solution, but takes more work: you'd need to use the onEdit trigger to run a function on every edit; the function would need to check if the edit
Custom functions are only recalculated when their arguments change. You could use this feature to prevent that the result changes.
To force a recalculation you could
Delete and reenter the formula
Use a control argument that you changes every time that you want that the formula result be recalculated.

Find answer for data in A in predefined list of answers - VLOOKUP - Google Spreadsheets

I've got a google spreadsheet with a main sheet tab. column A contains a bunch of company names, some of which repeat, and are included multiple times. In column B i want to have a predefined unique code for each company. For instance if I had a company name Nike in a10, a14, a21 I would have the same code each time in b10, b14, b21.
I was initially looking at if / else blocks and switch statements (not sure if google spreadsheet can even do them) to accomplish this, but they would become massive and unmanageable as single line pieces of code will involve several hundred company names.
Instead I've setup another tab called Codes Data with a predefined list of all of the company names in column A and the code in column B. This list will be added to over time.
What I'm trying to do is have a formula in the main sheet column B that will check the value of the corresponding column A cell, find the unique code for that company in the Codes Data tab and place that code in column B.
I started using VLOOKUP for this and at first it seemed to work, but now I'm getting inconsistent results (i.e. its outputting Addidas | am-1121 and ACMECO RESTAUR | am-1121 where according to the Codes Data sheet it should output Addidas | ad-5426).
I've provided an example spreadsheet here : https://docs.google.com/spreadsheets/d/156Lla5IyLjB-hp7s50jpotC1qcaov9RdFkpUzATe710/edit#gid=458436476
Is VLOOKUP the correct function to be doing this? If so, how can I use it more properly, and if not what would be a better approach?
You must add FALSE to your lookup formula, or it won't work:
=VLOOKUP(A5, 'Codes Data'!$A:$B, 2, FALSE)
Use the Help menu, and choose "Sheets Help", and then type in "vlookup". You'll get the documentation:
is_sorted - [OPTIONAL - TRUE by default] - Indicates whether the column to be searched (the first column of the specified range) is sorted.
If is_sorted is TRUE or omitted, the nearest match (less than or equal to the search key) is returned. If all values in the search column are greater than the search key, #N/A is returned.
If is_sorted is set to TRUE or omitted, and the first column of the range is not in sorted order, an incorrect value might be returned.
If is_sorted is FALSE, only an exact match is returned. If there are multiple matching values, the content of the cell corresponding to the first value found is returned, and #N/A is returned if no such value is found.

Google Spreadsheet Populating Cells in Other Sheet Based on Value

Am new to Google Docs, but have to create a cumulative report of comments that are flagged as positive or negative. I have 6 worksheets that ideally would populate to a single report, but I could create 6 individual reports for now.
In the source sheet, ColA is a numeric code identifying the category. Col B is the category description; Col C are the notes from one person; Col D is the code to identify it as positive or negative; Cols E and F are the notes from a 2nd person; G/H from a 3rd, etc.
The report sheet needs to transpose the vertical comments by category with the positive comments for all persons for the first category in Col G, the negative comments for the 1st category in Col H, etc for all 6 categories.
I was able to manually create this report using the following formula to extract the Positive comments from column C:
QUERY(EntrySheet1!C5:D15;"select * where D='P'")
But, it's pretty tedious to copy the formula laterally and vertically to accommodate all 6 categories and all 6 note takers.
So, my questions are whether or not there is an easier way to extract the information the way I need to report it. Also, is there a way to use something like Excel's Indirect function where I could use the concatenate function to build the formulas and the Indirect to evaluate that function. My thought here is that I could have an entry cell where I would identify which cumulative report I wanted to view by simply updating the cell. An alternative would be to load the data into an array and use a script to populate a static cumulative report. Real-time updating with formulas would be ideal, but creating a static report that is created from a script is acceptable. My biggest concern is the manual effort to update the formulas since they are sheet specific.
Use Google Spreadsheet INDIRECT function.
See the Google spreadsheets function list:
INDIRECT(reference)
Returns the reference specified by a text string. This function can also be used to
return the area of a corresponding string. Reference is a reference to a cell or an
area (in text form) for which to return the contents.
You might be able to feed the results of indirect into your query.