I'm new to this site for the main purpose that I plan to pursue a career in programming. I've landed my first job at an engineering company who is asking me to set up a system in which they can easily determine the time between a job being filed, and it's completion. We're using spreadsheet docs right now to accomplish certain pieces of this.
I'm looking to create a custom function in Google Docs that will allow me to traverse the array of values in row C and then compare it with a number that the function was called with, compare the number to the number in the array and give me which one is the smaller number. EDIT: The function will be called on another sheet called "parsed data" located in the same project file. It's purpose is to automatically file the order number of a current project (just for the sake of being organized) All the other functions I plan to implement will be based off of this order number being correct.
So far, I've gathered this much (I'm learning this on the fly because I still lack experience, so bear with me.)
{
/**created by Alexander Bickford for use at Double E Company
*sorts through a range of values to determine the lowest next value
*returns lowest determined value of next cell
*/
//List Of To Be Implemented Functions
// sheet.appendRow
function setValue(num)
{
var ss = SpreadsheetApp.getActiveSpreadsheet('parsed data');
var ss = ss.getSheets()[0];
var myRange = ss.getRange("C:C").getValues();
newValues = [];
for(i=1;i<=myRange;i++) //Loop to traverse the C range and find the lowest value.
{
if(num<=range[3][i])
{
}
else
num = range[3][i];
}
return num;
}
}
when I call the function in the spreadsheet, I'm getting an error passed that says:
error: ReferenceError: "SPREADSHEET_ID_GOES_HERE" is not defined. (line 8, file "Code")
Google predefines some functions at the top that look like this:
/**
* Retrieves all the rows in the active spreadsheet that contain data and logs the
* values for each row.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
function readRows() { <---Line 8 in the file
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
Logger.log(row);
}
};
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the readRows() function specified above.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Read Data",
functionName : "readRows"
}];
sheet.addMenu("Script Center Menu", entries);
};
End Code I don't need */
I assume it has something to do with the earlier lines (I pointed out line 8). Any thoughts?
Below code is working fine for me.
var ss = SpreadsheetApp.getActiveSheet();
var myRange = ss.getRange("C:C").getValues();
newValues = [];
for(i=1;i<=myRange.length;i++)
{
Logger.log(myRange[i]);
}
Looking at your code, it seems like you have a few problems.
You seem to be mixing up "sheets" with "spreadsheet", and your redundant declaration of "ss" as a variable is bound to cause you some problems.
You seem to be passing in arguments to the incorrect methods. I had this same problem when working with the Google App script earlier. It took a lot of poking around Google's Documentation (which you should really take a look at: https://developers.google.com/apps-script/). You seem to be making the same mistake I did, coding by analogy. looking at Google's sample code and trying to replicate is bound to bump you into some trouble.
Some useful advice:
The most confusing thing to wrap your head around is the structure: spreadsheet>>sheet>>range, you have to explicitely deal with the one's on top before moving to the one's on the bottom.
Remove the 'parsed data' argument from getActiveSpreadsheet(), it should be blank. What you want to use is "getSheetByName("parsed data")" and pass that into a sheet variable.
In your for loop, you also need to use the ".length" method, or use the ".getLastRow()" method with a sheet object to find the last row in your sheet.
Your code might look something like this:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("parsed data");
var endRowNumber = sheet1.getLastRow();
//insert rest of code
Related
Original Question:
I have multiple tabs in a Google Spreadsheet that represent different data sources. Currently, I have a variable (var = quote1location) that is equal to the sheet name that I would like to get my data from based on other logic.
Pretend that quote1location can equal 'Sheet1', 'Sheet2', or 'Sheet3' depending on the logic but for this case, it equals 'Sheet1'.
var totalpeople = quote1location.getRange('A1').getValue();
In the function above, Apps Script will return an error saying 'quote1location.getRange is not a function' because Apps Script is not substituting the value of the variable that I have designated ('Sheet1') but is using the variable name ('quote1location' instead. I would like Apps Script to process this as 'Sheet1.getRange('A1').getValue()'.
Your help would be appreciated
Answer:
Thank you all for your responses. What I was trying to do is use a string in the 'getRange()' function. Pretend I had two Google Sheets named 'Sheet1' and 'Sheet2' and I had a variable that helped me determine what sheet to grab as my data reference. I was trying to set a variable as either (var source = 1) or (var source = 2) so that I could then use this variable in my getRange() function like this: ('Sheet' + source).getRange('A1').getValue();
What I was trying to do here is if var source = 1, then I would get my data from 'Sheet1'. If the var source = 2, then I would get my data from 'Sheet2'.
The issue (as mentioned by those who responded) is that I was trying to use .getRange() on a string, not an object like a specific spreadsheet. Instead of using var source = 2 or var source = 1 I should be using
ss = SpreadSheetApp.getActiveSpreadsheet()
if(somevariable = somecondition){
var source = ss.getSheetbyName('Sheet1')
}
if(someothervariable = someothercondition){
var source = ss.getSheetByName('Sheet2')
}
Now when I use getRange()' on 'source', it will be calling the sheet that I have designated rather than trying to retrieve a range from a string which will not work.
Thank you very much to all who provided feedback.
I believe you are looking to do:
const quote1Location = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(`Sheet1`)
const totalPeople = quote1Location.getRange(`A1`).getValue()
Alternatively:
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
const quote1Location = `Sheet1`
const totalPeople = spreadsheet.getSheetByName(quote1Location)
.getRange(`A1`)
.getValue()
Whether these are the exact syntax you're hoping to use or not, I hope this helps you better understand how to accomplish accessing a Sheet.
I have managed with VBA and Excel to achieve my purposes, but I'd like to move to google spreadsheet for particular reasons.
I'm trying to replicate a code that works just fine in VBA.
It's simple, I have a sheet with a bank of questions in column A, and I'd like a macro that can select 1 random question and copy it to a second sheet.
I'm having trouble understanding how I can access a random cell, copy it and paste it to the second sheet. Some plain explanation would be appreciated since I have very little or non-existent knowledge of programming or javascript.
function test() {
var ss = SpreadsheetApp.openById("sheetID");
//Say I have 10 questions in the BANKSHEET, for instance
var rQuestion = Math.floor(Math.random()*10+1);
//What goes in A1? So that I can access the range randomly according to rQuestion value.
var inputRange = ss.getSheetByName("BANKSHEET").getRange("A1");
var inputValues = inputRange.getValues();
var outputRange = ss.getSheetByName("QUIZZ").getRange("A1").setValues(inputValues);
How about this modification? I think that there are several solutions for your situation. So please think of this as one of them.
Modification points :
Retrieve the number of cells at "A1:A" from sheet of "BANKSHEET".
Retrieve randomly one of the number.
Copy the cell value of the retrieved number to "A1" of "QUIZZ".
Modified script :
function test() {
var ss = SpreadsheetApp.openById("sheetID");
// Retrieve randomly a value from sheet of BANKSHEET
var sheet = ss.getSheetByName("BANKSHEET");
var src = sheet.getRange("A" + (1 + Math.floor(Math.random() * sheet.getLastRow())));
// Put the value to "A1" at sheet of QUIZZ
var dst = ss.getSheetByName("QUIZZ").getRange("A1");
src.copyTo(dst);
}
Note :
It supposes that there are values in only column A of "BANKSHEET".
This modified script randomly retrieves one value from column A of "BANKSHEET" every time.
If you don't want to use the value which has already been used, please modify the script for your situation.
Reference :
copyTo()
If I misunderstand your question, I'm sorry.
I've been busy trying to use the build-in javascript in Google Spreadsheet, however, not having worked in either javascript or Google Spreadsheet, i'm having a few difficulties.
My script is supposed to read a number (1-3) in a cell, and from that number parse an image to the cell below (I've been using the setFormula command for this).
So far it's working for 1 cell (B6 as i've choosen right now), but i would like to loop through a column with numbers in every other cell (So that after the script has run, it's number-picture-number-picture etc) - i just can't figure out how.
The code i'm using right now:
function numbtoimage() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var url = 'IMAGE("https://dl.dropboxusercontent.com/s/bpqy8o796casqjl/belt.JPG?dl=0", 2)';
var url2 = 'IMAGE("https://dl.dropboxusercontent.com/s/4q8sakhkpot0h65/belt2.JPG?dl=0",2)';
var url3 = 'IMAGE("https://dl.dropboxusercontent.com/s/kvsf4z6z45rcg53/belt3.JPG?dl=0",2)';
var cell = sheet.getRange("B6")
var data = cell.getValue()
if(data==1) {cell.offset(1, 0, 1).setFormula(url);}
else if(data==2) {cell.offset(1, 0, 1).setFormula(url2);}
else if(data==3) {cell.offset(1, 0, 1).setFormula(url3);}
}
I've looked at This similar problem, but have been unable to make it work for my case.
Any help is greatly and truly appreciated!
Nicklas
You need some sort of loop to go through the data. I Would suggest a FOR loop.
Your script is currently written to get one single cell value, rather than all the values.
So it might be an idea to get all values in one go, then check whats in them.
Also from you question, it's not clear where the numbers will be found.
Only in column B?
Here is a quick example (untested), that goes through column B looking for a number and it should insert the link in the cell below based on that number. This code is based on your original example and untested but hopefully it helps.
function numbtoimage() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var url = 'IMAGE("https://dl.dropboxusercontent.com/s/bpqy8o796casqjl/belt.JPG?dl=0", 2)';
var url2 = 'IMAGE("https://dl.dropboxusercontent.com/s/4q8sakhkpot0h65/belt2.JPG?dl=0",2)';
var url3 = 'IMAGE("https://dl.dropboxusercontent.com/s/kvsf4z6z45rcg53/belt3.JPG?dl=0",2)';
var values = sheet.getValues();
for(i=0; i < values.lenth ; i++){
if(values[i][1]==1) {sheet.getRange(i+2, 2).setFormula(url);}
else if(values[i][1]==2) {sheet.getRange(i+2, 2).setFormula(url2);}
else if(values[i][1]==3) {sheet.getRange(i+2, 2).setFormula(url3);}
}
}
The context: I need to process/correct many text documents containing multiple particular textual errors, highlight keywords in 'bold' and then output the result. I have a Google spreadsheet with two worksheets: one with two columns of 'wrong wordforms' and 'replacement wordforms' (2d array) that I intend to add to over time and use it as a datastore to 'call from;' the other, a single-column collection of words (1d array) I designate "keywords" to check for and then highlight in the target documents.
Things I've tried that worked: I used a basic array iteration loop from a beginner video (I can't add more links yet, I apologize) and swapped in body.replaceText() for the sendEmail(), successfully, to process the corrections from my "datastore" into my target document, which works nearly perfectly. It ignores text values without the exact same case...but that's a problem for another day.
function fixWords() {
// Document to edit
var td = DocumentApp.openById('docId1');
// Document holding comparison datastore
var ss = SpreadsheetApp.openById('docId2');
// Create data objects
var body = td.getBody();
var sheet = ss.getSheetByName("Word Replacements");
var range = sheet.getDataRange();
var values = range.getValues();
// Create a loop (iterate through the cell data)
for (i=1;i<values.length;i++) {
fault = values[i][0];
solution = values[i][2];
body.replaceText(fault, solution);
}
}
Things I've tried that fail: I then tried just swapping out values for setBold() with the replaceText() code, but the closest I got was the first instance of a keyword from the array would be styled correctly, but no further instances of it...unlike ALL of the instances of an incorrectly spelled word being corrected from the Word Replacements array using the fixWords function.
I found the 'highlightTextTwo' example here at stackoverflow which works very well, but I couldn't figure out how to swap in an external data source or force the included different iteration loop to work in my favor.
I've scanned the GAS reference, watched Google developer videos for snippets that might apply...but clearly I'm missing something that's probably basic to programming. But I honestly don't know why this isn't as easy as the body.replaceText() functionality.
function boldKeywords() { // https://stackoverflow.com/questions/12064972
// Document to edit
var doc = DocumentApp.openById('docId1');
// Access the keyword worksheet, create objects
var ss = SpreadsheetApp.openById('docId2');
var sheet = ss.getSheetByName("Keywords");
var range = sheet.getDataRange();
var values = range.getValues();
var highlightStyle = {};
highlightStyle[DocumentApp.Attribute.BOLD] = 'true';
for (i=1; i<values.length; ++i) {
textLocation = values[i];
if (textLocation != null && textLocation.getStartOffset() != -1) {
textLocation.getElement().setAttributes(textLocation.getStartOffset(),textLocation.getEndOffsetInclusive(), highlightStyle);
}
}
}
This throws out 'TypeError: Cannot find function getStartOffset in object DIV. (line 15, file "boldIt").' I guess this means that by just blindly swapping in this code, it's looking in the wrong object...but I cannot figure out why it works for x.replaceText() and not for x.setAttributes() or x.setBold or .getElement().getText().editAsText()...there just doesn't seem to be a "Learn Google Apps Script example" that deals with something this low on a scale of mundane, uninteresting use cases...enough for me to figure out how to direct it to the right object, and then manipulate the "if statement" parameters to get the behavior I need.
My current brick wall: I spotted this example, again, Text formatting for strings in Google Documents from Google Apps Script, and it seemed promising, even though the DocsList syntax has been deprecated (I'm fairly sure). But now I get "bold is not defined" thrown at me. Bold...is not defined. :: mouth agape ::
function boldKeywords() {
// Access the keyword worksheet, create objects
var ss = SpreadsheetApp.openById('docId1');
var sheet = ss.getSheetByName("Keyterms");
var range = sheet.getDataRange();
var values = range.getValues();
// Open target document for editing
var doc = DocumentApp.openById('docId2');
var body = doc.getBody();
// Loop function: find given keyword value from spreadsheet in target document
// and then bold it (highlight with style 'bold')
for (i=1; i<values.length; ++i) {
keyword = values[i];
target = body.findText(keyword);
body.replaceText(target,keyword);
text = body.editAsText();
text.setBold(text.startOffset, text.endOffsetInclusive, bold);
}
}
I will happily sacrifice my firstborn so that your crops may flourish for the coming year in exchange for some insight.
I use this for my scripts, the setStyleAttribute method.
Documentation : https://developers.google.com/apps-script/ui_supportedStyles
Example :
TexBox.setStyleAttribute("fontWeight", "bold");
The bold parameter is a Boolean data type. You need to use the word true or false.
Replace "bold" with "true".
text.setBold(text.startOffset, text.endOffsetInclusive, true);
Check out the "Type" column in the documentation:
Google Documentation - setBold
Good evening,
I'm trying to use some coding skills to help manipulate a spreadsheet in Google Docs and think the logic I've worked out is sound - but the script just returns results as 'Range'.
Essentially the script is a nested loop and (should) take values from six points in a row of data (starting in 11) and plonk them into a long vertical (column 38). Then it should move onto the next row.
I think it works, but the results just come back as 'Range' and can't see how to put the values into range, if that's what this means.
I also realise that it might be more effective to use a single array to gather the data on an individual array, but I'm still trying to get to grips with the syntax.
Here's my code:
function Transform() {
//load spreadsheet data and initialise variables
var sheet = SpreadsheetApp.getActiveSheet();
var firstrow = 11;//this is a manual figure
var d = firstrow;
var valuerplc = sheet.getRange(firstrow, 38);
var value =1;
for(var c=firstrow; c<sheet.getLastRow(); c++){
for (var e=3; e<33; e=e+6){
var mon = sheet.getRange(c, e);
valuerplc = sheet.getRange(d, 38);
valuerplc.setValue(mon);
}
d++;
}
}
Can anyone help, or at least point me in the right direction, please?
You've been caught with a common newbie problem, having trouble differentiating between Ranges and Values.
A Range expresses a region of a spreadsheet, with methods that give you access to various characteristics of the object. The contents, or data that you see in a spreadsheet is accessible via the .getValue() method (for one cell) or .getValues() (for more than one cell).
Change:
var mon = sheet.getRange(c, e);
To:
var mon = sheet.getRange(c, e).getValue();
... and you'll have the data that's in that range, as a String, Number or Date, depending on what was there.
The variable names you've selected may lead to confusion, it's worthwhile being careful with that. For example, look at valuerplc. The name implies that it's a value, which can be confused with .getValue() and .setValue(). But the way that it's used is as a Range, as in valuerplc.setValue(mon), so it's clearly NOT a value.
function Transform() {
//load spreadsheet data and initialise variables
var sheet = SpreadsheetApp.getActiveSheet();
var firstrow = 11;//this is a manual figure
var d = firstrow;
var valuerplc = sheet.getRange(firstrow, 38);
var value =1;
for(var c=firstrow; c<sheet.getLastRow(); c++){
for (var e=3; e<33; e=e+6){
var mon = sheet.getRange(c, e).getValue();
valuerplc = sheet.getRange(d, 38);
valuerplc.setValue(mon);
}
d++;
}
}