How to remove data validations? - google-apps-script

I want to remove all data validations from a sheet, tried following but it does not get rid of them. Anyway to do this through apps script?
var ss = SpreadsheetApp.getActiveSpreadsheet();
var accountSheet = ss.getSheetByName("Account A");
accountSheet.getRange(1,1,274,61).clear();

accountSheet.getRange(1,1,274,61).setDataValidation(null)
That should do the job.

A more generic answer to remove all data validations from the whole sheet (remove from all cells in sheet):
mySheet.getRange(1,1, mySheet.getMaxRows(), mySheet.getMaxColumns()).setDataValidation(null);
You could in theory use this less verbose version (might be faster because it affects a smaller range of cells):
mySheet.getDataRange().setDataValidation(null);
However, there may be empty cells outside the DataRange that do have validations and those validations will not be removed (they are outside the scope of DataRange, won't be selected by DataRange). Hence, you should use the first version I mentioned for more robust code: it selects all the cells in the sheet and removes validations.

Related

Canonical way to reference Elements

Is there a canonical way to set an ID—or other searchable, persistent data attribute—on Elements in Google Docs, such that I can easily refer back to it later? I'm looking for something equivalent to getElementById in javascript. Almost all examples I've seen, including Google's own docs, seem to reference objects by searching for text strings or inserting new strings.
I've found one reference in the NamedRanges class to a getId function, but I can't find any place to set that ID. I do see the setAttributes function on Elements but that seems to apply only for pre-defined attribute types. I haven't tested that, though.
In case it's relevant: my interest is in automatically creating a document from a Google Sheet and populating based on the current values in the sheet. I'd like to assign specific Elements individual IDs so I can easily retrieve the Element and replace the text if the values in the sheet change later on.
Turns out that this is possible using NamedRanges, I just didn't read carefully enough.
Note: All the following examples are working off this Google doc. You can make a copy and select "Script Editor" from the Tools menu to see the code.
You can assign named ranges pretty easily using Apps Script. The below code looks through the doc for [[TITLE]] and [[ABSTRACT]] and assigns named ranges to those chunks. Note that in the aforelinked doc I put them in a table to avoid issues with partial ranges.
function assignNamedRanges() {
const doc = DocumentApp.getActiveDocument();
const body = doc.getBody();
const placeholders = ["title", "abstract"];
placeholders.forEach(p => {
const rangeBuilder = doc.newRange();
const text = body.findText("[[" + p.toUpperCase() + "]]");
rangeBuilder.addElement(text.getElement());
doc.addNamedRange(p, rangeBuilder.build());
});
}
Once you assigned them, you can update the range to something else in a separate function:
function updateNamedRanges() {
const doc = DocumentApp.getActiveDocument();
const body = doc.getBody();
const title = doc.getNamedRanges("title")[0];
const abstract = doc.getNamedRanges("abstract")[0];
title.getRange().getRangeElements()[0].getElement().asText().setText("Bob");
abstract.getRange().getRangeElements()[0].getElement().asText().setText("I like pancakes");
}
Note that NamedRanges are persistent, and the multiple NamedRange instances can have the same name. This means that if you run the first function four times, you'll have eight named ranges. You can make a convenience function to clear all those out pretty easily:
function clearNamedRanges() {
DocumentApp.getActiveDocument().getNamedRanges().forEach(r => {
r.remove();
})
}
So I been checking the documentation about elements for Google Docs in AppScript and it seems that some of them can be modified but not as freely as it looks as noted in the documentation:
Elements shown in bold can be inserted; non-bold elements can only be manipulated in place.
I tried checking with setAttributes as you mentioned however the attributes itself can only be from a document elements like: TEXT, PARAGRAPH, TABLE, ETC, this elements can't receive an ID as there is not method to insert an specific ID as you are requiring, most of the values that can be inserted are specific element attributes like: Font size, Font family, etc.

How to apply the same conditional formatting rule to multiple columns in Google sheets using apps script?

I have multiple columns - G, L, Q, V, AA, AF - to which I want to apply a conditional format rule in Google sheets. Starting in row 2 - so that I don't include the header row - I want any given cell in the specified column to .setBackgroundColor ("orange") if any text or data is found to the right of that cell. For example, I want cell G2 to be orange if cell H2 has anything entered inside of it, and L17 to be orange if S17 has data, and AA5 to be orange if AD5 is not blank.
My experience with apps script is very primative. I can only successfully write very few lines of code, so my dilemma is past my ability. I understand it is possible to apply conditional formatting using sheets' built in conditional formatting tab, but it will not work for my project seeing as I am gathering data with a Google form, and with every response I receive from the form, the sheet creates a new line for the submission that retains none of the formatting from the rest of the sheet. My plan would be to add a form submission trigger to the code so that the conditional formatting in the columns updates regularly with the sheet.
I have been looking around for some time online and have not found a solution to my problem. Any help would be greatly appreciated! Thank you!
The following example shows the process of creating a new conditional format rule, applying it to the sheet. Then copying and pasting the format of a range to a target range. You can find the references for the methods used in the references section at the end of this answer.
Example:
function myFunction() {
// The range where the formatting will be applied.
var range = 'G2:G'
// Get the array containing the conditional formatting rules for the sheet
var spreadsheet = SpreadsheetApp.getActive();
var conditionalFormatRules = spreadsheet.getActiveSheet().getConditionalFormatRules();
// Build the new conditional formatting rule and push it to the array
conditionalFormatRules.push(SpreadsheetApp.newConditionalFormatRule()
.setRanges([spreadsheet.getRange(range)]) // The range to apply to
.whenFormulaSatisfied('=H2<>""') // The formula to check
.setBackground('orange') // The format to apply
.build());
// Set the conditional format rules for the sheet with the updated array
spreadsheet.getActiveSheet().setConditionalFormatRules(conditionalFormatRules);
// Paste the format of the range into the next desired range
spreadsheet.getRange(range).copyTo(spreadsheet.getRange('L2:L'), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
/* repeat the previous instructions for all your target ranges replacing "L2:L" with the target range */
};
References:
-getConditionalFormatRules()
-newConditionalFormatRule()
-setConditionalFormatRules()
-copyTo(destination, copyPasteType, transposed)

Script to set default font size and style in google sheets

I have a shared google sheet where people constantly paste new data in however the data is always in different styling and restyling it is very time consuming. I was wondering if it it's possible with a script that auto correct styling and size in a document.
If you are looking at resetting it to the default theme then you can use this script:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSheet();
var range = ss.getRange(1, 1, ss.getMaxRows(), ss.getMaxColumns());
range.clearFormat();
}
This triggers every-time a user edits the sheet (including pasting some data) and clears all formats in the sheet. If this doesn't work for you in case you have specific formats for some cells, like data headers that you don't want to change, then you can customise the script using methods like setFontSize(size) etc.
Edit: Changed the answer for the specific spreadsheet.
Use this script
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSheet();
var range = ss.getRangeList(['B29:B42', 'B27']);
range.setFontFamily("Arial")
.setFontSize(11)
.setFontColor("#000000")
.setBackground("#ffffff");
}
The following script will reset the formatting on the edited range. You can further validate the row/column/sheet before resetting the formatting (eg. to prevent header rows from getting affected) using the values of e.range or e.range.getSheet()
function onEdit(e) {
e.range.setFontColor() // Resets color
.setFontSize(10) // Sets size to 10 (has to be a number)
.setFontFamily() // Resets font family
.setFontLine() // Resets underline, strikethrough
.setFontWeight() // Resets bold
.setFontStyle() // Resets italics
}
Instead of onEdit, some other options include
making a timed trigger that routinely resets the formatting
running a script manually when you would like to reset formatting
Refer to Range class.

