My basic problem is this.
I will be taking data from a Google Sheet that looks a LOT like this:
My current code is basically grabbing the selection turning it into a Range[], turning that into an object array, and going through that array row by row.
Here is the code:
var sheet = ss.getActiveSheet();
var ranger = sheet.getSelection().getActiveRange();
var num = ranger.getNumRows()
var dataArray = ranger.getValues();
for (var i = 0; i < num; i++) {
From here, I open the Doc from Template and replace placeholder values with those procured above:
body.replaceText("##SONG NAME##", songname);
body.replaceText("##Artist##", artist);
Each ROW of data is a new copy of a Google Doc.
So, in superficial terms:
I grab all data. Put it into an object array. Then for each row of the array (which is a different song for our business), I open a new doc, replace the data. Rename, save and close the doc.
Cleanse, Repeat.
I could create a business case to APPEND data to the same document.
Thus grab all data, put into object array, then each row is a new appended SECTION of the same document. Once the for loop ends, we rename, save close...
And that leads to my question:
What are the server implications of what I'm doing? What are the performance hits?
If I want this to run as quickly and efficiently as possible should I change the way I'm collecting data? How I'm passing and replacing the data in the target doc? Should I append? Or is it not a big hit to create anew each time?
I'm just looking for knowledge about the code running optimally, please don't surmise about business or aesthetics.
Related
I have a Google Sheet which is being populated by a Google Form. I am using Google Apps Script to add some extra functionality. Please feel free to access and modify these as needed in order to help.
My goal is to be able to take responses from a Google Form, have that come into a Google Sheet, and then, using a template file, populate the template with the responses and have that sent out as an email attachment to whomever I specify.
This is a dumbed down version of my ultimate project, but the process should remain the same so that I can transpose from this small scale example to that bigger one.
Currently, in my Apps Script, I have code which is successfully able to make a copy of the template file and name it accordingly:
//Enter collected info into Requirements Template
const googleSheetTemplate = DriveApp.getFileById('1wqCwMhpuDLReU1hE1CbcDL-Vdw_4zge1xM6oOl34Ohg');
const destinationFolder = DriveApp.getFolderById('1GxNZQmP8mxHBhVl5AMoqBFs8sAIYzcm3');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 2');
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId());
const A1 = newSheet.getActiveRange();
But the next few lines which are meant to be able to find and replace certain strings within the newly copied Sheet does not seem to function properly.
A1.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
A1.createTextFinder("{{Car}}").replaceAllWith(row[1]);
A1.createTextFinder("{{Color}}").replaceAllWith(row[2]);
A1.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
I just get the same dummy lines back in the new copy.
I was following another post which I found on a different issue but with the same goal. The majority of the concept I was looking to copy came from this blog post, but where they used a Google Doc, I was hoping to use a Google Sheet. Ultimately, the person that receives this new sheet will need to do some calculations and things with the provided information, so it still needs to be in Sheet form.
What modifications do I need to make in order to successfully replace the text in the template with the answers provided from the Google Form responses?
As far as I can tell, this line means some cells on the sheet were selected:
const A1 = newSheet.getActiveRange();
And script will search and replace within these cells only.
Probably you need to define the range with no reference on active range. Something like this:
const A1 = newSheet.getRange("A1:A"); // or "A1:Z", or .getDataRange()
I don't know what the range you need.
From the documentation, createTextFinder(findText) only works on a Sheet class, this means you need to define a Sheet variable before replacing text:
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId()).getSheets()[0];
newSheet.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
newSheet.createTextFinder("{{Car}}").replaceAllWith(row[1]);
newSheet.createTextFinder("{{Color}}").replaceAllWith(row[2]);
newSheet.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
I created an item named “import” under the menu “database” in my google sheet. What I want to execute with this item is that the excel file, with two columns only, can be uploaded and the values nested within them can be stored in an array without appending a new spreadsheet for this excel file. However, I got stuck in “how to upload excel file” this way. After loading the array with the newly uploaded data, another function will be called to add the name-style pair which doesn’t exist in sheet 1 from the array to the unoccupied cells. So this item is designed for updating the sheet1 automatically.
function interface() {
var ui = SpreadsheetApp.getUi();
var menu=ui.createMenu("Data base")
menu.addItem("Import","cal")
menu.addToUi()
}
function onOpen(){
interface()
}
function cal() {
var ss = SpreadsheetApp.getActive().getSheetByName("updated list");// I don't know how to accomplish this part so I created a sheet to store the data as an alternative for the time being.
var lastRow=ss.getLastRow()
var dataBase=ss.getRange(2,1,lastRow,1).getValues()// I want to store the valuse nested within this two columns but there is an error when I use "indexOf" to pick out the data which doesn't exist in sheet1 and push it to the unoccupied cells so I only take one column of values here(Making it one level deep only).
var dataBase2=ss.getRange(2,2,lastRow,1)
var ss1 = SpreadsheetApp.getActive().getSheetByName("sheet1")
var lastRow1=ss1.getLastRow();
var storedData=ss1.getRange(2,1,lastRow1,1).getValues()// Faced with the same problem as described above.
for(var i=0; i<lastRow1;i++){
if(storedData.indexOf(dataBase[i])==-1){
var counter=1
ss1.getRange(lastRow1+counter,1),setValue=dataBase[i]
ss1.getRange(lastRow1+counter,1),offset(0,1),setValue=dataBase2[i]// The error "offset is not defined" shows up here
Logger.log(ss1.getRange(lastRow1+counter,1),setValue=dataBase[i])
counter++
}
}
}
Sheet1 is the worksheet used for looking up who takes charge of which style
Updated list contains the data which I want to add to the array
The logic is that me and my team mates can just take a look at the sheet1 to look for the merchandiser(Name) to know the style he or she takes charge of. But this list should be updated at least once a week. So I wonder if it's possible to automatically add the names and styles in the "updated list" to sheet1 when there is no match found.
For example:
Jason S55567899 and
Nick Jack52578 should be added into worksheet1 right below the last occupied row since these two styles don't exist in sheet1 yet.
I'm building a web app that lets the user curate a double-feature film showing. The user enters a title, a blurb, and two film titles. On a submit button a function is called that displays the user-submitted title, user-submitted blurb, and makes two separate API calls to retrieve movie information on each respective feature.
I'm trying to establish something of a favorites functionality that utilizes localStorage. Conceptualizing the solution, let alone implementing it may be my first mistake, so I'm open to alternative suggestions, but I believe the best way to do this is to capture each search field value (title, blurb, movie_1, movie_2), store these four string values in an object and then push that object to an array, placing each object into localStorage and then getting each object from localStorage later on with a button click.
I'm able to capture these items, store them in localStorage and dynamically generate buttons that when clicked populates the four search field values back into the respective search fields, allowing the user to click the submit button again which runs the api calls and displays all of the content (again: title, blurb, movie_1, movie_2).
My problem is looping through the objects and grabbing the different search field data values. I suppose the problem is in assigning a name or key to the different objects that I'm looping through in the array and then accessing the correct values from the appropriate button through localStorage. I seem to be setting the same localStorage object (or rewriting it) and accessing it over and over, as opposed to setting a new localStorage object and getItem'ing the right one.
I'll provide some code snippets below, but it might be easier to peruse my GitHub repo: https://github.com/mchellagnarls/double_feature
If you look at the repo, latest code is found in index_test.html and app_test.js, whereas a previous version without any of the broken favorite functionality is found in index.html and app.js.
Some code snippets:
// logic to capture search field values and to eventually display them as buttons
// empty array
var dfArray = [];
// object to hold each of the string values to populate the search fields
var doubleFeature = {
feature_1: movie_1,
feature_2: movie_2,
DFTitle: title,
DFBlurb: blurb
}
dfArray.push(doubleFeature);
for (var i = 0; i < dfArray.length; i++) {
localStorage.setItem("df", JSON.stringify(dfArray[i]));
var button = $("<button>");
button.addClass("df-favorite-button");
button.text(title);
$("#buttons-view").append(button);
}
$(document).on("click", ".df-favorite-button", function() {
event.preventDefault();
var savedDF = JSON.parse(localStorage.getItem("df"));
$("#movie-input-1").val(savedDF.feature_1);
$("#movie-input-2").val(savedDF.feature_2);
$("#df-title-input").val(savedDF.DFTitle);
$("#df-blurb-input").val(savedDF.DFBlurb);
})
Thanks for any help. I'm learning web development and I may be overcomplicating things or missing out on an easier way to think about it and/or solve it.
Instead of this loop:
for (var i = 0; i < dfArray.length; i++) {
localStorage.setItem("df", JSON.stringify(dfArray[i]));
var button = $("<button>");
button.addClass("df-favorite-button");
button.text(title);
$("#buttons-view").append(button);
}
I would place the whole array into local storage
localStorage.setItem("df", JSON.stringify(dfArray));
Also then you have to decide which object to get from array in click function
$(document).on("click", ".df-favorite-button", function() {
event.preventDefault();
var id = -1; // which one
var savedDF = (JSON.parse(localStorage.getItem("df")) || []).find(pr => pr.id === id);
$("#movie-input-1").val(savedDF.feature_1);
$("#movie-input-2").val(savedDF.feature_2);
$("#df-title-input").val(savedDF.DFTitle);
$("#df-blurb-input").val(savedDF.DFBlurb);
})
I want to search a sheet for a value in a sheet, and then return the row and the column where the value was found.
I am well-versed in VBA and have used the .Find function to accomplish this very easily. However, after searching for the last 30 minutes online, I have been stunned to discover that is is so hard to find the code for this extremely simple function. I feel like I am in the twilight zone. Does Javascript really not have anything analogous to .Find? If so, why is this language used so much when VBA appears to be able to accomplish the same tasks in a much more simple manner? Please advise.
I assume you are calling something like mysheet.getDataRange().getValues(), which returns the contents of a google sheet as an array of arrays, eg, [[row1A, row1B], [row2A, row2B]].
With JS, you can get the index of a value in an array using indexOf, which returns the index of the found item or -1 if the item is not in the array. I don't think you can directly search across the two nested arrays. Instead, you could try iterating over the outer array and searching the inner array. Something like this:
// get data from google sheet, doing something like this
var data = mysheet.getDataRange().getValues()
// define our own function
function findItem(data) {
// loop over outer array
for (var i=0; i < data.length; i++) {
var row = data[i]; // get the inner array
var idx = row.indexOf(searchValue); // search for value
// if the value is found, return [row, column]
if (idx > -1) {
return [i, idx];
}
}
// call the function
var res = findItem(data);
var row = res[0];
var col = res[1];
You're comparing apples and oranges. JavaScript and VBA are different languages with different goals. VBA was built to allow it to integrate seamlessly with the MSSQLServer. JavaScript in its native form has no relational-database functionality at all. It's meant more for manipulating web pages through the DOM. (It can do more than that, but that's its primary function.) While VBA can do some of the things Javascript can do, it's a rather clunky way (IMHO) of doing so and narrowly focused on a rather specific set of problems that are tied to very specific software and hardware infrastructures. While that functionality might be nice to have in some cases, most of the JavaScript you see on the web today isn't interested in databases at all.
It's not clear to me what source of data you're trying to connect to but if you are specifically looking for a JavaScript data solution you might want to look into something like MongoDB, and the code libraries that have been developed specifically for that. And there are tons of other JS libraries that are relational-data or database-specific, and you can search places like npm for those. Or you can combine JavaScript with languages that inherently include database functionality, and PHP is an excellent example of that.
i am working on a asp.net site.
For this I need a very complex site: I need to have a site in which a user can enter as much Name:Value-pairs as he wants, save them to a database from backend on click, delete this pairs while edeting and add new ones.
Here is a screenshot from a other page where i found such thing:
http://s7.directupload.net/file/d/3377/rm8zzcqe_jpg.htm
As you see you have 2 textboxes, can delete every pair on the right, add textboxes as much as you want and after this, save it, done.
I have very good asp.net knowlegde but less JS knowlegde and I think 99% of this code will be JS, so im a little helpless here.
How to solve that?
Here are couple resources and tips that will hopefully point you in the right direction.
Implementing drag/drop: check out jQueryUI library for examples http://jqueryui.com/draggable/
Adding/removing text boxes: Add a piece of JS code that will create html input elements with appropriate IDs that you can track.
Storing data on the client side: you can keep the data in a two dimensional array that looks like
//Lets assume that there are not more than 100 elements
var x = new Array(100);
for (var i = 0; i < 100; i++) {
x[i] = new Array(2);
}
x[0][0] = "textboxID";
x[0][1] = "value1:value2";
x[1][0] = "textboxID2";
x[1][1] = "value3:value4";
Sending data to the server: Simplest way is to convert those values into JSON string that you can put in a hidden field and then find on the server.