Appending multiple rows in one doc - google-apps-script

I'm trying to automate filling up tables in doc with data from sheets. I created code which creates doc for each row. Now I'd like to upgrade it a bit, so it creates only one file and appends a new table for each row from the sheet. I'm struggling with looping through the data and adding data to the same file.
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('Wygeneruj tabele');
menu.addItem('Nowa tabela', 'createNewGoogleDocs');
menu.addToUi();
}
function createNewGoogleDocs() {
const googleDocTemplate = DriveApp.getFileById('file id');
const destinationFolder = DriveApp.getFolderById('folder id');
const sheet = SpreadsheetApp.getActiveSpreadsheet();
const rows = sheet.getDataRange().getValues();
rows.forEach(function(row, index) {
if (index === 0) return;
if (index === 1) return;
if (row[34]) return;
const ss = sheet.getRange('A3').getValue();
const copy = googleDocTemplate.makeCopy((ss), destinationFolder);
const doc = DocumentApp.openById(copy.getId());
const body = doc.getBody();
body.replaceText('{{Name}}', row[1]);
body.replaceText('{{Date}}', row[2]);
body.replaceText('{{Data}}', row[3]);
rows.forEach(function(row,index) {
let final = copy.appendRow(body)
})
doc.saveAndClose();
const url = doc.getUrl();
sheet.getRange('AI3').setValue(url);
})
}

Related

Search function data entry form

With some help from here i've made a data form, whereby data is put from an input sheet to a data sheet and then the input sheet is emptied again.
Now I want to be able to find the data back in the input sheet when I put the right code.
How do I do this?
This is the script to put data from the input sheet towards the data sheet.
function Process() {
const ss = SpreadsheetApp.getActive();
const dataSheet = ss.getSheetByName('NIEUW Invoerbestand');
const inputSheet =ss.getSheetByName('Input')
const idCell = ss.getRangeByName('Barcode');
const id = idCell.getValue();
const cellFound = dataSheet.getRange('A:A')
.createTextFinder(id)
.matchCase(true)
.matchEntireCell(true)
.findNext()
if (!cellFound) return;
const fieldRange = inputSheet.getRange('Input!E4:E231');
const fieldValues = [fieldRange.getValues().flat()];
dataSheet
.getRange(cellFound.getRow(), 6)
.offset(0, 0, fieldValues.length, fieldValues[0].length)
.setValues(fieldValues);
fieldRange.clearContent();
idCell.clearContent();
}
I've tried this script, but this gives the error 'forEach is not a function'
const searchCell = inputSheet.getRange ("B2")
const searchValue = searchCell.getValue()
const data = dataSheet.getRange ("A4:HY").getValues()
const recordsFound = data.filter( r => r[0] == searchValue)
if(recordsFound.lenght === 0) return
fieldRange.forEach ((f,i) => inputSheet.getRange(f).setValue(recordsFound[0][i+6]))
}

I want google script to run a new document only if one doesn't already exist. I do not want to keep re-writing the documents