How can I email a specific range of cells while KEEPING the displayed formatting?

I am trying to export a specific range of cells in the form of an email. The cells are formatted a certain way, and also have conditional formatting associated for color-coding.
Here is my demo sheet: https://docs.google.com/spreadsheets/d/1ibB87Vhz7wTjKrIrasYSRLoAiadQHtNqqmyl-xywtOI/edit?usp=sharing
Ive gotten the email to send successfully, however I cant figure out how to take the associated formatting, conditional formatting, fonts, borders...etc.
Currently, it's taking the displayValues, and listing them with comas. I'm also looking to get rid of the comas, and if possible, limit the range to only cells with data within the range.
Here is what I've got:
function sendReport(){
var incidents = SpreadsheetApp.getActiveSheet().getRange(2,1,4,1).getDisplayValues();
var subjectRange = SpreadsheetApp.getActiveSheet().getRange("A1");
var subjectCell = subjectRange.getValues();
for (i in subjectCell) {
var rowData = subjectCell[i];
var subject = rowData [0];
}
MailApp.sendEmail("emailaddress#domain.com",
subject,
incidents);
}
That's because you are literally sending an Array in your email (since getValues() returns a 2-dimensional Array). If you want to keep formatting, you should construct an html table from this array by iterating over it and append the result to email body via htmlBody property in options.
Take a look at the documentation for detailed info on how to get styles from Range. You will have to map each styling into style="" attribute for HtmlElements you want to be formatted, like so (to save resources, get styling in bulk and include into Array loop):
getFontColors() - color:{method result} (if one, apply to HtmlTableElement);
getFontFamilies() - font-family:{method result};
...etc...
or simply get all styles in bulk with getTextStyles() and access individual style property with appropriate methods (note that you will still need to access background colors with getBackgrounds() method, height with getHeight(), etc).

Can we hide column in sheet using google apps script?

I want to share the sheet with others but i also want them to not able to see some columns. Is there any way out to solve this using google apps script or if any alternate option for the same. Thank you.
You should take a look at the documentation, it will help you to find the function you're looking for. In this case, you need the Sheet.hideColumns(columnIndex) method
hideColumns(columnIndex)
Hides the column at the given index.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// Hides the first column
sheet.hideColumns(1);
Very simple function
function onOpen(){
ss = SpreadsheetApp.openById( 'sheetid' ),
sheet = ss.getSheetByName('sheet_name'),
ss.getActiveCell();
sheet.hideColumns(start_column_number, end_column_number);
}
If the columns to be hidden are part of a merged column set, the hide columns methods don't work unless you hide all the columns in the merge.