How do I move all Google Sheets rows of data into Google Docs template fields - for-loop

I'm currently have a Google Sheet (Pushed to a website via PHP) with all my clients beer data. I'd like to take that data and copy it into a Google Doc Template for easy printing. In my example I can move the first row of data from the Sheet into the Doc but all the other rows from the sheet do not copy over.
I could use some help with the forEach statement, I'm thinking I need to parse the array and iterate through it in a different way than I'm currently attempting. (First time using Apps Script)
Here is what I've currently coded up.
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('Print Menu');
menu.addItem('Create New Print Menu', 'createNewMenu')
menu.addToUi();
}
function createNewMenu() {
//Google Doc Template ID and Where to Save the New File
const googleDocTemplate = DriveApp.getFileById('1xzlvVOSW_LsgOrm2N2o1-FKYzfqp_2EAbhqrLTn53yk');
const destinationFolder = DriveApp.getFolderById('11HU0TvSPMMXUZaK5gTgg8jvofxTTt02j');
//Get all spreadsheet sheets and add values as 2D arrays.
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Draft List');
const rows = sheet.getDataRange().getValues();
//Create date for new filename.
const dateData = new Date();
const curr_date = dateData.getDate();
const curr_month = dateData.getMonth() + 1; //Months are zero based
const curr_year = dateData.getFullYear();
const theDate = curr_year + "-" + curr_month + "-" + curr_date;
const newFileName = theDate + ' - Bar Print Menu';
//Using the row data in a template literal, we make a copy of our template document in our destinationFolder
const copy = googleDocTemplate.makeCopy(newFileName, destinationFolder)
//Once we have the copy, we then open it using the DocumentApp
const doc = DocumentApp.openById(copy.getId())
//All of the content lives in the body, so we get that for editing
const body = doc.getBody();
rows.forEach(function(rowData) {
//In these lines, we replace our template replacement tokens with values from our spreadsheet rows.
body.replaceText('{{onTapName}}', rowData[0]);
body.replaceText('{{onTapDescription}}', rowData[1]);
body.replaceText('{{onTapPrice}}', rowData[2]);
//Logger.log(rowData);
});
//We make our changes permanent by saving and closing the document
doc.saveAndClose();
}
This code will create a copy of the template file, copy the first row of data from Google Sheets and paste it into the template in the {{onTapName}}, {{onTapDescription}} & {{onTapPrice}} areas but the other rows from the Google Sheet do not copy over.
- Screenshot of Google Sheet, Google Doc Template and Result after running above code
If I uncomment out the "Logger.log(rowData);" line, I can see the code is going through each line of the data from the Google Sheet.
- Screenshot of Execution Log
How do I modify this forEach area to copy through each line of code into the template? I feel like I'm missing something very obvious here.
Thanks in advance for the help.

Related

Automatically copy values from an importrange column to another column before it updates [duplicate]

I have a sheet with data that is imported through IMPORTRANGE to another sheet. When I make changes to Spreadsheet 1 >>> Spreadsheet 2 I have a script that copy the data from Copy to Paste. It is working all fine however I want to make sure that the script only runs when changes are made in the 'Copy' sheet and not any other. At the moment it runs independent on what sheet I make changes in.
Spreadsheet 1
Spreadsheet2
I tried onChange trigger two different ways...
This one makes the change but triggers when changes are made in any of the sheets
function Trigger2(e) {
var sheet = e.source.getActiveSheet();
if (sheet.getName() === 'Copy') {
copyInfo();
}
}
AND
(this does not work)
function Trigger2(e) {
var sheet = e.source.getActiveSheet();
var sheet = SpreadsheetApp.getActiveSpreadsheet();
if( sheet.getActiveSheet().getName() !== "Copy" ) return;{
copyInfo();
}}
The copy code looks like this...
function copyInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Copy");
var pasteSheet = ss.getSheetByName("Paste");
// get source range
var source = copySheet.getRange(2,1,12,8);
// get destination range
var destination = pasteSheet.getRange(2,1,12,8);
// copy values to destination range
source.copyTo(destination);
}
Copy Changes from one Sheet To Another after Imported Range Changes
Spreadsheet 2 Imports a range to Sheet1 from Spreadsheet 1 Sheet1 and when a change occurs in Spreadsheet 2 Sheet1 we copy data from Spreadsheet2 Sheet1 to Spreadsheet2 Sheet 2.
function onMyChange(e) {
//Logger.log(JSON.stringify(e));//useful during setup
//e.source.toast("Entry");//useful during setup
const sh = e.source.getSheetByName("Sheet1")
Logger.log(sh.getName());
if(e.changeType == "OTHER") {
let tsh = e.source.getSheetByName("Sheet2");
sh.getRange(2,1,12,8).copyTo(tsh.getRange(2,1));//Only need the upper left hand corner of the range. Thus you change change the size of the source data without having to change the target range.
}
}
One might be inclined to attempt to use e.source.getActiveSheet() unfortunately this does not necessary get the sheet that you have written unless in is SpreadsheetApp.getActive().getSheets()[0]. onChange event object always returns the most left sheet in the spreadsheet in this situation so it can't be used to identify the sheet that is being written to from the importRange function.
With this function you no longer require another function.
A simple if should work, but you're trying to compare the name to the wrong field. According to Google's documentation, the source field in the Event Object e returns the Spreadsheet object, which is the entire document.
Instead you can use the e.range field, which contains the exact range where the edit was made, and the Range class has a getSheet() method to get the parent Sheet.
So you can modify your sample to the following:
function Trigger2(e) {
var sheet = e.range.getSheet();
if (sheet.getName() === 'Copy') {//Edit: this will only work if sheet is the most left sheet in the spreadsheet
copyInfo();
}
}