Below is the script I am using. It creates documents as forms are submitted. The script works but every time it runs it rewrites every single form. I only want it to write new documents as forms are submitted.
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('AutoFill Docs');
menu.addItem('Create New Docs', 'createNewGoogleDocs')
menu.addToUi();
}
function createNewGoogleDocs() {
const googleDocTemplate =
DriveApp.getFileById('');
const destinationFolder = DriveApp.getFolderById('')
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('RAW');
const rows = sheet.getDataRange().getValues();
rows.forEach(function (row, index) {
if (index === 0) return;
if (row[52]) return;
const copy = googleDocTemplate.makeCopy(`${row[2]}, ${row[0]} Employee Details`,
destinationFolder)
const doc = DocumentApp.openById(copy.getId())
const body = doc.getBody();
const friendlyDate = new Date(row[4]).toLocaleDateString();
body.replaceText('{Q1}', row[2]);
body.replaceText('{Q2}', row[3]);

How to copy multiple rows from multiple sheets to paste into one sheet

I'm trying to paste rows A3:M from XLE, XLF, XLU, XLI, and downwards into the sheet Calendar.
The code below works perfectly for pasting XLE A3:M but I can't figure out how to do the same with the other sheets and append the data at the end of the previous data pasted.
Below is the code:
function copyRowsWithSetValues() {
const id = '113-_bKJT9GkbXBGmB3sOQYhNMrAdQ2xx_oPmAPJrxHA';
const spreadsheet = SpreadsheetApp.openById(id);
const XLE = spreadsheet.getSheetByName('XLE');
const XLF = spreadsheet.getSheetByName('XLF');
const XLU = spreadsheet.getSheetByName('XLU');
const XLI = spreadsheet.getSheetByName('XLI');
const XLK = spreadsheet.getSheetByName('XLK');
const XLV = spreadsheet.getSheetByName('XLV');
const XLY = spreadsheet.getSheetByName('XLY');
const XLP = spreadsheet.getSheetByName('XLP');
const XLC = spreadsheet.getSheetByName('XLC');
const XLB = spreadsheet.getSheetByName('XLB');
const XLRE = spreadsheet.getSheetByName('XLRE');
const COUNTRY = spreadsheet.getSheetByName('COUNTRY');
const Calendar = spreadsheet.getSheetByName('Calendar');
var lastRow = Calendar.getLastRow();
var lastColumn = Calendar.getLastColumn();
var range_to_copy = XLE.getRange("A3:M");
var range_to_paste = Calendar.getRange(lastRow + 1, 2);
range_to_copy.copyTo(range_to_paste, SpreadsheetApp.CopyPasteType.PASTE_FORMAT);
}
I thought I could copy the data from each sheet using this code: var range_to_copy = XLE.getRange("XLE!A3:M, XLF!A3:M, XLU!A3:M"); and then paste that into the main sheet Calendar.
Try is this way
function copyRows() {
const ss = SpreadsheetApp.openById("id");
const shts = ['XLE','XLF','XLU','XLI','XLK','XLV','XLY','XLP','XLC','XLB','XLRE'];
const cal = ss.getSheetByName('Calendar');
shts.forEach((n,i) => {
let sh = ss.getSheetByName(n);
let src = sh.getRange("A3:M" + sh.getLastRow());
let des = cal.getRange(cal.getLastRow() + 1,2);
src.copyTo(des, SpreadsheetApp.CopyPasteType.PASTE_FORMAT);
});
}

Trying to copy merged cells from one sheet to another

I have a script that creates a new file, names it and copies data from a template. The problem I am having is getting all of the formatting over such as merged cells. Here is the code I have so far.
function createNewSheet(e) {
const sh = e.range.getSheet();
var name = sh.getRange(e.range.rowStart, 1).getValue();
var crNew = SpreadsheetApp.create("Job Traveler-" + name);
var ssNew = SpreadsheetApp.openByUrl(crNew.getUrl()).getId();
importRange("1X4iOzc_shcOR8UM7OEM4F1-eR62YZmwKWyyEuu59Pf4","Job!A1:D", ssNew,"Sheet1!A1");
copiedFormat();
}
function importRange(sourceId,sourceRange,destinationID,destinationRangeStart){
const sourceSS = SpreadsheetApp.openById(sourceId);
const sourceRng = sourceSS.getRange(sourceRange);
const sourceVals = sourceRng.getValues();
// Get formatting data
const sourceFontStyle = sourceRng.getFontStyles();
const sourceFontWeight = sourceRng.getFontWeights();
const sourceFontBackgroundColor = sourceRng.getBackgrounds();
const destinationSS = SpreadsheetApp.openById(destinationID);
const destStartRange = destinationSS.getRange(destinationRangeStart);
const destSheet = destinationSS.getSheetByName(destStartRange.getSheet().getName());
destSheet.clear();
const destRange = destSheet.getRange(
destStartRange.getRow(),
destStartRange.getColumn(),
sourceVals.length,
sourceVals[0].length
);
destRange.setValues(sourceVals);
// Set formatting
destRange.setFontStyles(sourceFontStyle);
destRange.setFontWeights(sourceFontWeight);
destRange.setBackgrounds(sourceFontBackgroundColor);
SpreadsheetApp.flush();
}
Best
Description
I've only provided the addtional steps to duplicate merged cells from one range to another. I leave it to you to incorporate the relavent code to your script. I've included a debugging step 'merged.forEach()' which you can remove for production.
Script
function createNewSheet() {
try {
// in my case source and destination are the same spreadsheet but different sheets
// and I have made the ranges arbitrary
importRange("Sheet5","Sheet5!C6:L11","Sheet6","Sheet6!E11")
}
catch(err) {
console.log(err)
}
}
function importRange(sourceId,sourceRange,destinationID,destinationRangeStart) {
try {
var sourceSS = SpreadsheetApp.getActiveSpreadsheet();
var sourceRng = sourceSS.getRange(sourceRange);
var sourceVals = sourceRng.getValues();
var destinationSS = sourceSS;
var destStartRange = destinationSS.getRange(destinationRangeStart);
var destSheet = destinationSS.getSheetByName(destStartRange.getSheet().getName());
var row = destStartRange.getRow();
var col = destStartRange.getColumn();
var rows = sourceVals.length;
var cols = sourceVals[0].length;
destSheet.getRange(row,col,rows,cols).setValues(sourceVals);
var merged = sourceRng.getMergedRanges();
merged.forEach( range => console.log(range.getA1Notation()));
var rowOffset = destStartRange.getRow()-sourceRng.getRow();
var columnOffset = destStartRange.getColumn()-sourceRng.getColumn();
for( var i=0; i<merged.length; i++ ) {
row = merged[i].getRow()+rowOffset;
col = merged[i].getColumn()+columnOffset;
rows = merged[i].getNumRows();
cols = merged[i].getNumColumns();
destSheet.getRange(row,col,rows,cols).merge();
}
}
catch(err) {
console.log(err)
}
}
Reference
https://developers.google.com/apps-script/reference/spreadsheet/range#getMergedRanges()
https://developers.google.com/apps-script/reference/spreadsheet/range#merge()

I am writing a script to transfer data entered into google sheets into a google doc

I am trying to write a script to pull information from a google sheet in a formatted google doc. I had the script running before the google update. It will no longer run. The error I usually get is attempted to execute, but could not save. Also, illegal character line 18. I can not figure out how to fix it. I am somewhat new to all this and teaching myself along the way. Help is appreciated. The script is below.
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('AutoFill Docs');
menu.addItem('Create New Docs', 'createNewGoogleDocs')
menu.addToUi();
}
function createNewGoogleDocs() {
const googleDocTemplate = DriveApp.getFileById('1-
TMh56SXOs6dWEsa1YWc5l9nbdTNn5pSIaCC23w-okc');
const destinationFolder =
DriveApp.getFolderById('1K6U9327cBby96eXoX-YPVTpWRgznt7I1')
const sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('TEST DOR
62');
const rows = sheet.getDataRange().getValues();
rows.forEach(function(row, index){
if (index === 0) return;
if (row[50]) return;
const copy = googleDocTemplate.makeCopy(`${row[2]}, ${row[0]}
Employee Details` , destinationFolder)
const doc = DocumentApp.openById(copy.getId())
const body = doc.getBody();
const friendlyDate = new Date(row[4]).toLocaleDateString();
body.replaceText('{{Q1}}', row[2]);
body.replaceText('{{Q2}}', row[3]);
body.replaceText('{{Q3}}', friendlyDate);
body.replaceText('{{Q4}}', row[5]);
body.replaceText('{{Q5}}', row[6]);
body.replaceText('{{Q6}}', row[7]);
body.replaceText('{{Q7}}', row[8]);
body.replaceText('{{Q8}}', row[9]);
body.replaceText('{{Q9}}', row[10]);
body.replaceText('{{Q10}}', row[11]);
body.replaceText('{{Q11}}', row[12]);
body.replaceText('{{Q12}}', row[13]);
body.replaceText('{{Q13}}', row[14]);
body.replaceText('{{Q14}}', row[15]);
body.replaceText('{{Q15}}', row[16]);
body.replaceText('{{Q16}}', row[17]);
body.replaceText('{{Q17}}', row[18]);
body.replaceText('{{Q18}}', row[19]);
body.replaceText('{{Q19}}', row[20]);
body.replaceText('{{Q20}}', row[21]);
body.replaceText('{{Q21}}', row[22]);
body.replaceText('{{Q22}}', row[23]);
body.replaceText('{{Q23}}', row[24]);
body.replaceText('{{Q24}}', row[25]);
body.replaceText('{{Q25}}', row[26]);
body.replaceText('{{Q26}}', row[27]);
body.replaceText('{{Q27}}', row[28]);
body.replaceText('{{Q28}}', row[29]);
body.replaceText('{{Q29}}', row[30]);
body.replaceText('{{Q30}}', row[31]);
body.replaceText('{{Q31}}', row[32]);
body.replaceText('{{Q32}}', row[33]);
body.replaceText('{{Q33}}', row[34]);
body.replaceText('{{Q34}}', row[35]);
body.replaceText('{{Q35}}', row[36]);
body.replaceText('{{Q36}}', row[37]);
body.replaceText('{{Q37}}', row[38]);
body.replaceText('{{Q38}}', row[39]);
body.replaceText('{{Q39}}', row[40]);
body.replaceText('{{Q40}}', row[41]);
body.replaceText('{{Q41}}', row[42]);
body.replaceText('{{Q42}}', row[43]);
body.replaceText('{{Q43}}', row[44]);
body.replaceText('{{Q44}}', row[45]);
doc.saveAndClose();
const url = doc.getUrl();
sheet.getRange(index + 1, 46).setValue(url)
})
}
I see at least two problems:
Bad formatting. The 'line 18' (the number depends on formatting as well) is broken. Probably it should be:
const copy = googleDocTemplate.makeCopy(`${row[2]}, ${row[0]} Employee Details`, destinationFolder);
And probably here:
doc.saveAndClose();
const url = doc.getUrl();
You close the doc and then you're trying to get its URL. It doesn't look right.
I'd propose to change the lines this way:
const url = doc.getUrl();
doc.saveAndClose();
Just in case, here is the code with fixed formatting. Try it:
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('AutoFill Docs');
menu.addItem('Create New Docs', 'createNewGoogleDocs')
menu.addToUi();
}
function createNewGoogleDocs() {
const googleDocTemplate = DriveApp.getFileById('1-TMh56SXOs6dWEsa1YWc5l9nbdTNn5pSIaCC23w-okc');
const destinationFolder = DriveApp.getFolderById('1K6U9327cBby96eXoX-YPVTpWRgznt7I1')
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('TEST DOR 62');
const rows = sheet.getDataRange().getValues();
rows.forEach(function (row, index) {
if (index === 0) return;
if (row[50]) return;
const copy = googleDocTemplate.makeCopy(`${row[2]}, ${row[0]} Employee Details`, destinationFolder)
const doc = DocumentApp.openById(copy.getId())
const body = doc.getBody();
const friendlyDate = new Date(row[4]).toLocaleDateString();
body.replaceText('{{Q1}}', row[2]);
body.replaceText('{{Q2}}', row[3]);
body.replaceText('{{Q3}}', friendlyDate);
// the loop instead of the 40 lines of code
for (var i = 4; i < 45; i++) {
body.replaceText('{{Q'+ i +'}}', row[i+1]);
}
const url = doc.getUrl();
doc.saveAndClose();
sheet.getRange(index + 1, 46).setValue(url)
})
}