Background:
At my (new) job, we have a number of Sales Reps who book gigs for our organization. Until now, they handle all of their sales tasks in our CRM (Pipedrive [PD]). They then use that information to create an "activity" (event) on PD's calendar, which is set up for two-way sync with our general work Calendar (Outlook [OL]).
Problem:
Between the number of different Reps who edit the PD Calendar, the variety in bookings for our org, and just general human error, our Calendar system is a NIGHTMARE. Formatting inconsistencies, typos, lack of necessary information, and even straight up wrong details make my job (creating a program around, and then organizing the talent for each booking) nearly impossible.
"Genius" "Solution":
Even though it's a mess, I hate the type of person who comes into a new position and instantly tries to make changes to a system that has (somehow) worked before their arrival. So instead I sat down with the reps, learned what their needs were for the calendar, as well as their process, and built a system that not only gives me what I need, but also cuts the busy work on their end in half.
Previously, they not only entered into into PD, and then manually created the events, they also created three separate supplementary Word files that documented the details, created a detailed schedule of events, and outlined contractual needs based on the type of event.
So to solve all of this, I created a Spreadsheet (SS) Template that had all the fluff prefilled, was able to fill in all the contact info from an external contact database, and fill in the entire event schedule based on "type" and "start time". So basically they just need to enter in "Where", When", and "What", and the SS would auto populate the rest.
How that benefits me, is I then painstakingly scoured YouTube, Reddit, and Stack overflow for information on how to build Scripts for Google. And managed to make a function that can pull all the information from their new fancy form, and automatically create a 100% accurate and consistent Event for me.
Everybody wins, right?
New Problem:
Due to things well beyond my current knowledge, I am unable to create a dummy proof way for the event to "Trigger". I know it has to do with user permissions, and the limitations of Simple Triggers yada yada, but I'm incredibly annoyed that I managed to eliminate so much busy work, entirely solve my problem in the process, and yet the thing blocking me in the end is that I have to actively go to my Script and hit "Run" for it to properly function.
(For any "Expedition Force" readers out there, this feels a lot like how for so long Skippy could program intricate FTL Jumps across Spacetime, but still needed a "filthy monkey" to push the "jump" button)
Relevant Additional Details:
As I said, we use Office, but we're likely switching to Google down the road (and as someone who works in the arts and has been a poor student/struggling artist for the last two decades, I am much more versed with Google than Microsoft. I've also rarely found anything of value within my needs that one could do that the other couldn't, so I've built this whole system in Google Apps Script. However, if someone finds a potential solution where this will work in Excel with VBA instead, then I'd learn to translate what I've written so far.
Also, the Script works. I can make it work 100% of the time via the Apps Dashboard (where they don't worry as much about permissions), so it's not a problem with the code itself, which is why I haven't posted it here (but I can if anyone has a reason to think it's relevant).
It is a frequent need for our Reps to go in and edit the gig (people get sick, availabilities change, or mistakes were made the first time, etc.), so to combat this, I've actually written two Scripts. The first is a "Create" script which takes all the information, creates an event, and then pulls the EventID # which it pastes in a safe cell on a different tab. The second is an "Edit" script which searches for the previously created event by ID, and then makes the changes as needed.
In addition to PD and Office, we also use Monday.com and have a Zappier account. But I'd rather avoid either of those if possible since they have apparently changed software packages every other year before I got here, and we are in the middle of a search for a new Executive Director, so I'd rather not have this whole thing come crashing down because one minor part of it depended on Zappier, which our next ED cut from the budget, ya know?
Potential Solutions:
I can make the whole thing run via their Installable Triggers. However, I find them limiting:
I can do it by "Open" which creates the event every single time the SS is opened (which is both obnoxious AND useless, since the edits happen AFTER it is opened).
I can do it by "Edit" or by "Change", but again this just creates a whole new Event every time. I even tested it and made three random edits on empty cells in a useless tab, and it made three identical events to match the first (although this could be a solution for my 2nd Script...). I wish they could do onEdit of specific Cell, because THAT would be useful.
I can do it by form submission.. which means I can instead make a form that they fill out that creates the whole doc, and after they submit, it creates the doc AND event, but this limits the idea of having a different SS for every contract.
And lastly, which I really want to avoid, since I don't trust the Reps who manage to spell the same name wrong three different ways in three different places with having to open Scripts and hit "run", I could create a macro that notifies ME whenever changes are made, and then I could go in and manually hit the button. But..... Is that REALLY the best solution?
I know that's a lot, but I'm more looking for creative coding ways to solve a general problem, rather than a specific fix to a single string. Anything that could make what I want happen, without making me do annoying extra steps, or without requiring me to trust others with a keyboard, I am open to suggestions!
You would benefit from more research on triggers gerenally, onEdit in particular. It is broadly true that onEdit is triggered "when anything was edited" but the script can be written so that it evaluates specific rows &/or columns &/or cells &/or sheets &/or values. It can do this by using Event Objects which involve including an argument (often the letter "e", or the word "event"). The Event objects provide a lot of information about the nature of the edit.
For example, if you had a checkbox in sheet "Sheet2", column D, and you wanted to trigger something if the checkbox value was changed to "checked", then an onEdit(e) script might include an IF statement such as:
if(e.range.getSheet().getName() == "Sheet2" && e.range.columnStart == 4 && e.value == true){//do stuff}
In the scenario described, an automated trigger might not be necessary - a user might select a row (or a cell in a row), and click the "Button" in order to execute the script. However, it might be desirable to "check" a checkbox so that there is no doubt about that row has been calendarized or not. The advantage of this is that an event is not calendarized twice.
The following script might be an appropriate example:
function buttonTrigger() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheetName = "Sheet1"
var sheet = ss.getSheetByName(sheetName)
// get the row to be calendarized
var row = sheet.getCurrentCell().getRow()
// Logger.log("DEBUG: the cursor is on row is "+row)
// check is this row is already processed
if (sheet.getRange(row,4).getValue == true){
// this row already processed
// insert abend code
return
}
else{
// this row is OK to update
// insert script to calendarize event
// update checkbox to show event is updated
// checkbox is in Column 4
sheet.getRange(row,4).setValue("true")
}
}
Example
Creating a button and assigning a script
There is a good explanation of this process in StackOverflow topic Run script only on click on button instead with open the sheets
This is a probably convoluted process in data collection. Any advice on how to best do this will be appreciated.
I am working on data collection and I am trying to clean it real time. The data is set up such hat each RA has their own tab on google sheet to put in observations. Then I have this master sheet that queries from all the RA tabs to create this master data. The master sheet can tell me which are duplicates and which of those duplicates have a better quality of information.
Doing a master data using query does not allow me to edit on it, for some reason. So, I copy and paste as value to another tab. I use the master tab to analyze any duplicate information. Ideally, when I clean the master tab and delete the lesser quality duplicate, it also deletes from the RA tab it originated from. How do I do this? Is this the best way of doing this? In a similar fashion, if I would like to edit in the master sheet and also have that row to be edited in the original tab.
I created a trial sheet to practice with.
https://docs.google.com/spreadsheets/d/12XhUzH_v565C8fll_JwjloU0E12XmVarXesrUY83D-4/edit?usp=sharing
I have been doing this manually and wondering if there is a better way. I am open to using google apps script but I am still a new at that. I am thinking of using onEdit function but I do not know how to test my code or how to know what is in e.
The data is set up such hat each RA has their own tab on google sheet to put in observations.
One easy solution would be to keep all the data in the master tab, have everyone edit that tab only, and use filter views to give every user their own private view so that everyone only sees "their" rows. This feature lets multiple simultaneous users sort, filter and edit the sheet without disturbing each other.
For additional ease of use, you can insert links in the frozen section of the sheet to easily switch between filter views, instead of having to go to Data > Filter views to switch. See the Filter views example spreadsheet for an illustration.
I’ve created a Google Sheet – kind of like an app – using script. It’s a number of blank cells where once added some information, it creates a string with that information in the right order. I created this to help some colleagues. We are using free accounts.
I face 2 problems:
The app is supposed to be used by only one person at a time, but I’m sure at some point two or more people will want to use it at the same time. Is there a way to allow this without they interfering with each other? I’ve read you can share a link that creates copies of your doc, but that wouldn’t work in this case because I intend to keep updating it regularly.
The changes people make to the sheet will stay there. Right now I have a onOpen function that just rewrites everything, but if someone accesses the document while someone is using it they’ll rewrite everything and ruin their work.
Any ideas on how to solve these two problems? Thank you so much in advance!
I think that you have to find another way to implement your "app" because Google Sheets not a good tool for limiting that only one user edit a spreadsheet a time, but if for any reason you decide to keep with it,...
... you need to implement a workflow like the following
Save the active user email on PropertiesService.getUserProperties().
This should be done by each user by running a script themselves. The most user-friendly will be by using a macro, custom menu or button (a drawing with an assigned Google Apps Script function). You might use an open installable trigger to validate that the active user have already done this.
You might have to make the function that clears the data a "smart" function.
You might have to consider additional cases, like if the owner of the spreadsheet opens it when there is an editor working on the spreadsheet.
Use installable triggers to manage the sharing settings.
Use an open trigger to remove all the editors except the active user
Use a time-driven trigger to add again the editors. To make this work effectively should define how the time-driven trigger will know that the last editor have finished their session, i.e. you might use DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getLastUpdated()
The above should help you with both problems, as long you as the owner do not open the spreadsheet as is used by someone else.
Other alternatives that might work better is to create an add-on or a web application.
Related
Determine current user in Apps Script
Last modified date in Google App Script GAS sheets
I am familiar with the Lock Service but that is only for locking scripts.
I have some code that will "process" a large Google Sheet. My script needs to re-order the rows. I need/want to make it so while the script is running nobody else can change the order. However, I still need another script to be able to append rows.
We use a Google Form for our team's intake. It appends rows to a sheet. I have an hourly job that will go through all the rows/records and "process them". I have a column that stores the last time a record/row was "processed". I want to sort on that column such that the "oldest" records are on top and then start processing from the top down. If the script fails or times out then the next iteration will just start over...
I know I could use getValues or getDisplayValues to get an array and then write the array back but I worry what would happen if someone sorted the rows as it would muck things up when writing the array back.
Is there some way to accomplish my goal? I want to be able to process the records, and maintain row order to avoid breaking my processing.
The way to block a spreadsheet "completely" is by changing the spreadsheet sharing settings. Remove all editors or change them to viewers, once your script finish, change them back as editors. In a extreme case, usa a second account to act as the owner of the critical files / spreadsheets and only use it for this purpose,so you could block your regular account for doing changes to the spreadsheet.
NOTE: A Google Form editResponseUrl could be used to edit the linked spreadsheet.
I'm facing a similar situation but I took a different approach, I'm using an index/key column (you could use the timestamp column) and using the index/key to save each edited row to the right position, then write the whole resulting array in a single operation (by using setValues()). In my case this is simple because I only require values, I'm not worried about notes, data validation, conditional formatting, comments, etc. and there isn't a Google Form linked to my spreadsheet.
Related
Google Spreadsheet -- get sharing permissions by script
Any way to share google docs programmatically?
Can anyone help with these Google Apps Script questions? I've never used scripts before, but I think they could solve my issues...
How do I most easily insert the current date?
Is there a way to highlight a row when the current date is added, and then move that row to the bottom of the current rows?
Is there a way to highlight a name field when it is a duplicate in another sheet?
Is there a way to highlight a row when it is highlighted in another sheet?
I would like to develop a spreadsheet to track the progress of magazine advertisers. I need to track when we receive an advertiser's information and when the ads are proofed out. (Lots of dates to insert!) Then when the ad is approved, I need to highlight that row and move it to the bottom of the other rows. (The number of current rows will be constantly changing.) Then once I receive the layout, I need to know what ads we have and of those, which are approved.
I hope someone can help me out with these questions--thank you in advance!!
Cortny!
A few places to start at regarding Events, Triggers and Spreadsheet handling:
https://developers.google.com/apps-script/understanding_events
https://developers.google.com/apps-script/understanding_triggers
https://developers.google.com/apps-script/reference/spreadsheet/
I have scripts that upon editing a row record in a particular column of that row the time it was edited and in another column the username (email address) of the user editing. This script was originally in a couple of different libraries and I tried to paste the relevant portions into a single script and generalize it to the extent possible. I have not tested as it appears here -- I hope I copied everything:
https://script.google.com/d/1qVLXiKZA8SAgOoW2BAcOCtQ2bXeCNz6oRed8bN9YOOPpvdI0HzAdxeC0/edit?usp=sharing
Since this script also accesses the user's email address it must be explicitly authorized by each user before it works properly. It is for this reason that the main functions is called onEditDelegate() that must be added manually to the onEdit trigger instead of being called onEdit(). If you don't need the username, you can remove that part and it will be easier to install the script.
You can also extend this script so that when all the necessary info is entered the script copies the content of the row, deletes it from the spreadsheet and pastes it at the bottom of the sheet.
Similarly the other points you mentioned can be achieved using triggers/events.
Good luck!