Gappscript customer menu to trigger copy range to range of another spreadsheet for loop

What I am trying to do is transfer rows depending on the value in column p starting at row number 7. If cell in column P has a value of " Order" then copy that row from column B to Q to a completely separate already made spreadsheet. I have the script written in the target sheet.
Currently my script does loop through the row and will console.log the data I need... My issue is I have tried multiple things to then write the data to the correct range and can't figure it out.. I need to write the data to starting at row7 columnB... could use a little help..
function transferMonth() {
// SETTING UP THE LAST MONTH SHEET TO PULL NON SOLD DATA FROM
const lastmonthSheetss = SpreadsheetApp.openById("ID OF SPREADSHEET").getSheetByName("CDJR");
const lastSourceRow = lastmonthSheetss.getLastRow();
const sourceRange = lastmonthSheetss.getRange(7, 2, lastSourceRow, 15);
const sourceData = sourceRange.getValues();
// SETTING UP THE SHEET WHERE WE WANT TO TRANSFER LAST MONTHS DATA TO
const targetsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TestCopy");
const lastRow = targetsheet.getLastRow();
const lastCol = targetsheet.getLastColumn();
var sdata = [];
// KEY FOR ACCESSING THE DATA PULLED FROM LAST MONTHS SHEET
//console.log (sourceData[0]);
//console.log(sourceData[0][1]);
//console.log(sourceData[0][3]);
//console.log(sourceData[0][5])
//console.log(sourceData[0][14])
//console.log(sourceData[1][1]);
//console.log(sourceData[1][14]);
//SETTING UP PLACE TO STORE VALUES THAT NEED COPIED
for (i = 0; i < sourceData.length; i++) {
if (sourceData[i][14] === 'Order') {
sdata.push.apply(sdata, lastmonthSheetss.getRange(i + 7, 2, 1, 15).getValues());
sdata.push(i);
}
console.log(sdata)
}
targetsheet.getRange(7,2).setValues(sdata);
}
You can start with this.
Script:
function transferMonth() {
// SETTING UP THE LAST MONTH SHEET TO PULL NON SOLD DATA FROM
const lastmonthSheetss = SpreadsheetApp.openById("ID OF SPREADSHEET").getSheetByName("CDJR");
const lastSourceRow = lastmonthSheetss.getLastRow();
const sourceRange = lastmonthSheetss.getRange(7, 2, lastSourceRow, 15);
const sourceData = sourceRange.getValues();
// SETTING UP THE SHEET WHERE WE WANT TO TRANSFER LAST MONTHS DATA TO
const targetsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TestCopy");
const lastRow = targetsheet.getLastRow();
// use filter to only get the data with 'Order' as the 15th column
var sdata = sourceData.filter(x => x[14] === 'Order');
// always write starting at B7
targetsheet.getRange(7, 2, sdata.length, sdata[0].length).setValues(sdata);
}
Sample Data:
Initial target sheet:
Output:
Note:
Your main issues were the wrong usage of setValues and the pushed index on the array, aside from that, your code should still be workable.

A script to update linked sheet from google doc

I have linked part of a sheet in google doc (as linked object). Now, whenever I change the sheet data, I can click a button in google doc and the data is reflected in the google doc linked sheet too (this is all built in google doc stuff).
What I want to do is the other side of this. I am able to see a bunch of data in one place (google doc) based on the sheets I have linked. I would like to update the data in the google doc, and "upload" it to the linked google sheets.
I am trying to write a script to do that. But cannot seem to find any method to access linked sheets. I found this slides API page that can does the sheet -> slide syncing.
I am looking at the document API page, but I scanning through add... and get... methods, I don't see to find any way to get linked objects. Is it represented as NamedRange? If so, how do I access it?
There was another similar question, but without any satisfactory answer.
If you can share some pointers to get started, I would appreciate it.
Edit: Here is an example doc (and a spreadsheet contained their in) to explain the situation clearer.
Test document for updating spreadsheet - Google Docs
You can find the Table elements in your Document via findElement(elementType). If that's the only Table in your Document, as in the sample you shared, this is immediate.
Once you retrieve the Table, you can loop through its rows and cells and come up with a 2D array with the values from the table:
function getTableValues() {
const doc = DocumentApp.getActiveDocument();
const body = doc.getBody();
const table = body.findElement(DocumentApp.ElementType.TABLE).getElement();
let tableValues = [[]];
for (let i = 0; i < table.getNumRows(); i++) {
const tableRow = table.getRow(i);
for (let j = 0; j < tableRow.getNumCells(); j++) {
const tableCell = tableRow.getCell(j);
const text = tableCell.getText();
tableValues[i].push(text);
}
if (i == table.getNumRows() - 1) break;
tableValues.push([]);
}
return tableValues;
}
Once you've done that, you just need to copy it to your spreadsheet via setValues(values):
function copyToSheet(tableValues, spreadsheetId) {
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName("Sheet1");
sheet.getRange(1, 1, tableValues.length, tableValues[0].length).setValues(tableValues);
}
Calling both of these in the same function, you would get this:
function main() {
const tableValues = getTableValues();
const spreadsheetId = "{your-spreadsheet-id}";
copyToSheet(tableValues, spreadsheetId);
}
Note:
getActiveDocument() is used to retrieve the Document, so this assumes the script is bound to your Document. If that's not the case, use openById(id) or openByUrl(url) instead.

How to add image to google doc with text wrapping via Google Script

I have an image saved in my Google drive called "logo.png".
I want to add the image to a Google document so that it's in the top left corner and so that it does not distort the text around it. (In other words, I want the text to "wrap" around the image).
How do I add an image to a Google Doc using Google Script so that surrounding text wraps around the image?
My script so far:
function myFunction(e) {
var t1 = 'Center for Success';
var t2 = 'Foundational Hall';
var t3 = 'Instruction Sheet for Testing Requirements';
var boldRight ={};
boldRight[DocumentApp.Attribute.BOLD]=true;
boldRight[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT]=DocumentApp.HorizontalAlignment.RIGHT;
var boldCenterUnderline ={};
boldCenterUnderline[DocumentApp.Attribute.BOLD]=true;
boldCenterUnderline[DocumentApp.Attribute.UNDERLINE]=true;
boldCenterUnderline[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT]=DocumentApp.HorizontalAlignment.CENTER;
var filename = 'fileTest';
var doc = DocumentApp.create(filename);
var body = doc.getBody();
body.appendParagraph(t1).setAttributes(boldRight);
body.appendParagraph(t2).setAttributes(boldRight);
body.appendParagraph(space);
body.appendParagraph(t3).setAttributes(boldCenterUnderline);
doc.saveAndClose();
}
Desired Result:
I saw here that an image can be added in various ways, but neither approach has worked for me AND I do not see how I can control a wrapping attribute.
Update
I tried using the following code (with fake ID shown in URL), but it just created a blank document:
var image = "https://drive.google.com/open?id=2PJGK5C64HLKKoQIv52jGhUjjdiXU34Mp";
var fileID = image.match(/[\w\_\-]{25,}/).toString();
var blob = DriveApp.getFileById(fileID).getBlob();
body.appendImage(blob)

Find&Replace script in Google Docs SpreadSheets

I have google spreadsheet with direct links to images (jpg and png):
https://docs.google.com/spreadsheet/ccc?key=0AoPGWppcjtzhdDh6MW1QNVJhSHlwVTlfRnRtd0pvNGc&usp=sharing
I want to increase rows heights starting from "2nd row" to 100px and render images there.
It's possible to do via Find&Replace:
Find jpg and Replace to jpg", 1)
Find http://img and Replace to =image("http://img)
Select rows and Scale them
and the same for png image-urls.
Watch this screencast http://www.screenr.com/S0RH
Is it possible to automate it via script? I think - YES! It have to be pretty simple but I googled a lot but haven't found the solution. I can't do it myself as don't know coding. Will anyone help and make this script?
A function to do what you ask is simple, if you have a basic understanding of the language (Javascript), know how to use the development environment, and read the API documentation.
For example, see this script. It's been added to your shared spreadsheet, so you can also view it (and run it) in the script editor there.
/**
* Scan column A, looking for images that have been inserted using
* =image() function. For any row with an image, set the row height
* to 100 pixels.
*/
function resizeImageRows() {
var sheet = SpreadsheetApp.getActiveSheet(); // Get a handle on the sheet
var HEADERS = 1; // Number of header rows at top
var firstRow = HEADERS + 1; // First row with data
var lastRow = sheet.getLastRow(); // Last row with data
var imageRange = sheet.getRange(1, 1, lastRow, 1); // Column A
// Get all formulas from Column A, without Headers
var formulas = imageRange.getFormulas().slice(HEADERS);
// Look for image() formulas, and set the row height.
for (var i = 0; i< formulas.length; i++) {
if (formulas[i][0].indexOf('image') !== -1) {
sheet.setRowHeight(i+firstRow, 100); // Set height to 100 pixels
}
}
}
You can absolutely do this with the find and replace function under the edit menu, just make sure you click "search in formulas" and it will find and replace in the formula.

Resources